From 16a9a1054c35e9a8718cf2118b6942de0aab3952 Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Tue, 8 Aug 2023 10:46:36 -0400 Subject: [PATCH] mac key derivation --- obfu_block.py | 60 ++++++++++++++++++++++++++++++++++++--------------- peacestone.py | 18 +++++++++++----- 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/obfu_block.py b/obfu_block.py index 3cd08b4..21130ab 100644 --- a/obfu_block.py +++ b/obfu_block.py @@ -36,6 +36,7 @@ image_start = ql.loader.images[0].base image_end = ql.loader.images[0].end image_size = image_end - image_start pe = pefile.PE(data=ql.mem.read(image_start, image_size)) +scratch_base = ql.mem.map_anywhere(0x1000) def mem_read_int(addr): return ql.unpack(ql.mem.read(addr, 4)) @@ -52,7 +53,7 @@ def array_write_int(array, offset, val): return arr_copy -stub_frame = 0x010BE265 +stub_frame = 0x120f989 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"] @@ -108,16 +109,43 @@ val1 = (obd[index][1] + obd[index][0]) % (1 << 32) val2 = (obd[index][2] - obd[index][0]) % (1 << 32) val3 = (obd[index][4] + obd[index][3]) % (1 << 32) unk3 = obd[index][3] + +print(f"VAL1 {hex(val1)} VAL2 {hex(val2)} VAL3 {hex(val3)} UNK3 {hex(unk3)}") + data_size = unk3 & 0xfff xor_plus_binstart = image_start + xor_value -val1_bytes = val1.to_bytes(4, "little") -val2_bytes = val2.to_bytes(4, "little") enc_bytes = ql.mem.read(xor_plus_binstart, data_size + 1) dec_bytes = [0] * data_size chksum = 0xa5 if val2 & 0x1000000 == 0: - raise Exception("USES MAC-DERIVED KEY") + print("DERIVING KEY FROM MAC") + mac_func = mem_read_int(sym_data_inv["?g_apMacFuncs@WARBIRD@@3PAP6AXAA_JPBE1ABU_CBCKey2@1@@ZA"] + (val2 >> 25) * 4) + + for instr in md.disasm(ql.mem.read(mac_func, 0x100), mac_func): + if instr.mnemonic == "ret": + mac_end = instr.address + break + + ql.mem.write(scratch_base, b"\x00\x01\x02\x03\x04\x05") + ql.mem.write(scratch_base + 0x10, ql.pack(xor_value)) + ql.mem.write(scratch_base + 0x14, ql.pack(0)) + ql.arch.stack_push(scratch_base) + ql.arch.stack_push(val1 + image_start + (val2 & 0xffff)) + ql.arch.stack_push(val1 + image_start) + ql.arch.stack_push(0x10) + ql.arch.stack_push(0x69696969) + + old_sp = ql.arch.regs.esp + ql.run(begin=mac_func, end=mac_end) + ql.arch.regs.esp = old_sp + + key1 = ql.mem.read(0x10, 4) + key2 = ql.mem.read(0x14, 2) +else: + print("USING BLOCK VALUES AS KEY") + key1 = val1.to_bytes(4, "little") + key2 = (val2 & 0xFFFF).to_bytes(2, "little") for i in range(data_size - 1, -1, -1): enc_byte = enc_bytes[i] @@ -128,30 +156,30 @@ for i in range(data_size - 1, -1, -1): b = 0 if i % 2 == 1: - if (enc_byte ^ val1_bytes[3]) % 2 == 1: - a = (enc_byte ^ val1_bytes[3] ^ val1_bytes[2] ^ 0x100) >> 1 + if (enc_byte ^ key1[3]) % 2 == 1: + a = (enc_byte ^ key1[3] ^ key1[2] ^ 0x100) >> 1 else: - a = (enc_byte ^ val1_bytes[3]) >> 1 + a = (enc_byte ^ key1[3]) >> 1 if (a ^ b) % 2 == 1: - dec_byte = (a ^ b ^ val2_bytes[1] ^ 0x100) >> 1 + dec_byte = (a ^ b ^ key2[1] ^ 0x100) >> 1 else: dec_byte = (a ^ b) >> 1 else: - if (enc_byte ^ val1_bytes[1]) % 2 == 1: - a = (enc_byte ^ val1_bytes[1] ^ val1_bytes[0] ^ 0x100) >> 1 + if (enc_byte ^ key1[1]) % 2 == 1: + a = (enc_byte ^ key1[1] ^ key1[0] ^ 0x100) >> 1 else: - a = (enc_byte ^ val1_bytes[1]) >> 1 + a = (enc_byte ^ key1[1]) >> 1 if (a ^ b) % 2 == 1: - dec_byte = (a ^ b ^ val2_bytes[0] ^ 0x100) >> 1 + dec_byte = (a ^ b ^ key2[0] ^ 0x100) >> 1 else: dec_byte = (a ^ b) >> 1 chksum ^= dec_byte dec_bytes[i] = dec_byte -if chksum != val2_bytes[2]: +if chksum != (val2 >> 16) & 0xFF: raise Exception("CHECKSUM FAILED!") print(dec_bytes) @@ -187,11 +215,9 @@ while index < num_relocs: 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)) + if ((private_relocs[index] >> 30) & 3) == 2 and offset != 0: + print(f"RELOC @ OFFSET {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) diff --git a/peacestone.py b/peacestone.py index e5c5a0e..b904cef 100644 --- a/peacestone.py +++ b/peacestone.py @@ -41,7 +41,7 @@ ks = Ks(KS_ARCH_X86, KS_MODE_32) md = Cs(CS_ARCH_X86, CS_MODE_32) md.detail = 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_end = ql.loader.images[0].end image_size = image_end - image_start @@ -79,15 +79,17 @@ if __name__ == "__main__": f = open("log.txt", "w") for match in re.finditer(STUB_RET4_REGEX, pe_data): + print(hex(match.start())) + match_addr = image_start + match.start() - stub_code = ql.mem.read(match_addr - 0x1000, 0x1000) + stub_code = ql.mem.read(match_addr - 0x50, 0x50) try: stub_start_offset = list(re.finditer(PUSH_REGEX, stub_code))[0].start() except: continue - stub_start_addr = match_addr - 0x1000 + stub_start_offset + stub_start_addr = match_addr - 0x50 + stub_start_offset instrs = list(md.disasm(ql.mem.read(stub_start_addr, 0x47), stub_start_addr)) ret = 0 @@ -170,7 +172,13 @@ if __name__ == "__main__": else: handler_name = hex(handler_addr) - f.write(f"J R4 S {hex(jmp_insert_addr)} H {handler_name} N {hex(next_addr)}\n") + if next_addr in sym_data: + next_name = f"{hex(next_addr)} {sym_data[next_addr]}" + else: + next_name = hex(next_addr) + + f.write(f"J R4 S {hex(jmp_insert_addr)} H {handler_name} N {next_name}\n") # input() - print() \ No newline at end of file + print() + # input() \ No newline at end of file