windbg查找Kernel32.dll基址

windbg查找Kernel32.dll基址,第1张

windbg查找Kernel32.dll基址


一、首先准备好一个程序,运行起来,用windbg进行附加调试,由于每个windows下的程序都会加载kernel32.dll,因此,找基址的过程是一样的;

 

二、查看PEB地址;


一、r $peb


二、通过TEB获取,r $teb

获取到teb地址后,对_TEB结构体解析dt _TEB 3ca000


三、通过fs寄存器获取,我们知道fs:[0]就是TEB结构体的首地址,但是,在windbg里dd fs:[0]时,地址却做了隐藏:

那该怎么办呢,其实,这就要看下TEB的结构了

在TEB结构的0x18偏移处,存放的其实就是TEB的地址,和fs:[0]是一样的;

另外,在TEB结构的0x30偏移处,存放的就是PEB的地址,我们再来看下:

和上面两种方法,得到的结果都是一致的,这也验证了我们的想法;

 

三、接下来,既然PEB的地址找到了,就对PEB进行解析:

首先找到LDR:

接下来,解析LDR:

这里,也许有人会有疑问:那个_LIST_ENTRY后面,怎么有两个值,是什么含义呢?加个-b,就看出来了:

typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

其实,内核数据结构中,比较常见,使用的这个双向链表;

我们就选取InLoadOrderModuleList这个链;对它的Flink进行解析,

通过查阅MSDN,知道,这个Flink指向的具体的数据结构类型是:_LDR_DATA_TABLE_ENTRY

继续遍历InLoadOrderLinks的Flink字段:

还不是Kernel32.dll,继续走:

到此,通过遍历InLoadOrderLinks链,我们找到了KERNEL32.DLL,取出基址就比较容易了,在0x18偏移处;

取出这个基址,我们就可以解析PE导出表,找到我们需要的函数的地址了;


四、代码

int GetKernel32Base() {
int nAddress = ;
_asm {
push eax;
mov eax, fs:[0x30]; // PEB
mov eax, [eax + 0xC] // LDR
mov eax, [eax + 0xC] // InLoadOrderModuleList, exe
mov eax, [eax]; // nt.dll
mov eax, [eax]; // kernel32.dll
mov eax, dword ptr ds:[eax + 0x18]; // BaseAddr;
mov nAddress, eax;
pop eax;
} return nAddress;
}

附录:

参考MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/aa813708%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/589009.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存