寻找遗失的Kernal32.dll—WinDbg&汇编—手动&动态
如果你是因为标题进来的, 那么你一定在好奇, 好好的Kernal32.dll躺在我的C盘里面, 怎么会遗失呢,你一定没想到,在你打开这篇文章链接的瞬间,你的Kernal32.dll已经被我隐藏了,只有读完这篇文章,你才能找到**的办法。
哈哈,只是开个玩笑!我还没有厉害到这个程度。
其实我这里给大家分享的是如何找到一个重要结构体, 并从这个结构体中获取有价值的数据。
这个结构体就是,铛铛铛铛:
_LDR_DATA_TABLE_ENTRY
这个名字是直接可以在WinDbg中通过dt这条命令来查看所包含元素的,客官请看:
注:浅蓝色行是输入的命令
大家也能看到,这个结构体很庞大,不过不要方,本人才疏学浅,能勉强讲给大家听的也就是本文章所涉及的元素已被标注为黄色,至于为什么是黄色。
首先跟着我来一起看看上面这个大大大结构体的第一个元素,结构体的第一个元素,顾名思义,直接取结构体内容即可获得其数据,那这个数据是什么呢?
我们再次使用 dt 这副照妖镜来看看这第一个元素:
啊哈,这很明显就是一个双向链表,问我为什么,老师上课教的。 另,我这么吊我妈并不知道。
_LDR_DATA_TABLE_ENTRY结构体中第一个元素中的第一个元素是前一个_LDR_DATA_TABLE_ENTRY结构体的地址,
嗯?有点绕,没事,先记着,看下面两个重要元素:
看图可得,这两个元素分别为模块基址和模块名称。
单纯无公害的观众到这里应该知道从这里开始可以做什么事了吧,千里之行始于足下。
思路便是:通过双向链表来遍历 _LDR_DATA_TABLE_ENTRY结构体,匹配模块名称,获取模块基址。
如果你不幸跟上了我的胡诌,那么现在你想的应该是,如何获取这个结构体呢?
经过我上面的一些混淆措辞,我们进入正题,
我这里分别动态和手动获取一次,以便于比我更晚入门的同学理解。
先上干货,不掺水的,连寄存器环境都不带保存一下的:
反汇编: 注释: WinDbg命令:
_asm{
MOV EAX, FS:[0x30]; // _PEB
MOV EAX, [EAX + 0xC]; // _PEB_LDR_DATA | dt _PEB_LDR_DATA 77627c00
MOV EAX, [EAX + 0xC]; // _LDR_DATA_TABLE_ENTRY[0] | dt _LDR_DATA_TABLE_ENTRY 0x723588
MOV EAX, [EAX]; // _LDR_DATA_TABLE_ENTRY[-1] | dt _LDR_DATA_TABLE_ENTRY 0x723480
MOV EAX, [EAX]; // _LDR_DATA_TABLE_ENTRY[-2] | dt _LDR_DATA_TABLE_ENTRY 0x723958
MOV EAX, DWORD PTR DS : [EAX + 0x18]; // DllBase :_LDR_DATA_TABLE_ENTRY[-2]+0x18 | dd 0x723970
}
注:WinDbg命令后面的地址以实物为准。
动态获取过程:
这里我们主要关注EAX的值,毕竟也没别的关注点。
Step1:EAX == 0x77627c00
Step2:EAX == 0x00883b18
Step3:EAX == 0x00883a10
Step4:EAX == 0x00883ee8
Step5:EAX == 0x769a0000
以防出现太长不看的评论:
Step1:EAX == 0x77627c00
Step2:EAX == 0x00883b18
Step3:EAX == 0x00883a10
Step4:EAX == 0x00883ee8
Step5:EAX == 0x769a0000
以上是动态获取下面通过手动获取来验证并详细解释:
如何验证一个用有动态基址的程序中获取的地址是否正确呢?
WinDbg->File->Attach to a process->选择你的程序`
Note:勾选Noninvasive
在内核层有一个传说中的结构体,叫做ETHREAD,它在凡间即用户层就变成了TEB线程环境块,而通过FS便能直接找到这个结构体
而它偏移0x30的位置是另一个传说在凡间的样子,那就是PEB,在座的有没有一个大胆的想法,猜猜这个结构体是谁?
MOV EAX, FS:[0x30]
没错,它就是进程环境块:
通过进程环境块的0x0C处找到下一个结构体:
在这个结构体中,终于看到一个面熟的,根据上面讲解的思路,接下来的故事就顺理成章了,忘记思路的同学,看这里:
思路便是:通过双向链表来遍历 _LDR_DATA_TABLE_ENTRY结构体,匹配模块名称,获取模块基址。
MOV EAX,[EAX+0x0C]
Step1:EAX == 0x77627c00
MOV EAX,[EAX+0x0C]
Step2:EAX == 0x00883b18
MOV EAX,[EAX]
Step3:EAX == 0x00883a10
MOV EAX,[EAX]
Step4:EAX == 0x00883ee8
Step5:EAX == 0x769a0000
那么获取到的Kernal32.dll的基址便是0x769a0000,遗失的Kernal32.dll也回家了,大家可以接着安稳地敲代码了。
彩蛋:
大家应该发现了,虽然思路是遍历双向链表并匹配模块名,但是代码并没有这个操作,简直是虚假广告,
请允许我做个悲伤的表情并接着忽悠,
首先,定位到的第一个_LDR_DATA_TABLE_ENTRY结构体通常为进程加载的exe模块,前一个是ntdll.dll,
再前面一个便是Kernal32.dll。
其次,师傅领进门修行靠个人,遍历和匹配字符串的代码就留给大家作为作业吧,大宝明天见!
在这个结构体中,终于看到一个面熟的
MOV EAX,[EAX+0x0C]