Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- from unicorn import *
- from unicorn.arm_const import *
- DIR = os.path.dirname(os.path.realpath(__file__))
- # Create main unicorn emulator
- # mu = Uc (UC_ARCH_ARM, UC_MODE_LITTLE_ENDIAN)
- mu = Uc (UC_ARCH_ARM, UC_MODE_THUMB) # Warning, code in thumb mode (16 bits)
- # Set base address and size of the .text and stack segment
- BASE = 0x10000
- STACK_ADDR = 0x300000
- STACK_SIZE = 1024*1024
- # Map .text and stack segments
- mu.mem_map(BASE, 1024*1024)
- mu.mem_map(STACK_ADDR, STACK_SIZE)
- # Write the complete code from the unpacked executable to .text segement
- mu.mem_write(BASE, open(DIR+"/cryptoarm_unpack",'rb').read())
- # Initialize stack pointer in the middle of the stack segment
- mu.reg_write(UC_ARM_REG_SP, STACK_ADDR + STACK_SIZE//2)
- # Some address given by ghidra analysis
- PROG_GHIDRA_BASE = 0x8000
- FN_ENTRY = 0x8798
- FN_END = 0x87f2
- # Get start and end addresses emulated by unicorn
- code_offset_start = BASE + (FN_ENTRY - PROG_GHIDRA_BASE)
- code_offset_end = BASE + (FN_END - PROG_GHIDRA_BASE)
- # Skip two instructions which set stack cookies
- instructions_skip_list = [BASE+(0x87a6-PROG_GHIDRA_BASE), BASE+(0x87ac-PROG_GHIDRA_BASE)]
- # strlen not callable by unicorn, we hook it
- strlen_cipher_addr = BASE+(0x87d2-PROG_GHIDRA_BASE) # 0x107d2
- # malloc not callable by unicorn, we hook it
- malloc_101h_addr = BASE+(0x87d8-PROG_GHIDRA_BASE) # 0x107d8
- # address where unciphering function is called
- uncipher_call_addr = BASE+(0x87ee-PROG_GHIDRA_BASE) # 0x107ee
- def hook_code(mu, address, size, user_data):
- # print('>>> Tracing instruction at 0x%x, instruction size = 0x%x' %(address, size)) # usefull debug function to see where unicorn crash
- if address in instructions_skip_list:
- print("SKIP 0x%x" %(address))
- mu.reg_write(UC_ARM_REG_PC , address+size | 1) # Modify $PC register, warning, add "| 1" to keep te thumb mode
- if address == strlen_cipher_addr:
- ret_len = 26
- print("call strlen(cipher_text) at 0x%x - skip and set R0 to %d" % (address, ret_len))
- mu.reg_write(UC_ARM_REG_R0, ret_len)
- mu.reg_write(UC_ARM_REG_PC, address + size | 1) # Modify $PC register, warning, add "| 1" to keep te thumb mode
- if address == malloc_101h_addr:
- ret_addr = STACK_ADDR + STACK_SIZE - 0x1000 # Set static address for the malloc[0x101] put in stack !
- print("call malloc(0x101) at 0x%x - skip and set R0 to 0x%x" % (address, ret_addr))
- mu.reg_write(UC_ARM_REG_R0, ret_addr)
- mu.reg_write(UC_ARM_REG_PC, address + size | 1) # Modify $PC register, warning, add "| 1" to keep te thumb mode
- if address == uncipher_call_addr:
- buffer_addr = mu.reg_read(UC_ARM_REG_R1) # Get cipher buffer address
- print("Cipher buffer located at 0x%x"%(buffer_addr))
- # print("Cipher buffer content: [%s]" % (enhex(mu.mem_read(buffer_addr, 26))))
- print("Cipher buffer content: [%s]" % (mu.mem_read(buffer_addr, 26)).hex())
- key_addr = mu.reg_read(UC_ARM_REG_R6)
- print("Key buffer located at 0x%x"%(key_addr))
- print("Key buffer content: [%s]" % (mu.mem_read(key_addr, 257)).hex())
- # if code_offset_end< address:print(hex(address),hex(code_offset_end));input()
- if address == code_offset_end:
- flag_addr = mu.reg_read(UC_ARM_REG_R0)
- print("Unciphering process ended at 0x%x" % (address))
- print(mu.mem_read(flag_addr, 26))
- print("Unciphered buffer content: [%s]" % ((mu.mem_read(flag_addr, 26)).decode()))
- # Add our hook function to unicorn emulator
- mu.hook_add(UC_HOOK_CODE, hook_code)
- # Start emulation
- # Note we start at ADDRESS | 1 to indicate THUMB mode.
- mu.emu_start(code_offset_start | 1, code_offset_end+2)
- ## Valid fl@g is ~^NHv<uz2O;T
Add Comment
Please, Sign In to add comment