当写shellcode的时候往往会遇到这么一个问题,如何使用汇编准确的定位到想要调用DLL中API的内存地址。

因操作系统版本以及安全补丁可能会修改DLL加载的基址,所以使用硬编码的API入口地址可能会使shellcode失效。在不同的Windows系统环境中如何动态寻址就是shellcode的Writer需要关心的问题了。

在Windows中动态寻址可以通过FS段来实现。

什么是FS段?

FS段是用来存放当前线程的线程环境块(TEB[Thread Environment Block])的一个段,FS寄存器本身的值指向的是全局段描述表(GDT)里面相应的一条索引。

FS段如何工作?

线程环境块保存了当前线程的各种信息,该结构的具体内容不同的系统也有区别,这个结构体的具体内容可以使用Windbg的dt ntdll!_TEB命令来查看重要的是该结构里面保存了我们想要的DLL的信息。
TEB的起始部分也就是fs:[0]的部分是叫做线程信息块(TIB[Thread Information Block])的结构,这个结构TIB中slef的值保存了TEB的起始值,当然了在GDT中也是可以获取这个值的。当fs寄存器知道了fs段开始的位置之后,它根据相应的偏移量(0x030)找到进程环境块(PEB[Process Environment Block])在Windbg中可以用!peb命令来查看进程环境块的内容。

07A3B5D0-D45F-44B1-8111-68302D637465.png

以上具体的内容可以去看以下书本中的相关知识:
《软件调试》(50-54页 && 713-714页)
《逆向工程核心原理》(第46章)
《0Day安全:软件漏洞分析技术》(87-97页)

可以在图中清楚的看到我们需要的DLL的基址了。当我们找到DLL的基址之后,众所周知DLL在Windows中也具有PE头,也有相应的EAT,这时候只要找到相应的函数在EAT里面的指针就大功告成了。

当然实际上可能还会碰到很多其他问题,例如让人头疼的空字节截断shellcode的问题,下一篇写一个具体利用