当有人问我这个问题的时候,我真的是一脸懵逼,我只知道编译的时候尽量少的引用dll可以减少导入表的量。
后来尝试一个正常的程序,将PE结构的导入表大小和位置全部设置为0:
该程序只负责调用MessageBox(实际是MessaheBoxW,或者MessageBoxA,但是大家都懂,不作区分):
然后运行,炸掉了,很正常:
看来不会是一个特别简单的问题。
经过研究,是要通过PEB来自己找了。首先看这个程序依赖的DLL:
由于MessageBox是User32.dll导出的,所以,会依赖User32.dll,为了尽量减少DLL依赖,因此重新写一段代码:
这段代码,设置了入口点,并将编译器优化关掉。
编译后重新看依赖DLL:
好了至此导入表没了,那我们怎么调用其它的函数呢?
使用OD加载后,查看可执行模块:
发现默认就有几个dll。这时候就有一个关键的函数LdrLoadDll,该函数声明如下:
NTSTATUS NTAPI LdrLoadDll(
IN PWCHAR PathToFile OPTIONAL,
IN ULONG Flags OPTIONAL,
IN PUNICODE_STRING ModuleFileName,
OUT PHANDLE ModuleHandle);
这个函数和LoadLibrary是一样的效果。这个函数在ntdll.dll中导出:
我们能看到,代码就算不依赖任何DLL,程序加载后,还是会有几个DLL会一同加载,而ntdll.dll也在其中;因此思路就有了,只需要程序运行后,找到ntdll.dll然后就能找到LdrLoadDll了。-
##接下来是找ntdll.dll
运行在应用层的程序,通过fs寄存器可以拿到很多