代码更新:全C版,自动脱掉自己写的MessageBox,解压算法使用了徐大力大牛逆向的解压算法,主要代码如下,这个头文件就是解压算法
代码:
#include <windows.h> #include <stdlib.h> #include "upx.h" #ifndef _IMAGEHLP_H #include "imagehlp.h" #pragma comment ( lib, "imagehlp.lib" ) #endif IMAGE_DOS_HEADER *DosHeader = NULL; //DOS头 IMAGE_NT_HEADERS *NtHeader = NULL; //NT头 IMAGE_FILE_HEADER *FileHeader = NULL; //文件头 IMAGE_OPTIONAL_HEADER32 *OptHeader = NULL; //可选头 IMAGE_SECTION_HEADER *SecHeader =NULL; IMAGE_IMPORT_DESCRIPTOR *pIID = NULL; //数据目录 DWORD dwImportBase; PIMAGE_DOS_HEADER GetDosHeader(LPVOID ImageBase) { //////////////////////////////结构声明 PIMAGE_DOS_HEADER pDosHeader = NULL; /////////////////////////////获得DosHeader结构 pDosHeader = (PIMAGE_DOS_HEADER)ImageBase; return pDosHeader; } PIMAGE_NT_HEADERS GetNtHeader(LPVOID ImageBase) { //////////////////////////////结构声明 PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNtHeader = NULL; /////////////////////////////获得NtHeader结构 pDosHeader = (PIMAGE_DOS_HEADER)ImageBase; pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew); return pNtHeader; } PIMAGE_FILE_HEADER GetFileHeader(LPVOID ImageBase) { //////////////////////////////结构声明 PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNtHeader = NULL; PIMAGE_FILE_HEADER pFileHeader = NULL; /////////////////////////////获得FileHeader结构 pDosHeader = (PIMAGE_DOS_HEADER)ImageBase; pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew); pFileHeader =(PIMAGE_FILE_HEADER)&pNtHeader->FileHeader; return pFileHeader; } PIMAGE_OPTIONAL_HEADER GetOptionalHeader(LPVOID ImageBase) { //////////////////////////////结构声明 PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNtHeader = NULL; PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL; /////////////////////////////获得OptionalHeader结构 pDosHeader = (PIMAGE_DOS_HEADER)ImageBase; pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)&pNtHeader->OptionalHeader; return pOptionHeader; } PIMAGE_SECTION_HEADER GetSectionHeader(LPVOID ImageBase) { //////////////////////////////结构声明 PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNtHeader = NULL; PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL; PIMAGE_FILE_HEADER pFileHeader = NULL; PIMAGE_SECTION_HEADER pSecHeader = NULL; /////////////////////////////获得SectionHeader结构 pDosHeader = (PIMAGE_DOS_HEADER)ImageBase; pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew); pFileHeader =(PIMAGE_FILE_HEADER)&pNtHeader->FileHeader; pOptionHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeader->OptionalHeader; pSecHeader =(PIMAGE_SECTION_HEADER)((LPBYTE)pOptionHeader + pFileHeader->SizeOfOptionalHeader); return pSecHeader; } PIMAGE_IMPORT_DESCRIPTOR GetFirstImportDesc(LPVOID ImageBase) { //////////////////////////////结构声明 PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNtHeader = NULL; PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL; PIMAGE_FILE_HEADER pFileHeader = NULL; PIMAGE_SECTION_HEADER pSecHeader = NULL; /////////////////////////////获得OptionalHeader结构 pDosHeader = (PIMAGE_DOS_HEADER)ImageBase; pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew); pFileHeader =(PIMAGE_FILE_HEADER)&pNtHeader->FileHeader; pOptionHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeader->OptionalHeader; pSecHeader =(PIMAGE_SECTION_HEADER)((LPBYTE)pOptionHeader + pFileHeader->SizeOfOptionalHeader); DWORD pImportOffset = (pOptionHeader->DataDirectory[1]).VirtualAddress ; PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageRvaToVa (pNtHeader,ImageBase,pImportOffset,&pSecHeader ) ; return pImportDesc; } ////////////////////比较是否为PE文件 BOOL MemCmpPe(LPVOID ImageBase) { PIMAGE_DOS_HEADER pDosHeader =(PIMAGE_DOS_HEADER)ImageBase; PIMAGE_NT_HEADERS pNtHeader =(PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew); while(!ImageBase) return FALSE; while(pDosHeader->e_magic!=IMAGE_DOS_SIGNATURE) return FALSE; while(pNtHeader->Signature!=IMAGE_NT_SIGNATURE) return FALSE; return TRUE; } ///////////////////////////读取文件到内存 LPVOID MapFileToMemory(char *szFileName) { HANDLE hFile = CreateFile(szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile==INVALID_HANDLE_VALUE) { MessageBox(NULL,"不能打开文件","提示",MB_OK); return NULL; } HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); LPVOID pMap = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); return pMap; } ///////////////////////////获得对齐值 DWORD Alignment(DWORD Size,DWORD Align) { if(Size%Align!=0) return (Size/Align+1)*Align; return Size; } /////////////////////修复区段名字 void ModifySecName(PIMAGE_SECTION_HEADER SecHeader,DWORD SecNum) { int i=0; while(i<SecNum) { strcpy((char*)SecHeader[i].Name,"UnPack"); i++; } } ///////////////////修复输入表 void ModifyImport(DWORD SecOffset,DWORD SecOffsetA,DWORD SecOffsetB) { DWORD SecOffsetC=SecOffset+SecOffsetA; DWORD ImPort =*(DWORD*)SecOffsetC; while(ImPort) { DWORD FuncAddr =*(DWORD*)(SecOffsetC+4); HMODULE hMod=LoadLibraryA((char*)SecOffsetB+ImPort); FuncAddr+=SecOffset; SecOffsetC+=8; while(*(BYTE*)SecOffsetC!=0) { ++SecOffsetC; *(DWORD*)FuncAddr=(DWORD)GetProcAddress(hMod,(char*)SecOffsetC); FuncAddr+=4; SecOffsetC+=strlen((char*)SecOffsetC)+1; } ++SecOffsetC; ImPort=*(DWORD*)SecOffsetC; } } ////////////用于处理0xE8,0xE9//////////////C语言表示///////////////有点问题 void ModifyCall(BYTE *Start,int Size) { BYTE DB; DWORD DDb; DWORD FixAddr=(DWORD)Start; WORD DWA; BYTE Hi8; WORD Lo8; while(Size) { DB=*(BYTE*)Start-0xE8; ++Start; if(DB>1||*Start!=3) { continue; } DDb=*(DWORD*)Start; DWA=DDb&0x0ffff; DWA>>=8; DDb&=0xffff0000; DDb|=DWA; DDb=((DDb<<0x10)|(DDb>>0x10)); DWA=DDb&0x0ffff; Lo8=((WORD)DWA<<8); Hi8=(BYTE)(DWA>>8); DWA=(Lo8+Hi8); DDb&=0xffff0000; DDb|=DWA; DDb-=(DWORD)Start; *(DWORD*)Start=DDb+FixAddr; Start+=4; --Size; } } ///////////////////设置区段对齐 void SetSectionAlignment(IMAGE_SECTION_HEADER *TempSecHeader,int SectionNum,DWORD SecValue) { int AlignValue=0; for(int i=0;i<SectionNum;i++) { AlignValue=Alignment(TempSecHeader->Misc.VirtualSize, SecValue); TempSecHeader->SizeOfRawData =AlignValue; TempSecHeader->Misc.VirtualSize=AlignValue; TempSecHeader->PointerToRawData=TempSecHeader->VirtualAddress; TempSecHeader++; } } BYTE PCode; //压缩后的代码的文件指针 BYTE *pImage; //新的映像空间 DWORD ImageSize; //加壳后的映像大小 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { DWORD dwWrite; LPBYTE lpFile=(LPBYTE)MapFileToMemory("Test.exe"); if(MemCmpPe(lpFile)==FALSE) { MessageBoxA(NULL,"PE签名无效","提示",MB_OK); } DosHeader =GetDosHeader(lpFile); NtHeader =GetNtHeader(lpFile); FileHeader =GetFileHeader(lpFile); OptHeader =GetOptionalHeader(lpFile); SecHeader =GetSectionHeader(lpFile); pIID =GetFirstImportDesc(lpFile); /////////////////////处理第一个区段,并复制到内存中 ImageSize=Alignment(OptHeader->SizeOfImage,OptHeader->SectionAlignment);//获得加壳后的映像大小,也就是虚拟空间大小 pImage =VirtualAlloc(NULL,ImageSize,MEM_COMMIT,PAGE_READWRITE); //分配新的PE映像空间 memcpy(pImage,lpFile,OptHeader->SizeOfHeaders); //复制PE头到新分配的映像控件里面 IMAGE_SECTION_HEADER *TempSecHeader =SecHeader; //临时区段结构 ////////////////////依次复制区段到新的PE的区段里面去 for(int i=0;i<FileHeader->NumberOfSections;i++) //依次复制代码到新的映像空间里面 { memcpy(pImage+TempSecHeader->VirtualAddress, //接收代码的映像地址 lpFile+TempSecHeader->PointerToRawData, //复制代码的文件偏移地址 Alignment(TempSecHeader->SizeOfRawData,OptHeader->FileAlignment)//复制代码大小以文件大小和对齐计算 ); ++TempSecHeader; } ////////////////////修正Image里面的PE头 IMAGE_NT_HEADERS *NewNtHeader = GetNtHeader(pImage); //NT头 IMAGE_SECTION_HEADER *NewSecHeader = GetSectionHeader(pImage); IMAGE_OPTIONAL_HEADER *NewOptHeader =GetOptionalHeader(pImage); ////////////////////设置入口点 NewNtHeader->OptionalHeader.AddressOfEntryPoint=0x1020; ////////////////////文件对齐方式 NewNtHeader->OptionalHeader.SizeOfImage =Alignment(NewOptHeader->SizeOfImage,NewOptHeader->SectionAlignment); NewNtHeader->OptionalHeader.FileAlignment =NewOptHeader->FileAlignment; NewNtHeader->OptionalHeader.SizeOfHeaders =NewSecHeader->VirtualAddress; ////////////////////修正区段位置和大小 SetSectionAlignment(NewSecHeader,NewNtHeader->FileHeader.NumberOfSections,0x1000); //修复区段对齐 ////////////////////开始解压代码 UnCompress(pImage+SecHeader->VirtualAddress,(BYTE*)lpFile+SecHeader->PointerToRawData); //从只读内存中得压缩代码解压回映像空间 //DisposureE8(pImage+SecHeader->VirtualAddress,0x84); //现在处理E8 ModifyCall(pImage+SecHeader->VirtualAddress,0x84); ////////////////////修复输入表 ModifyImport((DWORD)pImage+0x1000,0x9000,(DWORD)pImage+0xC000); ////////////////////修改区段名字 ModifySecName(GetSectionHeader(pImage),3); ///////////////////写入文件 HANDLE Handle=CreateFile("UnpackMe.exe", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); SetFilePointer(Handle,0,0,FILE_BEGIN); WriteFile(Handle,pImage,ImageSize,&dwWrite,NULL); MessageBox(NULL,"脱壳成功","UnpackMe",MB_OK); return TRUE; }