mac key derivation

This commit is contained in:
WitherOrNot 2023-08-08 10:46:36 -04:00
parent 6604a71d07
commit 16a9a1054c
2 changed files with 56 additions and 22 deletions

View File

@ -36,6 +36,7 @@ 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))
scratch_base = ql.mem.map_anywhere(0x1000)
def mem_read_int(addr): def mem_read_int(addr):
return ql.unpack(ql.mem.read(addr, 4)) return ql.unpack(ql.mem.read(addr, 4))
@ -52,7 +53,7 @@ def array_write_int(array, offset, val):
return arr_copy return arr_copy
stub_frame = 0x010BE265 stub_frame = 0x120f989
num_obd = mem_read_int(sym_data_inv["?g_nNumObfuscatedBlockData@WARBIRD@@3KA"]) 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"]
@ -108,16 +109,43 @@ val1 = (obd[index][1] + obd[index][0]) % (1 << 32)
val2 = (obd[index][2] - obd[index][0]) % (1 << 32) val2 = (obd[index][2] - obd[index][0]) % (1 << 32)
val3 = (obd[index][4] + obd[index][3]) % (1 << 32) val3 = (obd[index][4] + obd[index][3]) % (1 << 32)
unk3 = obd[index][3] unk3 = obd[index][3]
print(f"VAL1 {hex(val1)} VAL2 {hex(val2)} VAL3 {hex(val3)} UNK3 {hex(unk3)}")
data_size = unk3 & 0xfff data_size = unk3 & 0xfff
xor_plus_binstart = image_start + xor_value 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) 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
if val2 & 0x1000000 == 0: 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): for i in range(data_size - 1, -1, -1):
enc_byte = enc_bytes[i] enc_byte = enc_bytes[i]
@ -128,30 +156,30 @@ for i in range(data_size - 1, -1, -1):
b = 0 b = 0
if i % 2 == 1: if i % 2 == 1:
if (enc_byte ^ val1_bytes[3]) % 2 == 1: if (enc_byte ^ key1[3]) % 2 == 1:
a = (enc_byte ^ val1_bytes[3] ^ val1_bytes[2] ^ 0x100) >> 1 a = (enc_byte ^ key1[3] ^ key1[2] ^ 0x100) >> 1
else: else:
a = (enc_byte ^ val1_bytes[3]) >> 1 a = (enc_byte ^ key1[3]) >> 1
if (a ^ b) % 2 == 1: if (a ^ b) % 2 == 1:
dec_byte = (a ^ b ^ val2_bytes[1] ^ 0x100) >> 1 dec_byte = (a ^ b ^ key2[1] ^ 0x100) >> 1
else: else:
dec_byte = (a ^ b) >> 1 dec_byte = (a ^ b) >> 1
else: else:
if (enc_byte ^ val1_bytes[1]) % 2 == 1: if (enc_byte ^ key1[1]) % 2 == 1:
a = (enc_byte ^ val1_bytes[1] ^ val1_bytes[0] ^ 0x100) >> 1 a = (enc_byte ^ key1[1] ^ key1[0] ^ 0x100) >> 1
else: else:
a = (enc_byte ^ val1_bytes[1]) >> 1 a = (enc_byte ^ key1[1]) >> 1
if (a ^ b) % 2 == 1: if (a ^ b) % 2 == 1:
dec_byte = (a ^ b ^ val2_bytes[0] ^ 0x100) >> 1 dec_byte = (a ^ b ^ key2[0] ^ 0x100) >> 1
else: else:
dec_byte = (a ^ b) >> 1 dec_byte = (a ^ b) >> 1
chksum ^= dec_byte chksum ^= dec_byte
dec_bytes[i] = dec_byte dec_bytes[i] = dec_byte
if chksum != val2_bytes[2]: if chksum != (val2 >> 16) & 0xFF:
raise Exception("CHECKSUM FAILED!") raise Exception("CHECKSUM FAILED!")
print(dec_bytes) print(dec_bytes)
@ -187,11 +215,9 @@ while index < num_relocs:
offset = -xor_plus_binstart % (1 << 32) offset = -xor_plus_binstart % (1 << 32)
elif ofmode == 2: elif ofmode == 2:
offset = xor_plus_binstart offset = xor_plus_binstart
elif ofmode == 3:
offset = 0
if ((private_relocs[index] >> 30) & 3) == 2: if ((private_relocs[index] >> 30) & 3) == 2 and offset != 0:
print(hex(addr - xor_value), hex(offset)) print(f"RELOC @ OFFSET {hex(addr - xor_value)} +{hex(offset)}")
val = array_read_int(dec_bytes, addr - xor_value) val = array_read_int(dec_bytes, addr - xor_value)
val = (val + offset) % (1 << 32) val = (val + offset) % (1 << 32)
dec_bytes = array_write_int(dec_bytes, addr - xor_value, val) dec_bytes = array_write_int(dec_bytes, addr - xor_value, val)

View File

@ -41,7 +41,7 @@ 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
@ -79,15 +79,17 @@ if __name__ == "__main__":
f = open("log.txt", "w") f = open("log.txt", "w")
for match in re.finditer(STUB_RET4_REGEX, pe_data): for match in re.finditer(STUB_RET4_REGEX, pe_data):
print(hex(match.start()))
match_addr = image_start + 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: try:
stub_start_offset = list(re.finditer(PUSH_REGEX, stub_code))[0].start() stub_start_offset = list(re.finditer(PUSH_REGEX, stub_code))[0].start()
except: except:
continue 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)) instrs = list(md.disasm(ql.mem.read(stub_start_addr, 0x47), stub_start_addr))
ret = 0 ret = 0
@ -170,7 +172,13 @@ if __name__ == "__main__":
else: else:
handler_name = hex(handler_addr) 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() # input()
print() print()
# input()