吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 825|回复: 8
上一主题 下一主题
收起左侧

[原创] 自实现LoadLibrary和GetProcAddress

[复制链接]
跳转到指定楼层
楼主
wolfSpicy 发表于 2026-9-13 12:50 回帖奖励

自实现 LoadLibrary 和 GetProcAddress

虽然现在有 AI 了,但对于 PE 结构,仍是我们学习 Windows 逆向绕不过去的关卡。
必须把基础打好,才能更加熟练地运用 AI。

完整工程(可编译对照):https://github.com/1903247335/manual-map-loadlibrary


为什么要自实现 LoadLibrary 和 GetProcAddress

我们可以对 PE 结构更加了解,明白底层 Loader 是怎么样加载程序、展开的。
因为这样可以免除掉部分 R3 层的检测,例如:

  • CreateToolhelp32Snapshot(TH32CS_SNAPMODULE) + Module32First / Next
  • EnumProcessModules / EnumProcessModulesEx(psapi)
  • GetModuleHandle / GetModuleHandleEx(按名字找;你的 DLL 本来也没注册名字)
  • 自己遍历:
    • PEB → Ldr → InLoadOrderModuleList
    • InMemoryOrderModuleList
    • InInitializationOrderModuleList

需要的前置知识

  • 对常规 Win API 有一定的了解
  • 熟悉 PE 结构:只需要会导入表导出表重定位表原理

我们的目标是不考虑 TLS 表,只考虑简单的程序。单单会这个,别的也可以举一反三了。


接下来简单说下原理

LoadLibrary 是把 DLL 从文件结构直接拓展到内存结构,然后进行:

  1. 导入表修复(根据 INT 来把 IAT 换成真实函数地址)
  2. 重定位修复(根据写死的地址换成加载之后正确的地址)

很简单:

新地址 = 目标写死的地址 + 实际载入到内存的基地址 - 写死的基地址

修复完后找到 DLL 入口直接调用,传入 DLL_PROCESS_ATTACH,来实现 DLL 初始化函数执行。

GetProcAddress 是根据名字或者序号来读取 DLL 的导出表,拿到对应函数。

FreeLibrary 原理就是把 DLL 句柄传入,然后获取到 DLL 主入口,传入 DLL_PROCESS_DETACH 来调用卸载入口,再然后进行 VirtualFree 进行内存释放。


接下来就直接开始吧

我不会直接给代码,不然直接粘贴一堆代码太无聊了,我只说思路。
完整代码见仓库:https://github.com/1903247335/manual-map-loadlibrary

内存空间开辟

  1. CreateFileA 打开 DLL 路径  
  2. GetFileSize 来获取 DLL 的文件大小  
  3. ReadFile 根据读出来的 File Size 移动到 buffer 当中做准备  

从文件结构拓展到内存结构

这时候 buffer 已经是把 DLL 的文件结构一比一复制了,目的是为了可以直接读取它们的 PE 结构。

读取 DOS 头这些是常规操作了,直接到 OptionalHeader 里面拿到了 SizeOfImage。拿到它的目的是为了开辟「展开到内存」的结构——它代表着文件展开后的大小。

这时候可以用 VirtualAlloc 来真正开辟给 DLL 展开的空间了,同时得到的指针也是 baseAddress
然后我们可以把 PE 头都给移动到 baseAddress 中,直接用 OptionalHeader.SizeOfHeaders

(PE 头不需要按节去「拓展」;真正要按内存布局展开的是各个节区内容。节表告诉我们每个节该怎么搬。)

导入表修复

修复的原理是:从 INT 给出的信息来读取我们要找哪个外部 DLL、哪个函数;
找到它们的地址后,填充到 IAT 里面,以此来达到修复。

这一步是从 INT 中获取我们要找的 DLL(因为是导入系统 DLL,所以直接 LoadLibrary 不影响。
但你要是不爽,可以自己再写一个不需要系统函数也能加载系统 DLL 的——不过难度可能会非常的大)。

得到了 DLL 的句柄后,就是判断 INT 是用什么方式载入函数的——有可能是序号,也有可能是函数名。
但最核心的就是得到函数地址,并写回 IAT。

重定位表修复

这个实际也不难:

  1. 获取当前载入内存的地址,和实际 PE 的 OptionalHeader.ImageBase 进行比较,看看差了多少  
  2. 获取重定位表的每一项,取出 offset  
  3. 我们要改的地方就是:当前载入内存的地址 + 页RVA + offset  
  4. 然后给这个地方加上(当前载入内存的地址 - ImageBase),就是重定位成功了  

实际一点都不难。

调用 DllMain

找到 entryPoint,然后直接传入规定参数:

DllMain(base, DLL_PROCESS_ATTACH, nullptr)

就可以实现调用了。

实现 GetProcAddress(根据函数名)

根据导出表来找到对应函数名。GetProcAddress 根据序号同理。

FreeLibrary 实现

找到 AddressOfEntryPoint,往里面传入 DLL_PROCESS_DETACH
VirtualFree 释放内存,就这样。


写在最后

实际上并没有我们想象的那么难,就是过程代码实现可能曲折点,但思路是摆在那的。
现在有 AI 了,我们可以花更多时间在研究思路上,而不是实际代码上了。

完整工程:https://github.com/1903247335/manual-map-loadlibrary

仅供学习 Windows PE / Loader 原理,请勿用于未授权场景。

免费评分

参与人数 2吾爱币 +6 热心值 +2 收起 理由
Command + 2 + 1 用心讨论,共获提升!
冥界3大法王 + 4 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
GDExecW 发表于 2026-9-14 12:06
这应该是反射加载了,恶意软件经常用
还有 Neurosama
沙发
aonima 发表于 2026-9-13 13:24
3#
 楼主| wolfSpicy 发表于 2026-9-13 16:13 |楼主
aonima 发表于 2026-9-13 13:24
以前也实现过,不过只能xp系统

现在知道原理就行了 大佬肯定已经很牛逼了
4#
董督秀 发表于 2026-9-13 16:47
自实现很厉害了。之前尝试过生成纯sc版本的ldrloaddll进行常规加载dll。但是模块里可以看得到,还得在dll里加上模块断链隐藏。仍然躲不过ark的扫描。
5#
冥界3大法王 发表于 2026-9-13 18:50
感谢感谢,又可以升级改造DNA,重新生产小猪仔啦。
6#
XIUDAO 发表于 2026-9-13 20:10
原来是这样吗?
7#
pspkin23 发表于 2026-9-13 20:50
原来是这样的啊?
8#
kilkilo502 发表于 2026-9-13 22:57
你说的有道理。。。脱壳搞修复DLL不修复  导入表  在64位上貌似现在比较严格不好搞。。我也是头一次见 学习了!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-9-15 10:59

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表