Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from elftools.elf.constants import P_FLAGS
- from elftools.elf.elffile import ELFFile
- from unicorn import Uc, UC_ARCH_ARM, UC_MODE_LITTLE_ENDIAN, UC_HOOK_CODE, UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC
- from unicorn.arm_const import *
- from capstone import Cs, CS_ARCH_ARM, CS_MODE_THUMB, CsInsn
- from keystone import Ks, KS_MODE_THUMB, KS_ARCH_ARM
- # 找到.text节
- filename = "./libcms.so"
- fd = open(filename, 'rb')
- elf = ELFFile(fd)
- sh_offset = elf.get_section_by_name(".text").header['sh_offset']
- sh_size = elf.get_section_by_name(".text").header['sh_size']
- fd.seek(sh_offset)
- text_data = fd.read(sh_size)
- # 找到 [PUSH{...}; MOV RX,PC; MOV RX,PC -> 只找thumb
- cs = Cs(CS_ARCH_ARM, CS_MODE_THUMB)
- # (address, push_regs)
- entries = []
- step = 1000
- for i in range(0, len(text_data), step):
- _i = max(0, i - 10)
- g = cs.disasm(text_data[_i:_i + step], 0)
- while True:
- try:
- ins = next(g)
- assert isinstance(ins, CsInsn)
- # push {rx, rx}
- if ins.mnemonic != 'push':
- continue
- ins2 = next(g)
- assert isinstance(ins2, CsInsn)
- # mov rx, pc
- if not ins2.mnemonic.startswith('mov') or not ins2.op_str.endswith('pc'):
- continue
- ins3 = next(g)
- assert isinstance(ins3, CsInsn)
- # mov rx, pc
- if not ins3.mnemonic.startswith('mov') or not ins3.op_str.endswith('pc'):
- continue
- entries.append((_i + sh_offset + ins.address, ins.op_str))
- except StopIteration:
- break
- print(entries)
- # 加载 so 到内存中
- def align(addr, size, align):
- fr_addr = addr // align * align
- to_addr = (addr + size + align - 1) // align * align
- return fr_addr, to_addr - fr_addr
- def pflags2prot(p_flags):
- ret = 0
- if p_flags & P_FLAGS.PF_R != 0:
- ret |= UC_PROT_READ
- if p_flags & P_FLAGS.PF_W != 0:
- ret |= UC_PROT_WRITE
- if p_flags & P_FLAGS.PF_X != 0:
- ret |= UC_PROT_EXEC
- return ret
- load_base = 0
- emu = Uc(UC_ARCH_ARM, UC_MODE_LITTLE_ENDIAN)
- load_segments = [x for x in elf.iter_segments() if x.header.p_type == 'PT_LOAD']
- for segment in load_segments:
- fr_addr, size = align(load_base + segment.header.p_vaddr, segment.header.p_memsz, segment.header.p_align)
- emu.mem_map(fr_addr, size, pflags2prot(segment.header.p_flags))
- emu.mem_write(load_base + segment.header.p_vaddr, segment.data())
- # 依次进入所有的entry,执行到栈平衡时退出
- STACK_ADDR = 0x7F000000
- STACK_SIZE = 1024 * 1024
- start_addr = None
- def hook_code(mu: Uc, address, size, user_data):
- if mu.reg_read(UC_ARM_REG_PC) != start_addr and mu.reg_read(UC_ARM_REG_SP) == STACK_ADDR + STACK_SIZE:
- emu.emu_stop()
- emu.mem_map(STACK_ADDR, STACK_SIZE)
- emu.hook_add(UC_HOOK_CODE, hook_code)
- _to_reg_id = {
- "r0": UC_ARM_REG_R0, "r1": UC_ARM_REG_R1, "r2": UC_ARM_REG_R2, "r3": UC_ARM_REG_R3,
- "r4": UC_ARM_REG_R4, "r5": UC_ARM_REG_R5, "r6": UC_ARM_REG_R6, "r7": UC_ARM_REG_R7,
- "r8": UC_ARM_REG_R8, "r9": UC_ARM_REG_R9, "r10": UC_ARM_REG_R10, "r11": UC_ARM_REG_R11,
- "r12": UC_ARM_REG_R12, "r13": UC_ARM_REG_R13, "r14": UC_ARM_REG_R14, "r15": UC_ARM_REG_R15,
- "lr": UC_ARM_REG_LR, "pc": UC_ARM_REG_PC, "sp": UC_ARM_REG_SP,
- "sb": UC_ARM_REG_SB, "sl": UC_ARM_REG_SL, "fp": UC_ARM_REG_FP, "ip": UC_ARM_REG_IP,
- }
- ret = []
- MAGIC32 = 0x12345678
- for push_entry, push_regs in entries:
- emu.reg_write(UC_ARM_REG_SP, STACK_ADDR + STACK_SIZE)
- print("Emulate arm code start", hex(push_entry))
- start_addr = push_entry
- for r in push_regs.strip('{}').replace(' ', '').split(','):
- emu.reg_write(_to_reg_id[r], MAGIC32)
- emu.emu_start(push_entry + 1, 0, 0, 100)
- print("Emulation arm code done")
- changed = False
- for r in push_regs.strip('{}').replace(' ', '').split(','):
- if emu.reg_read(_to_reg_id[r]) != MAGIC32:
- changed = True
- break
- stop_addr = emu.reg_read(UC_ARM_REG_PC)
- if not changed:
- print("Match:", start_addr, stop_addr)
- ret.append((start_addr, stop_addr))
- else:
- print("Cannot handle:", start_addr)
- fd.close()
- print(ret)
- # [(55302, 55386), (55390, 55474), (55538, 55624), (55916, 56002), (56006, 56090), (56114, 56200), (60314, 60398), (60780, 60866), (61258, 61342), (61346, 61432), (96392, 96476), (107254, 107338), (107412, 107498), (130468, 130552), (131490, 131574), (131578, 131664), (132818, 132902), (135238, 135324), (135456, 135542), (136624, 136710), (144270, 144354), (144434, 144520), (144856, 144940), (145070, 145156), (147232, 147316), (151298, 151382), (151512, 151598), (151662, 151748), (152022, 152106), (152110, 152196), (157910, 157996), (158170, 158256), (159260, 159346), (159348, 159434), (161294, 161380), (161476, 161562), (161574, 161660), (161806, 161890), (161930, 162016), (165348, 165434), (165504, 165588), (165600, 165686), (165756, 165840), (165852, 165938), (166008, 166092), (166104, 166190), (166260, 166344), (166356, 166442), (166512, 166596), (166608, 166694), (166764, 166848), (166860, 166946), (167016, 167100), (167112, 167198), (167268, 167352), (167364, 167450), (169646, 169732), (169744, 169830), (170418, 170504), (170518, 170604), (172880, 172964), (173540, 173626), (173638, 173724), (173732, 173816), (173820, 173906), (185340, 185424), (185568, 185652), (185830, 185914), (186568, 186654), (211188, 211272), (211418, 211504), (211550, 211634), (211680, 211766), (211790, 211874), (211880, 211968), (211974, 212058), (212068, 212154), (212162, 212246), (214604, 214690), (217610, 217694), (222522, 222608), (224688, 224772), (225110, 225194), (225280, 225366), (226396, 226482), (226680, 226766), (226874, 226960), (227020, 227104), (227172, 227258), (484228, 484314), (486500, 486586), (487556, 487642), (487696, 487782), (487828, 487914), (487916, 488000), (490978, 491064), (492458, 492544), (494114, 494200), (494444, 494528), (494568, 494654), (505414, 505498), (506140, 506226), (507860, 507944), (509882, 509968), (510050, 510136), (510540, 510624), (512724, 512810), (512858, 512942), (513104, 513188), (513282, 513366), (513406, 513490), (516024, 516108), (516152, 516238), (516476, 516562)]
- # in idapython
- # for start, stop in ret:
- # ks = Ks(KS_ARCH_ARM, KS_MODE_THUMB)
- # a = ks.asm("B.W $+" + str(stop - start))
- # PatchByte(start, a[0][0])
- # PatchByte(start + 1, a[0][1])
- # PatchByte(start + 2, a[0][2])
- # PatchByte(start + 3, a[0][3])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement