Skip to content

Instantly share code, notes, and snippets.

@andretavare5
Last active February 14, 2024 08:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andretavare5/66ec413cdb4c7c39d35c22d38c7067a8 to your computer and use it in GitHub Desktop.
Save andretavare5/66ec413cdb4c7c39d35c22d38c7067a8 to your computer and use it in GitHub Desktop.
Script that decrypts most of PrivateLoader stack strings - https://tavares.re/blog/2022/06/06/hunting-privateloader-pay-per-install-service/
import pefile
import struct
from capstone import *
def extract_var(op):
if ']' in op:
op = ''.join(op.split(' ')[-1])[:-1].replace('[', '')
return op
def search(instructions, var):
data_chunks = []
for inst in instructions:
if inst[2] == 'mov':
try:
imm = int(inst[3].split(' ')[-1], 16)
data_chunks.append(struct.pack('<I', imm))
if extract_var(inst[3].split(', ')[0]) == var:
return b''.join(data_chunks[::-1]) # 16 bytes str chunk
except: # not a dword
pass
if extract_var(inst[3].split(', ')[0]) == var:
var = extract_var(inst[3].split(', ')[1])
def decrypt_strings(filename):
# disassemble .text section
pe = pefile.PE(filename)
md = Cs(CS_ARCH_X86, CS_MODE_32)
md.skipdata = True
instructions = []
text = pe.sections[0]
text_addr = pe.OPTIONAL_HEADER.ImageBase + text.VirtualAddress
for (addr, size, mnemonic, op_str) in md.disasm_lite(text.get_data(), text_addr):
instructions.append((addr, size, mnemonic, op_str))
# search, build and decrypt strings
strings = []
addr = None
string = ''
for i, inst in enumerate(instructions):
if inst[2] == 'pxor':
try: # possible string decryption found
encrypted_str = search(instructions[:i][::-1], extract_var(inst[3].split(', ')[0])) # reverse search
key = search(instructions[:i][::-1], extract_var(inst[3].split(', ')[1])) # reverse search
string += bytearray(encrypted_str[j] ^ key[j] for j in range(len(key))).decode(errors='ignore') # bug
if not addr:
addr = hex(inst[0])
if '\x00' in string:
strings.append((addr, string.replace('\x00', '')))
string = ''
addr = None
except Exception as e:
print(f'Fail at {hex(inst[0])}')
print(len(strings))
for s in strings:
print(f'{s[0]} {s[1]}')
decrypt_strings('aa2c0a9e34f9fa4cbf1780d757cc84f32a8bd005142012e91a6888167f80f4d5')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment