unicorn_learning2

  1. 目标
  2. 创建虚拟机
  3. 建立内存映射+写入数据
  4. 添加hook函数
  5. 开始执行
  6. 最后代码:

unicorn start

用unicorn调用so文件中的某个函数,观察函数的输入与输出

目标

hook so文件中的sign1函数的输出与输入

image-20221230100636171

这个函数内部调用了两个函数,tea_encrypt和sprintf,这两个函数中tea_encrypt函数只需要修复got表项即可调用tea_encrypt,但是sprintf函数不行

这里我们开始实验

创建虚拟机

由于这里的指令都是两个字节为一条指令

image-20221230145634256

所以这里为thumb指令集

def test_arm():
    print("Emulate ARM code")
    try:
        # Initialize emulator in ARM mode
        mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB)	# 创建代码
        # 其它代码添加到此处
        return mu
    except UcError as e:
        print("ERROR: %s" % e)

mu = test_arm() # mu就是arm虚拟机

建立内存映射+写入数据

由于这是要模拟执行一段函数,所以要建立镜像区,栈区,数据段区的内存

这里各个区的大小存粹靠估算

image = open('./libnative-lib.so','rb').read()
# 镜像内存
image_base = 0x0
mu.mem_map(image_base, 0x10000*8)  # 这里大小自己估算
mu.mem_write(image_base,image)

# 栈内存
stack_base = 0xa0000
stack_size = 0x10000 * 3
mu.mem_map(stack_base, stack_size)  # 这里大小自己估算
stack_top = stack_base + stack_size - 0x4
mu.reg_write(UC_ARM_REG_SP,stack_top)

# 数据段内存
a1 = b'123'
data_base = 0xf0000
data_size = 0x10000 * 3
mu.mem_map(data_base, data_size)  # 这里大小自己估算
mu.mem_write(data_base,a1)

这里栈区的sp指针应小于栈大小的0x4,防止栈溢出,这里我们将‘123’字符串写入数据段,来作为函数的参数使用

添加hook函数

主要用于程序报错时可以及时追踪到哪里有问题

def hook_code(uc, address, size, user_data):
    print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))

def hook_memory(uc, access, address, size,value, userdata):
    pc = uc.reg_read(UC_ARM_REG_PC)
    print ("memory error: pc:%x address:%x size:%x" % (pc, address, size))
    
mu.hook_add(UC_HOOK_CODE,hook_code,0)
mu.hook_add(UC_HOOK_MEM_UNMAPPED,hook_memory,0)

开始执行

#开始执行虚拟机
start_addr = 0x9B68
end_addr = 0x9C2C
try:
    mu.emu_start(start_addr, end_addr)
    R2 = mu.reg_read(UC_ARM_REG_R2)
    res = mu.mem_read(R2,16)
    print(binascii.b2a_hex(res))
except UcError as e:
    print(e)

结果只运行到第一条指令:

image-20221230141126071

image-20221230141137038

这里将开始地址+1,然后执行:

image-20221230141419595

image-20221230141523486

然后这里就遇到了函数地址外的地址,很奇怪!!!,这里找到0x91ac,也就是最后一次正常的地方,发现来到了plt表,点击后又来到got表,这里的got表其实是ida已经自动补全了,unicorn需要自己手动补全

image-20221230141839711

image-20221230142108868

补全后:

image-20221230152353412

执行代码:

#开始执行虚拟机
start_addr = 0x9B68
end_addr = 0x9C2C
try:
    # 添加got表
    mu.mem_write(0x1EDB0,b'\xD9\x98\x00\x00')
    mu.emu_start(start_addr+1, end_addr)
    R2 = mu.reg_read(UC_ARM_REG_R2)
    res = mu.mem_read(R2,16)
    print(binascii.b2a_hex(res))
except UcError as e:
    print(e)

最后代码:

from unicorn import *
from unicorn.arm_const  import *
import binascii
def hook_code(uc, address, size, user_data):
    print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))

def hook_memory(uc, access, address, size,value, userdata):
    pc = uc.reg_read(UC_ARM_REG_PC)
    print ("memory error: pc:%x address:%x size:%x" % (pc, address, size))
    
def test_arm():
    print("Emulate ARM code")
    try:
        # Initialize emulator in ARM mode
        mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB)	# 创建代码
        # 其它代码添加到此处
        return mu
    except UcError as e:
        print("ERROR: %s" % e)

mu = test_arm() # mu就是arm虚拟机
image = open('./libnative-lib.so','rb').read()
# 镜像内存
image_base = 0x0
mu.mem_map(image_base, 0x10000*8)  # 这里大小自己估算
mu.mem_write(image_base,image)

# 栈内存
stack_base = 0xa0000
stack_size = 0x10000 * 3
mu.mem_map(stack_base, stack_size)  # 这里大小自己估算
stack_top = stack_base + stack_size - 0x4
mu.reg_write(UC_ARM_REG_SP,stack_top)



# 数据段内存
a1 = b'123'
data_base = 0xf0000
data_size = 0x10000 * 3
mu.mem_map(data_base, data_size)  # 这里大小自己估算
mu.mem_write(data_base,a1)

#函数参数通过数据段传递 寄存器是R0
mu.reg_write(UC_ARM_REG_R0,data_base)

# 添加hook函数
# mu.hook_add(UC_HOOK_CODE,hook_code,0)
# mu.hook_add(UC_HOOK_MEM_UNMAPPED,hook_memory,0)

#开始执行虚拟机
start_addr = 0x9B68
end_addr = 0x9C2C
try:
    # 添加got表
    mu.mem_write(0x1EDB0,b'\xD9\x98\x00\x00')
    mu.emu_start(start_addr+1, end_addr)
    R2 = mu.reg_read(UC_ARM_REG_R2)
    res = mu.mem_read(R2,16)
    print(binascii.b2a_hex(res))
except UcError as e:
    print(e)

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 jaytp@qq.com

×

喜欢就点赞,疼爱就打赏