首页
社区
课程
招聘
[原创]菜鸟注释PEMaker6源代码(一)
发表于: 2007-9-16 00:11 8575

[原创]菜鸟注释PEMaker6源代码(一)

2007-9-16 00:11
8575

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


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 2134
活跃值: (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
2
支持,希望继续把后面的注释出来,
最好能把整个程序给个额外的注释,说明整体思路
2007-9-16 15:05
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
3
是个好习惯
2007-9-18 13:57
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
4
看样子还有后续!
2007-9-18 15:28
0
雪    币: 242
活跃值: (1664)
能力值: ( LV9,RANK:410 )
在线值:
发帖
回帖
粉丝
5
确实不错,学习一下
2007-9-18 17:13
0
雪    币: 332
活跃值: (30)
能力值: ( LV12,RANK:460 )
在线值:
发帖
回帖
粉丝
6
后续在下面~~~~~~~~
2007-9-18 19:56
0
雪    币: 3686
活跃值: (1036)
能力值: (RANK:760 )
在线值:
发帖
回帖
粉丝
7
不错,不错,正需要这样一个PELibrary,自己重写太麻烦
2007-9-19 13:53
0
游客
登录 | 注册 方可回帖
返回
//