代码更新:全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;
}