浅析代码重定位技术
前言
大家好,我是科锐49期远程班的一名学员。此篇文章是我消化上课内容后写的一篇教学向文章如有理解错误的地方恳请各位前辈斧正,学习任务繁重,所以文章更新较慢请各位谅解。
我将尽量用简单易懂的语言阐述清楚该技术要点,并且辅以相关代码示例帮助新手小白更好的理解。
0x00 大纲
- 什么是代码重定位?
- 为什么我们需要它?(应用场景)
- 重定位实现方法一(段首地址法)
- 重定位实现方法二(段偏移法)
- 结语
- 参考
环境: Windows11 23H2
编译器: ml.exe
链接器: link.exe
适用语言: 32位汇编
0x01 什么是代码重定位?
代码重定位 代码重定位技术是指在程序执行的过程中,操作系统或加载器将程序中的地址引用调整到实际加载时的内存地址的过程, 它允许我们在不同的程序中正确的执行一个片段的代码而不用考虑在当前代码中的实际加载偏移,换句话讲地址无关(Position-Independent Code, PIC)技术的实现就是基于代码重定位来进行实现的。
0x02 代码重定位的应用场景
我们考虑如下问题,当前存在一个进程A,他需要在注入进程B之后立马执行一段自己的代码且这段代码中包含地址相关的指令比如某变量的读写。这时我们采用远程线程注入的形式利用API
CreateRemoteThread
VirtualAllocEx
WriteProcessMemory
将要执行的汇编代码注入到目标进程中。首先我们先给出这段代码的汇编实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
|
我们尝试进行注入如下代码,我们希望在目标进程中弹出一个框
1 2 3 4 5 6 7 8 |
|
我们直接用两个x64dbg进行调试
这里已经成功将要执行的代码注入到了目标进程中
我们尝试直接运行看看会发生什么?
可以看到我们这里在执行之后出现了C05这是在我们的意料之中的因为在这里不仅仅是MessageBoxA
,整个代码片段都是地址强相关的一切的偏移都是在原有进程的偏移所以在新的进程无法使用。
所以在这里我们需要通过地址重定位技术让代码段脱离地址依赖能够自己获取偏移以便于成功运行。
下面我将给出两种重定位技术
- 段首地址法
- 段偏移法
0x03 段首地址法
为什么叫段首地址法这个词很形象的描述了这种方法,当我们在编译汇编程序的时候我们能够确定的并且控制的东西是从地址标签
INJECT_BEGIN
到CODE_BEGIN
中的各种变量偏移,不能控制的是加载的地址,但是如果我们能够获取到INJECT_BEGIN
的地址则可以根据已知的偏移获取到正确的代码偏移量。到此自身代码的偏移问题已经可以解决,现在我们还需要解决调用系统API的时候在不同的进程中API加载的地址也是不同的问题,那么这个问题如何解决呢?
对于这个问题我们应该利用系统自身带的PIC API去进行定位,看过我写的文章的小伙伴应该已经知道了,没错就是
LoadLibrary
和GetProcAddress
这两个API是系统自带的PIC API, 他们通常在不同进程中的地址是相同的,我们通过这个API将MessageBoxA
的地址加载到要注入的地址中去。tips: 对于32位汇编我们不能直接拿到IP寄存器的值我们需要通过call命令将返回地址压入栈中然后利用pop手动获取到IP的值,对于地址重定向中我们获取到当前执行的命令的IP值则可以通过如下代码段
1 2 3 4 5 6 |
|
基于如上原理我们给出如下实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
MessageBox地址获取实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
我们通过调试来观察下过程
成功定位到代码段
成功运行! 至此就是段首地址法的内容
下面我们进入段偏移法的讲解
0x04 段偏移法
段偏移法和段首地址法的最大区别就是段偏移法是通过计算加载到目标进程的地址和原进程地址的偏移,通过
原进程地址 + 偏移 = 目标进程的地址
的方式重定位代码段给出如下实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
成功重定位到代码段
成功运行
0x05 结语
代码重定位技术在许多计算机科学和软件工程领域中扮演着重要角色,尤其是在注入技术、动态链接库(DLL)、以及操作系统内存管理等方面。掌握代码重定位技术不仅有助于理解这些领域的基础概念,还能为开发和安全研究提供强大的支持。
0x06 参考
- MSDN
- 结语和0x01为ChatGpt编写(理论性的东西实在不想动手写)
PS
欢迎大家在评论区讨论。