Module refinery.units.obfuscation.ps1
Expand source code Browse git
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import re
from refinery.lib.patterns import formats
from refinery.units.obfuscation import StringLiterals
from refinery.units.encoding.ps1str import ps1str
def dq_unescape(string):
def unescape(match):
char = match[0]
return ps1str.UNESCAPE.get(char, char[1:])
def splitvars(string):
backtick = False
variable = ''
lbc, rbc = None, None
brackets = 0
position = 0
for k, character in enumerate(string):
if backtick:
backtick = False
continue
if not variable:
if character == '`':
backtick = True
elif character == '$':
variable = True
yield string[position:k]
position = k
continue
if position == k - 1:
if character in '?$':
variable = False
next_pos = k + 1
if character not in '({':
lbc, rbc = None, None
elif character == '(':
lbc, rbc = '(', ')'
elif character == '{':
lbc, rbc = '{', '}'
if lbc:
if character == lbc:
brackets += 1
if character == rbc:
brackets -= 1
if not brackets:
variable = False
next_pos = k + 1
elif variable:
variable = character.isalnum() or character in '_:'
next_pos = k
if not variable:
yield string[position:next_pos]
position = next_pos
yield string[position:]
if variable:
yield ''
for k, item in enumerate(splitvars(string)):
yield item if k % 2 else re.sub('`.', unescape, item).replace('""', '"')
def string_unquote(string: str):
"""
Returns the string contents without quotes as they would appear in double
quotes. If the input string uses single quotes, it is escaped.
"""
quote = string[0]
if quote != string[-1] or quote not in ''''"''':
raise ValueError(F'not a valid quoted string: {string}')
string = string[1:-1]
if quote == '"':
yield from dq_unescape(string)
else:
yield string.replace("''", "'")
def string_quote(parts, quote=True):
def escaper(match):
char = match[0]
return ps1str.ESCAPE.get(char, char)
if isinstance(parts, str):
parts = [parts]
chunks = [
part if k % 2 else re.sub(R'''[\x00\x07-\x0D`$'"]''', escaper, part)
for k, part in enumerate(parts)
]
for k in range(1, len(chunks) - 1, 2):
suffix = chunks[k + 1]
if suffix and chunks[k][~0] not in '})' and (suffix[0].isalnum() or suffix[0] in ':_'):
chunks[k] = F'${{{chunks[k][1:]}}}'
result = ''.join(chunks)
if quote: result = '"{}"'.format(result)
return result
def string_apply(string, callback):
def application(parts):
for k, part in enumerate(parts):
if k % 2:
yield part
continue
result = callback(part)
if isinstance(result, str):
yield result
else:
yield from result
return string_quote(application(string_unquote(string)))
class Ps1StringLiterals(StringLiterals):
def __init__(self, data: str):
super().__init__(formats.ps1str, data)
Sub-modules
refinery.units.obfuscation.ps1.all
refinery.units.obfuscation.ps1.b64convert
refinery.units.obfuscation.ps1.brackets
refinery.units.obfuscation.ps1.cases
refinery.units.obfuscation.ps1.concat
refinery.units.obfuscation.ps1.encodings
refinery.units.obfuscation.ps1.escape
refinery.units.obfuscation.ps1.format
refinery.units.obfuscation.ps1.invoke
refinery.units.obfuscation.ps1.securestring
refinery.units.obfuscation.ps1.stringreplace
refinery.units.obfuscation.ps1.typecast
refinery.units.obfuscation.ps1.uncurly
Functions
def dq_unescape(string)
-
Expand source code Browse git
def dq_unescape(string): def unescape(match): char = match[0] return ps1str.UNESCAPE.get(char, char[1:]) def splitvars(string): backtick = False variable = '' lbc, rbc = None, None brackets = 0 position = 0 for k, character in enumerate(string): if backtick: backtick = False continue if not variable: if character == '`': backtick = True elif character == '$': variable = True yield string[position:k] position = k continue if position == k - 1: if character in '?$': variable = False next_pos = k + 1 if character not in '({': lbc, rbc = None, None elif character == '(': lbc, rbc = '(', ')' elif character == '{': lbc, rbc = '{', '}' if lbc: if character == lbc: brackets += 1 if character == rbc: brackets -= 1 if not brackets: variable = False next_pos = k + 1 elif variable: variable = character.isalnum() or character in '_:' next_pos = k if not variable: yield string[position:next_pos] position = next_pos yield string[position:] if variable: yield '' for k, item in enumerate(splitvars(string)): yield item if k % 2 else re.sub('`.', unescape, item).replace('""', '"')
def string_unquote(string)
-
Returns the string contents without quotes as they would appear in double quotes. If the input string uses single quotes, it is escaped.
Expand source code Browse git
def string_unquote(string: str): """ Returns the string contents without quotes as they would appear in double quotes. If the input string uses single quotes, it is escaped. """ quote = string[0] if quote != string[-1] or quote not in ''''"''': raise ValueError(F'not a valid quoted string: {string}') string = string[1:-1] if quote == '"': yield from dq_unescape(string) else: yield string.replace("''", "'")
def string_quote(parts, quote=True)
-
Expand source code Browse git
def string_quote(parts, quote=True): def escaper(match): char = match[0] return ps1str.ESCAPE.get(char, char) if isinstance(parts, str): parts = [parts] chunks = [ part if k % 2 else re.sub(R'''[\x00\x07-\x0D`$'"]''', escaper, part) for k, part in enumerate(parts) ] for k in range(1, len(chunks) - 1, 2): suffix = chunks[k + 1] if suffix and chunks[k][~0] not in '})' and (suffix[0].isalnum() or suffix[0] in ':_'): chunks[k] = F'${{{chunks[k][1:]}}}' result = ''.join(chunks) if quote: result = '"{}"'.format(result) return result
def string_apply(string, callback)
-
Expand source code Browse git
def string_apply(string, callback): def application(parts): for k, part in enumerate(parts): if k % 2: yield part continue result = callback(part) if isinstance(result, str): yield result else: yield from result return string_quote(application(string_unquote(string)))
Classes
class Ps1StringLiterals (data)
-
Expand source code Browse git
class Ps1StringLiterals(StringLiterals): def __init__(self, data: str): super().__init__(formats.ps1str, data)
Ancestors
- refinery.units.obfuscation.StringLiterals