# Trace 分析
打开菜单项 [Debugger] -> [Tracing] -> [Tracing Options] 配置 Trace 选项
在准备开始 Trace 的指令位置设置断点,并使该断点命中
开启 Trace:[Debugger] -> [Tracing] -> [Instruction Tracing]
开启后,单步执行一条指令,发现已经执行的指令变色表示开启 Trace 成功
按下 F9 继续运行,直到下一个断点手动停止 Trace 或直到程序结束
指令级 Trace 记录每一条指令的执行情况
基本块 trace
函数级别 trace
实操去混淆
先在开头 start 下了一个断点
运行起来后即可 trace
trace 会把执行过的指令染色 退出调试 能在 tracing window 分析 trace 的结果
通过 trace 找到堆栈平衡点 就能确定花指令区间然后去除
result 是当前指令执行后,被修改的寄存器列表及对应的值
# Fork 双进程调试
将子进程的第一条指令 patch 为死循环 (这样子进程就在死循环的等待状态)
重新打开另外一个 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 键效果 |
条件断点脚本编写
-
编写断点函数脚本,并在 IDA 底部导入该函数
-
设置普通断点,在 call rand 之后设置(此时能获取 rand 的返回值)
-
[右键] -> [Edit Break …]
-
点击 [Condition]-> […]
-
输入 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