您的位置:首页 > 其它

(未完待续)Windows PE 文件加壳学习笔记

2008-11-05 18:14 369 查看
要想给PE文件加壳,搞清楚PE文件的格式是前提。
以可执行程序EXE文件为例, 由描述程序信息的文件头和记录代码数据的节组成。
文件头包括DOS文件头, PE文件头, PE可选信息头组成
下面给出个结构的C定义(在windos开发包 winnt.h 文件中可以找到)

typedef struct _PE_IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} PE_IMAGE_DOS_HEADER;

typedef struct _PE_IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} PE_IMAGE_FILE_HEADER;

typedef struct _PE_IMAGE_OPTIONAL_HEADER32 {
//
// Standard fields.
//

WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;

//
// NT additional fields.
//

DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
PE_IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} PE_IMAGE_OPTIONAL_HEADER32;

typedef struct _PE_IMAGE_NT_HEADERS32 {
DWORD Signature;
PE_IMAGE_FILE_HEADER FileHeader;
PE_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} PE_IMAGE_NT_HEADERS32;

结构好像很复杂,其实很多部分的定义已经弃用了。 这是因为这个结构兼容 DOS, Win16, Win32以及Win64系统。 而前二者已经成为历史了,所以不少和它们相关的定义已经失效了。

文件信息头之后就是节(SECTION)信息了。 先是节头,让后才是节的数据。
给出节头的定义:
typedef struct _PE_IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} PE_IMAGE_SECTION_HEADER;

这个节头把文件空间与程序运行的虚拟空间联系起来, Windos PE 加载器正是根据这个节头还有上面提到的文件头中的数据把文件映像加载到内存中。

当加载器把数据读到内存后,还要做一些初始化工作。 这有牵涉到上面提到的PE可选信息头PE_IMAGE_OPTIONAL_HEADER32里面的最后一个数据项DataDirectory了。
DataDirectory这个数组有16个元素,各含义如下:
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory
// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage)
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP
#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor
#define IMAGE_DIRECTORY_ENTRY_RESERVED 15

其中比较重要的是
导出符号表 IMAGE_DIRECTORY_ENTRY_EXPORT;
导入符号表 IMAGE_DIRECTORY_ENTRY_IMPORT;
资源 IMAGE_DIRECTORY_ENTRY_RESOURCE;
导入地址表 IMAGE_DIRECTORY_ENTRY_IAT;

导出符号表作用是记录该程序导出的符号,通常是DLL文件的符号,可由其他进程调用。
导入符号表示记录该程序需要调用的外部程序。
资源的作用是记录程序资源的结构信息。
导入地址表是改程序用到的外部程序的地址。

这些数据存在于文件中的某一个节。

关于这些表的结构不是三言两语可以解释的了的,分析EXE文件的数据或者看代码吧 ,嘿嘿
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "./bst/bst_stdafx.h"
#include "./bst/bst_blob.h"
#include "./bst/bst_pack.h"

#define XPAKER_FILE_ALIGNMENT 0x1000
#define XPAKER_SECTION_ALIGNMENT 0X200

int main(int argc, char** argv)
{
//必须先做节的内存映射,否则PE文件中的虚地址不能用
char szInputFile[0x100];
char szOutputFile[0x100];

if(argc<2) return 0;
strcpy(szInputFile, argv[1]);
sprintf(szOutputFile, "_%s",szInputFile);

memptr_t pRead, pWrite;
PE_IMAGE_DOS_HEADER* pDosHeader;
PE_IMAGE_NT_HEADERS32* pPEHeaders;
PE_IMAGE_SECTION_HEADER* pSecHeader;
uint_t nSecNum;
PE_IMAGE_IMPORT_DESCRIPTOR* pImportDesc;
uint_t nImportDescNum;
PE_IMAGE_IMPORT_BY_NAME* pImportName;
uint_t i,j;

blob_c PERawImage;
PERawImage.bload(szInputFile);

pRead=PERawImage.begin();
pDosHeader=(PE_IMAGE_DOS_HEADER*)pRead; //得到原始镜像dos头的地址

pRead+=pDosHeader->e_lfanew;
pPEHeaders = (PE_IMAGE_NT_HEADERS32*)pRead; //得到原始镜像PE头的地址

pRead+=sizeof(PE_IMAGE_NT_HEADERS32);
pSecHeader=(PE_IMAGE_SECTION_HEADER*)pRead; //得到原始镜像节表的地址
nSecNum = pPEHeaders->FileHeader.NumberOfSections;

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
blob_c PEImage(pPEHeaders->OptionalHeader.SizeOfImage);

//映射后的内存映像
memcpy(PEImage.begin(), PERawImage.begin(), pPEHeaders->OptionalHeader.SizeOfHeaders);
for(i=0;i<=nSecNum-1;i++)
{
memset(PEImage.begin()+pSecHeader[i].VirtualAddress, 0, pSecHeader[i].Misc.VirtualSize);
memcpy(PEImage.begin()+pSecHeader[i].VirtualAddress, PERawImage.begin()+pSecHeader[i].PointerToRawData, pSecHeader[i].SizeOfRawData);
}

pRead=PEImage.begin();
pDosHeader=(PE_IMAGE_DOS_HEADER*)pRead; //得到虚拟镜像dos头的地址

pRead+=pDosHeader->e_lfanew;
pPEHeaders = (PE_IMAGE_NT_HEADERS32*)pRead; //得到虚拟镜像PE头的地址

pRead+=sizeof(PE_IMAGE_NT_HEADERS32);
pSecHeader=(PE_IMAGE_SECTION_HEADER*)pRead; //得到虚拟镜像节表的地址
nSecNum = pPEHeaders->FileHeader.NumberOfSections;

pRead = PEImage.begin() + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
pImportDesc = (PE_IMAGE_IMPORT_DESCRIPTOR*)pRead; //得到虚拟镜像导入表的地址

//得到导入表的模块数目
for(i=0;TRUE;i++)
{
if(pImportDesc[i].Characteristics==0 && pImportDesc[i].FirstThunk==0)
break;
}
nImportDescNum = i;

//"winnt.h"
/*
//打印输入表
if(nImportDescNum!=0)
{
FILE* f_out;
f_out=fopen("debug.txt","wt");

for(i=0;i<=nImportDescNum-1;i++)
{
fprintf(f_out, "%s/n", PEImage.begin()+pImportDesc[i].Name);//打印模块名

if(pImportDesc[i].OriginalFirstThunk!=0)
pRead = PEImage.begin() + pImportDesc[i].OriginalFirstThunk;
else
pRead = PEImage.begin() + pImportDesc[i].FirstThunk;

for(j=0;TRUE;j++)
{
if(((DWORD*)pRead)[j]==0)
break;
if(((DWORD*)pRead)[j]&IMAGE_ORDINAL_FLAG32)
{
fprintf(f_out, " *%08X/n", ((DWORD*)pRead)[j]&0x7FFFFFFF);//打印无符号函数
}
else
{
pImportName = (PE_IMAGE_IMPORT_BY_NAME*)(PEImage.begin() + ((DWORD*)pRead)[j]);
fprintf(f_out, " %04X %s/n", pImportName->Hint, pImportName->Name);//打印函数
}

}
fprintf(f_out, "/n");
}
fclose(f_out);
}
//*/
/*
//重定位导入表内函数
HMODULE hModule;
FARPROC pProc;
//hModule = LoadLibrary();
//pProc = GetProcAddress(hModule, MAKEINTRESOURCE());

if(nImportDescNum!=0)
{
for(i=0;i<=nImportDescNum-1;i++)
{
hModule = LoadLibrary((LPCSTR)(PEImage.begin()+pImportDesc[i].Name));//fprintf(f_out, "%s/n", PEImage.begin()+pImportDesc[i].Name);//打印模块名

if(pImportDesc[i].OriginalFirstThunk!=0)
pRead = PEImage.begin() + pImportDesc[i].OriginalFirstThunk;
else
pRead = PEImage.begin() + pImportDesc[i].FirstThunk;

for(j=0;TRUE;j++)
{
if(((DWORD*)pRead)[j]==0)
break;
if(((DWORD*)pRead)[j]&IMAGE_ORDINAL_FLAG32)
{
pProc = GetProcAddress(hModule, MAKEINTRESOURCE(((DWORD*)pRead)[j]&0x7FFFFFFF));//fprintf(f_out, " *%08X/n", ((DWORD*)pRead)[j]&0x7FFFFFFF);//打印无符号函数
}
else
{
pImportName = (PE_IMAGE_IMPORT_BY_NAME*)(PEImage.begin() + ((DWORD*)pRead)[j]);
pProc = GetProcAddress(hModule, (LPCSTR)(pImportName->Name));//fprintf(f_out, " %04X %s/n", pImportName->Hint, pImportName->Name);//打印函数
}
pRead = PEImage.begin() + pImportDesc[i].FirstThunk;
((DWORD*)pRead)[j] = (DWORD)pProc;

}

}
}//if

//输出IAT 重定位外部符号的地址
if(pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress!=0)
{
FILE* f_out;
f_out=fopen("debug1.txt","wt");
j = pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size / 4;
pRead = PEImage.begin() + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
for(i=0;i<=j-1;i++)
{
fprintf(f_out, "%08X/n", ((DWORD*)pRead)[i]);
}

fclose(f_out);
}
//*/

//------------------------------------------------------------
//加壳,组装PE

uint_t PackerCodeRelocateOffset[0x10]={0x000B, 0x0013, 0x001B, 0x0023, 0x002B, 0x0033, 0x003B, };
blob_c PEReleaseBuf(pPEHeaders->OptionalHeader.SizeOfImage*3);
memset(PEReleaseBuf.begin(),0,PEReleaseBuf.size());
blob_c PELoaderData;
PELoaderData.bload(".//PackLoader//loader.dat");

///*写映像
blob_c tmpSectionBuf_text(pPEHeaders->OptionalHeader.SizeOfImage*4);
memset(tmpSectionBuf_text.begin(),0,tmpSectionBuf_text.size());

//编码
BYTE nPeek;
BYTE byCurByte, nRptCnt;
uint_t nOldImageSize = pPEHeaders->OptionalHeader.SizeOfImage;
uint_t nOldHeaderSize = pPEHeaders->OptionalHeader.SizeOfHeaders;
pRead = PEImage.begin()+pPEHeaders->OptionalHeader.SizeOfHeaders;
pWrite = tmpSectionBuf_text.begin();

nPeek = 0;

nRptCnt = 0;
byCurByte = *((BYTE*)pRead);
for(i=0;i<=nOldImageSize-nOldHeaderSize-1;i++)
{
if(byCurByte == *((BYTE*)pRead) && nRptCnt<=(0x3F-1)) //最长的重复记录 63 个
{
nRptCnt++;
}
else
{
if(nRptCnt==1)
{
if(byCurByte>=0xC0)
{
*((BYTE*)pWrite++) = 0xC1; //没有重复,但是值大于C0
*((BYTE*)pWrite++) = byCurByte;
}
else
{
*((BYTE*)pWrite++) = byCurByte;
}
}
else
{
*((BYTE*)pWrite++) = 0xC0+nRptCnt; //重复,输出重复的代码
*((BYTE*)pWrite++) = byCurByte;
nRptCnt = 1; //重新开始计数
}
byCurByte = *((BYTE*)pRead); //重复判定的字符更新
}
pRead++;
}
*((BYTE*)pWrite++) = 0xC0; //结束符

//写壳代码
uint_t nPackerCodeEntryOffset;
nPackerCodeEntryOffset = pWrite-tmpSectionBuf_text.begin();

pRead = PELoaderData.begin();
memcpy(pWrite, pRead, PELoaderData.size());

//重建导入表
uint_t nOriginalFirstThunkOfImportDataOffset, nFirstThunkOfImportDataOffset, nImportTableOfImportDataOffset, nStrOfImportDataOffset;
uint_t nOriginalFirstThunkOfImportDataPtr, nFirstThunkOfImportDataPtr, nImportTableOfImportDataPtr, nStrOfImportDataPtr;
nFirstThunkOfImportDataOffset = 0;
nOriginalFirstThunkOfImportDataOffset = nFirstThunkOfImportDataOffset + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
nImportTableOfImportDataOffset = nOriginalFirstThunkOfImportDataOffset + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
nStrOfImportDataOffset = nImportTableOfImportDataOffset + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;

nOriginalFirstThunkOfImportDataPtr = nOriginalFirstThunkOfImportDataOffset;
nFirstThunkOfImportDataPtr = nFirstThunkOfImportDataOffset;
nImportTableOfImportDataPtr = nImportTableOfImportDataOffset;
nStrOfImportDataPtr = nStrOfImportDataOffset;

uint_t nPackerImportDataOffset = nPackerCodeEntryOffset + PELoaderData.size();
uint_t nPackerIATOffset = nPackerCodeEntryOffset + PELoaderData.size();
uint_t nImortDataVirtualOffset = 0x1000 + (pPEHeaders->OptionalHeader.SizeOfImage - pPEHeaders->OptionalHeader.SizeOfHeaders) +nPackerIATOffset;
uint_t nPackerImportOffset = nPackerIATOffset + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
blob_c tmpImportTableBuf(pPEHeaders->OptionalHeader.SizeOfImage*2);
memcpy(tmpImportTableBuf.begin()+nImportTableOfImportDataOffset, pImportDesc, pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size);
memcpy(tmpImportTableBuf.begin()+nFirstThunkOfImportDataOffset, PEImage.begin()+pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress, pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size);
PE_IMAGE_IMPORT_DESCRIPTOR* ptmpImportDesc = (PE_IMAGE_IMPORT_DESCRIPTOR*)(tmpImportTableBuf.begin()+nImportTableOfImportDataOffset);

if(nImportDescNum!=0)
{
for(i=0;i<=nImportDescNum-1;i++)
{
//fprintf(f_out, "%s/n", PEImage.begin()+pImportDesc[i].Name);//打印模块名
strcpy((char*)tmpImportTableBuf.begin()+nStrOfImportDataPtr, (char*)PEImage.begin()+pImportDesc[i].Name);
ptmpImportDesc[i].Name = nStrOfImportDataPtr + nImortDataVirtualOffset;
nStrOfImportDataPtr += strlen((char*)PEImage.begin()+pImportDesc[i].Name)+1;

ptmpImportDesc[i].OriginalFirstThunk = 0;
pRead = PEImage.begin() + pImportDesc[i].FirstThunk;
ptmpImportDesc[i].FirstThunk = ptmpImportDesc[i].FirstThunk - pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress + nImortDataVirtualOffset;
nFirstThunkOfImportDataPtr = pImportDesc[i].FirstThunk - pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;

for(j=0;TRUE;j++)
{
if(((DWORD*)pRead)[j]==0)
break;
if(!(((DWORD*)pRead)[j]&IMAGE_ORDINAL_FLAG32))
{
pImportName = (PE_IMAGE_IMPORT_BY_NAME*)(PEImage.begin() + ((DWORD*)pRead)[j]);
//fprintf(f_out, " %04X %s/n", pImportName->Hint, pImportName->Name);//打印函数
*(BYTE*)(tmpImportTableBuf.begin()+nStrOfImportDataPtr+0) = 0;
*(BYTE*)(tmpImportTableBuf.begin()+nStrOfImportDataPtr+1) = 0; //Hint
strcpy((char*)tmpImportTableBuf.begin()+nStrOfImportDataPtr+2, (char*)pImportName->Name);

*((DWORD*)(tmpImportTableBuf.begin() + nFirstThunkOfImportDataPtr)) = nStrOfImportDataPtr + nImortDataVirtualOffset;nFirstThunkOfImportDataPtr+=4;
nStrOfImportDataPtr += strlen((char*)pImportName->Name)+2+1; //2位Hint的长度,1为字符串结束符
}
else
{
nFirstThunkOfImportDataPtr+=4;
}

}
nFirstThunkOfImportDataPtr+=4; //跳过0
}
}//if

uint_t ntmpImportTableBufSize;
ntmpImportTableBufSize = nStrOfImportDataPtr;

//写导入数据
pRead = tmpImportTableBuf.begin();
pWrite = tmpSectionBuf_text.begin() + nPackerImportDataOffset;
memcpy(pWrite, pRead, ntmpImportTableBufSize);

uint_t nSecTextImageSize;
nSecTextImageSize = nPackerImportDataOffset + ntmpImportTableBufSize;
nSecTextImageSize = (nSecTextImageSize+0x0FFF)&0xFFFFF000;

//重定位壳代码的地址
*((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[0])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.SizeOfImage;
*((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[1])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.SizeOfHeaders;
*((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[2])) = nPackerCodeEntryOffset;
*((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[3])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.AddressOfEntryPoint;
*((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[4])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.SizeOfImage+nPackerIATOffset;
*((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[5])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
*((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[6])) = pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;

//*/
//填表头
PE_IMAGE_SECTION_HEADER tmpSecHeader_data, tmpSecHeader_text;

memcpy(tmpSecHeader_data.Name, ".data", IMAGE_SIZEOF_SHORT_NAME);
tmpSecHeader_data.Misc.VirtualSize = pPEHeaders->OptionalHeader.SizeOfImage - pPEHeaders->OptionalHeader.SizeOfHeaders;
tmpSecHeader_data.VirtualAddress = pPEHeaders->OptionalHeader.SizeOfHeaders;
tmpSecHeader_data.SizeOfRawData = 0;//暂时
tmpSecHeader_data.PointerToRawData = pPEHeaders->OptionalHeader.SizeOfHeaders;//暂时
tmpSecHeader_data.PointerToRelocations = 0x00000000;
tmpSecHeader_data.PointerToLinenumbers = 0x00000000;
tmpSecHeader_data.NumberOfRelocations = 0x0000;
tmpSecHeader_data.NumberOfLinenumbers = 0x0000;
tmpSecHeader_data.Characteristics = 0xE0000080;

memcpy(tmpSecHeader_text.Name, ".text", IMAGE_SIZEOF_SHORT_NAME);
tmpSecHeader_text.Misc.VirtualSize = nSecTextImageSize;//暂时
tmpSecHeader_text.VirtualAddress = pPEHeaders->OptionalHeader.SizeOfImage;
tmpSecHeader_text.SizeOfRawData = tmpSecHeader_text.Misc.VirtualSize;//暂时
tmpSecHeader_text.PointerToRawData = pPEHeaders->OptionalHeader.SizeOfHeaders;//暂时
tmpSecHeader_text.PointerToRelocations = 0x00000000;
tmpSecHeader_text.PointerToLinenumbers = 0x00000000;
tmpSecHeader_text.NumberOfRelocations = 0x0000;
tmpSecHeader_text.NumberOfLinenumbers = 0x0000;
tmpSecHeader_text.Characteristics = 0xE0000040;

PE_IMAGE_DOS_HEADER tmpDosHeader;
tmpDosHeader.e_magic = IMAGE_DOS_SIGNATURE; // Magic number
tmpDosHeader.e_cblp = 0x0090; // Bytes on last page of file
tmpDosHeader.e_cp = 0x0003; // Pages in file
tmpDosHeader.e_crlc = 0x0000; // Relocations
tmpDosHeader.e_cparhdr = 0x0004; // Size of header in paragraphs
tmpDosHeader.e_minalloc = 0x0000; // Minimum extra paragraphs needed
tmpDosHeader.e_maxalloc = 0xFFFF; // Maximum extra paragraphs needed
tmpDosHeader.e_ss = 0x0000; // Initial (relative) SS value
tmpDosHeader.e_sp = 0x00B8; // Initial SP value
tmpDosHeader.e_csum = 0x0000; // Checksum
tmpDosHeader.e_ip = 0x0000; // Initial IP value
tmpDosHeader.e_cs = 0x0000; // Initial (relative) CS value
tmpDosHeader.e_lfarlc = 0x0040; // File address of relocation table
tmpDosHeader.e_ovno = 0x0000; // Overlay number
memset(tmpDosHeader.e_res, 0, sizeof(WORD)*4); // Reserved words
tmpDosHeader.e_oemid = 0x0000; // OEM identifier (for e_oeminfo)
tmpDosHeader.e_oeminfo = 0x0000; // OEM information; e_oemid specific
memset(tmpDosHeader.e_res2, 0, sizeof(WORD)*10); // Reserved words
tmpDosHeader.e_lfanew = 0x00C0; // File address of new exe header

PE_IMAGE_NT_HEADERS32 tmpPEHeaders;
tmpPEHeaders.Signature = IMAGE_NT_SIGNATURE;

tmpPEHeaders.FileHeader.Machine = 0x014C;
tmpPEHeaders.FileHeader.NumberOfSections = 0x0002; //就两个节
tmpPEHeaders.FileHeader.TimeDateStamp = 0x00000000;
tmpPEHeaders.FileHeader.PointerToSymbolTable = 0;
tmpPEHeaders.FileHeader.NumberOfSymbols = 0;
tmpPEHeaders.FileHeader.SizeOfOptionalHeader = 0x00E0;
tmpPEHeaders.FileHeader.Characteristics = 0x010F;

tmpPEHeaders.OptionalHeader.Magic = 0x010B;
tmpPEHeaders.OptionalHeader.MajorLinkerVersion = 0x06;
tmpPEHeaders.OptionalHeader.MinorLinkerVersion = 0x00;
tmpPEHeaders.OptionalHeader.SizeOfCode = 0x00000000;
tmpPEHeaders.OptionalHeader.SizeOfInitializedData = 0x00000000;
tmpPEHeaders.OptionalHeader.SizeOfUninitializedData = 0x00000000;
tmpPEHeaders.OptionalHeader.AddressOfEntryPoint = pPEHeaders->OptionalHeader.SizeOfImage+nPackerCodeEntryOffset;
tmpPEHeaders.OptionalHeader.BaseOfCode = 0; //没用
tmpPEHeaders.OptionalHeader.BaseOfData = 0; //没用

tmpPEHeaders.OptionalHeader.ImageBase = pPEHeaders->OptionalHeader.ImageBase;
tmpPEHeaders.OptionalHeader.SectionAlignment = 0x00001000;
tmpPEHeaders.OptionalHeader.FileAlignment = 0x000001000;
tmpPEHeaders.OptionalHeader.MajorOperatingSystemVersion = 0x0004;
tmpPEHeaders.OptionalHeader.MinorOperatingSystemVersion = 0x0000;
tmpPEHeaders.OptionalHeader.MajorImageVersion = 0x0000;
tmpPEHeaders.OptionalHeader.MinorImageVersion = 0x0000;
tmpPEHeaders.OptionalHeader.MajorSubsystemVersion = 0x0004;
tmpPEHeaders.OptionalHeader.MinorSubsystemVersion = 0x0000;
tmpPEHeaders.OptionalHeader.Win32VersionValue = 0;
tmpPEHeaders.OptionalHeader.SizeOfImage = pPEHeaders->OptionalHeader.SizeOfHeaders + tmpSecHeader_data.Misc.VirtualSize + tmpSecHeader_text.Misc.VirtualSize;
tmpPEHeaders.OptionalHeader.SizeOfHeaders = 0x00001000;
tmpPEHeaders.OptionalHeader.CheckSum = 0x00000000;
tmpPEHeaders.OptionalHeader.Subsystem = pPEHeaders->OptionalHeader.Subsystem;
tmpPEHeaders.OptionalHeader.DllCharacteristics = 0;
tmpPEHeaders.OptionalHeader.SizeOfStackReserve = 0x00100000;
tmpPEHeaders.OptionalHeader.SizeOfStackCommit = 0x00001000;
tmpPEHeaders.OptionalHeader.SizeOfHeapReserve = 0x00100000;
tmpPEHeaders.OptionalHeader.SizeOfHeapCommit = 0x00001000;
tmpPEHeaders.OptionalHeader.LoaderFlags = 0;
tmpPEHeaders.OptionalHeader.NumberOfRvaAndSizes = 0x00000010;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = pPEHeaders->OptionalHeader.SizeOfImage+nPackerImportDataOffset+nImportTableOfImportDataOffset;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = pPEHeaders->OptionalHeader.SizeOfImage+nPackerImportDataOffset+nFirstThunkOfImportDataOffset;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = 0x00000000;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESERVED].VirtualAddress = 0;
tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESERVED].Size = 0;

//写文件头
pWrite = PEReleaseBuf.begin();
memcpy(pWrite, &tmpDosHeader, sizeof(PE_IMAGE_DOS_HEADER));
pWrite = PEReleaseBuf.begin() + tmpDosHeader.e_lfarlc;
memcpy(pWrite, PERawImage.begin()+pDosHeader->e_lfarlc, 0x40); //0x40 dos stub 代码长度
pWrite = PEReleaseBuf.begin() + tmpDosHeader.e_lfanew;
memcpy(pWrite, &tmpPEHeaders, sizeof(PE_IMAGE_NT_HEADERS32));

//写2个节头
pWrite+=sizeof(PE_IMAGE_NT_HEADERS32);
memcpy(pWrite, &tmpSecHeader_data, sizeof(PE_IMAGE_SECTION_HEADER));
pWrite+=sizeof(PE_IMAGE_SECTION_HEADER);
memcpy(pWrite, &tmpSecHeader_text, sizeof(PE_IMAGE_SECTION_HEADER));

//写节数据
pWrite = PEReleaseBuf.begin() + tmpSecHeader_text.PointerToRawData;
memcpy(pWrite, tmpSectionBuf_text.begin(), tmpSecHeader_text.SizeOfRawData);

//dump成文件
FILE* f_rl;
f_rl = fopen(szOutputFile,"wb");
fwrite(PEReleaseBuf.begin(), tmpPEHeaders.OptionalHeader.SizeOfImage, 1, f_rl);
fclose(f_rl);

//...

return 0;
}

有点多,抱歉了。
功能不全,只能给不含资源的EXE加壳,比如win32 控制台程序。

搞清楚文件的结构之后,我们就可以开始操刀搞加壳了。

。。。待续
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: