# Trace 分析

打开菜单项 [Debugger] -> [Tracing] -> [Tracing Options] 配置 Trace 选项
在准备开始 Trace 的指令位置设置断点,并使该断点命中
开启 Trace:[Debugger] -> [Tracing] -> [Instruction Tracing]
开启后,单步执行一条指令,发现已经执行的指令变色表示开启 Trace 成功
按下 F9 继续运行,直到下一个断点手动停止 Trace 或直到程序结束

指令级 Trace 记录每一条指令的执行情况

基本块 trace

函数级别 trace

实操去混淆

先在开头 start 下了一个断点

image-20230922145513874

image-20230922145547232

运行起来后即可 trace

image-20230922145742213

trace 会把执行过的指令染色 退出调试 能在 tracing window 分析 trace 的结果

image-20230922145842252

通过 trace 找到堆栈平衡点 就能确定花指令区间然后去除

result 是当前指令执行后,被修改的寄存器列表及对应的值

# Fork 双进程调试

将子进程的第一条指令 patch 为死循环 (这样子进程就在死循环的等待状态)

image-20230922160814049 重新打开另外一个 IDA,附加子进程,恢复第一条指令,调试
(也可以 patch 成死循环后 detach 再重新 attach 子进程 然后 set IP 跳出死循环即可)

当然,如果 fork 的进程与原进程不存在交互,也可以直接 set IP 执行子进程的代码来调试

这个技巧适用于所有无法直接启动调试,而只能附加的场景

# IDA Python

寄存器操作

idc.get_reg_value('rax’) #读取
idaapi.set_reg_val("rax", 1234) #设置

读取 xmm 寄存器 (很少遇到)

def read_xmm_reg(name):
​       rv = idaapi.regval_t()
​       idaapi.get_reg_val(name, rv)
return (struct.unpack('Q', rv.bytes())[0])

调试内存操作

idc.read_dbg_byte(addr)
idc.read_dbg_memory(addr, size)
idc.read_dbg_dword(addr)
idc.read_dbg_qword(addr)
idc.patch_dbg_byte(addr, val)

调试内存读写封装

def patch_dbg_mem(addr, data):
for i in range(len(data)):
​             idc.patch_dbg_byte(addr + i, data[i])
def read_dbg_mem(addr, size):
​       dd = [ ]
for i in range(size):
​             dd.append(idc.read_dbg_byte(addr + i))
return bytes(dd)

本地内存操作(会修改 idb 数据库)

idc.get_qword(addr)
idc.patch_qword(addr, val)
idc.patch_dword(addr, val)
idc.patch_word(addr, val)
idc.patch_byte(addr, val)
idc.get_db_byte(addr)
idc.get_bytes(addr, size)

反汇编操作

GetDisasm(addr)  # 获取反汇编文本
idc.next_head(ea) # 获取下一条指令地址

杂项常用接口

idc.add_bpt(0x409437) 添加断点
idaapi.get_imagebase() 获取基地址
idc.create_insn(addr) # c, Make Code
ida_funcs.add_func(addr) # p , create function
ida_bytes.create_strlit(addr) # 创建字符串,A 键效果

条件断点脚本编写

  1. 编写断点函数脚本,并在 IDA 底部导入该函数

  2. 设置普通断点,在 call rand 之后设置(此时能获取 rand 的返回值)

  3. [右键] -> [Edit Break …]

  4. 点击 [Condition]-> […]

  5. 输入 bp () ,并选择语言为 Python

条件断点运用:提取 rand 函数每一次执行结果,不让程序停下来
条件断点函数返回 False,IDA 不会命中该断点
利用这个特性可提取运行时数据

注:若设置条件断点 在 idapython 脚本中未设置断下来的条件 (通俗的说法), 只是 print 的话运行时是不会断的

创建结构体

打开创建结构体的 Subview,点击工具栏 View->Open Subview->Structures ( Shift + F9)。

按键盘 I 弹出结构体的创建窗口,输入 Structure name。

在结构体的 ends 行,按键盘 d 键,创建新的结构体成员。

在结构体成员初按 d 键,修改数据类型(db dw dd dq),右键点击 Array 可以创建数组。

最后,分析代码。确定结构体中的成员在反汇编代码中的名称。之后,修改反编译代码中该 成员的类型,按 y 修改为 struct name(这里修改为 student)。

Local Types 修改方便!

参考:https://thinkycx.me/2019-07-15-how-to-create-structs-in-IDA.html