把前面一些程序中用到的PE相关函数集合在一个DLL中方便使用
#ifndef PE32_K_H
#define PE32_K_H
#ifdef __cplusplus
#define EXPORT extern "C" __declspec (dllexport)
#else
#define EXPORT __declspec (dllexport)
#endif
//指定
#define ADD_LAST_SECTION 1 //添加代码到最后一个区段
#define ADD_NEW_SECTION 2 //添加代码到一个新建的区段
#define ADD_PE_HEADER 3 //添加代码到PE头部
//重置,重置后可继续用文件初始化此DLL
EXPORT BOOL _stdcall Reset(TCHAR szFileName[]);
//使用函数前必须调用此函数初始化
//参数---szFileName:文件名
EXPORT BOOL _stdcall InitPE32(TCHAR szFileName[]);
//取得原文件数据指针,只读属性
EXPORT CONST PBYTE _stdcall GetFileBuffer();
//取得文件名
EXPORT CONST PTCHAR _stdcall GetFileName();
//添加代码到目标文件
//参数---szNewFile:添加代码后新文件的名字 lpCOdeStart:指向代码起始处
// dwCodeSize:添加代码的大小 dwTypeOfAdd:添加方法类型
EXPORT BOOL _stdcall AddCode(TCHAR szNewFile[], PBYTE lpCodeStart, DWORD dwCodeSize, DWORD dwTypeOfAdd);
//获得目标文件的CRC32校验值
EXPORT DWORD _stdcall GetCRC32(TCHAR szFileName[] );
//检测是否为PE文件
//参数---szFileName:文件名
EXPORT BOOL _stdcall IsPeFile(TCHAR szFileName[]);
//将RVA偏移转换成文件偏移,失败返回-1
EXPORT DWORD _stdcall RvaToOffset (IMAGE_DOS_HEADER *lpFileHead, DWORD dwRva);
//将RVA偏移转成文件指针偏移,失败返回NULL
EXPORT PBYTE _stdcall RvaToPointer(IMAGE_DOS_HEADER *lpFileHead,DWORD dwRva);
//将虚拟地址转成文件指针偏移,失败返回NULL
EXPORT PBYTE _stdcall VirtualAddressToPointer(IMAGE_DOS_HEADER *lpFileHead,DWORD dwVirtualAddress);
//获得RVA偏移处的节区名称,失败返回NULL
EXPORT CONST PBYTE _stdcall GetRvaSection (IMAGE_DOS_HEADER *lpFileHead, DWORD dwRva);
//获得指定RVA所处节区的节表头,失败返回NULL
EXPORT PIMAGE_SECTION_HEADER _stdcall GetSectionOfRva (IMAGE_DOS_HEADER *lpFileHead, char* secName);
//文件偏移转换成RVA,失败返回-1
EXPORT DWORD _stdcall OffsetToRVA(IMAGE_DOS_HEADER *lpFileHead, DWORD dwOffset);
//文件偏移转换成内存指针,失败返回NULL
EXPORT PBYTE _stdcall OffsetToPointer(IMAGE_DOS_HEADER *lpFileHead, DWORD dwOffset);
//提取图标数据,参数指定文件名
EXPORT BOOL _stdcall GetIcon (TCHAR szIconFileName[]);
#endif
#include <windows.h>
#include "PE32_K.H"
TCHAR g_szFileName[MAX_PATH] = { 0 };
HINSTANCE g_hInstDll = NULL; //DLL模块句柄
PBYTE g_lpBuffer = NULL; //存储文件数据
DWORD g_dwFileSize= 0; //文件数据大小
PBYTE g_lpNewFile = NULL; //存储添加代码后的数据
BOOL PE = FALSE; //指示是否是PE文件
void _stdcall DllClean();
///
BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, PVOID fImpLoad) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
// DLL is attaching to the address space of the current process.
g_hInstDll = hInstDll;
break;
case DLL_THREAD_ATTACH:
// A new thread is being created in the current process.
break;
case DLL_THREAD_DETACH:
// A thread is exiting cleanly.
break;
case DLL_PROCESS_DETACH:
// The calling process is detaching the DLL from its address space.
DllClean();
break;
}
return(TRUE);
}
///
///将RVA偏移转换成文件偏移,失败返回-1
DWORD _stdcall RvaToOffset (IMAGE_DOS_HEADER *lpFileHead, DWORD dwRva)
{
::IMAGE_NT_HEADERS *lpPEHead;
::IMAGE_SECTION_HEADER *lpSectionHead;
DWORD i;
lpPEHead = (IMAGE_NT_HEADERS*)( (BYTE*)lpFileHead + lpFileHead->e_lfanew);
i = lpPEHead->FileHeader.NumberOfSections;
lpSectionHead = (IMAGE_SECTION_HEADER*)(++lpPEHead);
for ( ; i > 0 ; i--, lpSectionHead++)
{
if ( (dwRva >= lpSectionHead->VirtualAddress) && (dwRva < (lpSectionHead->VirtualAddress + lpSectionHead->SizeOfRawData) ) )
{
dwRva = dwRva - lpSectionHead->VirtualAddress + lpSectionHead->PointerToRawData;
return dwRva;
}
}
return -1;
}
将RVA偏移转成文件指针偏移,失败返回NULL
PBYTE _stdcall RvaToPointer(IMAGE_DOS_HEADER *lpFileHead,DWORD dwRva)
{
DWORD Offset = RvaToOffset(lpFileHead, dwRva);
if(Offset == -1)
return NULL;
return (PBYTE)(lpFileHead) + Offset;
}
将虚拟地址转成文件指针偏移,失败返回NULL
PBYTE _stdcall VirtualAddressToPointer(IMAGE_DOS_HEADER *lpFileHead,DWORD dwVirtualAddress)
{
::IMAGE_NT_HEADERS *lpPEHead;
lpPEHead = (IMAGE_NT_HEADERS*)( (BYTE*)lpFileHead + lpFileHead->e_lfanew);
return (PBYTE)RvaToPointer(lpFileHead, dwVirtualAddress - lpPEHead->OptionalHeader.ImageBase);
}
获得RVA偏移处的节区名称
CONST PBYTE _stdcall GetRvaSection (IMAGE_DOS_HEADER *lpFileHead, DWORD dwRva)
{
IMAGE_NT_HEADERS *lpPEHead;
IMAGE_SECTION_HEADER *lpSectionHead;
DWORD i;
lpPEHead = (IMAGE_NT_HEADERS*)( (BYTE*)lpFileHead + lpFileHead->e_lfanew);
i = lpPEHead->FileHeader.NumberOfSections;
lpSectionHead = (IMAGE_SECTION_HEADER*)(++lpPEHead);
for ( ; i > 0 ; i--, lpSectionHead++)
{
if ( (dwRva >= lpSectionHead->VirtualAddress) && (dwRva < (lpSectionHead->VirtualAddress + lpSectionHead->SizeOfRawData) ) )
{
return (PBYTE)lpSectionHead;
}
}
return NULL;
}
///获得指定RVA所处节区的节表头,失败返回NULL/
PIMAGE_SECTION_HEADER _stdcall GetSectionOfRva (IMAGE_DOS_HEADER *lpFileHead, char* secName)
{
::PIMAGE_NT_HEADERS lpNtHead = (PIMAGE_NT_HEADERS)( (BYTE*)lpFileHead + lpFileHead->e_lfanew);
DWORD dwSec = lpNtHead->FileHeader.NumberOfSections;
IMAGE_SECTION_HEADER* lpSection = (PIMAGE_SECTION_HEADER) (lpNtHead + 1);
for (DWORD i=0; i < dwSec; i++)
{
if(!strncmp((char*)lpSection->Name, secName, IMAGE_SIZEOF_SHORT_NAME) )
return lpSection;
lpSection++;
}
return NULL;
}
文件偏移转换成RVA///
DWORD _stdcall OffsetToRVA(IMAGE_DOS_HEADER *lpFileHead, DWORD dwOffset)
{
::IMAGE_NT_HEADERS *lpPEHead;
::IMAGE_SECTION_HEADER *lpSectionHead;
DWORD i;
lpPEHead = (IMAGE_NT_HEADERS*)( (BYTE*)lpFileHead + lpFileHead->e_lfanew);
i = lpPEHead->FileHeader.NumberOfSections;
lpSectionHead = (IMAGE_SECTION_HEADER*)(++lpPEHead);
for ( ; i > 0; i--, lpSectionHead++)
{
if ( (dwOffset >= lpSectionHead->PointerToRawData) && (dwOffset < (lpSectionHead->PointerToRawData + lpSectionHead->SizeOfRawData) ) )
{
dwOffset = dwOffset - lpSectionHead->PointerToRawData + lpSectionHead->VirtualAddress;
return dwOffset;
}
}
return -1;
}
文件偏移转换成内存指针///
PBYTE _stdcall OffsetToPointer(IMAGE_DOS_HEADER *lpFileHead, DWORD dwOff