標(biāo) 題: 【原創(chuàng)】菜鳥注釋PEMaker6源代碼(一) 作 者: 火影 時 間: 2007-09-16,00:11:22 鏈 接: http://bbs./showthread.php?t=51750 這兩天看了精華8的“向?qū)氡碇凶⑷氪a“這篇文章,對閱讀PEMaker6源代碼進(jìn)行了部分注釋,,要不總是忘了哪一部分是什么功能,,為了增加點(diǎn)發(fā)帖量,將注釋過的幾個類逐一整理后發(fā)布,,老鳥就無需看了,也是為了自己加強(qiáng)學(xué)習(xí),。 這篇介紹CPELibrary類的功能:找回并重建PE文件(具體可參照加殼技術(shù)->加殼軟件的編寫->向PE中注入代碼) 類定義: class CPELibrary { private: //----------------------------------------- PCHAR pMem; DWORD dwFileSize; //----------------------------------------- protected: //----------------------------------------- PIMAGE_DOS_HEADER image_dos_header; PCHAR pDosStub; DWORD dwDosStubSize, dwDosStubOffset; PIMAGE_NT_HEADERS image_nt_headers; //指針 PIMAGE_SECTION_HEADER image_section_header[MAX_SECTION_NUM]; PCHAR image_section[MAX_SECTION_NUM]; /*typedef struct _IMAGE_TLS_DIRECTORY32 { DWORD StartAddressOfRawData; DWORD EndAddressOfRawData; PDWORD AddressOfIndex; PIMAGE_TLS_CALLBACK *AddressOfCallBacks; DWORD SizeOfZeroFill; DWORD Characteristics; } IMAGE_TLS_DIRECTORY32*/ PIMAGE_TLS_DIRECTORY32 image_tls_directory; //----------------------------------------- protected: //----------------------------------------- DWORD PEAlign(DWORD dwTarNum,DWORD dwAlignTo); void AlignmentSections(); //----------------------------------------- DWORD Offset2RVA(DWORD dwRO); DWORD RVA2Offset(DWORD dwRVA); //----------------------------------------- PIMAGE_SECTION_HEADER ImageRVA2Section(DWORD dwRVA); PIMAGE_SECTION_HEADER ImageOffset2Section(DWORD dwRO); //----------------------------------------- DWORD ImageOffset2SectionNum(DWORD dwRVA); PIMAGE_SECTION_HEADER AddNewSection(char* szName,DWORD dwSize); //----------------------------------------- public: //----------------------------------------- CPELibrary(); ~CPELibrary(); //----------------------------------------- void OpenFile(char* FileName); void SaveFile(char* FileName); //----------------------------------------- }; CPP文件: CPELibrary::CPELibrary() { //構(gòu)造DOS文件頭 image_dos_header=new (IMAGE_DOS_HEADER); dwDosStubSize=0; //構(gòu)造NT文件頭 image_nt_headers=new (IMAGE_NT_HEADERS); //構(gòu)造20個節(jié)表 for(int i=0;i<MAX_SECTION_NUM;i++) image_section_header[i]=new (IMAGE_SECTION_HEADER); image_tls_directory=NULL; } //---------------------------------------------------------------- CPELibrary::~CPELibrary() { delete []image_dos_header; dwDosStubSize=0; delete []image_nt_headers; for(int i=0;i<MAX_SECTION_NUM;i++) delete []image_section_header[i]; if(image_tls_directory!=NULL) delete image_tls_directory; } //================================================================ //---------------------------------------------------------------- // returns aligned value //對齊 DWORD CPELibrary::PEAlign(DWORD dwTarNum,DWORD dwAlignTo) { return(((dwTarNum+dwAlignTo-1)/dwAlignTo)*dwAlignTo); } //---------------------------------------------------------------- void CPELibrary::AlignmentSections() { //根據(jù)節(jié)的數(shù)量循環(huán) for(int i=0;i<image_nt_headers->FileHeader.NumberOfSections;i++) { //節(jié)中數(shù)據(jù)的RVA。 image_section_header[i]->VirtualAddress= PEAlign(image_section_header[i]->VirtualAddress, image_nt_headers->OptionalHeader.SectionAlignment); //對齊Misc.VirtualSize image_section_header[i]->Misc.VirtualSize= PEAlign(image_section_header[i]->Misc.VirtualSize, image_nt_headers->OptionalHeader.SectionAlignment); //對齊PointerToRawData image_section_header[i]->PointerToRawData= PEAlign(image_section_header[i]->PointerToRawData, image_nt_headers->OptionalHeader.FileAlignment); //對齊SizeOfRawData image_section_header[i]->SizeOfRawData= PEAlign(image_section_header[i]->SizeOfRawData, image_nt_headers->OptionalHeader.FileAlignment); } //是個RVA,,重建映象文件基址 image_nt_headers->OptionalHeader.SizeOfImage=image_section_header[i-1]->VirtualAddress+ image_section_header[i-1]->Misc.VirtualSize; image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress=0; image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size=0; image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress=0; image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size=0; image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress=0; image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size=0; } //================================================================ //---------------------------------------------------------------- // calulates the Offset from a RVA // Base - base of the MMF // dwRVA - the RVA to calculate // returns 0 if an error occurred else the calculated Offset will be returned DWORD CPELibrary::RVA2Offset(DWORD dwRVA) { DWORD _offset; PIMAGE_SECTION_HEADER section; section=ImageRVA2Section(dwRVA);//ImageRvaToSection(pimage_nt_headers,Base,dwRVA); if(section==NULL) { return(0); } //文件偏移 _offset=(dwRVA-section->VirtualAddress)+section->PointerToRawData; return(_offset); } //---------------------------------------------------------------- // calulates the RVA from a Offset // Base - base of the MMF // dwRO - the Offset to calculate // returns 0 if an error occurred else the calculated Offset will be returned DWORD CPELibrary::Offset2RVA(DWORD dwRO) { PIMAGE_SECTION_HEADER section; section=ImageOffset2Section(dwRO); if(section==NULL) { return(0); } //返回RVA return((dwRO-section->PointerToRawData)+section->VirtualAddress); } //================================================================ //---------------------------------------------------------------- PIMAGE_SECTION_HEADER CPELibrary::ImageRVA2Section(DWORD dwRVA) { int i; for(i=0;i<image_nt_headers->FileHeader.NumberOfSections;i++) { //確定包含在哪一個節(jié)中 if((dwRVA>=image_section_header[i]->VirtualAddress) && (dwRVA<=(image_section_header[i]->VirtualAddress+image_section_header[i]->SizeOfRawData))) { //返回該節(jié) return ((PIMAGE_SECTION_HEADER)image_section_header[i]); } } return(NULL); } //---------------------------------------------------------------- //The ImageOffset2Section function locates a Off Set address (RO) //within the image header of a file that is mapped as a file and //returns a pointer to the section table entry for that virtual //address. PIMAGE_SECTION_HEADER CPELibrary::ImageOffset2Section(DWORD dwRO) { for(int i=0;i<image_nt_headers->FileHeader.NumberOfSections;i++) { //確定包含在哪一個節(jié)中 if((dwRO>=image_section_header[i]->PointerToRawData) && (dwRO<(image_section_header[i]->PointerToRawData+image_section_header[i]->SizeOfRawData))) { //返回該節(jié) return ((PIMAGE_SECTION_HEADER)image_section_header[i]); } } return(NULL); } //================================================================ //---------------------------------------------------------------- // retrieve Enrty Point Section Number // Base - base of the MMF // dwRVA - the RVA to calculate // returns -1 if an error occurred else the calculated Offset will be returned //由文件偏移到節(jié)號 DWORD CPELibrary::ImageOffset2SectionNum(DWORD dwRO) { for(int i=0;i<image_nt_headers->FileHeader.NumberOfSections;i++) { if((dwRO>=image_section_header[i]->PointerToRawData) && (dwRO<(image_section_header[i]->PointerToRawData+image_section_header[i]->SizeOfRawData))) { return (i); } } return(-1); } //增加新節(jié)---------------------------------------------------------------- PIMAGE_SECTION_HEADER CPELibrary::AddNewSection(char* szName,DWORD dwSize) { DWORD roffset,rsize,voffset,vsize; //最后一節(jié) int i=image_nt_headers->FileHeader.NumberOfSections; rsize=PEAlign(dwSize, image_nt_headers->OptionalHeader.FileAlignment); vsize=PEAlign(rsize, image_nt_headers->OptionalHeader.SectionAlignment); roffset=PEAlign(image_section_header[i-1]->PointerToRawData+image_section_header[i-1]->SizeOfRawData, image_nt_headers->OptionalHeader.FileAlignment); voffset=PEAlign(image_section_header[i-1]->VirtualAddress+image_section_header[i-1]->Misc.VirtualSize, image_nt_headers->OptionalHeader.SectionAlignment); //初始化新節(jié)表 memset(image_section_header[i],0,(size_t)sizeof(IMAGE_SECTION_HEADER)); //通過計算上一節(jié)得到 image_section_header[i]->PointerToRawData=roffset; image_section_header[i]->VirtualAddress=voffset; //通過傳遞的參數(shù)得到 image_section_header[i]->SizeOfRawData=rsize; image_section_header[i]->Misc.VirtualSize=vsize; //屬性 image_section_header[i]->Characteristics=0xC0000040; //新節(jié)名稱 memcpy(image_section_header[i]->Name,szName,(size_t)strlen(szName)); //申請一個節(jié)的空間 image_section[i]=(char*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,rsize); //更新文件頭 image_nt_headers->FileHeader.NumberOfSections++; //返回新節(jié) return (PIMAGE_SECTION_HEADER)image_section_header[i]; } //================================================================ //---------------------------------------------------------------- void CPELibrary::OpenFile(char* FileName) { DWORD dwBytesRead = 0; HANDLE hFile= NULL; DWORD SectionNum; DWORD i; DWORD dwRO_first_section; //基類成員 pMem=NULL; //---------------------------------------- hFile=CreateFile(FileName, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile==INVALID_HANDLE_VALUE) { ShowErr(FileErr); return; } dwFileSize=GetFileSize(hFile,0); if(dwFileSize == 0) { CloseHandle(hFile); ShowErr(FsizeErr); return; } //不用內(nèi)存映射文件,奇怪,? pMem=(char*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,dwFileSize); if(pMem == NULL) { CloseHandle(hFile); ShowErr(MemErr); return; } //讀入文件 ReadFile(hFile,pMem,dwFileSize,&dwBytesRead,NULL); //關(guān)閉句柄 CloseHandle(hFile); //---------------------------------------- //讀出DOS文件頭 memcpy(image_dos_header,pMem,sizeof(IMAGE_DOS_HEADER)); //MS-DOS Stub Program(位于e_lfanew和Signature之間) dwDosStubSize=image_dos_header->e_lfanew-sizeof(IMAGE_DOS_HEADER); dwDosStubOffset=sizeof(IMAGE_DOS_HEADER); pDosStub=new CHAR[dwDosStubSize]; if((dwDosStubSize&0x80000000)==0x00000000) { CopyMemory(pDosStub,pMem+dwDosStubOffset,dwDosStubSize); } //讀出NT文件頭 memcpy(image_nt_headers, pMem+image_dos_header->e_lfanew, sizeof(IMAGE_NT_HEADERS)); //DOS頭大小+NT頭大小 dwRO_first_section=image_dos_header->e_lfanew+sizeof(IMAGE_NT_HEADERS); if(image_dos_header->e_magic!=IMAGE_DOS_SIGNATURE)// MZ { ShowErr(PEErr); GlobalFree(pMem); return; } if(image_nt_headers->Signature!=IMAGE_NT_SIGNATURE)// PE00 { ShowErr(PEErr); GlobalFree(pMem); return; } //---------------------------------------- //節(jié)的數(shù)量 SectionNum=image_nt_headers->FileHeader.NumberOfSections; //---------------------------------------- for( i=0;i<SectionNum;i++) { //讀取節(jié)表,儲存節(jié)表的空間已經(jīng)初始化了,。 CopyMemory(image_section_header[i],pMem+dwRO_first_section+i*sizeof(IMAGE_SECTION_HEADER), sizeof(IMAGE_SECTION_HEADER)); } //---------------------------------------- for(i=0;i<SectionNum;i++) { //為每個節(jié)數(shù)據(jù)分配空間,,大小為每個節(jié)在文件中的大小 image_section[i]=(char*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, PEAlign(image_section_header[i]->SizeOfRawData, image_nt_headers->OptionalHeader.FileAlignment)); //循環(huán)讀出每個節(jié),,按照文件對齊 CopyMemory(image_section[i], pMem+image_section_header[i]->PointerToRawData, image_section_header[i]->SizeOfRawData); } //是否存在TLS節(jié)---------------------------------------- if(image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress!=0) { //分配空間 image_tls_directory = new (IMAGE_TLS_DIRECTORY32); //文件偏移 DWORD dwOffset=RVA2Offset(image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); //復(fù)制 memcpy(image_tls_directory, pMem+dwOffset, sizeof(IMAGE_TLS_DIRECTORY32)); } //---------------------------------------- GlobalFree(pMem); } //---------------------------------------------------------------- void CPELibrary::SaveFile(char* FileName) { DWORD dwBytesWritten = 0; DWORD i; DWORD dwRO_first_section; DWORD SectionNum; HANDLE hFile= NULL; pMem=NULL; //---------------------------------------- hFile=CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile==INVALID_HANDLE_VALUE) { hFile=CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile==INVALID_HANDLE_VALUE) { ShowErr(FileErr); return; } } //對齊---------------------------------------- AlignmentSections(); //---------------------------------------- i=image_nt_headers->FileHeader.NumberOfSections; //得到新文件的大小 dwFileSize=image_section_header[i-1]->PointerToRawData+ image_section_header[i-1]->SizeOfRawData; //申請內(nèi)存 pMem=(char*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,dwFileSize); if(pMem == NULL) { CloseHandle(hFile); ShowErr(MemErr); return; } //復(fù)制DOS頭---------------------------------------- memcpy(pMem,image_dos_header,sizeof(IMAGE_DOS_HEADER)); //MS-DOS Stub Program if((dwDosStubSize&0x80000000)==0x00000000) { memcpy(pMem+dwDosStubOffset,pDosStub,dwDosStubSize); } //復(fù)制NT頭 memcpy(pMem+image_dos_header->e_lfanew, image_nt_headers, sizeof(IMAGE_NT_HEADERS)); //節(jié)表的偏移 dwRO_first_section=image_dos_header->e_lfanew+sizeof(IMAGE_NT_HEADERS); //節(jié)的數(shù)量 SectionNum=image_nt_headers->FileHeader.NumberOfSections; //復(fù)制節(jié)表---------------------------------------- for( i=0;i<SectionNum;i++) { CopyMemory(pMem+dwRO_first_section+i*sizeof(IMAGE_SECTION_HEADER), image_section_header[i], sizeof(IMAGE_SECTION_HEADER)); } //復(fù)制節(jié)數(shù)據(jù)---------------------------------------- for(i=0;i<SectionNum;i++) { CopyMemory(pMem+image_section_header[i]->PointerToRawData, image_section[i], image_section_header[i]->SizeOfRawData); } // ----- WRITE FILE MEMORY TO DISK ----- //設(shè)置文件指針 SetFilePointer(hFile,0,NULL,FILE_BEGIN); //寫內(nèi)存到磁盤 WriteFile(hFile,pMem,dwFileSize,&dwBytesWritten,NULL); // ------ FORCE CALCULATED FILE SIZE ------ //強(qiáng)制計算文件大小 SetFilePointer(hFile,dwFileSize,NULL,FILE_BEGIN); SetEndOfFile(hFile); CloseHandle(hFile); //---------------------------------------- GlobalFree(pMem); } |
|