注意:nop(00bf)指令可能在unicorn中不会进入hook_code回调,此时可以使用mov r0,r0(0046)指令替换。在这里卡了很久,断点一直进入不了。也没在网上找到文档。
文件及代码来自看雪3万班unicorn-unidbg目录中第三节课程。hanbinle大神写的代码在我本地已经跑不成功了。可能是unicorn 版本的问题。
以下是自写跑成功的源码,重点之一在于对指针如何传参及如何补环境,其二是看看so层汇编代码查看多于4个参数时的堆栈分配:
import binascii
import struct
from unicorn import *
from capstone import *
mu=Uc(UC_ARCH_ARM,UC_MODE_THUMB)
CP=Cs(CS_ARCH_ARM,CS_MODE_THUMB)
# start_addr=0x59928
# end_addr=0x59CD0
start_addr=0x854C
end_addr=0x85D8
stack_base=0x1000
stack_size=10*1024*1024
def printArm32Regs(mu):
for i in range(66,78):
print("R%d,value:%x"%(i-66,mu.reg_read(i)))
print("SP->value:%x" % (mu.reg_read(arm_const.UC_ARM_REG_SP)))
print("PC->value:%x" % (mu.reg_read(arm_const.UC_ARM_REG_PC)))
def readstring(mu,address):
result=''
tmp=mu.mem_read(address,1)
while(tmp[0]!=0):
result=result+chr(tmp[0])
address=address+1
tmp = mu.mem_read(address, 1)
return result
def hook_code(mu,address,size,userdata):
co = mu.mem_read(address, size)
print("value: %x"%(address-stack_base))
if address-stack_base == 0x859A:
#if(address-stack_base==0x859A):
print("enter....")
arg0str=readstring(mu,mu.reg_read(arm_const.UC_ARM_REG_R0))
arg1str = readstring(mu, mu.reg_read(arm_const.UC_ARM_REG_R1))
print(arg0str + "---" + arg1str)
find=arg0str.find(arg1str)
# mu.mem_write(address-stack_base,b'\x00\xbf\x00\xbf')
if(find==-1):
mu.reg_write(arm_const.UC_ARM_REG_R0,0)
else:
mu.reg_write(arm_const.UC_ARM_REG_R0, find)
print("hook_code start-----------------------------")
for i in CP.disasm(co, 0, len(co)):
print("[hook_code addr:%x opcode:%s]:%s %s\n" % (address-stack_base, binascii.b2a_hex(co),i.mnemonic, i.op_str))
printArm32Regs(mu)
print("hook_code end-----------------------------")
return
def hook_mem(mu,type,address,size,value,user_data):
if type==UC_MEM_WRITE:
print("write addr:0x%x,size:%d,value:0x%x"%(address,size,value))
if type==UC_MEM_READ:
print("read addr:0x%x,size:%d,value:0x%x"%(address,size,value))
print("hook_mem type:%d addr:0x%x,size:%d,value:0x%x"%(type,address,size,value))
return
def unmapped(mu,address,size):
print("UC_ERR_READ_UNMAPPED-----------------------------")
print("%d"%address)
co = mu.mem_read(address, size)
for i in CP.disasm(code, 0, len(co)):
print("[UC_ERR_READ_UNMAPPED addr:%x]:%s %s\n" % (address, i.mnemonic, i.op_str))
# printArm32Regs(mu)
print("UC_ERR_READ_UNMAPPED-----------------------------")
return
def fetch_unmapped(mu,address,size,user_data):
print("UC_ERR_fetch_UNMAPPED-----------------------------")
print("%x %x" %(address,size))
errbyte=mu.mem_read(address,size)
for i in CP.disasm(errbyte,0,len(errbyte)):
print("opcode: %s %s %s" % (binascii.b2a_hex(errbyte),i.mnemonic,i.op_str))
return False
if __name__ == '__main__':
#testthumb_arg2()
with open("D:\\backend\\xmlysign\\capstone\\callstrstr.so", "rb") as sofile:
code = sofile.read()
for i in CP.disasm(code[start_addr:end_addr], 0, 20):
print("[addr] %x]:%s %s\n" % (i.address, i.mnemonic, i.op_str))
mu.mem_map(stack_base, stack_size)
mu.mem_write(stack_base, code)
stack_top = stack_base + stack_size - 0x400
mu.reg_write(arm_const.UC_ARM_REG_SP, stack_top)
mu.reg_write(arm_const.UC_ARM_REG_LR, stack_base + 0x1000)
addr_r0 = stack_base + stack_size + 0x1000
mu.mem_map(addr_r0, 1024)
mu.mem_write(addr_r0, b"flag4")
bytes = mu.mem_read(addr_r0, 5)
print(binascii.b2a_hex(bytes))
# mu.mem_map(ADDRESS + SIZE + 0x1000, 1024)
# mu.mem_write(ADDRESS + SIZE + 0x1000, b'flag4')
# bytes = mu.mem_read(ADDRESS + SIZE + 0x1000, 5)
# print(binascii.b2a_hex(bytes))
mu.reg_write(arm_const.UC_ARM_REG_R0, addr_r0)
mu.reg_write(arm_const.UC_ARM_REG_R1, 0x2)
mu.reg_write(arm_const.UC_ARM_REG_R2, 0x3)
mu.reg_write(arm_const.UC_ARM_REG_R3, 0x4)
# mu.mem_write(stack_base + 0x859A, b"\x00\xbf\x00\xbf")
mu.mem_write(stack_base + 0x859A, b'\x00\x46\x00\x46')
mu.mem_write(stack_top, struct.pack('I', 5))
mu.mem_write(stack_top + 0x4, struct.pack('I', 6))
mu.hook_add(UC_HOOK_CODE, hook_code)
# mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem)
# mu.hook_add(UC_ERR_READ_UNMAPPED, unmapped)
# mu.hook_add(UC_ERR_FETCH_UNMAPPED,fetch_unmapped)
mu.emu_start(stack_base + start_addr + 1, stack_base + end_addr)
# r3 = mu.reg_read(arm_const.UC_ARM_REG_R3)
printArm32Regs(mu)
5+6=11=0xb,结果正确。


使用版本
C:\Users\86153>pyenv global 3.8.6
C:\Users\86153>pip list
Package Version
--------------- -------
androidemu 0.0.2
capstone 5.0.1
hexdump 3.3
keystone-engine 0.9.2
pip 20.2.1
pyelftools 0.27
setuptools 49.2.1
unicorn 1.0.3
WARNING: You are using pip version 20.2.1; however, version 23.2.1 is available.
You should consider upgrading via the 'd:\app\pyenv\.pyenv\pyenv-win\versions\3.8.6\python.exe -m pip install --upgrade pip' command.