Dll注入:修改PE文件 IAT注入

PE原理就不阐述了, 这个注入是PE感染的一种,通过添加一个新节注入,会改变PE文件的大小,将原有的导入表复制到新节中,并添加自己的导入表描述符,最后将数据目录项中指向的导入表的入口指向新节。

步骤:

1.添加一个新节;映射PE文件,判断是否可以加一个新节,找到节的尾部,矫正偏移,对齐RVA

填充新节PIMAGE_SECTION_HEADER,修改IMAGE_NT_HEADERS,将新节添加到文件尾部

2.修改导入表:判断是否使用了绑定导入表,往新节中拷贝原导入表内容,继续构造新的导入表描述符PIMAGE_IMPORT_DESCRIPTOR,构造IAT结构体PIMAGE_THUNK_DATA,填充PIMAGE_THUNK_DATA,将PIMAGE_IMPORT_DESCRIPTOR的OriginalFirstThunk和FirstThunk指向PIMAGE_THUNK_DATA,name指向DllName
最后修改导入表的VirtualAddress指向新节

  1 #include <windows.h>
  2 #include <iostream>
  3 #include <exception>
  4 #include <string>
  5
  6 using namespace std;
  7
  8 #define ERROR_MESSAGE(Msg) std::cout<<Msg<<std::endl;
  9 BOOL    AddImportTable(const string& strTargetFile, const string& strInjectDllName, const string& strFunctionName);
 10 BOOL    AddNewSection(const string& strTargetFile, ULONG ulNewSectionSize);
 11 BOOL    AddNewImportDescriptor(const string& strTargetFile, const string& strInjectDllName, const string& strFunctionName);
 12 DWORD   RVAToFOA(PIMAGE_NT_HEADERS pNtHeaders, DWORD dwRVA);
 13 ULONG32 PEAlign(ULONG32 dwNumber, ULONG32 dwAlign);
 14
 15 int main()
 16 {
 17     AddImportTable("Target.exe", "Dll.dll", "InjectFunction");
 18
 19     system("pause");
 20     return true;
 21 }
 22
 23 BOOL AddImportTable(const string& strTargetFile, const string& strInjectDllName, const string& strFunctionName)
 24 {
 25     BOOL bOk = false;
 26     try
 27     {
 28         bOk = AddNewSection(strTargetFile, 256);
 29         if (!bOk)
 30         {
 31             ERROR_MESSAGE("AddImportTable:AddNewSection failed.");
 32             return false;
 33         }
 34
 35         bOk = AddNewImportDescriptor(strTargetFile, strInjectDllName, strFunctionName);
 36         if (!bOk)
 37         {
 38             ERROR_MESSAGE("AddImportTable:AddNewImportDescriptor failed.");
 39             return false;
 40         }
 41     }
 42     catch (exception* e)
 43     {
 44         ERROR_MESSAGE((string("AddImportTable:") + e->what()).c_str());
 45         return false;
 46     }
 47
 48     return true;
 49 }
 50
 51 BOOL AddNewSection(const string& strTargetFile, ULONG ulNewSectionSize)
 52 {
 53     BOOL bOk = true;
 54     HANDLE TargetFileHandle = nullptr;
 55     HANDLE MappingHandle = nullptr;
 56     PVOID FileData = nullptr;
 57
 58     try
 59     {
 60         // 打开文件
 61         TargetFileHandle = CreateFileA(strTargetFile.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 62         if (TargetFileHandle == INVALID_HANDLE_VALUE)
 63         {
 64             ERROR_MESSAGE(string("AddNewSection:CreateFileA error with error code:" + GetLastError()).c_str());
 65             bOk = false;
 66             goto EXIT;
 67         }
 68
 69         ULONG ulFileSize = GetFileSize(TargetFileHandle, NULL);
 70
 71         // 映射文件
 72         MappingHandle = CreateFileMappingA(TargetFileHandle, NULL, PAGE_READWRITE, 0, ulFileSize, NULL);
 73         if (MappingHandle == NULL)
 74         {
 75             ERROR_MESSAGE(string("AddNewSection:CreateFileMapping error with error code:" + GetLastError()).c_str());
 76             bOk = false;
 77             goto EXIT;
 78         }
 79
 80         // 得到缓存头
 81         FileData = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, ulFileSize);
 82         if (FileData == NULL)
 83         {
 84             ERROR_MESSAGE(string("AddNewSection:MapViewOfFile error with error code:" + GetLastError()).c_str());
 85             bOk = false;
 86             goto EXIT;
 87         }
 88
 89         // 判断是否是PE文件
 90         if (((PIMAGE_DOS_HEADER)FileData)->e_magic != IMAGE_DOS_SIGNATURE)
 91         {
 92             ERROR_MESSAGE("AddNewSection:Target File is not a vaild file");
 93             bOk = false;
 94             goto EXIT;
 95         }
 96
 97         PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)FileData + ((PIMAGE_DOS_HEADER)FileData)->e_lfanew);
 98         if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
 99         {
100             ERROR_MESSAGE("AddNewSection:Target File is not a vaild file");
101             bOk = false;
102             goto EXIT;
103         }
104
105         // 判断是否可以增加一个新节
106         if ((pNtHeaders->FileHeader.NumberOfSections + 1) * sizeof(IMAGE_SECTION_HEADER) > pNtHeaders->OptionalHeader.SizeOfHeaders/*三个部分的总大小*/)
107         {
108             ERROR_MESSAGE("AddNewSection:There is not enough space to add a new section.");
109             bOk = false;
110             goto EXIT;
111         }
112
113         // 得到新节的起始地址, 最后的起始地址
114         PIMAGE_SECTION_HEADER pNewSectionHeader = (PIMAGE_SECTION_HEADER)(pNtHeaders + 1) + pNtHeaders->FileHeader.NumberOfSections;
115         PIMAGE_SECTION_HEADER pLastSectionHeader = pNewSectionHeader - 1;
116
117         // 对齐RVA和偏移
118         DWORD FileSize = PEAlign(ulNewSectionSize, pNtHeaders->OptionalHeader.FileAlignment);
119         DWORD FileOffset = PEAlign(pLastSectionHeader->PointerToRawData + pLastSectionHeader->SizeOfRawData, pNtHeaders->OptionalHeader.FileAlignment);
120         DWORD VirtualSize = PEAlign(ulNewSectionSize, pNtHeaders->OptionalHeader.SectionAlignment);
121         DWORD VirtualOffset = PEAlign(pLastSectionHeader->VirtualAddress + pLastSectionHeader->Misc.VirtualSize, pNtHeaders->OptionalHeader.SectionAlignment);
122
123         // 填充新节表
124         memcpy(pNewSectionHeader->Name, "Inject", strlen("Inject"));
125         pNewSectionHeader->VirtualAddress = VirtualOffset;
126         pNewSectionHeader->Misc.VirtualSize = VirtualSize;
127         pNewSectionHeader->PointerToRawData = FileOffset;
128         pNewSectionHeader->SizeOfRawData = FileSize;
129         pNewSectionHeader->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
130
131         // 修改IMAGE_NT_HEADERS
132         pNtHeaders->FileHeader.NumberOfSections++;
133         pNtHeaders->OptionalHeader.SizeOfImage += VirtualSize;
134         pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;            // 关闭绑定导入
135         pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
136
137         // 添加新节到文件尾部
138         SetFilePointer(TargetFileHandle, 0, 0, FILE_END);
139         PCHAR pNewSectionContent = new CHAR[FileSize];
140         RtlZeroMemory(pNewSectionContent, FileSize);
141         DWORD dwWrittenLength = 0;
142         bOk = WriteFile(TargetFileHandle, pNewSectionContent, FileSize, &dwWrittenLength, nullptr);
143         if (bOk == false)
144         {
145             ERROR_MESSAGE(string("AddNewSection:WriteFile error with error code:" + GetLastError()).c_str());
146             bOk = false;
147             goto EXIT;
148         }
149     }
150     catch (exception* e)
151     {
152         ERROR_MESSAGE((string("AddNewSection:") + e->what()).c_str());
153         bOk = false;
154     }
155 EXIT:
156     if (TargetFileHandle != NULL)
157     {
158         CloseHandle(TargetFileHandle);
159         TargetFileHandle = nullptr;
160     }
161     if (FileData != NULL)
162     {
163         UnmapViewOfFile(FileData);
164         FileData = nullptr;
165     }
166     if (MappingHandle != NULL)
167     {
168         CloseHandle(MappingHandle);
169         MappingHandle = nullptr;
170     }
171
172     return bOk;
173 }
174
175 ULONG32 PEAlign(ULONG32 dwNumber, ULONG32 dwAlign)
176 {
177     return(((dwNumber + dwAlign - 1) / dwAlign) * dwAlign);        //  想 dwAlign 对齐,加上 dwAlign - 1,这样就可以保证对齐后的值 >= dwNumber
178 }
179
180 BOOL AddNewImportDescriptor(const string& strTargetFile, const string& strInjectDllName, const string& strFunctionName)
181 {
182     bool bOk = true;
183     HANDLE TargetFileHandle = nullptr;
184     HANDLE MappingHandle = nullptr;
185     PVOID FileData = nullptr;
186     PIMAGE_IMPORT_DESCRIPTOR pImportTable = nullptr;
187
188     try
189     {
190         // 打开文件
191         TargetFileHandle = CreateFileA(strTargetFile.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
192         if (TargetFileHandle == INVALID_HANDLE_VALUE)
193         {
194             ERROR_MESSAGE(string("AddNewImportDescriptor:CreateFileA error with error code:" + GetLastError()).c_str());
195             bOk = false;
196             goto EXIT;
197         }
198
199         ULONG ulFileSize = GetFileSize(TargetFileHandle, NULL);
200
201         // 映射文件
202         MappingHandle = CreateFileMappingA(TargetFileHandle, NULL, PAGE_READWRITE, 0, ulFileSize, NULL);
203         if (MappingHandle == NULL)
204         {
205             cout << "AddNewImportDescriptor:CreateFileMapping error with error code:" << std::to_string(GetLastError()).c_str();
206             bOk = false;
207             goto EXIT;
208         }
209
210         // 得到缓存头
211         FileData = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, ulFileSize);
212         if (FileData == NULL)
213         {
214             ERROR_MESSAGE(string("AddNewImportDescriptor:MapViewOfFile error with error code:" + GetLastError()).c_str());
215             bOk = false;
216             goto EXIT;
217         }
218
219         // 判断是否是PE文件
220         if (((PIMAGE_DOS_HEADER)FileData)->e_magic != IMAGE_DOS_SIGNATURE)
221         {
222             ERROR_MESSAGE("AddNewImportDescriptor:Target File is not a vaild file");
223             bOk = false;
224             goto EXIT;
225         }
226
227         PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)FileData + ((PIMAGE_DOS_HEADER)FileData)->e_lfanew);
228         if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
229         {
230             ERROR_MESSAGE("AddNewImportDescriptor:Target File is not a vaild file");
231             bOk = false;
232             goto EXIT;
233         }
234
235         // 得到原导入表
236         pImportTable = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)FileData + RVAToFOA(pNtHeaders, pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
237         // 判断是否使用了绑定导入表
238         bool bBoundImport = false;
239         if (pImportTable->Characteristics == 0 && pImportTable->FirstThunk != 0)
240         {
241             // 桥一为0 桥二不是0 说明使用了绑定导入表
242             bBoundImport = true;
243             pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;    // 关闭绑定导入
244             pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
245         }
246
247         // 找到自己添加的新节
248         PIMAGE_SECTION_HEADER pNewSectionHeader = (PIMAGE_SECTION_HEADER)(pNtHeaders + 1) + pNtHeaders->FileHeader.NumberOfSections - 1;
249         PBYTE pNewSectionData = pNewSectionHeader->PointerToRawData + (PBYTE)FileData;
250         PBYTE pNewImportDescriptor = pNewSectionData;
251         // 往新节中拷贝原导入表内容
252         int i = 0;
253         while (pImportTable->FirstThunk != 0 || pImportTable->Characteristics != 0)
254         {
255             memcpy(pNewSectionData + i * sizeof(IMAGE_IMPORT_DESCRIPTOR), pImportTable, sizeof(IMAGE_IMPORT_DESCRIPTOR));
256             pImportTable++;
257             pNewImportDescriptor += sizeof(IMAGE_IMPORT_DESCRIPTOR);
258             i++;
259         }
260         // 复制最后一个描述符
261         memcpy(pNewImportDescriptor, pNewImportDescriptor - sizeof(IMAGE_IMPORT_DESCRIPTOR), sizeof(IMAGE_IMPORT_DESCRIPTOR));
262
263         // 计算修正值
264         DWORD dwDelt = pNewSectionHeader->VirtualAddress - pNewSectionHeader->PointerToRawData;
265
266         // pNewImportDescriptor 当前指向要构造的新描述符 再空出一个空描述符作为导入表的结束符 所以是 2 *
267         PIMAGE_THUNK_DATA pNewThunkData = PIMAGE_THUNK_DATA(pNewImportDescriptor + 2 * sizeof(IMAGE_IMPORT_DESCRIPTOR));
268         PBYTE pszDllName = (PBYTE)(pNewThunkData + 2);
269         memcpy(pszDllName, strInjectDllName.c_str(), strInjectDllName.length());
270         // 确定 DllName 的位置
271         pszDllName[strInjectDllName.length() + 1] = 0;
272         // 确定 IMAGE_IMPORT_BY_NAM 的位置
273         PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)(pszDllName + strInjectDllName.length() + 1);
274         // 初始化 IMAGE_THUNK_DATA
275         pNewThunkData->u1.Ordinal = (DWORD_PTR)pImportByName - (DWORD_PTR)FileData + /*加上修正值 - 这里应该填充在内存中的地址*/dwDelt;
276         // 初始化 IMAGE_IMPORT_BY_NAME
277         pImportByName->Hint = 1;
278         memcpy(pImportByName->Name, strFunctionName.c_str(), strFunctionName.length());
279         pImportByName->Name[strFunctionName.length() + 1] = 0;
280         // 初始化 PIMAGE_IMPORT_DESCRIPTOR
281         if (bBoundImport)
282         {
283             ((PIMAGE_IMPORT_DESCRIPTOR)pNewImportDescriptor)->OriginalFirstThunk = 0;
284         }
285         else
286         {
287             ((PIMAGE_IMPORT_DESCRIPTOR)pNewImportDescriptor)->OriginalFirstThunk = dwDelt + (DWORD_PTR)pNewThunkData - (DWORD_PTR)FileData;
288         }
289         ((PIMAGE_IMPORT_DESCRIPTOR)pNewImportDescriptor)->FirstThunk = dwDelt + (DWORD_PTR)pNewThunkData - (DWORD_PTR)FileData;
290         ((PIMAGE_IMPORT_DESCRIPTOR)pNewImportDescriptor)->Name = dwDelt + (DWORD_PTR)pszDllName - (DWORD_PTR)FileData;
291         // 修改导入表入口
292         pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = pNewSectionHeader->VirtualAddress;
293         pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (i + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
294     }
295     catch (exception* e)
296     {
297         ERROR_MESSAGE((string("AddNewImportDescriptor:") + e->what()).c_str());
298         bOk = false;
299     }
300
301 EXIT:
302     {
303         if (TargetFileHandle != NULL)
304         {
305             CloseHandle(TargetFileHandle);
306             TargetFileHandle = nullptr;
307         }
308
309         if (FileData != NULL)
310         {
311             UnmapViewOfFile(FileData);
312             FileData = nullptr;
313         }
314
315         if (MappingHandle != NULL)
316         {
317             CloseHandle(MappingHandle);
318             MappingHandle = nullptr;
319         }
320     }
321
322     return bOk;
323 }
324
325 PIMAGE_SECTION_HEADER GetOwnerSection(PIMAGE_NT_HEADERS pNTHeaders, DWORD dwRVA)
326 {
327     int i;
328     PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(pNTHeaders + 1);
329     for (i = 0; i < pNTHeaders->FileHeader.NumberOfSections; i++)
330     {
331         if ((dwRVA >= (pSectionHeader + i)->VirtualAddress) && (dwRVA <= ((pSectionHeader + i)->VirtualAddress + (pSectionHeader + i)->SizeOfRawData)))
332         {
333             return ((PIMAGE_SECTION_HEADER)(pSectionHeader + i));
334         }
335     }
336     return PIMAGE_SECTION_HEADER(NULL);
337 }
338
339 DWORD RVAToFOA(PIMAGE_NT_HEADERS pNTHeaders, DWORD dwRVA)
340 {
341     DWORD _offset;
342     PIMAGE_SECTION_HEADER section;
343     // 找到偏移所在节
344     section = GetOwnerSection(pNTHeaders, dwRVA);
345     if (section == NULL)
346     {
347         return(0);
348     }
349     // 修正偏移
350     _offset = dwRVA + section->PointerToRawData - section->VirtualAddress;
351     return(_offset);
352 }
时间: 2024-10-05 19:55:17

Dll注入:修改PE文件 IAT注入的相关文章

深入剖析PE文件

不赖猴的笔记,转载请注明出处. 深入剖析PE文件 PE文件是Win32的原生文件格式.每一个Win32可执行文件都遵循PE文件格式.对PE文件格式的了解可以加深你对Win32系统的深入理解. 一.        基本结构. 上图便是PE文件的基本结构.(注意:DOS MZ Header和部分PE header的大小是不变的:DOS stub部分的大小是可变的.) 一个PE文件至少需要两个Section,一个是存放代码,一个存放数据.NT上的PE文件基本上有9个预定义的Section.分别是:.t

深入学习PE文件(转)

PE文件是Win32的原生文件格式.每一个Win32可执行文件都遵循PE文件格式.对PE文件格式的了解可以加深你对Win32系统的深入理解. 一. 基本结构. 上图便是PE文件的基本结构.(注意:DOS MZ Header和部分PE header的大小是不变的:DOS stub部分的大小是可变的.) 一个PE文件至少需要两个Section,一个是存放代码,一个存放数据.NT上的PE文件基本上有9个预定义的Section.分别是:.text, .bss, .rdata, .data, .rsrc,

[DLL注入的方法]静态修改PE输入表法

1.三种DLL加载时机: 进程创建加载输入表中的DLL(静态输入) 通过调用LoadLibrary主动加载(动态加载) 系统预设加载 通过干预输入表处理过程加载目标dll 1.静态修改PE输入表法(测试程序 Notepad.exe) 准备工作:自行编写一个MsgDLL,到处一个函数Msg(); #include "stdafx.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpRe

IAT 注入ImportInject(dll)

原理:PE文件中的每一个导入表都代表一个库(dll),所以你添加一个导入表时,当你调用函数时就会去加载相应的DLL而达到注入.写法一: // INTInject.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<Windows.h> #include <exception> #include <iostream> using namespace std; BOOL AddImportTable(

Discuz!7.2 faq.php文件SQL注入漏洞分析及利用实战

[antian365.com] simeon 最近网上公开了Discuz!7.2版本faq.php文件SQL注入0day,通过对文件漏洞分析以及实战测试,效果不错,公开利用exp的利用需要对SQL语句以及数据库等相当了解,在某些情况下需要多种技术配合才能最终攻克目标,下面就漏洞代码以及实战利用等进行探讨,对获取管理员密码的利用,uc_key获取webshell,插件导入获取Webshell等进行探讨. 1. faq.php文件SQL注入漏洞代码分析 本次存在漏洞的文件为faq.php,打开该文件

反反注入 修改__RESTRICT,__restrict工具

通过在 Xcode 里的 Other Linker Flags 设置参数,可以防止App被注入dylib(仅限于iOS 10 以下系统)  比如,某艺 -Wl,-sectcreate,__RESTRICT,__restrict,/dev/null 通过阅读dyld源代码,我们可以得知其大概原理 static ImageLoader* loadPhase3(const char* path, const char* orgPath, const LoadContext& context, std:

[转载]Dll注入技术之远程线程注入

转自:黑客反病毒 DLL注入技术之远线程注入 DLL注入技术指的是将一个DLL文件强行加载到EXE文件中,并成为EXE文件中的一部分,这样做的目的在于方便我们通过这个DLL读写EXE文件内存数据,(例如 HOOK EXE文件中的API),或以被注入EXE的身份去执行一些操作等等.     远线程注入原理是利用Windows 系统中CreateRemoteThread()这个API,其中第4个参数是准备运行的线程,我们可以将LoadLibrary()填入其中,这样就可以执行远程进程中的LoadLi

destoon漏洞修复关于 $do-&gt;add($post); SQL注入修改

在阿里云漏洞提示查看发现destoon有关于mobile/guestbook.php $do->add($post); SQL注入修改 漏洞名称:Destoon SQL注入 补丁文件:/mobile/guestbook.php 漏洞描述:Destoon的/mobile/guestbook.php中$do->add($post); 这行代码对参数$post未进行正确转义,导致黑客可进行SQL注入,获取网站后台密码等. 修复步骤: 打开文件 Destoon的/mobile/guestbook.ph

[转载]Dll注入技术之依赖可信进程注入

转自:黑客反病毒 DLL注入技术之依赖可信进程注入 依赖可信进程注入原理是利用Windows 系统中Services.exe这个权限较高的进程,首先将a.dll远线程注入到Services.exe中,再利用a.dll将b.dll远线程注入到待注入进程中.具体过程如下图所示: 这里提供一个小技巧,当注入到Services.exe里的DLL时,想在做完事情后悄无声息的将自己释放掉,在Windows 中有这样的一个API函数FreeLibraryAndExitThread(),它可以把自己卸载掉并且退