因此,我正在尝试学习如何调试没有符号文件的文件。最常见的建议是发出bp $exentrybu @$exentry。但是,这些都不起作用。一旦执行g可执行文件,它就会在ntdll32!LdrpDoDebuggerBreak+0x2c上中断。调用堆栈中没有任何内容可提供任何有用的信息。如果再次发出g,可执行文件将终止运行。

有关如何在不手动执行所有启动代码的情况下到达main()的任何建议?

#1 楼

确保您具有正确的断点地址

发出lm,没有符号的exe将显示为

0:000> lm
start    end        module name
00400000 0040f000   image00400000   (no symbols)    


比较NtHeader->AddresssOfEntrypoint@$exentry

0:000> r $t0 = image00400000
0:000> ?? ((ntdll!_IMAGE_NT_HEADERS *) @@( poi( @$t0 + 0x3c ) + @$t0 ))->OptionalHeader.AddressOfEntryPoint + @$t0
unsigned int64 0x401280
0:000> ? @$exentry
Evaluate expression: 4199040 = 00401280


如果它们相同,则设置bp @$exentrybp 401280的断点仅在二进制文件中没有调试器检测的情况下都应在该地址正确地中断。

如果您的二进制文件具有调试器检测功能,那么您可能需要检查DllInitRoutines Tls回调和其他可爱的技巧

输出示例exe文件,而在下面的$$ exentry处没有任何反调试技巧会正确破解

0:000> .lastevent
Last event: bc.a70: Break instruction exception - code 80000003 (first chance)
  debugger time: Sun Sep 21 01:10:42.015 2014 (UTC + 5:30)
0:000> lm M *im*
start    end        module name
00400000 0040f000   image00400000   (no symbols)
0:000> $ binary without symbols whose module name is normally shown as imageXXXXXX

0:000> r $t0 = image00400000 ; $ set Pseudo Register to start

0:000> r $t1 = poi(@$t0+3c)  ; $ find pointer to Ntheader

0:000> r? $t2 = (ntdll!_IMAGE_NT_HEADERS *) (@$t0 + @$t1)  ; set c++ pseudo Register

0:000> ?? @$t2->OptionalHeader.AddressOfEntryPoint + @$t0  ; Find AddressofEntryPoint
unsigned int64 0x401280

0:000> ? @$exentry
Evaluate expression: 4199040 = 00401280

0:000> bp @$exentry

0:000> bl
 0 e 00401280     0001 (0001)  0:**** image00400000+0x1280

0:000> g
Breakpoint 0 hit    
image00400000+0x1280:
00401280 55              push    ebp
0:000>


这是not main()的开始,通常称为c runtime init code。如果您知道编译器通常可以发现初始化,则可能需要检查二进制文件以找到Main()。代码,这将是常见的代码