注释PEMaker6源代码(一)

转载 2007年09月26日 09:06:00



这两天看了精华8的“向导入表中注入代码“这篇文章,对阅读PEMaker6源代码进行了部分注释,要不总是忘了哪一部分是什么功能,为了增加点发帖量,将注释过的几个类逐一整理后发布,老鸟就无需看了,也是为了自己加强学习。
这篇介绍CPELibrary类的功能:找回并重建PE文件(具体可参照加壳技术->加壳软件的编写->向PE中注入代码)
类定义:
class CPELibrary 
{
private:
  //-----------------------------------------
  PCHAR          pMem;
  DWORD          dwFileSize;
  //-----------------------------------------
protected:
  //-----------------------------------------
  PIMAGE_DOS_HEADER    image_dos_header;
  PCHAR          pDosStub;
  DWORD          dwDosStubSize, dwDosStubOffset;
  PIMAGE_NT_HEADERS    image_nt_headers;  //指针
  PIMAGE_SECTION_HEADER  image_section_header[MAX_SECTION_NUM];
  PCHAR          image_section[MAX_SECTION_NUM];
  /*typedef struct _IMAGE_TLS_DIRECTORY32 {
    DWORD   StartAddressOfRawData;
    DWORD   EndAddressOfRawData;
    PDWORD  AddressOfIndex;
    PIMAGE_TLS_CALLBACK *AddressOfCallBacks;
    DWORD   SizeOfZeroFill;
    DWORD   Characteristics;
  } IMAGE_TLS_DIRECTORY32*/
  PIMAGE_TLS_DIRECTORY32  image_tls_directory;
  //-----------------------------------------
protected:
  //-----------------------------------------
  DWORD PEAlign(DWORD dwTarNum,DWORD dwAlignTo);
  void AlignmentSections();
  //-----------------------------------------
  DWORD Offset2RVA(DWORD dwRO);
  DWORD RVA2Offset(DWORD dwRVA);
  //-----------------------------------------
  PIMAGE_SECTION_HEADER ImageRVA2Section(DWORD dwRVA);
  PIMAGE_SECTION_HEADER ImageOffset2Section(DWORD dwRO);
  //-----------------------------------------
  DWORD ImageOffset2SectionNum(DWORD dwRVA);
  PIMAGE_SECTION_HEADER AddNewSection(char* szName,DWORD dwSize);
  //-----------------------------------------
public:
  //-----------------------------------------
  CPELibrary();
  ~CPELibrary();
  //-----------------------------------------
  void OpenFile(char* FileName);
  void SaveFile(char* FileName);  
  //-----------------------------------------
};
CPP文件:
CPELibrary::CPELibrary()
{    //构造DOS文件头
    image_dos_header=new (IMAGE_DOS_HEADER);
    dwDosStubSize=0;
    //构造NT文件头
    image_nt_headers=new (IMAGE_NT_HEADERS);
    //构造20个节表
    for(int i=0;i<MAX_SECTION_NUM;i++) image_section_header[i]=new (IMAGE_SECTION_HEADER);
    image_tls_directory=NULL;
}
//----------------------------------------------------------------
CPELibrary::~CPELibrary()
{
    delete []image_dos_header;
    dwDosStubSize=0;
    delete []image_nt_headers;
    for(int i=0;i<MAX_SECTION_NUM;i++) delete []image_section_header[i];
    if(image_tls_directory!=NULL) delete image_tls_directory;
}
//================================================================
//----------------------------------------------------------------
// returns aligned value
//对齐
DWORD CPELibrary::PEAlign(DWORD dwTarNum,DWORD dwAlignTo)
{    
    return(((dwTarNum+dwAlignTo-1)/dwAlignTo)*dwAlignTo);
}
//----------------------------------------------------------------
void CPELibrary::AlignmentSections()
{    //根据节的数量循环
    for(int i=0;i<image_nt_headers->FileHeader.NumberOfSections;i++)
    {
        //节中数据的RVA。
        image_section_header[i]->VirtualAddress=
            PEAlign(image_section_header[i]->VirtualAddress,
            image_nt_headers->OptionalHeader.SectionAlignment);
        //对齐Misc.VirtualSize
        image_section_header[i]->Misc.VirtualSize=
            PEAlign(image_section_header[i]->Misc.VirtualSize,
            image_nt_headers->OptionalHeader.SectionAlignment);
        //对齐PointerToRawData
        image_section_header[i]->PointerToRawData=
            PEAlign(image_section_header[i]->PointerToRawData,
            image_nt_headers->OptionalHeader.FileAlignment);
        //对齐SizeOfRawData
        image_section_header[i]->SizeOfRawData=
            PEAlign(image_section_header[i]->SizeOfRawData,
            image_nt_headers->OptionalHeader.FileAlignment);
    }
    //是个RVA,重建映象文件基址
    image_nt_headers->OptionalHeader.SizeOfImage=image_section_header[i-1]->VirtualAddress+
        image_section_header[i-1]->Misc.VirtualSize;
    image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress=0;
    image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size=0;
    image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress=0;
    image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size=0;
    image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress=0;
    image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size=0;
}
//================================================================
//----------------------------------------------------------------
// calulates the Offset from a RVA
// Base    - base of the MMF
// dwRVA - the RVA to calculate
// returns 0 if an error occurred else the calculated Offset will be returned
DWORD CPELibrary::RVA2Offset(DWORD dwRVA)
{
    DWORD _offset;
    PIMAGE_SECTION_HEADER section;
    section=ImageRVA2Section(dwRVA);//ImageRvaToSection(pimage_nt_headers,Base,dwRVA);
    if(section==NULL)
    {
        return(0);
    }
    //文件偏移
    _offset=(dwRVA-section->VirtualAddress)+section->PointerToRawData;
    return(_offset);
}
//----------------------------------------------------------------
// calulates the RVA from a Offset
// Base    - base of the MMF
// dwRO - the Offset to calculate
// returns 0 if an error occurred else the calculated Offset will be returned
DWORD CPELibrary::Offset2RVA(DWORD dwRO)
{
    PIMAGE_SECTION_HEADER section;
    section=ImageOffset2Section(dwRO);
    if(section==NULL)
    {
        return(0);
    }
    //返回RVA
    return((dwRO-section->PointerToRawData)+section->VirtualAddress);
}
//================================================================
//----------------------------------------------------------------
PIMAGE_SECTION_HEADER CPELibrary::ImageRVA2Section(DWORD dwRVA)
{
    int i;
    for(i=0;i<image_nt_headers->FileHeader.NumberOfSections;i++)
    {    //确定包含在哪一个节中
        if((dwRVA>=image_section_header[i]->VirtualAddress) && (dwRVA<=(image_section_header[i]->VirtualAddress+image_section_header[i]->SizeOfRawData)))
        {    //返回该节
            return ((PIMAGE_SECTION_HEADER)image_section_header[i]);
        }
    }
    return(NULL);
}

//----------------------------------------------------------------
//The ImageOffset2Section function locates a Off Set address (RO) 
//within the image header of a file that is mapped as a file and
//returns a pointer to the section table entry for that virtual 
//address.
PIMAGE_SECTION_HEADER CPELibrary::ImageOffset2Section(DWORD dwRO)
{
    for(int i=0;i<image_nt_headers->FileHeader.NumberOfSections;i++)
    {
        //确定包含在哪一个节中
        if((dwRO>=image_section_header[i]->PointerToRawData) && (dwRO<(image_section_header[i]->PointerToRawData+image_section_header[i]->SizeOfRawData)))
        {    //返回该节
            return ((PIMAGE_SECTION_HEADER)image_section_header[i]);
        }
    }
    return(NULL);
}
//================================================================
//----------------------------------------------------------------
// retrieve Enrty Point Section Number
// Base    - base of the MMF
// dwRVA - the RVA to calculate
// returns -1 if an error occurred else the calculated Offset will be returned
//由文件偏移到节号
DWORD CPELibrary::ImageOffset2SectionNum(DWORD dwRO)
{
    for(int i=0;i<image_nt_headers->FileHeader.NumberOfSections;i++)
    {
        if((dwRO>=image_section_header[i]->PointerToRawData) && (dwRO<(image_section_header[i]->PointerToRawData+image_section_header[i]->SizeOfRawData)))
        {
            return (i);
        }
    }
    return(-1);
}
//增加新节----------------------------------------------------------------
PIMAGE_SECTION_HEADER CPELibrary::AddNewSection(char* szName,DWORD dwSize)
{
    DWORD roffset,rsize,voffset,vsize;
    //最后一节
    int i=image_nt_headers->FileHeader.NumberOfSections;
    rsize=PEAlign(dwSize,
                image_nt_headers->OptionalHeader.FileAlignment);
    vsize=PEAlign(rsize,
                image_nt_headers->OptionalHeader.SectionAlignment);
    roffset=PEAlign(image_section_header[i-1]->PointerToRawData+image_section_header[i-1]->SizeOfRawData,
                image_nt_headers->OptionalHeader.FileAlignment);
    voffset=PEAlign(image_section_header[i-1]->VirtualAddress+image_section_header[i-1]->Misc.VirtualSize,
                image_nt_headers->OptionalHeader.SectionAlignment);
    //初始化新节表
    memset(image_section_header[i],0,(size_t)sizeof(IMAGE_SECTION_HEADER));
    //通过计算上一节得到
    image_section_header[i]->PointerToRawData=roffset;
    image_section_header[i]->VirtualAddress=voffset;
    //通过传递的参数得到
    image_section_header[i]->SizeOfRawData=rsize;
    image_section_header[i]->Misc.VirtualSize=vsize;
    //属性
    image_section_header[i]->Characteristics=0xC0000040;
    //新节名称
    memcpy(image_section_header[i]->Name,szName,(size_t)strlen(szName));
    //申请一个节的空间
    image_section[i]=(char*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,rsize);
    //更新文件头
    image_nt_headers->FileHeader.NumberOfSections++;
    //返回新节
    return (PIMAGE_SECTION_HEADER)image_section_header[i];
}
//================================================================
//----------------------------------------------------------------
void CPELibrary::OpenFile(char* FileName)
{
    DWORD    dwBytesRead        = 0;
    HANDLE    hFile= NULL;
    DWORD SectionNum;
    DWORD i;
    DWORD dwRO_first_section;
    //基类成员
    pMem=NULL;
    //----------------------------------------
    hFile=CreateFile(FileName,
                     GENERIC_READ,
                     FILE_SHARE_WRITE | FILE_SHARE_READ,
                     NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    if(hFile==INVALID_HANDLE_VALUE)
    {
        ShowErr(FileErr);
        return;
    }
    dwFileSize=GetFileSize(hFile,0);
    if(dwFileSize == 0)
    {
        CloseHandle(hFile);
        ShowErr(FsizeErr);
        return;
    }
    //不用内存映射文件,奇怪?
    pMem=(char*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,dwFileSize);
    if(pMem == NULL)
    {
        CloseHandle(hFile);
        ShowErr(MemErr);
        return;
    }
    //读入文件
    ReadFile(hFile,pMem,dwFileSize,&dwBytesRead,NULL);
    //关闭句柄
    CloseHandle(hFile);
    //----------------------------------------
    //读出DOS文件头
    memcpy(image_dos_header,pMem,sizeof(IMAGE_DOS_HEADER));
    //MS-DOS Stub Program(位于e_lfanew和Signature之间)
    dwDosStubSize=image_dos_header->e_lfanew-sizeof(IMAGE_DOS_HEADER);
    dwDosStubOffset=sizeof(IMAGE_DOS_HEADER);
    pDosStub=new CHAR[dwDosStubSize];
    if((dwDosStubSize&0x80000000)==0x00000000)
    {
        CopyMemory(pDosStub,pMem+dwDosStubOffset,dwDosStubSize);
    }
    //读出NT文件头
    memcpy(image_nt_headers,
               pMem+image_dos_header->e_lfanew,
               sizeof(IMAGE_NT_HEADERS));
    //DOS头大小+NT头大小
    dwRO_first_section=image_dos_header->e_lfanew+sizeof(IMAGE_NT_HEADERS);
    if(image_dos_header->e_magic!=IMAGE_DOS_SIGNATURE)// MZ
    {
        ShowErr(PEErr);
        GlobalFree(pMem);
        return;
    }
    if(image_nt_headers->Signature!=IMAGE_NT_SIGNATURE)// PE00
    {
        ShowErr(PEErr);
        GlobalFree(pMem);
        return;
    }
    //----------------------------------------
    //节的数量
    SectionNum=image_nt_headers->FileHeader.NumberOfSections;
    //----------------------------------------
    for( i=0;i<SectionNum;i++) 
    {
        //读取节表,储存节表的空间已经初始化了。
        CopyMemory(image_section_header[i],pMem+dwRO_first_section+i*sizeof(IMAGE_SECTION_HEADER),
            sizeof(IMAGE_SECTION_HEADER));
    }
    //----------------------------------------
    for(i=0;i<SectionNum;i++)
    {
            //为每个节数据分配空间,大小为每个节在文件中的大小
            image_section[i]=(char*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
                PEAlign(image_section_header[i]->SizeOfRawData,
                image_nt_headers->OptionalHeader.FileAlignment));
            //循环读出每个节,按照文件对齐
            CopyMemory(image_section[i],
                    pMem+image_section_header[i]->PointerToRawData,
                    image_section_header[i]->SizeOfRawData);
    }
    //是否存在TLS节----------------------------------------
    if(image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress!=0)
    {
        //分配空间
        image_tls_directory = new (IMAGE_TLS_DIRECTORY32);
        //文件偏移
        DWORD dwOffset=RVA2Offset(image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
        //复制
        memcpy(image_tls_directory,
                pMem+dwOffset,
                sizeof(IMAGE_TLS_DIRECTORY32));        
    }
    //----------------------------------------
    GlobalFree(pMem);
}
//----------------------------------------------------------------
void CPELibrary::SaveFile(char* FileName)
{
    DWORD    dwBytesWritten    = 0;
    DWORD i;
    DWORD dwRO_first_section;
    DWORD SectionNum;
    HANDLE    hFile= NULL;
    pMem=NULL;
    //----------------------------------------
    hFile=CreateFile(FileName,
                     GENERIC_WRITE,
                     FILE_SHARE_WRITE | FILE_SHARE_READ,
                     NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
    if(hFile==INVALID_HANDLE_VALUE)
    {
        hFile=CreateFile(FileName,
                     GENERIC_WRITE,
                     FILE_SHARE_WRITE | FILE_SHARE_READ,
                     NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
        if(hFile==INVALID_HANDLE_VALUE)
        {
            ShowErr(FileErr);
            return;
        }
    }
    //对齐----------------------------------------
    AlignmentSections();
    //----------------------------------------
    i=image_nt_headers->FileHeader.NumberOfSections;
    //得到新文件的大小
    dwFileSize=image_section_header[i-1]->PointerToRawData+
        image_section_header[i-1]->SizeOfRawData;
    //申请内存
    pMem=(char*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,dwFileSize);
    if(pMem == NULL)
    {
        CloseHandle(hFile);
        ShowErr(MemErr);
        return;
    }
    //复制DOS头----------------------------------------
    memcpy(pMem,image_dos_header,sizeof(IMAGE_DOS_HEADER));
    //MS-DOS Stub Program
    if((dwDosStubSize&0x80000000)==0x00000000)
    {
        memcpy(pMem+dwDosStubOffset,pDosStub,dwDosStubSize);
    }
    //复制NT头
    memcpy(pMem+image_dos_header->e_lfanew,
        image_nt_headers,
        sizeof(IMAGE_NT_HEADERS));
    //节表的偏移
    dwRO_first_section=image_dos_header->e_lfanew+sizeof(IMAGE_NT_HEADERS);
    //节的数量
    SectionNum=image_nt_headers->FileHeader.NumberOfSections;
    //复制节表----------------------------------------
    for( i=0;i<SectionNum;i++) 
    {
        CopyMemory(pMem+dwRO_first_section+i*sizeof(IMAGE_SECTION_HEADER),
            image_section_header[i],
            sizeof(IMAGE_SECTION_HEADER));
    }
    //复制节数据----------------------------------------
    for(i=0;i<SectionNum;i++)
    {
        CopyMemory(pMem+image_section_header[i]->PointerToRawData,
                image_section[i],
                image_section_header[i]->SizeOfRawData);
    }
    // ----- WRITE FILE MEMORY TO DISK -----
    //设置文件指针
    SetFilePointer(hFile,0,NULL,FILE_BEGIN);
    //写内存到磁盘
    WriteFile(hFile,pMem,dwFileSize,&dwBytesWritten,NULL);
    
    // ------ FORCE CALCULATED FILE SIZE ------
    //强制计算文件大小
    SetFilePointer(hFile,dwFileSize,NULL,FILE_BEGIN);
    SetEndOfFile(hFile);
    CloseHandle(hFile);
    //----------------------------------------
    GlobalFree(pMem);
} 

注释PEMaker6源代码(三)

今天大概看了一下精华8《向PE中注入代码》的译文,之前没有仔细看过,因为发现看过之后对源代码还是不是很明白,所以就没有参照这篇译...
  • iiprogram
  • iiprogram
  • 2007年09月26日 09:10
  • 856

注释PEMaker6源代码(二)

 
  • iiprogram
  • iiprogram
  • 2007年09月26日 09:24
  • 601

看懂源码之注释规范

1.前言为了增强源代码的可阅读性、结构性,方便代码阅读者对源代码的阅读和理解,以及方便源代码文档的制作和生成,源代码的注释通常按一定的规范编写。 所以要想更好的读懂源码,就必须对注释规范有一定的了解...
  • qq_29012777
  • qq_29012777
  • 2016年10月10日 15:48
  • 828

linux 0.11源代码完全中文注释

http://markzhong.com/roller/page/mark/20050122#2005_01_22_%E9%98%B4%E5%86%B7在网上瞎逛找到本由赵炯博士写的linux 0.1...
  • zgzjw
  • zgzjw
  • 2005年01月24日 21:55
  • 1645

matlab大段注释的方法

方法一: 注释语句的快捷键是Ctrl+R 取消注释的快捷键是Ctrl+T 并且支持一次注释(或者取消注释)多行语句。 选定要注释(或者取消注释)的那些语句,然后按Ctrl+R(或者Ctrl+T...
  • u012150360
  • u012150360
  • 2017年03月26日 15:25
  • 943

Lua5.1 源码注释(一) table.c

/* ** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ ** Lua tables (hash) ** See Copyrig...
  • lovesmiles
  • lovesmiles
  • 2017年07月25日 20:02
  • 321

Html5第一篇&一些注释和总结

DTD、API、总结
  • xiaofuzi_outlook
  • xiaofuzi_outlook
  • 2018年01月05日 20:29
  • 22

java 五子棋源代码+注释

package cn.hcnu.fiveChess; import java.awt.Color; import java.awt.Graphics; public cl...
  • wangjian_an
  • wangjian_an
  • 2016年03月02日 12:06
  • 1105

vs2015源文件创建代码自动版权声明注释

我们在新建代码文件是时常要在头部加一些企业或个人的版权信息。而多次地手动的书写版权声明信息势必会麻烦。下面我们将以创建C#文件自动添加头部版权声明作为示范。 首先,要把下面版权信息加入模版中。 #re...
  • da454122373
  • da454122373
  • 2017年01月10日 14:10
  • 2617

删除c/c++源程序中的注释

题目:编写一个程序,用于处理c/c++源程序,将源程序中的注释部分去掉输入:c/c++文件名输出:处理后的程序源文件程序伪代码如下:c1,c2:chartag:inta:读入一个字符存入c1if ta...
  • qaz19870418
  • qaz19870418
  • 2010年04月24日 19:10
  • 2896
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:注释PEMaker6源代码(一)
举报原因:
原因补充:

(最多只允许输入30个字)