//PE.h
public:
HANDLE m_hFile; //PE文件句柄
LPBYTE m_pFileBuf; //PE文件缓冲区
DWORD m_dwFileSize; //文件大小
DWORD m_dwImageSize; //镜像大小
PIMAGE_DOS_HEADER m_pDosHeader; //Dos头
PIMAGE_NT_HEADERS m_pNtHeader; //NT头
PIMAGE_SECTION_HEADER m_pSecHeader; //第一个SECTION结构体指针
DWORD m_dwImageBase; //镜像基址
DWORD m_dwCodeBase; //代码基址
DWORD m_dwCodeSize; //代码大小
DWORD m_dwPEOEP; //OEP地址
DWORD m_dwShellOEP; //新OEP地址
DWORD m_dwSizeOfHeader; //文件头大小
DWORD m_dwSectionNum; //区段数量
DWORD m_dwFileAlign; //文件对齐
DWORD m_dwMemAlign; //内存对齐
DWORD m_IATSectionBase; //IAT所在段基址
DWORD m_IATSectionSize; //IAT所在段大小
IMAGE_DATA_DIRECTORY m_PERelocDir; //重定位表信息
IMAGE_DATA_DIRECTORY m_PEImportDir; //导入表信息
void CPE::GetPEInfo()
{
m_pDosHeader = (PIMAGE_DOS_HEADER)m_pFileBuf;
m_pNtHeader = (PIMAGE_NT_HEADERS)(m_pFileBuf + m_pDosHeader->e_lfanew);
m_dwFileAlign = m_pNtHeader->OptionalHeader.FileAlignment;
m_dwMemAlign = m_pNtHeader->OptionalHeader.SectionAlignment;
m_dwImageBase = m_pNtHeader->OptionalHeader.ImageBase;
m_dwPEOEP = m_pNtHeader->OptionalHeader.AddressOfEntryPoint;
m_dwCodeBase = m_pNtHeader->OptionalHeader.BaseOfCode;
m_dwCodeSize = m_pNtHeader->OptionalHeader.SizeOfCode;
m_dwSizeOfHeader= m_pNtHeader->OptionalHeader.SizeOfHeaders;
m_dwSectionNum = m_pNtHeader->FileHeader.NumberOfSections;
m_pSecHeader = IMAGE_FIRST_SECTION(m_pNtHeader);
m_pNtHeader->OptionalHeader.SizeOfImage = m_dwImageSize;
//保存重定位目录信息
m_PERelocDir =
IMAGE_DATA_DIRECTORY(m_pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);
//保存IAT信息目录信息
m_PEImportDir =
IMAGE_DATA_DIRECTORY(m_pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]);
}
DWORD CPE::XorCode(BYTE byXOR)
{
PBYTE pCodeBase = (PBYTE)((DWORD)m_pFileBuf + m_dwCodeBase);
for (DWORD i = 0; i < m_dwCodeSize; i++)
{
pCodeBase[i] ^= byXOR;
}
return m_dwCodeSize;
}
//导出ShellData结构体
extern"C" typedef struct _SHELL_DATA
{
DWORD dwStartFun; //启动函数
DWORD dwPEOEP; //程序入口点
DWORD dwXorKey; //解密KEY
DWORD dwCodeBase; //代码段起始地址
DWORD dwXorSize; //代码段加密大小
DWORD dwPEImageBase; //PE文件映像基址
IMAGE_DATA_DIRECTORY stcPERelocDir; //重定位表信息
IMAGE_DATA_DIRECTORY stcPEImportDir; //导入表信息
DWORD dwIATSectionBase; //IAT所在段基址
DWORD dwIATSectionSize; //IAT所在段大小
BOOL bIsShowMesBox; //是否显示MessageBox
}SHELL_DATA, *PSHELL_DATA;
HMODULE hShell = LoadLibrary(L"Shell.dll");
PSHELL_DATA pstcShellData = (PSHELL_DATA)GetProcAddress(hShell, "g_stcShellData");
pstcShellData->dwXorKey = 0x15;
pstcShellData->dwCodeBase = objPE.m_dwCodeBase;
pstcShellData->dwXorSize = dwXorSize;
pstcShellData->dwPEOEP = objPE.m_dwPEOEP;
pstcShellData->dwPEImageBase = objPE.m_dwImageBase;
pstcShellData->stcPERelocDir = objPE.m_PERelocDir;
pstcShellData->stcPEImportDir = objPE.m_PEImportDir;
pstcShellData->dwIATSectionBase = objPE.m_IATSectionBase;
pstcShellData->dwIATSectionSize = objPE.m_IATSectionSize;
pstcShellData->bIsShowMesBox = bIsShowMesBox;
BOOL CPE::SetShellReloc(LPBYTE pShellBuf, DWORD hShell)
{
typedef struct _TYPEOFFSET
{
WORD offset : 12; //偏移值
WORD Type : 4; //重定位属性(方式)
}TYPEOFFSET, *PTYPEOFFSET;
//1.获取被加壳PE文件的重定位目录表指针信息
PIMAGE_DATA_DIRECTORY pPERelocDir =
&(m_pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);
//2.获取Shell的重定位表指针信息
PIMAGE_DOS_HEADER pShellDosHeader = (PIMAGE_DOS_HEADER)pShellBuf;
PIMAGE_NT_HEADERS pShellNtHeader = (PIMAGE_NT_HEADERS)(pShellBuf + pShellDosHeader->e_lfanew);
PIMAGE_DATA_DIRECTORY pShellRelocDir =
&(pShellNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);
PIMAGE_BASE_RELOCATION pShellReloc =
(PIMAGE_BASE_RELOCATION)((DWORD)pShellBuf + pShellRelocDir->VirtualAddress);
//3.还原修复重定位信息
//由于Shell.dll是通过LoadLibrary加载的,所以系统会对其进行一次重定位
//我们需要把Shell.dll的重定位信息恢复到系统没加载前的样子,然后在写入被加壳文件的末尾
PTYPEOFFSET pTypeOffset = (PTYPEOFFSET)(pShellReloc + 1);
DWORD dwNumber = (pShellReloc->SizeOfBlock - 8) / 2;
for (DWORD i = 0; i < dwNumber; i++)
{
if (*(PWORD)(&pTypeOffset[i]) == NULL)
break;
//RVA
DWORD dwRVA =pTypeOffset[i].offset + pShellReloc->VirtualAddress;
//FAR地址(LordPE中这样标注)
//***新的重定位地址=重定位后的地址-加载时的镜像基址+新的镜像基址+代码基址(PE文件镜像大小)
DWORD AddrOfNeedReloc = *(PDWORD)((DWORD)pShellBuf + dwRVA);
*(PDWORD)((DWORD)pShellBuf + dwRVA)
= AddrOfNeedReloc - pShellNtHeader->OptionalHeader.ImageBase + m_dwImageBase + m_dwImageSize;
}
//3.1修改Shell重定位表中.text的RVA
pShellReloc->VirtualAddress += m_dwImageSize;
//4.修改PE重定位目录指针,指向Shell的重定位表信息
pPERelocDir->Size = pShellRelocDir->Size;
pPERelocDir->VirtualAddress = pShellRelocDir->VirtualAddress + m_dwImageSize;
return TRUE;
}
void CPE::MergeBuf(LPBYTE pFileBuf, DWORD pFileBufSize,
LPBYTE pShellBuf, DWORD pShellBufSize,
LPBYTE& pFinalBuf, DWORD& pFinalBufSize)
{
//获取最后一个区段的信息
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuf;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuf + pDosHeader->e_lfanew);
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
PIMAGE_SECTION_HEADER pLastSection =
&pSectionHeader[pNtHeader->FileHeader.NumberOfSections - 1];
//1.修改区段数量
pNtHeader->FileHeader.NumberOfSections += 1;
//2.编辑区段表头结构体信息
PIMAGE_SECTION_HEADER AddSectionHeader =
&pSectionHeader[pNtHeader->FileHeader.NumberOfSections - 1];
memcpy_s(AddSectionHeader->Name, 8, ".cyxvc", 7);
//VOffset(1000对齐)
DWORD dwTemp = 0;
dwTemp = (pLastSection->Misc.VirtualSize / m_dwMemAlign) * m_dwMemAlign;
if (pLastSection->Misc.VirtualSize % m_dwMemAlign)
{
dwTemp += 0x1000;
}
AddSectionHeader->VirtualAddress = pLastSection->VirtualAddress + dwTemp;
//Vsize(实际添加的大小)
AddSectionHeader->Misc.VirtualSize = pShellBufSize;
//ROffset(旧文件的末尾)
AddSectionHeader->PointerToRawData = pFileBufSize;
//RSize(200对齐)
dwTemp = (pShellBufSize / m_dwFileAlign) * m_dwFileAlign;
if (pShellBufSize % m_dwFileAlign)
{
dwTemp += m_dwFileAlign;
}
AddSectionHeader->SizeOfRawData = dwTemp;
//区段属性标志(可读可写可执行)
AddSectionHeader->Characteristics = 0XE0000040;
//3.修改PE头文件大小属性,增加文件大小
dwTemp = (pShellBufSize / m_dwMemAlign) * m_dwMemAlign;
if (pShellBufSize % m_dwMemAlign)
{
dwTemp += m_dwMemAlign;
}
pNtHeader->OptionalHeader.SizeOfImage += dwTemp;
//4.申请合并所需要的空间
pFinalBuf = new BYTE[pFileBufSize + dwTemp];
pFinalBufSize = pFileBufSize + dwTemp;
memset(pFinalBuf, 0, pFileBufSize + dwTemp);
memcpy_s(pFinalBuf, pFileBufSize, pFileBuf, pFileBufSize);
memcpy_s(pFinalBuf + pFileBufSize, dwTemp, pShellBuf, dwTemp);
}
[注意]APP应用上架合规检测服务,协助应用顺利上架!