https://bpsend.net/thread-316-1-1.html
LoadPE - pe 加載器 殼的前身
如果想訪問一個程序運行起來的內存,一種方法就是跨進程讀寫內存,但是跨進程讀寫內存需要來回調用api,不如直接訪問地址來得方便,那么如果我們需要直接訪問地址,該怎么做呢?.需要把dll注進程,注進去的代碼跟他在同一塊進程里面,這樣我們就可以直接訪問這個進程的地址,但是不想注入,也不想跨進程讀寫地址,就直接讀進程地址,有什么方法呢?如果把導入表里面加一個dll,這樣很容易檢查出來,模塊里一遍歷,就可容易看到了,?其實我們可以反其道行之,換種思路,不是往他進程里面塞東西,而是把他加載到我們進程里面.,這個時候再去訪問進程內存其實就是訪問我們自己的內存.
1.系統加載exe的流程
- 準備一個新的內存;
- 按照順序把節表內容映射進內存;
- 填寫導入表。
2.LoadPE的目的
- 可以在自己進程更改目標PE的內存。
3.LoadPE的重點
- 1.在自己代碼前留出足夠空間--目標進程的SizeofImage;
- 2.更改自己程序的ImageBase加載到目標ImageBase處:/base:0x。
這樣,目標進程的PE頭就占據了我們自己進程的 PE頭,他的數據節就覆蓋了我們自己的數據節,即目標進程的數據就會覆蓋我們自己進程的數據,因此我們需要 把我們的代碼往后移,給 目標進程 留出足夠的空間
4.LoadPE的實現思路
- 設置我們進程的 ImageBase 和 目標進程 ImageBase 保持一致
- 我們需要把我們的代碼往后移,騰出來的內存可以放目標程序
- 讀目標進程的數據,按照節表拷貝數據幫他處理導入表
- 執行目標進程代碼。
5.LoadPE的匯編實現
- 用winhex查看目標進程的 ImageBase 和 SizeofImage
- 新建工程,并且在工程選項設置 自己工程 的 ImageBase 與目標進程的一致
- 后移自己的代碼,可以在開頭定義 SizeofImage 大小的全局變量 或者通過指令 org 偏移調整指令
注意,很多 C 庫函數 并不會 保存 ecx , edx 環境,自己使用前記得先保存
進程的模塊基址和 數據大小可以通過 winhex看
.586 .model?flat,stdcall option?casemap:noneinclude?windows.incinclude?user32.incinclude?kernel32.incinclude?msvcrt.incincludelib?user32.libincludelib?kernel32.libincludelib?msvcrt.libIMAGE_SIZE?equ?20000h?????;往后移的大小,即目標進程的SizeofImage.datag_szFile?db?"winmine.exe",?0????;要讀取的進程.codeorg?IMAGE_SIZE?LoadPe?procLOCAL?@dwImageBase:DWORD???????;自己進程的模塊基址LOCAL?@hFile:HANDLE????????????;文件句柄LOCAL?@hFileMap:HANDLE?????????;映射句柄LOCAL?@pPEBuf:LPVOID???????????;映射文件的緩沖地址LOCAL?@pDosHdr:ptr?IMAGE_DOS_HEADER??????;目標進程的dos頭LOCAL?@pNTHdr:ptr?IMAGE_NT_HEADERS???????;目標進程的NT頭LOCAL?@pSecHdr:ptr?IMAGE_SECTION_HEADER??;目標進程的節表LOCAL?@dwNumOfSecs:DWORD?????????????????;目標進程的節表數量LOCAL?@pImpHdr:ptr?IMAGE_IMPORT_DESCRIPTOR???;目標進程的導入表LOCAL?@dwSizeOfHeaders:DWORD?????????????????;目標進程的選項頭大小LOCAL?@dwOldProc:DWORD???????????????????????;舊的內存屬性LOCAL?@hdrZeroImp:IMAGE_IMPORT_DESCRIPTOR????;導入表結束標志,所有項全0LOCAL?@hDll:HMODULE??????????????????????????;加載dll的句柄LOCAL?@dwOep:DWORD???????????????????????????;進程的入口地址;判斷導入表結束的標志清0invoke?RtlZeroMemory,?addr?@hdrZeroImp,?size?IMAGE_IMPORT_DESCRIPTOR;自己的模塊基址invoke?GetModuleHandle,?NULLmov?@dwImageBase,?eax;解析PE文件,獲取表;打開文件invoke?CreateFile,?offset?g_szFile,?GENERIC_READ,?FILE_SHARE_READ,NULL,?OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,?NULL;check?....mov?@hFile,?eax???;保存文件句柄invoke?CreateFileMapping,?@hFile,?NULL,?PAGE_READONLY,?0,?0,?NULL???;創建文件映射;checkmov?@hFileMap,?eax????;創建文件映射句柄invoke?MapViewOfFile,?@hFileMap,?FILE_MAP_READ,?0,?0,?0??????;將整個文件映射進內存;check?mov?@pPEBuf,?eax??????;保存映射文件內存的地址;解析目標進程;目標進程的?dos?頭mov?eax,?@pPEBuf????mov?@pDosHdr,?eax;目標進程的?nt頭mov?esi,?@pDosHdrassume?esi:ptr?IMAGE_DOS_HEADERmov?eax,?@pPEBufadd?eax,?[esi].e_lfanew???;獲取nt頭的偏移地址mov?@pNTHdr,?eaxmov?esi,?@pNTHdrassume?esi:ptr?IMAGE_NT_HEADERS;選項頭信息mov?eax,?[esi].OptionalHeader.SizeOfHeaders????;獲取選項頭大小mov?@dwSizeOfHeaders,?eax;進程的入口地址??=??進程的內存偏移地址?+?模塊基址mov?eax,?[esi].OptionalHeader.AddressOfEntryPointadd?eax,?@dwImageBasemov?@dwOep,?eax;節表??地址:?選項頭地址+大小movzx?eax,?[esi].FileHeader.NumberOfSectionsmov?@dwNumOfSecs,eaxlea?ebx,?[esi].OptionalHeader;獲取選項頭大小:用于定位節表位置=選項頭地址+選項頭大小movzx?eax,?[esi].FileHeader.SizeOfOptionalHeader???;把?word?轉為?dwordadd?eax,?ebxmov?@pSecHdr,?eax???;保存節表地址;修改內存屬性invoke?VirtualProtect,?@dwImageBase,?IMAGE_SIZE,?PAGE_EXECUTE_READWRITE,?addr?@dwOldProc;拷貝PE頭??從映射內存拷貝到?自己進程的最開始處?invoke?crt_memcpy,?@dwImageBase,?@pPEBuf,?@dwSizeOfHeaders;按照節表,拷貝節區數據mov?esi,?@pSecHdrassume?esi:ptr?IMAGE_SECTION_HEADERxor?ecx,?ecx.while?ecx?<?@dwNumOfSecs???;遍歷節表;目標mov?edi,?@dwImageBaseadd?edi,?[esi].VirtualAddress??;獲取節的內存地址?+?模塊地址?就是內存中的絕對地址;源mov?ebx,?@pPEBufadd?ebx,?[esi].PointerToRawData??;獲取指定進程的節數據的偏移地址??映射的首地址?+?文件偏移地址;大小[esi].SizeOfRawData;拷貝??注意,很多?C?庫函數?并不會?保存?ecx?,edx?環境,自己使用前記得先保存push?ecxpush?edxinvoke?crt_memcpy,?edi,?ebx,?[esi].SizeOfRawData???;將目標進程的節數據拷貝進自己的進程pop?edxpop?ecxinc?ecx??????;計數++add?esi,?size?IMAGE_SECTION_HEADER??;指針移動.endw;獲取導入表??如果在前面獲取導入表信息,那么就需要對內存地址和文件地址做轉化比較麻煩;但是把數據拷貝到我們進程之后只需要訪問內存進程就可以了mov?esi,?@pNTHdrassume?esi:ptr?IMAGE_NT_HEADERS;獲取導入表地址?,數組的第二個元素的第一個成員?mov?eax,?[esi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT*8].VirtualAddressadd?eax,?@dwImageBase???;獲取導入表在進程的絕對地址??內存偏移?+?模塊基址mov?@pImpHdr,?eax???????;保存導入表的地址;處理導入表mov?esi,?@pImpHdrassume?esi:ptr?IMAGE_IMPORT_DESCRIPTOR.while?TRUE?????;遍歷導入表;判斷結束,全0項結束invoke?crt_memcmp,?esi,?addr?@hdrZeroImp.if?eax?==?0.break.endif;判斷字段,為空則結束.if?[esi].Name1?==?NULL?||?[esi].FirstThunk?==?NULL.break.endif?;加載dllmov?eax,?[esi].Name1add?eax,?@dwImageBasepush?ecxpush?edxinvoke?LoadLibrary,?eax???;根據dll名加載?dll?pop?edxpop?ecx;check??????????????如果此時為空加說明無法找到dllmov?@hDll,?eax??????;保存dll的模句柄;獲取導入地址表,IATmov?ebx,?[esi].FirstThunkadd?ebx,?@dwImageBase;獲取導入名稱表,INTmov?edi,?ebx.if?[esi].OriginalFirstThunk?!=?NULLmov?edi,?[esi].OriginalFirstThunkadd?edi,?@dwImageBase??????????.endif;遍歷導入名稱表.while?dword?ptr?[edi]?!=?0.if?dword?ptr?[edi]?&?80000000h???;判斷最高位是否為1;序號導入,獲取序號mov?edx,?dword?ptr?[edi]and?edx,?0ffffh???????????????;獲取低?word?.else;名稱導入mov?edx,?dword?ptr?[edi]add?edx,?@dwImageBaseadd?edx,?2??????????????????;名稱前面有2個無用字節.endif;獲取dll導入函數進程加載后地址push?ecxpush?edxinvoke?GetProcAddress,?@hDll,?edxpop?edxpop?ecx;check;把地址存入?INT?表mov?dword?ptr?[ebx],?eaxadd?ebx,?4add?edi,?4.endwadd?esi,?size?IMAGE_IMPORT_DESCRIPTOR.endw;清理invoke?UnmapViewOfFile,@pPEBufinvoke?CloseHandle,@hFileMapinvoke?CloseHandle,@hFile;?執行加載的pe的代碼jmp?@dwOepretLoadPe?endpstart:invoke?LoadPeinvoke?ExitProcess,0end?start
需要合并節
.text,ERW
C++版:
#include?<windows.h> #include?<concrt.h> #include?<iostream> using?namespace?std;#define?IMAGE_SIZE?0x5000//留空的全局變量 char?szBuff[IMAGE_SIZE]?=?{?1?};#if?1 char?g_szExeName[]?=?"PE.exe";??//需要加載的PE路徑LPVOID?lpMapAddr?=?NULL;HANDLE?LoadPe() {DWORD??dwOldProc?=?0;PIMAGE_IMPORT_DESCRIPTOR?pImpHdr?=?NULL;IMAGE_IMPORT_DESCRIPTOR??zeroImp?=?{?0?};HANDLE?hDll?=?NULL;PIMAGE_THUNK_DATA?pTmpThunk?=?NULL;DWORD??dwPFNAddr?=?0;DWORD??dwIAT?=?0;//?獲取模塊句柄HANDLE?hInst?=?GetModuleHandle(NULL);//?讀取文件HANDLE?hFile?=?CreateFile(g_szExeName,?GENERIC_READ,?FILE_SHARE_READ,?NULL,?OPEN_EXISTING,?FILE_ATTRIBUTE_NORMAL,?NULL);if?(hFile?==?INVALID_HANDLE_VALUE){return?0;}//?創建文件映射對象HANDLE?hFileMap?=?CreateFileMapping(hFile,?NULL,?PAGE_READONLY,?0,?0,?NULL);if?(hFileMap?==?NULL){CloseHandle(hFile);return?0;}void*?lpMapAddr?=?MapViewOfFile(hFileMap,?FILE_MAP_READ,?0,?0,?0);if?(lpMapAddr?==?NULL){CloseHandle(hFileMap);CloseHandle(hFile);return?0;}//?拷貝PE頭PIMAGE_DOS_HEADER?pDosHeader?=?(PIMAGE_DOS_HEADER)lpMapAddr;PIMAGE_NT_HEADERS?pNtHeader?=?(PIMAGE_NT_HEADERS)((DWORD)lpMapAddr?+?pDosHeader->e_lfanew);DWORD?dwSizeOfHeaders?=?pNtHeader->OptionalHeader.SizeOfHeaders;DWORD?dwNumOfSection?=?pNtHeader->FileHeader.NumberOfSections;//獲取節表首地址??(選項頭地址+?大小)PIMAGE_SECTION_HEADER?pSecHdr?=?(PIMAGE_SECTION_HEADER)((DWORD)pNtHeader->FileHeader.SizeOfOptionalHeader?+?(DWORD)(&pNtHeader->OptionalHeader));DWORD?dwOep?=?(DWORD)hInst?+?pNtHeader->OptionalHeader.AddressOfEntryPoint;//?更改內存屬性VirtualProtect(hInst,?IMAGE_SIZE,?PAGE_EXECUTE_READWRITE,?&dwOldProc);//拷貝PE頭memcpy(hInst,?lpMapAddr,?dwSizeOfHeaders);//?拷貝拷貝節區數據DWORD?i?=?0;while?(dwNumOfSection?>?i){//拷貝數據DWORD?pDst?=?(DWORD)hInst?+?(DWORD)pSecHdr->VirtualAddress;DWORD?pSrc?=?(DWORD)lpMapAddr?+?(DWORD)pSecHdr->PointerToRawData;//DWORD?pSrc?=?(DWORD)pSecHdr;memcpy((void*)pDst,?(void*)pSrc,?pSecHdr->SizeOfRawData);int?nSecHdrSzie?=?sizeof(IMAGE_SECTION_HEADER);pSecHdr?=?(PIMAGE_SECTION_HEADER)((DWORD)pSecHdr?+?(DWORD)nSecHdrSzie);i++;}//獲取導入表地址pImpHdr?=?(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pNtHeader->OptionalHeader.DataDirectory[1].VirtualAddress?+?(DWORD)hInst);//?處理導入表while?(TRUE){//?遇到全0項,遍歷結束?int?nRet?=?memcmp(pImpHdr,?&zeroImp,?sizeof(IMAGE_IMPORT_DESCRIPTOR));if?(nRet?==?0){break;}//判斷字段,?為空則結束if?(pImpHdr->Name?==?NULL?||?pImpHdr->FirstThunk?==?NULL){break;}DWORD?pNameAddre?=?(DWORD)pImpHdr->Name?+?(DWORD)hInst;//?加載dllHMODULE?hDll?=?LoadLibrary((LPCSTR)pNameAddre);if?(hDll?==?NULL){break;}DWORD?pFunAddr?=?0;DWORD?pIAT?=?(DWORD)pImpHdr->FirstThunk?+?(DWORD)hInst;DWORD?pINT?=?(DWORD)pImpHdr->OriginalFirstThunk;if?(pINT?!=?0){pFunAddr?=?pINT?+?(DWORD)hInst;}else{pFunAddr?=?pIAT;}//?遍歷導入名稱表while?(true){DWORD?pAddr?=?*(DWORD*)pFunAddr;if?(pAddr?==?0){break;}DWORD??pFun?=?0;if?(pAddr?&?0x80000000){//序號導入,?獲取序號pFun?=?pAddr?&?0xffff;}else{pFun?=?pAddr?+?2?+?(DWORD)hInst;}DWORD??dwPFNAddr?=?(DWORD)GetProcAddress(hDll,?(LPCSTR)LOWORD(pFun));*(DWORD*)pIAT?=?dwPFNAddr;pIAT?+=?4;pFunAddr+=4;}pImpHdr?=?(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImpHdr?+?(DWORD)sizeof(IMAGE_IMPORT_DESCRIPTOR));}//?關閉句柄UnmapViewOfFile(lpMapAddr);CloseHandle(hFileMap);CloseHandle(hFile);//?返回地址return?&dwOep; }#endif?//?0int?main() {#if?1//?加載PE文件,返回原OEPvoid*?pOep?=?LoadPe();if?(pOep?!=?NULL){__asm?jmp?pOep}#endif?//?0return?0; }
#include?<iostream> #include?<Windows.h> #include?<stdio.h>using?namespace?std;#define?FILESIZE??0x00020000?????????//目標進程的SizeofImage #define?IMAGEBASE?0x01000000char?szExeDataBuff[FILESIZE]?=?{1}; char?g_szExeName[]?=?"winmine.exe";???//要加載的進程路徑DWORD?g_oep?=?0;void?LoadPe() {//?創建文件映射//打開文件HANDLE?hFile?=?CreateFile(g_szExeName,?GENERIC_READ,?FILE_SHARE_READ,?NULL,?OPEN_EXISTING,?FILE_ATTRIBUTE_NORMAL,?NULL);if?(hFile?==?INVALID_HANDLE_VALUE){return?;}//?創建文件映射對象HANDLE?hFileMap?=?CreateFileMapping(hFile,?NULL,?PAGE_READONLY,?0,?0,?NULL);if?(hFileMap?==?NULL){CloseHandle(hFile);return;}//將文件映射進內存LPVOID?pView?=?MapViewOfFile(hFileMap,?FILE_MAP_READ,?0,?0,?0);if?(pView?==?NULL){CloseHandle(hFileMap);CloseHandle(hFile);return;}//?修改代碼節屬性DWORD?nOldProtect?=?0;VirtualProtect((LPVOID)IMAGEBASE,?FILESIZE,?PAGE_EXECUTE_READWRITE,?&nOldProtect);//?處理PEPIMAGE_DOS_HEADER?pDos?=?(PIMAGE_DOS_HEADER)pView;//?獲取pe頭大小PIMAGE_NT_HEADERS32?pNt?=?(PIMAGE_NT_HEADERS32)((DWORD)pView?+?pDos->e_lfanew);memcpy((void*)IMAGEBASE,?(void*)pDos,?pNt->OptionalHeader.SizeOfHeaders);//?OEPg_oep?=?pNt->OptionalHeader.AddressOfEntryPoint?+?IMAGEBASE;//?解析節PIMAGE_SECTION_HEADER?pSec?=?(PIMAGE_SECTION_HEADER)((DWORD)?&?(pNt->OptionalHeader.Magic)?+?pNt->FileHeader.SizeOfOptionalHeader);//?節數量unsigned?int?nNumberOfSections?=?pNt->FileHeader.NumberOfSections;while?(nNumberOfSections?!=?0){void*?pVirtualAddress?=?(void*)(pSec->VirtualAddress?+?IMAGEBASE);void*?pFileAddress?=?(void*)(pSec->PointerToRawData?+?(DWORD)pDos);memcpy(pVirtualAddress,?pFileAddress,?pSec->SizeOfRawData);nNumberOfSections--;pSec++;}if?(pNt->OptionalHeader.NumberOfRvaAndSizes?>?2){//?處理導入表PIMAGE_IMPORT_DESCRIPTOR?pIm?=?(PIMAGE_IMPORT_DESCRIPTOR)(pNt->OptionalHeader.DataDirectory[1].VirtualAddress?+?IMAGEBASE);while?(pIm->Name?&&?pIm->FirstThunk){HMODULE?hModule?=?LoadLibraryA((char*)(pIm->Name?+?IMAGEBASE));if?(hModule?==?NULL){pIm++;continue;}DWORD?dwThunkData?=?pIm->OriginalFirstThunk???pIm->OriginalFirstThunk?:?pIm->FirstThunk;if?(dwThunkData?==?0){return?;}PIMAGE_THUNK_DATA?pThunkData?=?(PIMAGE_THUNK_DATA)(dwThunkData?+?IMAGEBASE);DWORD*?pPfn?=?(DWORD*)(pIm->FirstThunk?+?IMAGEBASE);while?(pThunkData->u1.AddressOfData){FARPROC?farProc?=?0;LPCSTR?lpParam2?=?0;//?最高位判斷if?(pThunkData->u1.AddressOfData?&?0x80000000){//?序號lpParam2?=?LPCSTR(LOWORD(pThunkData->u1.AddressOfData));}else{//?函數名lpParam2?=?LPCSTR(pThunkData->u1.AddressOfData?+?IMAGEBASE?+?2);}farProc?=?GetProcAddress(hModule,?lpParam2);//?填充IAT*pPfn?=?(DWORD)farProc;pThunkData++;pPfn++;}pIm++;}}//取消映射UnmapViewOfFile(pView);//關閉文件映射對象CloseHandle(hFileMap);//關閉文件CloseHandle(hFile); }int?main() {LoadPe();if?(g_oep?!=?0){__asm{jmp?g_oep;}}return?0; }
思路: 主要難點是代碼后移,留出空間
方法1: 內聯 匯編 開始 nop
方法2: 把代碼放到dll中
方法3: 合并節,全局變量是放在未初始化的節內合并后就會在第一個節
合并節代碼:
#include?<Windows.h> #pragma?bss_seg?(".mySec") char?g_aryImageSize[0x200000];#pragma?bss_seg() #pragma?comment(linker,"/MERGE:.mySec=.textbss")const?char*?g_szExe?=?"mspaint.exe";int?main() {HANDLE?hFile?=?NULL;HANDLE?hFileMap?=?NULL;LPVOID?pFileBuf?=?NULL;IMAGE_DOS_HEADER*?pDosHdr?=?NULL;IMAGE_NT_HEADERS*?pNtHdr?=?NULL;IMAGE_FILE_HEADER*?pFileHdr?=?NULL;IMAGE_OPTIONAL_HEADER*?pOptHdr?=?NULL;IMAGE_SECTION_HEADER*?pSecHdr?=?NULL;IMAGE_IMPORT_DESCRIPTOR*?pImpDes?=?NULL;DWORD?dwSizeOfOptHdr?=?0;DWORD?dwNumOfSecs?=?0;HANDLE?hMod?=?NULL;DWORD??dwSizeOfHeader?=?0;DWORD?dwOldProc?=?0;DWORD?dwEntry?=?0;HMODULE?hDll?=?NULL;LPDWORD?pINT?=?NULL;LPDWORD?pIAT?=?NULL;DWORD?dwAddrOfFunc?=?0;IMAGE_IMPORT_DESCRIPTOR?zeroImp;memset(&zeroImp,?0,?sizeof(IMAGE_IMPORT_DESCRIPTOR));//1、創建文件hMod?=?GetModuleHandle(NULL);hFile?=?CreateFile(g_szExe,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if?(hFile?==?INVALID_HANDLE_VALUE){OutputDebugString("Could?not?open?file.");return?-1;}//2、創建文件映射hFileMap?=?CreateFileMapping(hFile,?NULL,?PAGE_READONLY,?0,?0,?NULL);if?(hFileMap?==?NULL){OutputDebugString("Could?not?create?file-mapping?object.");return?-1;}//3、映射文件內容到內存pFileBuf?=?MapViewOfFile(hFileMap,?FILE_MAP_READ,?0,?0,?0);if?(pFileBuf?==?NULL){OutputDebugString("Could?not?map?view?of?file.");return?-1;}//4、解析DOS頭pDosHdr?=?(IMAGE_DOS_HEADER*)pFileBuf;//5、解析NT頭pNtHdr?=?(IMAGE_NT_HEADERS*)(pDosHdr->e_lfanew?+?(char*)pFileBuf);//6、解析文件頭pFileHdr?=?&(pNtHdr->FileHeader);//7、解析選項頭pOptHdr?=?&(pNtHdr->OptionalHeader);//8、獲取節表個數和選項頭大小dwSizeOfOptHdr?=?pFileHdr->SizeOfOptionalHeader;dwNumOfSecs?=?pFileHdr->NumberOfSections;//9、解析節表pSecHdr?=?(IMAGE_SECTION_HEADER*)((char*)pOptHdr?+?dwSizeOfOptHdr);//10、獲取PE頭大小和入口點(RVA)dwSizeOfHeader?=?pOptHdr->SizeOfHeaders;dwEntry?=?pOptHdr->AddressOfEntryPoint?+?(DWORD)hMod;//11、獲取導入表入口pImpDes?=?(IMAGE_IMPORT_DESCRIPTOR*)pOptHdr->DataDirectory[1].VirtualAddress;pImpDes?=?(IMAGE_IMPORT_DESCRIPTOR*)((DWORD)pImpDes?+?(DWORD)hMod);//12、拷貝PE頭VirtualProtect(hMod,?dwSizeOfHeader,?PAGE_EXECUTE_READWRITE,?&dwOldProc);memcpy(hMod,?pDosHdr,?dwSizeOfHeader);//13、拷貝節數據IMAGE_SECTION_HEADER*?pSecTmpHdr?=?pSecHdr;for?(size_t?i?=?0;?i?<?dwNumOfSecs;?i++){LPVOID?pSecDataFileOffset?=?(char*)pFileBuf?+?pSecTmpHdr->PointerToRawData;LPVOID?pSecDataMemory?=?(LPVOID)((DWORD)hMod?+?pSecTmpHdr->VirtualAddress);VirtualProtect(pSecDataMemory,?pSecTmpHdr->Misc.VirtualSize,?PAGE_EXECUTE_READWRITE,?&dwOldProc);memcpy(pSecDataMemory,?pSecDataFileOffset,?pSecTmpHdr->SizeOfRawData);pSecTmpHdr?=?(IMAGE_SECTION_HEADER*)((char*)pSecTmpHdr?+?sizeof(IMAGE_SECTION_HEADER));}//14、拷貝導入表信息while?(true){if?(pImpDes->Characteristics?==?0?&&pImpDes->FirstThunk?==?0?&&pImpDes->Name?==?0){break;}if?(pImpDes->Name?==?NULL){break;}LPSTR?pDllName?=?(LPSTR)((DWORD)hMod?+?pImpDes->Name);hDll?=?LoadLibrary(pDllName);if?(pImpDes->FirstThunk?==?NULL){break;}//獲取導入名稱表pINT?=?(LPDWORD)((DWORD)hMod?+?pImpDes->OriginalFirstThunk);if?(pINT?==?NULL){pINT?=?(LPDWORD)((DWORD)hMod?+?pImpDes->FirstThunk);}//獲取導入地址表pIAT?=?(LPDWORD)((DWORD)hMod?+?pImpDes->FirstThunk);//while?(true){DWORD?dwINT?=?*pINT;if?(dwINT?==?0){break;}//判斷是符號導入還是名稱導入LPSTR?pApiName?=?NULL;if?(dwINT?&?0x80000000){pApiName?=?(LPSTR)dwINT;pApiName?=?LPSTR((DWORD)pApiName?&?0x0000ffff);}else{pApiName?=?LPSTR(dwINT?+?(DWORD)hMod?+?sizeof(WORD));}*pIAT?=?(DWORD)GetProcAddress(hDll,?pApiName);pINT++;pIAT++;}pImpDes++;}__asm?jmp?dwEntry;return?0; }