最经刚刚看完PE 文件的格式规范,发现手工添加区块太麻烦,所以 自己花了4个小时编写一个自动添加区段的程序。(高手就不要看了,鄙人就不献丑了)
添加区段一共分四个步骤
1 修改块的数目(即文件头的NumberOfSections字段)
2 增加块头
3 修改PE文件的景象尺寸(即可选头的SizeOfImage字段)
4 增加块
代码注释很详细,本人就不废话了。
定义的变量如下:
private:
IMAGE_DOS_HEADER dos_header; //大小是64
IMAGE_NT_HEADERS32 nt_header; //大小是248
IMAGE_SECTION_HEADER *section_header; //大小是40
函数如下。
BOOL CPeFile::ReadPEFile(HANDLE hFile)
{
DWORD dwRead;
if(hFile==INVALID_HANDLE_VALUE)
return FALSE;
//读取DOS MZ header
if(! ReadFile(hFile,(LPBYTE)&dos_header,sizeof(IMAGE_DOS_HEADER),&dwRead,NULL))
return FALSE;
//判断读取是否成功
if(dwRead!=sizeof(IMAGE_DOS_HEADER))
return FALSE;
//判断是否是DOS MZ header
if(dos_header.e_magic!=0x5A4D)
return FALSE;
//将文件指针移到真正的PE文件头
SetFilePointer(hFile,dos_header.e_lfanew,NULL,FILE_BEGIN);
//读取PE文件头
if(! ReadFile(hFile,(LPBYTE)&nt_header,sizeof(IMAGE_NT_HEADERS32),&dwRead,NULL))
return FALSE;
//判断读取是否成功
if(dwRead!=sizeof(IMAGE_NT_HEADERS32))
return FALSE;
//判断是否是真正的PE文件
if(nt_header.Signature!=0x4550)
return FALSE;
WORD numSect=nt_header.FileHeader.NumberOfSections;
section_header=new IMAGE_SECTION_HEADER[numSect];
if(section_header==NULL) //申请内存失败
return FALSE;
//读取块表
if(! ReadFile(hFile,(LPBYTE)section_header,numSect*sizeof(IMAGE_SECTION_HEADER),&dwRead,NULL))
return FALSE;
//判断读取是否成功
if(dwRead!=numSect*sizeof(IMAGE_SECTION_HEADER))
return FALSE;
return TRUE;
}
BOOL CPeFile::AddSection(BYTE name[IMAGE_SIZEOF_SHORT_NAME],DWORD len,HANDLE hFile)
{
if(hFile==INVALID_HANDLE_VALUE)
return FALSE;
IMAGE_SECTION_HEADER newSect; //新块
//获取信息
DWORD fileAlign=nt_header.OptionalHeader.FileAlignment; //文件粒度
DWORD sectAlign=nt_header.OptionalHeader.SectionAlignment; //块的粒度
WORD numofsect=nt_header.FileHeader.NumberOfSections; //块的数目
/*****************************初始化newSect的数据************************/
//重定位偏移
newSect.PointerToRelocations=0;
//重定位表数目
newSect.NumberOfRelocations=0;
//行号表的偏移
newSect.PointerToLinenumbers=0;
//行号表的中行号数目
newSect.NumberOfLinenumbers=0;
//块属性
newSect.Characteristics=IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
//块的名字
for(int i=0;i<IMAGE_SIZEOF_SHORT_NAME;i++)
newSect.Name[i]=name[i];
//快的真实长度
newSect.Misc.PhysicalAddress=len;
//文件中对齐后的尺寸
newSect.SizeOfRawData=(len%fileAlign?fileAlign*(len/fileAlign+1):len);
//在文件中的偏移
newSect.PointerToRawData=section_header[numofsect-1].PointerToRawData+section_header[numofsect-1].SizeOfRawData;
//该块的RVA
DWORD virtualSize;
if(section_header[numofsect-1].SizeOfRawData % sectAlign) //计算上一块的景象大小
virtualSize=sectAlign*(section_header[numofsect-1].SizeOfRawData/sectAlign+1);
else
virtualSize=section_header[numofsect-1].SizeOfRawData;
newSect.VirtualAddress=section_header[numofsect-1].VirtualAddress+virtualSize;
/**********************************修改PE文件**************************************/
DWORD dwWrite;
DWORD pointloc;
//修改快的数目
WORD newNumofsect=1+numofsect;
//将文件指针移到块数目位置
SetFilePointer(hFile,dos_header.e_lfanew+6,NULL,FILE_BEGIN);
if(! WriteFile(hFile,(LPBYTE)&newNumofsect,sizeof(WORD),&dwWrite,NULL))
return FALSE;
//判断是否写入成功
if(dwWrite!=sizeof(WORD))
return FALSE;
//修改PE文件的景象尺寸
DWORD size=nt_header.OptionalHeader.SizeOfImage+(len%sectAlign?sectAlign*(len/sectAlign+1):len);;
//将文件指针移到块数目位置
SetFilePointer(hFile,dos_header.e_lfanew+0x50,NULL,FILE_BEGIN);
if(! WriteFile(hFile,(LPBYTE)&size,sizeof(DWORD),&dwWrite,NULL))
return FALSE;
//判断是否写入成功
if(dwWrite!=sizeof(DWORD))
return FALSE;
//增加块头
pointloc=dos_header.e_lfanew+sizeof(IMAGE_NT_HEADERS32)+sizeof(IMAGE_SECTION_HEADER)*nt_header.FileHeader.NumberOfSections;
//将文件指针移到所有的块末尾。
SetFilePointer(hFile,pointloc,NULL,FILE_BEGIN);
if(!WriteFile(hFile,(LPBYTE)&newSect,sizeof(IMAGE_SECTION_HEADER),&dwWrite,NULL))
return FALSE;
//判断是否写入成功
if(dwWrite!=sizeof(IMAGE_SECTION_HEADER))
return FALSE;
//增加块
char ret[200]={'0'};
//将文件指针移到所有的块末尾。
SetFilePointer(hFile,newSect.PointerToRawData,NULL,FILE_BEGIN);
if(!WriteFile(hFile,(LPBYTE)ret,newSect.SizeOfRawData,&dwWrite,NULL))
return FALSE;
//判断是否写入成功
if(dwWrite!=newSect.SizeOfRawData)
return FALSE;
return TRUE;
}
代码还不是很完善,望谅解。比如:没有判断所有块头之后是否可以添加新块头,
还有就是没有判断所有块之后是否还有其他信息,比如COFF行号 COFF符号表,Code View调试信息 。
- 标 题:用vc6.0自己实现添加区段
- 作 者:machfe
- 时 间:2008-11-14 13:23
- 链 接:http://bbs.pediy.com/showthread.php?t=76692