博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
注入(5)---导入表注入(HookINT)
阅读量:6247 次
发布时间:2019-06-22

本文共 11841 字,大约阅读时间需要 39 分钟。

导入表是WindowsPE文件中的一组数据结构,可执行程序(即EXE文件)被加载到地址空间后,每个导入的DLL模块都有一个对应的导入表,PE加载器会根据导入表来加载进程需要的其他DLL模块。

导入表的数据结构如下:

typedef struct _IMAGE_IMPORT_DESCRIPTOR {    union {        DWORD   Characteristics;            // 0 for terminating null import descriptor        DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)    } DUMMYUNIONNAME;    DWORD   TimeDateStamp;                  // 0 if not bound,                                            // -1 if bound, and real date\time stamp                                            //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)                                            // O.W. date/time stamp of DLL bound to (Old BIND)    DWORD   ForwarderChain;                 // -1 if no forwarders    DWORD   Name;    DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)} IMAGE_IMPORT_DESCRIPTOR;

OriginalFirstThunk/Characteristics:指向导入表(INT)的RVA(相对虚拟地址)。INT是一个IMAGE_THUNK_DATA结构的数组,数组中的每个元素指向一个IMAGE_IMPORT_BY_NAME结构,INT以元素0结束。
TimeDateStamp:时间戳,可以忽略。
ForwarderChain:如果没有前向引用(forwarders)的话就是-1.
Name:被导入DLL的名字指针,是一个RVA。
FirstThunk:指向导入表(IAT)的RVA。IAT是一个IMAGE_THUNK_DATA结构的数组。

导入表逻辑结构如下:

下面贴出源码:

// INTHook.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include
#include
#include
using namespace std;BOOL AddImportTable(const WCHAR * wzPEFilePath, char * szInjectDllName, char *szFunctionName);BOOL AddNewImportDescriptor(const WCHAR * wzPEFilePath, char * szInjectDllName, char *szImportFunctionName);BOOL AddNewSection(LPCTSTR lpModulePath, DWORD dwNewSectionSize);DWORD PEAlign(DWORD dwTarNumber, DWORD dwAlignTo);DWORD RVAToOffset(PIMAGE_NT_HEADERS pImageNTHeader, DWORD dwRVA);PIMAGE_SECTION_HEADER ImageRVAToSection(PIMAGE_NT_HEADERS pImageNTHeader, DWORD dwRVA);int main(){ WCHAR TargetPath[0x20] = {0}; char DllPath[0x20] = "InjectDll.dll"; printf("Please Input Target Full Path:\r\n"); //scanf_s(TargetPath, "%s"); wcin >> TargetPath; AddImportTable(TargetPath,DllPath, "InjectFunction"); return 0;}BOOL AddImportTable(const WCHAR * wzPEFilePath, char * szInjectDllName, char *szFunctionName){ BOOL bOk = FALSE; try { //增加一个叫"WINSUN"的节 bOk = AddNewSection(wzPEFilePath, 256); if (!bOk) { MessageBox(NULL, L"Add New Section Fail", L"Error", MB_OK); return bOk; } //增加一个导入表 AddNewImportDescriptor(wzPEFilePath, szInjectDllName, szFunctionName); } catch (exception* e) { return bOk; } return bOk;}////增加导入表项//BOOL AddNewSection(LPCTSTR lpModulePath, DWORD dwNewSectionSize){ BOOL bOk = FALSE; LPVOID lpMemoryModule = NULL; LPBYTE lpData = NULL; DWORD dwNewSectionFileSize, dwNewSectionMemorySize; HANDLE FileHandle = INVALID_HANDLE_VALUE, MappingHandle = INVALID_HANDLE_VALUE; PIMAGE_NT_HEADERS NtHeader = NULL; PIMAGE_SECTION_HEADER NewSection = NULL, LastSection = NULL; printf("[!] AddNewSection Enter!\n"); //TODO:可能还涉及关闭windows文件保护 __try { //pe文件映射到内存 FileHandle = CreateFile( lpModulePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (INVALID_HANDLE_VALUE == FileHandle) { printf("[-] AddNewSection CreateFile Fail!\n"); goto _EXIT_; } DWORD dwFileLength = GetFileSize(FileHandle, NULL); //映射PE文件 MappingHandle = CreateFileMapping(FileHandle, NULL, PAGE_READWRITE/* | SEC_IMAGE*/, 0, dwFileLength,L"WINSUN_MAPPING_FILE"); if (NULL == MappingHandle) { printf("[-] AddNewSection CreateFileMapping Fail!\n"); goto _EXIT_; } lpMemoryModule = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, dwFileLength); if (NULL == lpMemoryModule) { printf("[-] AddNewSection MapViewOfFile Fail!\n"); goto _EXIT_; } lpData = (LPBYTE)lpMemoryModule; //判断是否是PE文件 if (((PIMAGE_DOS_HEADER)lpData)->e_magic != IMAGE_DOS_SIGNATURE) { printf("[-] AddNewSection PE Header MZ error!\n"); goto _EXIT_; } NtHeader = (PIMAGE_NT_HEADERS)(lpData + ((PIMAGE_DOS_HEADER)(lpData))->e_lfanew); if (NtHeader->Signature != IMAGE_NT_SIGNATURE) { printf("[-] AddNewSection PE Header PE Error!\n"); goto _EXIT_; } //判断是否可以增加一个新节 if (((NtHeader->FileHeader.NumberOfSections + 1) * sizeof(IMAGE_SECTION_HEADER)) > (NtHeader->OptionalHeader.SizeOfHeaders)) { printf("[-] AddNewSection Cannot Add A New Section!\n"); goto _EXIT_; } NewSection = (PIMAGE_SECTION_HEADER)(NtHeader + 1) + NtHeader->FileHeader.NumberOfSections; LastSection = NewSection - 1; DWORD rSize, vSize, rOffset, vOffset; //对齐偏移和RVA rSize = PEAlign(dwNewSectionSize, NtHeader->OptionalHeader.FileAlignment); rOffset = PEAlign(LastSection->PointerToRawData + LastSection->SizeOfRawData, NtHeader->OptionalHeader.FileAlignment); vSize = PEAlign(dwNewSectionSize, NtHeader->OptionalHeader.SectionAlignment); vOffset = PEAlign(LastSection->VirtualAddress + LastSection->Misc.VirtualSize, NtHeader->OptionalHeader.SectionAlignment); //填充新节表 memcpy(NewSection->Name, "WINSUN", strlen("WINSUN")); NewSection->VirtualAddress = vOffset; NewSection->PointerToRawData = rOffset; NewSection->Misc.VirtualSize = vSize; NewSection->SizeOfRawData = rSize; NewSection->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; //修改IMAGE_NT_HEADERS,增加新节表 NtHeader->FileHeader.NumberOfSections++; NtHeader->OptionalHeader.SizeOfImage += vSize; NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0; //增加新节到文件尾部 DWORD dwWriteBytes; SetFilePointer(FileHandle, 0, 0, FILE_END); PBYTE pbNewSectionContent = new BYTE[rSize]; ZeroMemory(pbNewSectionContent, rSize); bOk = WriteFile(FileHandle, pbNewSectionContent, rSize, &dwWriteBytes, NULL); if (!bOk) { MessageBox(NULL, L"新增节失败", L"Error", MB_OK); goto _EXIT_; } } __except (EXCEPTION_EXECUTE_HANDLER) { printf("[-] AddImportTableItem Exception!\n"); return false; } printf("[!] AddNewSection Exit!\n"); bOk = true;_EXIT_: if (FileHandle) { CloseHandle(FileHandle); } if (lpMemoryModule) { UnmapViewOfFile(lpMemoryModule); } if (MappingHandle) { CloseHandle(MappingHandle); } return true;}//内存对齐DWORD PEAlign(DWORD dwTarNumber, DWORD dwAlignTo){ return(((dwTarNumber + dwAlignTo - 1) / dwAlignTo)*dwAlignTo);}//增加一个导入表BOOL AddNewImportDescriptor(const WCHAR * wzPEFilePath, char * szInjectDllName, char *szImportFunctionName){ BOOL bOk = FALSE; LPVOID lpMemoryModule = NULL; LPBYTE lpData = NULL; DWORD dwNewSecFileSize, dwNewSecMemSize; HANDLE FileHandle = INVALID_HANDLE_VALUE, MappingHandle = INVALID_HANDLE_VALUE; PIMAGE_NT_HEADERS NtHeader = NULL; PIMAGE_IMPORT_DESCRIPTOR ImportTable = NULL; PIMAGE_SECTION_HEADER SectionHeader = NULL; __try { //pe文件映射到内存 FileHandle = CreateFile( wzPEFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (INVALID_HANDLE_VALUE == FileHandle) { printf("[-] AddNewImportDescriptor CreateFile fail!\n"); goto _EXIT_; } DWORD dwFileLength = GetFileSize(FileHandle, NULL); MappingHandle = CreateFileMapping(FileHandle, NULL, PAGE_READWRITE/* | SEC_IMAGE*/, 0, dwFileLength,L"WINSUN_MAPPING_FILE"); if (NULL == MappingHandle) { printf("[-] AddNewImportDescriptor CreateFileMapping fail!\n"); goto _EXIT_; } lpMemoryModule = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, dwFileLength); if (NULL == lpMemoryModule) { printf("[-] AddNewImportDescriptor MapViewOfFile fail!\n"); goto _EXIT_; } lpData = (LPBYTE)lpMemoryModule; //判断是否是PE if (((PIMAGE_DOS_HEADER)lpData)->e_magic != IMAGE_DOS_SIGNATURE) { printf("[-] AddNewImportDescriptor PE Header MZ error!\n"); goto _EXIT_; } NtHeader = (PIMAGE_NT_HEADERS)(lpData + ((PIMAGE_DOS_HEADER)(lpData))->e_lfanew); if (NtHeader->Signature != IMAGE_NT_SIGNATURE) { printf("[-] AddNewImportDescriptor PE Header PE error!\n"); goto _EXIT_; } ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)(lpData + RVAToOffset(NtHeader, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); BOOL bBoundImport = FALSE; if (ImportTable->Characteristics == 0 && ImportTable->FirstThunk != 0) { bBoundImport = TRUE; NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0; } SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1) + NtHeader->FileHeader.NumberOfSections - 1; PBYTE pbNewSection = SectionHeader->PointerToRawData + lpData; int i = 0; while (ImportTable->FirstThunk != 0) { memcpy(pbNewSection, ImportTable, sizeof(IMAGE_IMPORT_DESCRIPTOR)); ImportTable++; pbNewSection += sizeof(IMAGE_IMPORT_DESCRIPTOR); i++; } memcpy(pbNewSection, (pbNewSection - sizeof(IMAGE_IMPORT_DESCRIPTOR)), sizeof(IMAGE_IMPORT_DESCRIPTOR)); DWORD dwDelt = SectionHeader->VirtualAddress - SectionHeader->PointerToRawData; //avoid import not need table PIMAGE_THUNK_DATA pImgThunkData = (PIMAGE_THUNK_DATA)(pbNewSection + sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2); //import dll name PBYTE pszDllNamePosition = (PBYTE)(pImgThunkData + 2); memcpy(pszDllNamePosition, szInjectDllName, strlen(szInjectDllName)); pszDllNamePosition[strlen(szInjectDllName)] = 0; //确定IMAGE_IMPORT_BY_NAM的位置 PIMAGE_IMPORT_BY_NAME pImgImportByName = (PIMAGE_IMPORT_BY_NAME)(pszDllNamePosition + strlen(szInjectDllName) + 1); //init IMAGE_THUNK_DATA pImgThunkData->u1.Ordinal = dwDelt + (DWORD)pImgImportByName - (DWORD)lpData; //init IMAGE_IMPORT_BY_NAME pImgImportByName->Hint = 1; memcpy(pImgImportByName->Name, szImportFunctionName, strlen(szImportFunctionName)); //== dwDelt + (DWORD)pszFuncNamePosition - (DWORD)lpData ; pImgImportByName->Name[strlen(szImportFunctionName)] = 0; //init OriginalFirstThunk if (bBoundImport) { ((PIMAGE_IMPORT_DESCRIPTOR)pbNewSection)->OriginalFirstThunk = 0; } else ((PIMAGE_IMPORT_DESCRIPTOR)pbNewSection)->OriginalFirstThunk = dwDelt + (DWORD)pImgThunkData - (DWORD)lpData; //init FirstThunk ((PIMAGE_IMPORT_DESCRIPTOR)pbNewSection)->FirstThunk = dwDelt + (DWORD)pImgThunkData - (DWORD)lpData; //init Name ((PIMAGE_IMPORT_DESCRIPTOR)pbNewSection)->Name = dwDelt + (DWORD)pszDllNamePosition - (DWORD)lpData; //改变导入表 NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = SectionHeader->VirtualAddress; NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (i + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR); } __except (EXCEPTION_EXECUTE_HANDLER) { printf("[-] AddNewImportDescriptor Exception!\n"); return false; }_EXIT_: if (FileHandle) { CloseHandle(FileHandle); } if (lpMemoryModule) { UnmapViewOfFile(lpMemoryModule); } if (MappingHandle) { CloseHandle(MappingHandle); } return true;}//// calulates the Offset from a RVA// Base - base of the MMF// dwRVA - the RVA to calculate// returns 0 if an error occurred else the calculated Offset will be returnedDWORD RVAToOffset(PIMAGE_NT_HEADERS pImageNTHeader, DWORD dwRVA){ DWORD _offset; PIMAGE_SECTION_HEADER section; section = ImageRVAToSection(pImageNTHeader, dwRVA);//ImageRvaToSection(pimage_nt_headers,Base,dwRVA); if (section == NULL) { return(0); } _offset = dwRVA + section->PointerToRawData - section->VirtualAddress; return(_offset);}PIMAGE_SECTION_HEADER ImageRVAToSection(PIMAGE_NT_HEADERS pImageNTHeader, DWORD dwRVA){ int i; PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(pImageNTHeader + 1); for (i = 0; i
FileHeader.NumberOfSections; i++) { if ((dwRVA >= (pSectionHeader + i)->VirtualAddress) && (dwRVA <= ((pSectionHeader + i)->VirtualAddress + (pSectionHeader + i)->SizeOfRawData))) { return ((PIMAGE_SECTION_HEADER)(pSectionHeader + i)); } } return(NULL);}

 

转载于:https://www.cnblogs.com/Toring/p/6628280.html

你可能感兴趣的文章
MySql相关及如何删除MySql服务
查看>>
jdk future
查看>>
我的友情链接
查看>>
Jenkins插件安装及配置
查看>>
我的友情链接
查看>>
SVN提交工作时需要注意的事项
查看>>
配置ospf虚拟链路
查看>>
python学习初步
查看>>
18年,年中自省
查看>>
常用开源软件maven坐标
查看>>
Linux——解决apache"300 Multiple Choices"
查看>>
Macbook Pro Retina实现OSX10.10 Yosemite 和Win7双系统(Win7多分区)
查看>>
qt 学习之路2
查看>>
IOS学习之 导航栏
查看>>
SNMP网络监控
查看>>
我的友情链接
查看>>
模糊查询like的写法问题
查看>>
我的友情链接
查看>>
yum安装lamp分离教程
查看>>
Java基础学习总结(22)——异常处理
查看>>