mirror of https://github.com/UMSKT/peacestone.git
finish code decryption and reloc impl
This commit is contained in:
parent
cf89342b36
commit
6604a71d07
|
@ -20,5 +20,5 @@ edx <- STUB_FRAME (??)
|
||||||
|
|
||||||
val_3 -> {???}{7 bits select offset for something}{12 bits size decrypted data}
|
val_3 -> {???}{7 bits select offset for something}{12 bits size decrypted data}
|
||||||
offset_1 -> key1
|
offset_1 -> key1
|
||||||
offset_2 -> {byte1:last_bit = skip_verify_offset_1}{verify_byte}{key2 as word}
|
offset_2 -> {byte1:last_bit = no_derive_key_from_mac}{verify_byte}{key2 as word}
|
||||||
offset_3 -> some addr?
|
offset_3 -> some addr?
|
108
obfu_block.py
108
obfu_block.py
|
@ -5,21 +5,10 @@ from keystone import *
|
||||||
import pefile
|
import pefile
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
# Set to binary name
|
# Set to binary name
|
||||||
BIN_NAME = "sppsvc.exe"
|
BIN_NAME = "sppsvc.exe"
|
||||||
|
|
||||||
# Set to function to be analyzed
|
|
||||||
# ANLZ_FUNC = "?VerifyPKeyByInstalledPidConfig@CSLSLicenseManager@@IBEJPAVCSLPKey@@PBGPAUtagPKEY_BASIC_INFO@@PAPAGPAUDECODED_PKEY_DATA@@@Z"
|
|
||||||
ANLZ_FUNC = "_wmain"
|
|
||||||
|
|
||||||
# These magic regexes are derived from the byte markers in notes.txt
|
|
||||||
PUSH_REGEX = rb"(?:\x8dd\$\xfc\x89[\x04\x0c\x14\x1c,4<]\$|[PQRSUVW]){2}\x8d[x\x05\r\x15\x1d-5=].{4}"
|
|
||||||
STUB_RET4_REGEX = rb"\x8b[DLT\\lt\|]\$\x04\xc2\x04\x00"
|
|
||||||
STUB_RET0_REGEX = rb"\x87[\x04\x0c\x14\x1c,4<]\$\xc3"
|
|
||||||
STUB_MAX_SIZE = 0x40 # Maximum size of jump stub
|
|
||||||
|
|
||||||
REG_NAMES = {
|
REG_NAMES = {
|
||||||
19: "EAX",
|
19: "EAX",
|
||||||
20: "EBP",
|
20: "EBP",
|
||||||
|
@ -42,13 +31,30 @@ ks = Ks(KS_ARCH_X86, KS_MODE_32)
|
||||||
md = Cs(CS_ARCH_X86, CS_MODE_32)
|
md = Cs(CS_ARCH_X86, CS_MODE_32)
|
||||||
md.detail = True
|
md.detail = True
|
||||||
md.skipdata = True
|
md.skipdata = True
|
||||||
ql = Qiling(["./rootfs/sppsvc.exe"], "./rootfs")
|
ql = Qiling(["./rootfs/sppsvc.exe"], "./rootfs", verbose=QL_VERBOSE.OFF)
|
||||||
image_start = ql.loader.images[0].base
|
image_start = ql.loader.images[0].base
|
||||||
image_end = ql.loader.images[0].end
|
image_end = ql.loader.images[0].end
|
||||||
image_size = image_end - image_start
|
image_size = image_end - image_start
|
||||||
pe = pefile.PE(data=ql.mem.read(image_start, image_size))
|
pe = pefile.PE(data=ql.mem.read(image_start, image_size))
|
||||||
|
|
||||||
num_obd = ql.unpack(ql.mem.read(sym_data_inv["?g_nNumObfuscatedBlockData@WARBIRD@@3KA"], 4))
|
def mem_read_int(addr):
|
||||||
|
return ql.unpack(ql.mem.read(addr, 4))
|
||||||
|
|
||||||
|
def array_read_int(array, offset):
|
||||||
|
return int.from_bytes(array[offset:offset+4], "little")
|
||||||
|
|
||||||
|
def array_write_int(array, offset, val):
|
||||||
|
arr_copy = list(array)
|
||||||
|
val_bytes = val.to_bytes(4, "little")
|
||||||
|
|
||||||
|
for i in range(4):
|
||||||
|
arr_copy[offset + i] = val_bytes[i]
|
||||||
|
|
||||||
|
return arr_copy
|
||||||
|
|
||||||
|
stub_frame = 0x010BE265
|
||||||
|
|
||||||
|
num_obd = mem_read_int(sym_data_inv["?g_nNumObfuscatedBlockData@WARBIRD@@3KA"])
|
||||||
obd_addr = sym_data_inv["?g_ObfuscatedBlockData@WARBIRD@@3PAU_OBFUSCATED_BLOCK_DATA@1@A"]
|
obd_addr = sym_data_inv["?g_ObfuscatedBlockData@WARBIRD@@3PAU_OBFUSCATED_BLOCK_DATA@1@A"]
|
||||||
obd = []
|
obd = []
|
||||||
|
|
||||||
|
@ -56,11 +62,17 @@ for i in range(num_obd):
|
||||||
obf_block = []
|
obf_block = []
|
||||||
|
|
||||||
for j in range(5):
|
for j in range(5):
|
||||||
obf_block.append(ql.unpack(ql.mem.read(obd_addr + 4*(5*i + j), 4)))
|
obf_block.append(mem_read_int(obd_addr + 4*(5*i + j)))
|
||||||
|
|
||||||
obd.append(obf_block)
|
obd.append(obf_block)
|
||||||
|
|
||||||
stub_frame = 0x120f989
|
num_relocs = mem_read_int(sym_data_inv["?g_PrivateRelocationsTable@WARBIRD@@3VCPrivateRelocationsTable@1@B"])
|
||||||
|
reloc_addr = sym_data_inv["?g_PrivateRelocationsTable@WARBIRD@@3VCPrivateRelocationsTable@1@B"] + 4
|
||||||
|
private_relocs = []
|
||||||
|
|
||||||
|
for i in range(num_relocs):
|
||||||
|
private_relocs.append(mem_read_int(reloc_addr + 4*i))
|
||||||
|
|
||||||
stub_frame_offset = stub_frame - image_start
|
stub_frame_offset = stub_frame - image_start
|
||||||
|
|
||||||
first = 0
|
first = 0
|
||||||
|
@ -87,6 +99,9 @@ while True:
|
||||||
last_prev = last
|
last_prev = last
|
||||||
sum_diff = (obd[index][0] + obd[index][3]) % (1 << 32)
|
sum_diff = (obd[index][0] + obd[index][3]) % (1 << 32)
|
||||||
|
|
||||||
|
if first > last:
|
||||||
|
raise Exception("Offset not found in block table!")
|
||||||
|
|
||||||
print(f"XOR {hex(xor_value)} SUMDIFF {hex(sum_diff)} INDEX {hex(index)}")
|
print(f"XOR {hex(xor_value)} SUMDIFF {hex(sum_diff)} INDEX {hex(index)}")
|
||||||
|
|
||||||
val1 = (obd[index][1] + obd[index][0]) % (1 << 32)
|
val1 = (obd[index][1] + obd[index][0]) % (1 << 32)
|
||||||
|
@ -101,9 +116,16 @@ enc_bytes = ql.mem.read(xor_plus_binstart, data_size + 1)
|
||||||
dec_bytes = [0] * data_size
|
dec_bytes = [0] * data_size
|
||||||
chksum = 0xa5
|
chksum = 0xa5
|
||||||
|
|
||||||
for i in range(data_size - 1, 0, -1):
|
if val2 & 0x1000000 == 0:
|
||||||
|
raise Exception("USES MAC-DERIVED KEY")
|
||||||
|
|
||||||
|
for i in range(data_size - 1, -1, -1):
|
||||||
enc_byte = enc_bytes[i]
|
enc_byte = enc_bytes[i]
|
||||||
|
|
||||||
|
if i > 0:
|
||||||
b = enc_bytes[i - 1]
|
b = enc_bytes[i - 1]
|
||||||
|
else:
|
||||||
|
b = 0
|
||||||
|
|
||||||
if i % 2 == 1:
|
if i % 2 == 1:
|
||||||
if (enc_byte ^ val1_bytes[3]) % 2 == 1:
|
if (enc_byte ^ val1_bytes[3]) % 2 == 1:
|
||||||
|
@ -127,5 +149,57 @@ for i in range(data_size - 1, 0, -1):
|
||||||
dec_byte = (a ^ b) >> 1
|
dec_byte = (a ^ b) >> 1
|
||||||
|
|
||||||
chksum ^= dec_byte
|
chksum ^= dec_byte
|
||||||
print(hex(dec_byte))
|
|
||||||
dec_bytes[i] = dec_byte
|
dec_bytes[i] = dec_byte
|
||||||
|
|
||||||
|
if chksum != val2_bytes[2]:
|
||||||
|
raise Exception("CHECKSUM FAILED!")
|
||||||
|
|
||||||
|
print(dec_bytes)
|
||||||
|
|
||||||
|
first = 0
|
||||||
|
last = num_relocs - 1
|
||||||
|
|
||||||
|
while last >= first:
|
||||||
|
index = (first + last) // 2
|
||||||
|
addr = private_relocs[index] & 0xFFFFFFF
|
||||||
|
|
||||||
|
if xor_value >= addr:
|
||||||
|
if xor_value == addr:
|
||||||
|
first = (first + last) // 2
|
||||||
|
break
|
||||||
|
|
||||||
|
first = index + 1
|
||||||
|
else:
|
||||||
|
last = index - 1
|
||||||
|
|
||||||
|
index = first
|
||||||
|
|
||||||
|
while index < num_relocs:
|
||||||
|
addr = private_relocs[index] & 0xFFFFFFF
|
||||||
|
|
||||||
|
if addr >= (xor_value + data_size):
|
||||||
|
break
|
||||||
|
|
||||||
|
offset = 0
|
||||||
|
ofmode = (private_relocs[index] >> 28) & 3
|
||||||
|
|
||||||
|
if ofmode == 1:
|
||||||
|
offset = -xor_plus_binstart % (1 << 32)
|
||||||
|
elif ofmode == 2:
|
||||||
|
offset = xor_plus_binstart
|
||||||
|
elif ofmode == 3:
|
||||||
|
offset = 0
|
||||||
|
|
||||||
|
if ((private_relocs[index] >> 30) & 3) == 2:
|
||||||
|
print(hex(addr - xor_value), hex(offset))
|
||||||
|
val = array_read_int(dec_bytes, addr - xor_value)
|
||||||
|
val = (val + offset) % (1 << 32)
|
||||||
|
dec_bytes = array_write_int(dec_bytes, addr - xor_value, val)
|
||||||
|
print(dec_bytes)
|
||||||
|
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
dec_bytes = bytes(dec_bytes)
|
||||||
|
|
||||||
|
for instr in md.disasm(dec_bytes, 0):
|
||||||
|
print(instr)
|
|
@ -92,7 +92,7 @@ if __name__ == "__main__":
|
||||||
ret = 0
|
ret = 0
|
||||||
|
|
||||||
for i, instr in enumerate(instrs):
|
for i, instr in enumerate(instrs):
|
||||||
print(instr)
|
# print(instr)
|
||||||
|
|
||||||
if instr.mnemonic == "ret" and instr.op_str == "4":
|
if instr.mnemonic == "ret" and instr.op_str == "4":
|
||||||
ret = i
|
ret = i
|
||||||
|
@ -138,7 +138,7 @@ if __name__ == "__main__":
|
||||||
jmp_insert_addr = 0
|
jmp_insert_addr = 0
|
||||||
|
|
||||||
for inst in instrs[max(0,stub_start_index-4):stub_start_index][::-1]:
|
for inst in instrs[max(0,stub_start_index-4):stub_start_index][::-1]:
|
||||||
print(inst)
|
# print(inst)
|
||||||
if inst.bytes in push_instrs:
|
if inst.bytes in push_instrs:
|
||||||
# ql.mem.write(inst.address, NOP * len(inst.bytes))
|
# ql.mem.write(inst.address, NOP * len(inst.bytes))
|
||||||
jmp_insert_addr = inst.address
|
jmp_insert_addr = inst.address
|
||||||
|
@ -165,7 +165,12 @@ if __name__ == "__main__":
|
||||||
print("JUMP TARGET @ " + hex(next_addr))
|
print("JUMP TARGET @ " + hex(next_addr))
|
||||||
print(ql.arch.regs.esp)
|
print(ql.arch.regs.esp)
|
||||||
|
|
||||||
f.write(f"J R4 S {hex(jmp_insert_addr)} H {hex(handler_addr)} N {hex(next_addr)}\n")
|
if handler_addr in sym_data:
|
||||||
|
handler_name = sym_data[handler_addr]
|
||||||
|
else:
|
||||||
|
handler_name = hex(handler_addr)
|
||||||
|
|
||||||
|
f.write(f"J R4 S {hex(jmp_insert_addr)} H {handler_name} N {hex(next_addr)}\n")
|
||||||
|
|
||||||
# input()
|
# input()
|
||||||
print()
|
print()
|
Loading…
Reference in New Issue