我有一个没有调试符号的可执行文件,并且我想使用它的main()函数。要进入$exentry,我需要一步一步,直到看到正在运行的应用程序中有一些更改为止。

还有其他跳过CRT代码的程序吗?

#1 楼

不,没有快捷方式加载器只知道$ exentry,因为它是PeHeader中的嵌入式指针,从那里到main大部分都是通过单步执行或通过实践和经验来观察和识别已知功能的方法
crt代码相当普遍,任何Visual Studio安装的crt文件夹中都包含crt的源代码(如果您的二进制文件带有调试信息

,如果二进制文件被剥离或构建时没有debuginfo,这将很有帮助在释放模式下crt src不会帮助您查明main()

,在那种情况下,您应该能够识别crt将要进行的某些标准调用,例如,通常调用kernel32!GetCommandLineXXXX settig该函数的一个bp使您更接近main()另一个可以设置断点的函数是
kernel32!GetEnvironemStringXXXX
,然后在遇到这些断点时在结果上设置硬件中断您可以
使用标准p main
int main(int argc,char ** argv,char * envp)的原型,以
标识您的main

:\>cdb -c "bp $exentry;g;bp kernel32!GetCommandlineA;g;g poi(@esp)" hell.exe

0:000> cdb: Reading initial command 'bp $exentry;g;bp kernel32!GetCommandlineA;g;g poi(@esp)'
Breakpoint 0 hit
Breakpoint 1 hit
eax=002b36d8 ebx=7ffdf000 ecx=002b47e8 edx=002b4813 esi=00000000 edi=00000000
eip=01314082 esp=0024f9b0 ebp=0024f9e4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
image01310000+0x4082:
01314082 a3c4933201      mov     dword ptr [image01310000+0x193c4 (013293c4)],ea
x ds:0023:013293c4=00000000


相同exec_main和getcommandline函数之间的距离和距离,就像ollydbg调试相同的可执行文件的图像一样

/>

要更近一点,您可以使用int argc
执行二进制文件,这样就知道您传递了多少个参数
如果没有将参数传递给二进制,则如果您传递了8个参数,则int argc将等于1
请记住,一旦您到达上述枚举的断点,则int argc将等于9

,您可以运行一个枚举的循环堆栈中的int argc

bp $exentry
bp kernel32!GetCommandLineA
g
g
g poi(@esp)
.while(@$t0= 0) {
pc 
.if ( poi(@esp) == 1) {r $t0 = 1} .else { r $t0 = 0}
}  


运行脚本的结果请注意上面屏幕快照中的地址,您只需调用一次即可调用main()的包装器

cdb -c "$$>a< findwmain.txt" hell.exe

0:000> cdb: Reading initial command '$$>a< findwmain.txt'
Breakpoint 0 hit
Breakpoint 1 hit

eax=00000000 ebx=7ffd3000 ecx=00461228 edx=00461228 esi=00000000 edi=00000000
eip=000a40b5 esp=0034fb5c ebp=0034fb94 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
image000a0000+0x40b5:
000a40b5 e8e4420000      call    image000a0000+0x839e (000a839e)