我想创建一个二进制文件的执行跟踪。确切地说,我想记录每条执行的汇编指令以及可能的内存访问。内存访问是指从内存中读取或写入内存。对于这些访问,我想记录指令从何处读取(分别写入)以及它读取什么值(分别写入什么值)。

如果可能的话,我希望使用一种在Windows和Linux以及不同类型的CPU上均可使用。

目前性能并不重要,即调试器脚本可以。

我尝试了几件事,但没有设法得到想要的东西:具有内容的访问(有诸如idc.GetTevRegMem之类的晦涩功能(请参见此处),但要达到我的目标,事情变得非常复杂。 > GDB:由于无法使用观察点,因此无法选择

目前,PANDA似乎是最有前途的选择(请参见PANDA作者的评论)。 PANDA因此无法确定创建合适的PANDA插件会变得多么复杂。例如,一些调试器脚本代码行,一个PIN工具(仅Intel)或一个qemu参数等。

评论

我肯定会使用DBI框架。 PIN可以轻松做到这一点(尽管您只能使用x86 / x64)。检查pinatrace示例源。使用PIN_SafeCopy(在示例中未使用)访问内存,您就完成了。

我也想到了DBI,但是PIN(和DynamoRIO)无法跟踪内核空间访问。

您可以查阅这份(PDF)论文报告,特别是第3章

@ExtremeCoders谢谢,他们也正在使用PANDA。如果所有人都想要:不同的CPU,内核+用户空间,不同的操作系统,这似乎真的是可行的方法。
由于valgrind是开源的,所以我想在--trace-mem = yes输出中添加内存内容不会太难。

#1 楼

我知道这个问题是在不久前提出的,但是在Windows上可以使用该解决方案。

注意:请参阅本答案的最后一部分以获取其他系统和体系结构的解决方案。
x86 32位文件

OllyDbg2是该工具可用于记录每条汇编指令以及存储器的读写操作。下面是记录日志的简短指南:


运行OllyDbg。
选择Options-> Options...(或使用Alt + o快捷方式)。将显示选项窗口。
搜索Run trace部分并选择下图所示的选项:



当然,如果您不希望使用Olly要在系统DLL中记录所有字符串指令或代码,您只需选择两个相关的框即可。此外,如果要将日志转储到文件中,可以选择较小的跟踪缓冲区大小。


现在,打开目标应用程序,但不启动它。
选择View-> Run trace
右键单击出现的窗口,然后选择要在跟踪中包含的内存和注册选项。

再次右键单击该窗口,然后选择Log to file...选项,然后选择要写入整个运行轨迹的文件。
Ctrl + F11开始跟踪。
何时要使其停止,请单击“暂停”按钮(或F12)以暂停执行。
您将在Run trace窗口中看到记录的说明。
右键单击Run trace窗口并选择Stop logging选项。这将关闭并保存跟踪文件。

就这样!您现在可以打开并分析文件了(尽管它可能仍然很大)。

下面是该文件的摘录(仅显示修改后的寄存器,不输入系统DLL):

main  <ModuleEntryPoint>          JMP SHORT 00401012
main  00401012                    MOV EAX,[DWORD DS:4F61EF]               [004F61EF]=0                EAX=00000000
main  00401017                    SHL EAX,2
main  0040101A                    MOV [DWORD DS:4F61F3],EAX               [004F61F3]=0
main  0040101F                    PUSH EDX                                [0019FF80]=0                ESP=0019FF80
main  00401020                    PUSH 0                                  [0019FF7C]=0                ESP=0019FF7C
main  00401022                    CALL <JMP.&KERNEL32.GetModuleHandleA>                               EAX=00400000, ECX=DC5CD787, ESP=0019FF80
main  00401027                    MOV EDX,EAX                                                         EDX=00400000
main  00401029                    CALL 004E7210                                                       ESP=0019FF7C
main  004E7210                    MOV EAX,EDX
main  004E7212                    CMP [BYTE DS:4F61E0],0                  [004F61E0]=00
main  004E7219                    JNE SHORT 004E7240
main  004E721B                    CMP [BYTE DS:4F61E1],0                  [004F61E1]=00
main  004E7222                    JE SHORT 004E7238
main  004E7238                    MOV ECX,[DWORD DS:57D7D4]               [0057D7D4]=ollydbg.0061B108 ECX=0061B108
main  004E723E                    MOV [DWORD DS:ECX],EAX                  [0061B108]=0
main  004E7240                    MOV EAX,[DWORD DS:57D7D8]               [0057D7D8]=ollydbg.0061B131 EAX=0061B131
main  004E7245                    MOV [BYTE DS:EAX],1                     [0061B131]=00

DOS可执行文件


DOSBox调试器将在分析DOS可执行文件时记录您想要的所有内容。


例如,从此处下载它。
通过将可执行文件拖放到DOSBox Debugger图标上来启动应用程序。
要开始记录执行跟踪时,按Alt + Pause-应用程序将冻结。
切换到调试器窗口。您将看到类似以下内容的信息:


键入logl n,其中n是要记录的(十六进制)指令数;例如:logl ffff
日志文件已创建,应该与DOSBox调试器位于同一目录中-名称为LOGCPU.txt

01A2:00004654  mov  ax,si                                              8B C6                 EAX:0000002A EBX:0000002A ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:1 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007293 CR0:00000000
01A2:00004656  mov  dx,000E                                            BA 0E 00              EAX:00000004 EBX:0000002A ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:1 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007293 CR0:00000000
01A2:00004659  imul dx                                                 F7 EA                 EAX:00000004 EBX:0000002A ECX:00000A00 EDX:0000000E ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:1 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007293 CR0:00000000
01A2:0000465B  mov  bx,ax                                              8B D8                 EAX:00000038 EBX:0000002A ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:0 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007296 CR0:00000000
01A2:0000465D  cmp  word [bx+56F6],0001        ds:[572E]=0000          83 BF F6 56 01        EAX:00000038 EBX:00000038 ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:0 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007296 CR0:00000000
01A2:00004662  jne  00004678 ($+14)            (down)                  75 14                 EAX:00000038 EBX:00000038 ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:1 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007296 CR0:00000000
01A2:00004678  inc  si                                                 46                    EAX:00000038 EBX:00000038 ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:1 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007296 CR0:00000000


每个或几乎每个体系结构和系统

radare2是可以用于您的目的的工具,而不论系统和体系结构(完整在此处给出它们的列表。)


运行r2 -c aei -d programToDebug
在要开始跟踪的地址处放置一个断点(例如,使用db address_in_hex)。
运行dc继续直到遇到断点。
键入e dbg.trace=1并按Enter。
运行des N到步骤N指令(例如des 10)。
使用dtd > log1打印追溯到log1文件的指令。
使用dte > log2打印所有内存并注册对log2文件的访问。
这些文件的示例内容如下:

说明:
q 4312010q
和一些相应的内存访问:


当然,最好以OllyDbg的方式列出这些输出,但是需要编写一个脚本,将这两个文件链接在一起,并以更方便的方式显示信息。例如,例如:


可从这些文件创建此类输出的Python脚本在此处提供。用法:

./prettyTraceLog.py file1 file2


,其中log1log2是默认值。如果您发现任何错误,或由于其他原因想要对其进行修改,请随时执行。

感谢@pancake告诉我如何在radare2中进行跟踪。