今天大概看了一下精华8《向PE中注入代码》的译文,之前没有仔细看过,因为发现看过之后对源代码还是不是很明白,所以就没有参照这篇译文进行注释,大多都是自己理解+网上搜索,今天发现很多地方有失误。
大框的地方一定要参照译文,不要被我蒙蔽了。 继续注释CPECryptor类,如下: //在pecrypt.cpp里,我提供了另外一个类――CPECryptor,用它组建新区段的数据。 //然而,新区段的数据是被loader.cpp里的DynLoader()(在DynLoader Step 1中介绍的)创建的。 //因此,我们用CPECryptor类把这些数据(也有其它的数据)输入新区段。 //看完这段翻译基本没懂 const char *szWindowsAPIs[]= { "Kernel32.dll", "GetModuleHandleA", "VirtualProtect", "GetModuleFileNameA", "CreateFileA", "GlobalAlloc", "VirtualAlloc", "LoadLibraryA", "GetProcAddress", 0, "User32.dll", "MessageBoxA", 0, 0, }; //================================================================ //---------------------------------------------------------------- // Function: ReturnToBytePtr // void* FuncNum: Function Name // DWORD findstr: String to find // This code was written by FEUERRADER [AHTeam], Thanks him! //在loader.cpp文件中的DynLoader函数里寻找指定字符串,并返回其地址 void* CPECryptor::ReturnToBytePtr( void* FuncName, DWORD findstr) { void* tmpd; __asm { mov eax, FuncName jmp df hjg: inc eax df: mov ebx, [ eax] cmp ebx, findstr jnz hjg mov tmpd, eax } return tmpd; } //================================================================ //此函数构建新节及导入表---------------------------------------------------------------- void CPECryptor::CryptFile( int( __cdecl *progress) ( unsigned int, unsigned int)) { PCHAR ch_temp; PIMAGE_SECTION_HEADER pimage_section_header; DWORD dwNewSectionSize; DWORD dwCodeSize; DWORD dwCodeOffset; //进度条控件---------------------------------------- progress(0,0); //是否DLL if((image_nt_headers->FileHeader.Characteristics&IMAGE_FILE_DLL)==IMAGE_FILE_DLL) { //构造CITMaker类 ImportTableMaker = new CITMaker(IMPORT_TABLE_OCX); } else { ImportTableMaker = new CITMaker(IMPORT_TABLE_EXE); } //---------------------------------------- //======================================== //ch_temp指向DYN_LOADER_START_MAGIC之后的地址 ch_temp=(PCHAR)DWORD(ReturnToBytePtr(DynLoader, DYN_LOADER_START_MAGIC))+4; //计算DynLoader函数代码长度 dwCodeSize=DWORD(ReturnToBytePtr(DynLoader, DYN_LOADER_END_MAGIC))-DWORD(ch_temp); //自定义导入表大小 dwCodeOffset = ImportTableMaker->dwSize; //新节大小=DynLoader函数代码长度+自定义导入表大小 dwNewSectionSize = dwCodeSize + ImportTableMaker->dwSize; //分配空间 pNewSection= new TCHAR[dwNewSectionSize]; //复制DynLoader函数代码到偏移dwCodeOffset的位置之后 memcpy(pNewSection+dwCodeOffset, ch_temp, dwCodeSize); //======================================== //---------------------------------------- //添加新节,并返回新节指针 pimage_section_header=AddNewSection( ".xxx",dwNewSectionSize); //---------------------------------------- //======================================== //参数为新节在内存的偏移地址 CopyData1(pimage_section_header->VirtualAddress); //参数同上,构建自定义导入表 ImportTableMaker->Build(pimage_section_header->VirtualAddress); // build import table by the current virtual address //构建的导入表在新节数据前,注意相互位置 memcpy(pNewSection, ImportTableMaker->pMem, ImportTableMaker->dwSize); //======================================== //将新节数据复制到image_section(已经初始化)---------------------------------------- memcpy(image_section[image_nt_headers->FileHeader.NumberOfSections-1], pNewSection, dwNewSectionSize); //入口地址更改为新节的DynLoader函数代码处 image_nt_headers->OptionalHeader.AddressOfEntryPoint=pimage_section_header->VirtualAddress + dwCodeOffset; //导入表地址更改为新导入表地址 image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress=pimage_section_header->VirtualAddress; image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size=ImportTableMaker->dwSize; image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress=0; image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size=0; SetSectionsWritePermission(); //---------------------------------------- delete []pNewSection; delete ImportTableMaker; //---------------------------------------- progress(100,0); } //这个结构对应DynLoader函数里DYN_LOADER_START_DATA1标志后面的东西,具体 //是自定义结构?请高手指点,本人水平到此,分析不出了 //译文:为了找到OEP的virtual address,我们立即保存原始的OEP和Image Base。 //我在DynLoader()的尾部预留了一块空地来保存它们 typedef struct { //保留 DWORD dwReserved1; //文件类型 DWORD dwFileType; //基地址 DWORD dwImageBase; //原始入口点 DWORD dwOrgEntryPoint; //导入表虚拟地址 DWORD dwImportVirtualAddress; //重定位表虚拟地址及大小 DWORD dwRelocationVirtualAddress; DWORD dwRelocationSize; //TLS IMAGE_TLS_DIRECTORY32 image_tls_directory; }t_DATA_1,*pt_DATA_1; //此函数将实际数据填充到DynLoader函数指定位置里 void CPECryptor::CopyData1(DWORD dwVirtualAddress) { int i, API_num; PCHAR pData1; DWORD dwOffset; size_t l; UCHAR temp; //为结构分配内存 pt_DATA_1 pDataTable= new(t_DATA_1); //---------------------------------------- //保留,0xcccccccc应该没有意义 pDataTable->dwReserved1=0xCCCCCCCC; //如果为DLL,填入文件类型 if((image_nt_headers->FileHeader.Characteristics&IMAGE_FILE_DLL)==IMAGE_FILE_DLL) pDataTable->dwFileType=IMPORT_TABLE_OCX; else pDataTable->dwFileType=IMPORT_TABLE_EXE; //填充镜像首地址 pDataTable->dwImageBase=image_nt_headers->OptionalHeader.ImageBase; //填充入口点 pDataTable->dwOrgEntryPoint=image_nt_headers->OptionalHeader.AddressOfEntryPoint; //填充导入表地址(RVA) pDataTable->dwImportVirtualAddress=image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; if((image_nt_headers->FileHeader.Characteristics&IMAGE_FILE_DLL)==IMAGE_FILE_DLL) { //如果是DLL,填充重定位表 pDataTable->dwRelocationVirtualAddress=image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; pDataTable->dwRelocationSize=image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; } //前面已经将DynLoader函数读入我们申请的内存中---------------------------------------- //故在pNewSection指向的内存中找到DYN_LOADER_START_DATA1标志,返回地址 pData1=(PCHAR)ReturnToBytePtr(pNewSection, DYN_LOADER_START_DATA1); //看了好几个TLS了,是什么? //通过使用线程本地储存(TLS),一个程序能够执行多线程程序, //这样子的程序大多数是用Borland链接器:Delphi和C++, Builder. //当你包装一个PE文件时,你应该小心的清空TLS, //否则,你的打包器就不支持Borland Delphi 和 C++ Builder链接的EXE文件。 //修正可选头部TLS目录入口是很有必要的。 if(image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress!=0) { //image_tls_directory定义在pelib.cpp中 memcpy(&pDataTable->image_tls_directory, image_tls_directory, sizeof(IMAGE_TLS_DIRECTORY32)); dwOffset=DWORD(pData1)-DWORD(pNewSection); //计算偏移 dwOffset+= sizeof(t_DATA_1)- sizeof(IMAGE_TLS_DIRECTORY32); //更新文件头,指向新的TLS表 //传递的参数在这里应用 image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress=dwVirtualAddress + dwOffset; } //替换为实际数值---------------------------------------- memcpy(pData1,pDataTable, sizeof(t_DATA_1)); dwOffset= sizeof(t_DATA_1); i=API_num=0; temp=0; //循环填充实际数值 do { l=strlen(szWindowsAPIs[i])+1; //复制动态库名 memcpy(pData1+dwOffset,szWindowsAPIs[i],l); //偏移长度 dwOffset+=l; do { i++; if(szWindowsAPIs[i]!=0) { //复制下一个函数名 l=strlen(szWindowsAPIs[i])+1; memcpy(pData1+dwOffset,szWindowsAPIs[i],l); dwOffset+=l; //API数量 API_num++; } else { //放置0 CopyMemory(pData1+dwOffset,&temp,1); dwOffset++; } } while(szWindowsAPIs[i]!=0); i++; } while(szWindowsAPIs[i]!=0); //---------------------------------------- delete pDataTable; } //---------------------------------------------------------------- void CPECryptor::SetSectionsWritePermission() { for( int i=0;i<image_nt_headers->FileHeader.NumberOfSections;i++) { //设置所有表的标志 image_section_header[i]->Characteristics=0xC0000040; } } //---------------------------------------------------------------- |
注释PEMaker6源代码(三)
最新推荐文章于 2014-08-22 10:36:33 发布