欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

用vc6.0自己实现添加区段

用vc6.0自己实现添加区段

最经刚刚看完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调试信息 。

上传的附件 LoadPE.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功