关闭

注释PEMaker6源代码(一)

865人阅读 评论(0) 收藏 举报



这两天看了精华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);
} 
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3649737次
    • 积分:59819
    • 等级:
    • 排名:第40名
    • 原创:1549篇
    • 转载:1252篇
    • 译文:0篇
    • 评论:459条
    最新评论