首页
社区
课程
招聘
[未解决,已结帖] Unicorn在跑exe文件初始化时报错 100雪币
发表于: 2024-8-15 03:48 1132

[未解决,已结帖] Unicorn在跑exe文件初始化时报错 100雪币

2024-8-15 03:48
1132

问题描述

相关exe附件已上传,我先描述下问题所在,我在试图用unicorn模拟执行一个exe以获取所有间接跳转的具体值并patch,而这些值存储在data段,这些硬编码在程序运行时会进行重定位工作,于是我为了方便打算将映射的内存基地址直接设置为0x400000,原先设置的值为0,而在我修改后,代码开始报错。经过我闲的没事干的测试,似乎值大于大约0x157000时就开始报错。
图片描述

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
from unicorn import *
from unicorn.arm_const import *
from unicorn.x86_const import *
from capstone import *
from keystone import *
import pefile
 
X86_REGISTERS = {
    "rax": UC_X86_REG_RAX,
    "rbx": UC_X86_REG_RBX,
    "rcx": UC_X86_REG_RCX,
    "rdx": UC_X86_REG_RDX,
    # 添加其他 x86 寄存器
}
def hook_memory(uc, access, address, size, value, user_data):
    pc = uc.reg_read(UC_X86_REG_RIP)
    md = Cs(CS_ARCH_X86, CS_MODE_64)
    md.syntax = CS_OPT_SYNTAX_INTEL
    instruction_data = uc.mem_read(pc, 16)
    instructions = md.disasm(instruction_data, pc)
    print("内存出错*********************************")
    for i in instructions:
        machine_code = " ".join(f"{byte:02x}" for byte in i.bytes)
        print(f"0x{i.address:x}:\t{machine_code:<20}\t{i.mnemonic}\t{i.op_str}")
    print(f"Memory error at pc: 0x{pc:x}, address: 0x{address:x}, size: {size}")
    print("****************************************")
 
def hook_code(uc, address, size, user_data):
    global sodata
    global Patch
    Patch={}
    # Capstone 反汇编器实例
    md = Cs(CS_ARCH_X86, CS_MODE_64)
    md.syntax = CS_OPT_SYNTAX_INTEL
 
    # Keystone 初始化
    ks = Ks(KS_ARCH_X86, KS_MODE_64)
 
    if address + size > len(sodata):
        return
    print(f"RIP: {hex(mu.reg_read(UC_X86_REG_RIP))}")
    print(hex(address-ADDRESS-0x1000+0x400))
    ins = md.disasm(sodata[address-ADDRESS-0x1000+0x400:address-ADDRESS-0x1000+0x400+size], address)#减去偏移量0x1000再加上0x400就是在sodata中的相应位置
    registers = ["rax", "rbx", "rcx", "rdx"]
    for i in ins:
        machine_code = " ".join(f"{byte:02x}" for byte in i.bytes)  
        print(f"Assembly: {i.mnemonic} {i.op_str}")   
        if i.mnemonic == "call":
            # 打印 CALL 指令的汇编代码及机器码
            print(f"CALL instruction found at {hex(i.address)}")
            print(f"Assembly: {i.mnemonic} {i.op_str}")
            print(f"Machine Code: {machine_code}")
            uc.reg_write(UC_X86_REG_RIP, address + i.size)
            print(f"指令从 {hex(address)} 跳转至 {hex(address + i.size)}")
            return  # 跳过call指令
        if i.mnemonic == "jmp":
            for p in registers:
                if i.op_str.startswith(p):
                    reg_value = uc.reg_read(X86_REGISTERS[p])
                    print("寄存器值:"+str(hex(reg_value)))
                    offset = reg_value - address
                    Patch[address]=offset
                    jmp_inst, _ = ks.asm(f"jmp {offset}")
                    uc.mem_write(address, bytes(jmp_inst))
                    uc.reg_write(UC_X86_REG_RIP, address +offset)
                    print(f"Replaced jmp {p} with jmp {hex(offset)} at {hex(address)}")
                    break
 
def init(filename):
    global mu
    global sodata
    global pe
    global ADDRESS
    pe = pefile.PE(filename)
    entry_point = 0xBE70
    with open(filename, mode="rb") as f:
        sodata = f.read()
         
    if isinstance(sodata, bytearray):
        sodata = bytes(sodata)
    print("=========================Begin============================")
    try:
        mu = Uc(UC_ARCH_X86, UC_MODE_64)
        ADDRESS = 0x157000#这里设置为0x400000是因为data段数据需要重定位,设为0x400000省去这一步      
        STACK_ADDRESS = 0x80000000
        mu.mem_map(STACK_ADDRESS, 8 * 0x1000 * 0x1000# 栈
        mu.mem_map(ADDRESS, 32 * 1024 * 1024# 16MB
        #将文件写入内存
        for section in pe.sections:
            start=ADDRESS+section.VirtualAddress
            print(hex(start))
            file_offset = section.PointerToRawData
            section_data = sodata[file_offset:file_offset + section.SizeOfRawData]
            if section.Name.strip(b'\0').decode() == '.text':
                text_offet=section.VirtualAddress
                print(f".text section address: {hex(start)}")
            mu.mem_write(start, section_data)  # 写入文件
             
        Text_Start=ADDRESS + entry_point+text_offet
        # 设置 rsp 和 rip 寄存器
        mu.reg_write(UC_X86_REG_RSP, STACK_ADDRESS + 0x1000 * 4)
        mu.reg_write(UC_X86_REG_RIP,Text_Start)
 
        mu.hook_add(UC_HOOK_MEM_UNMAPPED, hook_memory, begin=ADDRESS, end=ADDRESS + 16 * 1024 * 1024)
        mu.hook_add(UC_HOOK_CODE, hook_code, begin=Text_Start, end=Text_Start+ 0x10000)
 
        #print(f"Starting emulation from {hex(ADDRESS + entry_point + 0x400)} to {hex(ADDRESS + 0xD2000 + 0x400)}")
        md = Cs(CS_ARCH_X86, CS_MODE_64)
        md.syntax = CS_OPT_SYNTAX_INTEL
        ins = md.disasm(sodata[entry_point+0x400:entry_point+0x400+0x400],Text_Start)#ADDRESS不设为0的话这里要重新写一下
 
#将反汇编内容打出================================================
        for i in ins:
            machine_code = " ".join(f"{byte:02x}" for byte in i.bytes)
            #print(f"0x{i.address:x}:\t{machine_code:<20}\t{i.mnemonic}\t{i.op_str}")
#===============================================================
        print("设定模拟执行的入口地址:",hex(Text_Start))
        mu.emu_start(Text_Start, Text_Start+0x10000)
 
    except UcError as e:
        print(f"ERROR: {e}")
        print(f"RIP: {hex(mu.reg_read(UC_X86_REG_RIP))}")
        print(f"RSP: {hex(mu.reg_read(UC_X86_REG_RSP))}")
# 调用 init 函数
init("C:\\Users\\rea1\\Desktop\\ofution.exe")
print("test success")

附一张ADDRESS=0时运行的结果
图片描述


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2024-8-15 04:25 被螺丝兔编辑 ,原因:
上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//