-
-
[推荐][原创]修复内存加载mfc dll的Bug,x64
-
-
[推荐][原创]修复内存加载mfc dll的Bug,x64
在很早之前写过反射性注入dll的代码,但是最近验证了一下常规的内存代码无法加载mfc的dll,于是我便开始寻找解决之道。
、
先看下异常原因:
发现在kernelBase这个模块发生了异常,于是我打开x64dbg在异常处设下断点。
然后我们执行到这个地方,查看下调用堆栈,如图:
在调用堆栈中,前面几个调用堆栈地址里面里面都没有执行代码,真正执行的代码的是ntdll.LdrGetDllFullName,然后我们在LdrGetDLlFullName那里设下断点,经过反复的测试找出现异常的那次调用,其信息如下图:
大家可以查到LdrGetDllFullName的函数原型,其中rcx中存储的是模块的基址,我们可以在内存中看一下LdrGetDllFullName查询的是哪一个模块的路径名称。
很显然这块内存属于我们的用户模块,且其起始地址并不属于我们的程序的基地址,那么这个地址是谁呢?先猜测下应该是我们内存加载mfc dll的基址,结果发现确实是我们mfc dll的基址:
所以猜测应该是call mfc入口点的时候,mdc的dll查找自己的路径,但是我们是自己内存加载的mfc dll,进程中没有这个dll的信息,导致抛出了异常。
继续单步执行找出哪里跳到异常点,发现调用LdrGetDllFullName的是GetModuleFileNameW,然而进程中没有没有关于这个基址的是不是一个模块基址的信息,显然GetModuleFileNameW执行失败,返回的值为空,下面那张图的je是跳到我们出异常的地方。
既然发现了一个bug,那我们先简单修复一下这个bug,把返回的值和获得的dll路径给改下就行了,看看修复完这个bug还有没有bug,如果有,就继续寻找bug并修复,直到没有bug为止。
修复思路是:在内存加载修复iat表里面的GetModuleFileNameW的地址改为我们自己的GetModuleFileNameW,也就是iathook一下:
然后发现我们dll就加载成功了:
至此,发现没有必要继续修复bug,这样我们的mfc dll就成功加载了。
后来发现GetMouduleFileName是跟据模块的基址在 _PEB_LDR_DATA中遍历InLoadOrderModuleList,对比dllBase来获取模块的路径,所以我们可以劫持一个模块,将模块的dllBase改成我们无模块的基址同样可以成功,可以成功加载。
以上就是我查找异常,修复bug的思路,如果有错误希望大佬可以指正。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2024-3-6 19:32
被mb_maiyudos编辑
,原因: