c++ 实现PE文件格式分析

在这里插入
#include <Windows.h>
#include <stdio.h>
#include <winnt.h>

PIMAGE_DOS_HEADER dos_header;
HANDLE handle;
PIMAGE_NT_HEADERS ntheader;
DWORD bytesRead;
DWORD lfanew;
PIMAGE_FILE_HEADER fileheader;

PIMAGE_SECTION_HEADER sectionheader;

PIMAGE_DATA_DIRECTORY data_directory;

// 导出表
PIMAGE_EXPORT_DIRECTORY Export;

// 导入表
PIMAGE_IMPORT_DESCRIPTOR import;

DWORD VirtualAddress;

DWORD exportVirtualAddress;
DWORD exportsize;

DWORD importVirtualAddress;
DWORD importsize;

DWORD *name;
DWORD FirstThunkfileRVA;
DWORD OriginalFirstThunkfileRVA;

PIMAGE_IMPORT_BY_NAME funcname;

WORD Machine;

WORD NumberOfSections;
DWORD SizeOfOptionalHeader;

DWORD getRWA(DWORD RVA, PIMAGE_SECTION_HEADER sectionheader)
{

    DWORD RWA = 0;
    for (int i = 0; i < 16; i++)
    {
        if (RVA >= sectionheader->VirtualAddress && RVA < sectionheader->VirtualAddress + sectionheader->SizeOfRawData)
        {

            RWA = (RVA - sectionheader->VirtualAddress) + sectionheader->PointerToRawData;
            return RWA;
        }

        sectionheader = PIMAGE_SECTION_HEADER((BYTE *)sectionheader + (sizeof(IMAGE_SECTION_HEADER)));
    }

    return RWA;
}

void getImport(char *pFileBuf, int i)
{
    if (i)
    {
        PIMAGE_THUNK_DATA32 FirstThunk;
        PIMAGE_THUNK_DATA32 OriginalFirstThunk;
        importVirtualAddress = data_directory[1].VirtualAddress;
        importsize = data_directory[1].Size;
        if (importVirtualAddress != 0 || importsize != 0)

        {
            printf("=======================导入表======================\n\n");
            import = (PIMAGE_IMPORT_DESCRIPTOR)((char *)dos_header + getRWA(importVirtualAddress, sectionheader));

            while (import->Name)

            {
                name = (DWORD *)(pFileBuf + getRWA(import->Name, sectionheader));
                // printf("%s \n",name);
                FirstThunkfileRVA = getRWA(import->FirstThunk, sectionheader);
                FirstThunk = (PIMAGE_THUNK_DATA32)(pFileBuf + FirstThunkfileRVA);
                OriginalFirstThunkfileRVA = getRWA(import->OriginalFirstThunk, sectionheader);
                OriginalFirstThunk = (PIMAGE_THUNK_DATA32)(pFileBuf + OriginalFirstThunkfileRVA);

                while (OriginalFirstThunk->u1.Ordinal != 0)
                {

                    if (OriginalFirstThunk->u1.AddressOfData & 0x80000000)
                    {

                        printf("模块名: %s 序号导出 %x \n", name, OriginalFirstThunk->u1.AddressOfData);
                    }
                    else
                    {

                        funcname = (PIMAGE_IMPORT_BY_NAME)(pFileBuf + getRWA(OriginalFirstThunk->u1.Function, sectionheader));
                        // printf("%x", getRWA(0x3c1b0, sectionheader2));
                        printf("------------------\n");
                        printf("模块名:%s ", name);
                        printf("函数名:%s ", funcname->Name);
                        printf("OriginalFirstThunk RVA:%x  ", OriginalFirstThunk->u1.Function);
                        printf("FirstThunk RVA:%x  \n", import->FirstThunk);
                    }
                    OriginalFirstThunk++;
                }
                import++;
            }
        }
        else
        {
            printf("没有导出表 \n");
        }
    }
    else
    {
        PIMAGE_THUNK_DATA64 FirstThunk;
        PIMAGE_THUNK_DATA64 OriginalFirstThunk;
        importVirtualAddress = data_directory[1].VirtualAddress;
        importsize = data_directory[1].Size;
        if (importVirtualAddress != 0 || importsize != 0)

        {
            printf("=======================导入表======================\n\n");
            import = (PIMAGE_IMPORT_DESCRIPTOR)((char *)dos_header + getRWA(importVirtualAddress, sectionheader));
           

            while (import->Name)

            {
                name = (DWORD *)(pFileBuf + getRWA(import->Name, sectionheader));
                // printf("%s \n",name);
                FirstThunkfileRVA = getRWA(import->FirstThunk, sectionheader);
                FirstThunk = (PIMAGE_THUNK_DATA64)(pFileBuf + FirstThunkfileRVA);
                OriginalFirstThunkfileRVA = getRWA(import->OriginalFirstThunk, sectionheader);
                OriginalFirstThunk = (PIMAGE_THUNK_DATA64)(pFileBuf + OriginalFirstThunkfileRVA);

                while (OriginalFirstThunk->u1.Ordinal != 0)
                {

                    if (OriginalFirstThunk->u1.AddressOfData & 0x80000000)
                    {

                        printf("模块名: %s 序号导出 %x \n", name, OriginalFirstThunk->u1.AddressOfData);
                    }
                    else
                    {

                        funcname = (PIMAGE_IMPORT_BY_NAME)(pFileBuf + getRWA(OriginalFirstThunk->u1.Function, sectionheader));
                        printf("------------------\n");
                        printf("模块名:%s ", name);
                        printf("函数名:%s ", funcname->Name);
                        printf("OriginalFirstThunk RVA:%x  ", OriginalFirstThunk->u1.Function);
                        printf("FirstThunk RVA:%x  \n", import->FirstThunk);
                       
                    }
                    OriginalFirstThunk++;
                }
                import++;
            }
        }
        else
        {
            printf("没有导入表 \n");
        }
    }
}

void getexport(char *pFileBuf)


{
    DWORD sum = 1;
    DWORD *fliename;

    DWORD NumberOfNames;

    // 输出函数地址的RVA
    DWORD *AddressOfFunctionsRVA;

    DWORD *AddressOfFunctions;

    // 输出函数名字的RVA
    DWORD *AddressOfNamesRVA;

    DWORD *AddressOfNames;

    // 指向输出函数序号的RVA
    WORD *AddressOfNameOrdinalsRVA;

    DWORD base;
    exportVirtualAddress = data_directory[0].VirtualAddress;
    exportsize = data_directory[0].Size;

    if (exportVirtualAddress || exportsize)
    {
        DWORD exportfileVAR;
        // 导出表文件偏移地址
        exportfileVAR = getRWA(exportVirtualAddress, sectionheader);
        printf("=======================导出表======================\n\n");

        Export = PIMAGE_EXPORT_DIRECTORY(pFileBuf + exportfileVAR);

        base = Export->Base;

        // 文件名
        fliename = (DWORD *)(pFileBuf + getRWA(Export->Name, sectionheader));

        // 导出函数的总数
        NumberOfNames = Export->NumberOfNames;

        AddressOfNamesRVA = (DWORD *)(pFileBuf + getRWA(Export->AddressOfNames, sectionheader));

        // 函数名
        AddressOfNames = (DWORD *)(pFileBuf + getRWA(*AddressOfNamesRVA, sectionheader));
        // 函数名的RVA
        AddressOfFunctionsRVA = (DWORD *)(pFileBuf + getRWA(Export->AddressOfFunctions, sectionheader));

        AddressOfNameOrdinalsRVA = (WORD *)(pFileBuf + getRWA(Export->AddressOfNameOrdinals, sectionheader));
        for (int i = 0; i < NumberOfNames; i++)
        {
            int index = 0;
            index = (base + *AddressOfNameOrdinalsRVA);
            AddressOfFunctionsRVA = (DWORD *)((BYTE *)AddressOfFunctionsRVA + (index - sum) * sizeof(DWORD));
            printf("\n函数名称:%s ", AddressOfNames);
            printf("RVA: %x ", *AddressOfFunctionsRVA);
            printf("文件偏移: %x \n", getRWA(*AddressOfFunctionsRVA, sectionheader));
            AddressOfNames++;
            AddressOfFunctionsRVA++;
        }
    }
    else
    {
        printf("没有导出表 \n");
    }
}

void printfsectionheader()
{

    printf("\n");
    for (int i = 0; i < NumberOfSections; i++)
    {

        printf("\n");
        printf("区块名称 :%s ", sectionheader[i].Name);
        printf("真实长度 :%x ", sectionheader[i].Misc.VirtualSize);
        printf("RVA 地址 :%x ", sectionheader[i].VirtualAddress);
        printf("按照0x200对齐后的长度 :%x ", sectionheader[i].SizeOfRawData);
        printf("磁盘文件的偏移 :%x ", sectionheader[i].PointerToRawData);
        printf("\n");
    }
    printf("\n");
}

void printdata_directroy()
{
    for (int i = 0; i < 16; i++)
        {

            printf("data_directroy[%d]: %x\n", i, data_directory[i].VirtualAddress);
            printf("data_directroy[%d]: %x\n", i, data_directory[i].Size);
        }
}
int main()
{
    do{

        handle = CreateFileA(".\\01.dll",
                             GENERIC_READ,
                             FILE_SHARE_READ,
                             NULL,
                             OPEN_EXISTING,
                             FILE_ATTRIBUTE_NORMAL,
                             NULL);
        if (handle == INVALID_HANDLE_VALUE)

        {
            printf("文件加载失败");
            break;
        }
        DWORD dwFileSize = GetFileSize(handle, NULL);

        if (dwFileSize==0){
            break;
        }

        CHAR *pFileBuf = new CHAR[dwFileSize];

        ReadFile(handle, pFileBuf, dwFileSize, &bytesRead, NULL);
        dos_header = (PIMAGE_DOS_HEADER)pFileBuf;
        // printf("dos_headr %x ",dos_header);
        if (!dos_header->e_magic == 0x5a4d)
        {
            printf("不是PE文件");
            break;
        }

        printf("dos_haendr->e_magic = %x \n", dos_header->e_magic);
        lfanew = dos_header->e_lfanew;
        printf("dos_header->e_lfanew %X \n", dos_header->e_lfanew);

        ntheader = (PIMAGE_NT_HEADERS)((BYTE *)dos_header + lfanew);
        if (!ntheader == 0x4550)
        {
            printf("不是PE文件");
            break;
        }
        printf("ntheader->Signature: %x\n", ntheader->Signature);

        fileheader = &(ntheader->FileHeader);

        SizeOfOptionalHeader = fileheader->SizeOfOptionalHeader;
        NumberOfSections = fileheader->NumberOfSections;

        Machine = fileheader->Machine;

        if (Machine == IMAGE_FILE_MACHINE_I386)
        {
            printf("\n=================32位================");
            PIMAGE_NT_HEADERS32 ntheader32;
            ntheader32 = (PIMAGE_NT_HEADERS32)((BYTE *)dos_header + lfanew);

            PIMAGE_OPTIONAL_HEADER32 opheader32;
            opheader32 = (PIMAGE_OPTIONAL_HEADER32) & (ntheader32->OptionalHeader);
            sectionheader = PIMAGE_SECTION_HEADER((BYTE *)opheader32 + SizeOfOptionalHeader);
            printfsectionheader();
            data_directory = opheader32->DataDirectory;
            printdata_directroy();
            getexport(pFileBuf);
            printf("\n");
            getImport(pFileBuf, 0);
        }
        else
        {

            printf("\n=================64位================");
            PIMAGE_NT_HEADERS64 ntheader64;
            ntheader64 = (PIMAGE_NT_HEADERS64)((BYTE *)dos_header + lfanew);

            PIMAGE_OPTIONAL_HEADER64 opheader64;

            opheader64 = &(ntheader64->OptionalHeader);
            sectionheader = PIMAGE_SECTION_HEADER((BYTE *)opheader64 + SizeOfOptionalHeader);
            printfsectionheader();
            data_directory = opheader64->DataDirectory;
            printdata_directroy();
            printf("\n");
            getexport(pFileBuf);
            printf("\n");
            getImport(pFileBuf, 0);
        }

        getchar();
    }while(0);

    CloseHandle(handle);
    return 0;

}



代码片

最近在学习PE 文件格式 。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值