Chinaunix首页 | 论坛 | 博客
  • 博客访问: 167900
  • 博文数量: 36
  • 博客积分: 1466
  • 博客等级: 上尉
  • 技术积分: 380
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-17 17:43
文章分类

全部博文(36)

分类: WINDOWS

2008-07-05 01:08:58

同一API在各个平台的内存地址都不同,所以要用用一种通用的办法得到API正确的地址。

原理大概如下:

找到kernel32.dll的基址,之后根据PE文件的格式找到DLL的输出表,之后找到相应的函数的地址。
如果想调用的函数存在于别的DLL,则先找到LoadLibraryA函数的地址,之后调用它得到目标DLL的基址,之后根据PE文件的格式找到输出表,最后找到要调用函数的地址,调用之。


原理是摆出来了,但是有好几个问题。

·怎么得到kernel32.dll基址。
1)首先通过段选择字FS 在内存中找到当前的线程控制块TEB
2)TEB偏移位置为030H的地方存放着 该线程所属进程的  进程控制块PEB 的指针。
3)PEB中偏移为 0CH 的地方存放着指向 PEB_LDR_DATA 结构体的指针,它存放着已经被进程装载的动态链接库的信息。
4)PEB_LDR_DATA结构体偏移位置为01CH的地方存放着指向 模块初始化链表 的头指针InInitializationOrderModuleList
5)模块初始化链表 InInitializationOrderModuleList 中按顺序存放着PE装入运行时初始化模块的信息,第一个链表结点是ntdl.dll,第二个链表结点就是kernel32.dll。
6)找到属于kernel32.dll的结点后,在其基础上再偏移080H就是kernel32.dll在内存中的加载基地址。

汇编代码如下

;find base addr of kernel32.dll
mov ebx, fs:[edx + 0x30]      ;ebx = addres of PEB
mov ecx, [ebx + 0x0C]         ;ecx = pointer to loader data
mov ecx, [ecx + 0x1C]         ;ecx = fist node in list (ntdll.dll)

mov ecx, [ecx]                ;ecx = second node in list (kernel32.dll)

mov ebp, [ecx + 0x08]         ;ebp = base address of kernel32.dll


我细心地看了一下代码,开始时想不明白为什么 mov ecx, [ecx + 0x1C]就已经得到链表的第一个节点,之后的mov ecx, [ecx]竟然还得到链表的第二个节点!
后来我想到有一种可能,就是 链表的节点的第一个成员变量是指向下一个节点的。
之后我在网上查看了一些资料证明了我的想法只对了一半。原因是这些结点的结构都用LIST_ENTRY连在一起。而LIST_ENTRY刚好是这些结点结构的第一个成员,同时LIST_ENTRY的第一个成员FLINK的作用是指向下一个LIST_ENTRY结构!

笔记做到这里不认真看的话真的会晕~~~  复习时认真多读几遍前面的一段话,加上写在P99的笔记应该就OK


得到kernel32.dll的基址一切就好办了, 都是PE格式的问题了。在看这章前已经恶补了一下PE格式,现在是记得,但不知一年半载后会怎么样?  有空还是再作一遍关于PE格式的笔记吧。

PE格式无非就是 BASE ADDRESS,RVA,VA,IMPORT TABLE,EXPORT TABLE罢了。




阅读(1884) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~