内存加载PE技术研究

一,背景

最近研究内存加载DLL技术,这个技术大概10年前的技术,用搜索引擎可以找到很多资料,我自己按照思路,综合其他各种实现思路,大概弄懂核心思路。

市面开源主流代码:

1:PE加载器,可以加载大部分程序,我测试TIM,微信都是可以,加壳的程序没有测试,代码写的非常专业,

https://github.com/polycone/pe-loader

2:DLL加载器,没有进程信息修改,貌似支持64位。

https://github.com/fancycode/MemoryModule

二,PE核心步骤

  1. 导入表修复
  2. 重定位表修复
  3. 进程信息修复(加载EXE才需要,DLL不需要)

三,疑惑问题?

1:为什么需要修复?

因为我们手动加载到内存,然后跳转到入口地址,开始执行代码,因为代码地址都是写死,每次加载都需要系统自动去修改,但我们手动加载就必须手动修改,所以才有修改导入表和重定位表。

因为我们调用函数和一些全局变量都是死地址,这些死地址记录在重定位表里面,所以我们需要修复他。

导入表记录API的地址,PE文件只记录名字或者序号,系统加载的DLL或者EXE会默认修改导入表的FristThunk(IAT),这里面保存API的地址,我们调用系统API的时候,我们调用的系统API的时候。我们调用导入表call的地址。

int main() {
    MessageBox(0, L"hello world", 0, 0);
    return 0;
}
这个导入表的IAT的地址,这里用IDA逆向,加载前等于INT。

CALL IAT对应变量(变量含有真的地址,我们IAT HOOK时候只要修改这个地址就可以了)

2:对齐

分为内存对齐和文件对齐,PE文件结构很多大小都是安装对应的对齐,PE文件保存了文件数据和内存数据,所以刚开始很容易搞混,说白就是告诉你文件怎么读和内存怎么读而已。因为PE是编译生成好的。

内存对齐:windows中,内存属性的基本单位是页,在32位系统是4KB(1000h),在64位系统中是8kb。
文件对齐:为了提高磁盘利用率,把一个物理扇区作为一个对齐粒度的大小,也就是12字节(200H),这是每个数据段都是200H的整数倍的原因。

为什么需要对齐的原因,性能问题。

3:偏移

所有都是基地址为偏移,内存加载就是内存分配起始地址做偏移

4:什么是导入表?

记录程序用哪些系统的API,同时加载后会被系统初始化,提供系统API的真正的地址,要软件能正常调用

资料:https://blog.csdn.net/Apollon_krj/article/details/77417063

5:什么是重定位表?

记录生成EXE或者DLL 函数死地址,如果重定向,就需要进行修改,默认是系统修改。但内存加载必须手动修改。

6:为什么会要重定向?

这种情况基本出现DLL,exe感觉永远不会,他是第一个模块加载,可以优先选位置,这个就好比我们小时候选读书的位置一样,每个都有选位置权利,我们默认可能都是最好一排,但如果我们的位置已经被人选择了,那么我们就只能选择其他的位置。我们编译程序默认按照最好位置涉及,一旦你的位置改变了,那么所有地址都需要更新。

7:为什么进程修复?(只针对EXE的情况)

我们加载的EXE,其实相当于一个新的模块,系统默认不知道的,所以当我们程序获取模块信息会获取不到或者错误,导致逻辑错乱。程序运行不了。如果不进行进程修复,MFC程序不可以内存直接运行的话,因为调用GetMoudleFileName 会获取为空。因为传入hinstance是我们假的地址,这个时候只要我们修改peb的里面模块List 基地址和peb的模块地址就可以了,改成内存new的地址。代码可以借鉴PE-LOADER。

这里PE-loader还对的一些进行hook

命令hook,传递参数,DLL可以直接调用的,可以传入保留那个字段为参数即可,因为PEloader 只针对 exe执行程序,不是针对dll,所以代码没有考虑,哪些需要修复可以通过逆向找到

8:以前人怎么想这个思路?

1:推想+逆向,函数+变量就可以做任何事情,远程注入代码逻辑,分配内测然后注入代码,就可以直接执行,但没有注入DLL舒服,内存加载DLL是为了隐藏DLL,这个好处有很多,防止报毒和加大别人分析代码难度。

2:通过微软的文档,知道系统大概逻辑,我猜测PE-loader就很类似这种,因为他的函数命名就是跟微软底层API命名一样。

9:官网文档?

介绍系统加载DLL的逻辑

https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_data_directory

PE 格式 微软资料

https://docs.microsoft.com/en-us/windows/win32/debug/pe-format

四:总结

围观:学习PE内存加载知识,熟悉PE结构

宏观:优化解决问题能力,怎么通过一个知识点,然后找到对应解决方案,然后通过分析了解,找到一个成熟的解决方案

我自己代码后面再贴,目前有好多日志,主要为了学习用途。