6.1.2 方法一、野蛮的暴力搜索

“在国内,首先想出方法的是guange。”老师说道。

“哦!又是他啊!”大家想起在编码时讲过他的方法。

“他在很早以前,就对Windows的系统技术炉火纯青。不仅编码,动态定位,而且在ShellCode高级功能、高级提取方面都有很深的造诣,但……鲜有详细的文档记录。现在他也把很多东西都忘了吧!我们只能通过他的程序临摹一招半式了。”

“哦!”

“所以,我给你们上的课,都是在做扫地的工作,也就是‘扫地僧’!”

“哇!做‘扫地僧’好啊,是金庸大侠手下武功最高的人物了!”小倩一副很羡慕的样子。

“汗~是啊!为了让像大家一样的初学者引起兴趣,尽快入门!我会担当起‘扫地僧’责任的。”老师说道。

“多谢老师!我们也会努力学习的,不会辜负老师的期望。”教室里大家都纷纷表态。

“别谢我什么,要谢就谢《Q版黑客》系列图书吧!谢谢他们全力的支持,才使这门课得以顺利开展。

”好了,我们来看看yuange提出的方法。”老师又回到了正题。

“yuange提出的思路就是:SHELLCODE只依靠GetProcAddress和LoadLibraryA这两个函数;而LoadLibraryA是在系统库KERNEL32.DLL里面的,也可以使用GetProcAddress得到,所以我们只需知道GetProcAddress的地址就可以了。

“哦!是啊!但GetProcAddress的地址又怎么获得呢?这是关键啊!”大家着急的说。

“呵呵,yuange说了(怎么像黑社会的……),kernel32.dll一般都会被加载,所以解决办法就是在内存里查找kernel32.dll这个系统库和GetprocAddress函数的地址。”

“查找?”

“俗称就是暴力搜索!”

“啊!暴力搜索!好恐怖啊!”大家紧张的的说。

“其实,只要了解了Windows的系统结构就不难。袁哥的程序,是从0x77e0000 或0xbff00000 开始搜索,搜索到MZ和PE标志时,就表示是kernel32.dll的开始地方。”

小知识:PE结构

PE的意思就是 Portable Executable(可移植的执行体)。它是 Win32环境自身所带的执行体文件格式。所有 Win32执行体都使用PE文件格式,包括NT的内核模式驱动程序。

PE文件结构以一个IMAGE_DOS_HEADER结构开始,所以开头是一个简单的 DOS MZ header,紧随 MZ header之后的是DOS stub。紧接着DOS stub的是PE header,所以可以根据MZ和PE标志来判断一个程序是否是可执行程序,其详细结构如下:

typedef struct _IMAGE_DOS_HEADER {?? 
    WORD e_magic; ;DOS可执行文件标记“MZ”
    WORD e_cblp;
    WORD e_cp;
    WORD e_crlc;
    WORD e_cparhdr;
    WORD e_minalloc;
    WORD e_maxalloc;
    WORD e_ss;
    WORD e_sp;
    WORD e_csum;
    WORD e_ip; 
    WORD e_cs;
    WORD e_lfarlc;
    WORD e_ovno;
    WORD e_res[4];
    WORD e_oemid;
    WORD e_oeminfo;
    WORD e_res2[10]; 
    LONG e_lfanew; ;指向PE文件头"PE",0,0
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

“找到kernel32后,再搜索函数的引出表,找到LoadLibrary的函数名和LoadLibrary函数对应的地址就完成了搜索。”

“我把yange的程序加上了一些注释,大家下来可参考SearchByYuange.cpp(光盘有收录),这里就不作详细解释了。”老师说道。

“啊?为什么不解释呢?还不大懂呢!”

“呵呵,第一是因为代码复杂难懂,我这个‘扫地僧’要解释清楚也很困难;第二是从0x77e00000或0xbff00000开始搜索,已经不完全通用了;第三是技术不断进步,后来有了更为优雅、更为完美的方法。而且后面讲的方法和yuange的方法大部分是一样的,我们学习之后,也就都清楚了。”