加载PE标头

发布于 2024-12-25 14:58:59 字数 641 浏览 5 评论 0原文

基本上,我想做的是找到 PE 文件的最后一部分。我非常仔细地阅读了PE规范,但我无法发现我的代码失败的地方。

PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)buffer;
PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)(pidh + pidh->e_lfanew);
PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
PIMAGE_OPTIONAL_HEADER pioh = (PIMAGE_OPTIONAL_HEADER)&pinh->OptionalHeader;
PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)(pinh + sizeof(IMAGE_NT_HEADERS) + (pifh->NumberOfSections - 1) * sizeof(IMAGE_SECTION_HEADER));

buffer 是一个包含加载的可执行文件的字节数组,pish 是指向最后一节的指针。由于某种原因,部分数量似乎超过 20 000。

有什么想法吗? 提前致谢

Basically, what I am trying to do is to find last section of PE file. I have read PE specification very attentively, yet I can't discover where my code fails.

PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)buffer;
PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)(pidh + pidh->e_lfanew);
PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
PIMAGE_OPTIONAL_HEADER pioh = (PIMAGE_OPTIONAL_HEADER)&pinh->OptionalHeader;
PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)(pinh + sizeof(IMAGE_NT_HEADERS) + (pifh->NumberOfSections - 1) * sizeof(IMAGE_SECTION_HEADER));

buffer is a byte array containing loaded executable, and pish is a pointer to the last section. For some reason, it appears that number of sections is over 20 000.

Any ideas ?
Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

遗心遗梦遗幸福 2025-01-01 14:59:00

我立即发现一个问题:e_lfanew 是 IMAGE_NT_HEADERS 结构的偏移量(以字节为单位)。您要将这个字节数添加到 IMAGE_DOS_HEADER 指针中,因此您将向前移动 sizeof(IMAGE_DOS_HEADER)*pidh->e_lfanew 字节。

修复版本:

PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)buffer;
PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE*)pidh + pidh->e_lfanew);
PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
PIMAGE_OPTIONAL_HEADER pioh = (PIMAGE_OPTIONAL_HEADER)&pinh->OptionalHeader;
PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)((BYTE*)pinh + sizeof(IMAGE_NT_HEADERS) + (pifh->NumberOfSections - 1) * sizeof(IMAGE_SECTION_HEADER));

调试此类问题的最佳方法是使用调试器进入代码并亲自查看内存中的 PE 数据。例如,您可以打开 Visual Studio 十六进制编辑器并查看所有字节数据以及您实际读取的值。

以下是有关在 VS 2010 中查看程序内存的一些信息:
http://msdn.microsoft.com/en-us/library/s3aw423e.aspx

There is one problem I see off hand: e_lfanew is the offset to the IMAGE_NT_HEADERS structure in bytes. You are adding this number of bytes to a IMAGE_DOS_HEADER pointer, so you are moving forward by sizeof(IMAGE_DOS_HEADER)*pidh->e_lfanew bytes.

Fixed version:

PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)buffer;
PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE*)pidh + pidh->e_lfanew);
PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
PIMAGE_OPTIONAL_HEADER pioh = (PIMAGE_OPTIONAL_HEADER)&pinh->OptionalHeader;
PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)((BYTE*)pinh + sizeof(IMAGE_NT_HEADERS) + (pifh->NumberOfSections - 1) * sizeof(IMAGE_SECTION_HEADER));

The best way to debug problems like this is to drop into the code with your debugger and view the PE data yourself in memory. You can open up the Visual Studio hex editor for example and see all of the byte data, and which values you are actually reading out.

Here's some information on viewing program memory in VS 2010:
http://msdn.microsoft.com/en-us/library/s3aw423e.aspx

雪花飘飘的天空 2025-01-01 14:59:00

各段地址和数据也可以通过以下方式获取:

#include<windows.h>
#include<iostream>

int main()
{
    LPCSTR fileName="inputFile.exe";
    HANDLE hFile;
    HANDLE hFileMapping;
    LPVOID lpFileBase;
    PIMAGE_DOS_HEADER dosHeader;
    PIMAGE_NT_HEADERS peHeader;
    PIMAGE_SECTION_HEADER sectionHeader;

    hFile = CreateFileA(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

    if(hFile==INVALID_HANDLE_VALUE)
    {
        std::cout<<"\n CreateFile failed \n";
        return 1;
    }

    hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);

    if(hFileMapping==0)
    {
        std::cout<<"\n CreateFileMapping failed \n";
        CloseHandle(hFile);
        return 1;
    }

    lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0);

    if(lpFileBase==0)
    {
        std::cout<<"\n MapViewOfFile failed \n";
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        return 1;
    }

    dosHeader = (PIMAGE_DOS_HEADER) lpFileBase;
    if(dosHeader->e_magic==IMAGE_DOS_SIGNATURE)
    {
        std::cout<<"\n DOS Signature (MZ) Matched \n";

        peHeader = (PIMAGE_NT_HEADERS) ((u_char*)dosHeader+dosHeader->e_lfanew);
        if(peHeader->Signature==IMAGE_NT_SIGNATURE)
        {
            std::cout<<"\n PE Signature (PE) Matched \n";
            sectionHeader = IMAGE_FIRST_SECTION(peHeader);
            UINT nSectionCount = peHeader->FileHeader.NumberOfSections;

            //No of Sections
            std::cout<<"\n No of Sections : "<<nSectionCount<<"  \n";

            //sectionHeader contains pointer to first section
            //sectionHeader++ will move to next section
            for( UINT i=0; i<nSectionCount; ++i, ++sectionHeader )
            {
                std::cout<<"\n-----------------------------------------------\n";
                std::cout<<"\n Section Name : "<<sectionHeader->Name<<" \n";
                //address can be obtained as (PBYTE)lpFileBase+sectionHeader->PointerToRawData
                std::cout<<"\n Size of section data : "<<sectionHeader->Misc.VirtualSize<<" \n";
                std::cout<<"\n-----------------------------------------------\n";
            }

            //Now sectionHeader will have pointer to last section
            //if you add sectionHeader++ in for loop instead of ++sectionHeader it will point to memory after last section

        }
        else
        {
            return 1;
        }
    }
    else
    {
        return 1;
    }
    return 0;
}

Various section address and data can be obtained by below way also :

#include<windows.h>
#include<iostream>

int main()
{
    LPCSTR fileName="inputFile.exe";
    HANDLE hFile;
    HANDLE hFileMapping;
    LPVOID lpFileBase;
    PIMAGE_DOS_HEADER dosHeader;
    PIMAGE_NT_HEADERS peHeader;
    PIMAGE_SECTION_HEADER sectionHeader;

    hFile = CreateFileA(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

    if(hFile==INVALID_HANDLE_VALUE)
    {
        std::cout<<"\n CreateFile failed \n";
        return 1;
    }

    hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);

    if(hFileMapping==0)
    {
        std::cout<<"\n CreateFileMapping failed \n";
        CloseHandle(hFile);
        return 1;
    }

    lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0);

    if(lpFileBase==0)
    {
        std::cout<<"\n MapViewOfFile failed \n";
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        return 1;
    }

    dosHeader = (PIMAGE_DOS_HEADER) lpFileBase;
    if(dosHeader->e_magic==IMAGE_DOS_SIGNATURE)
    {
        std::cout<<"\n DOS Signature (MZ) Matched \n";

        peHeader = (PIMAGE_NT_HEADERS) ((u_char*)dosHeader+dosHeader->e_lfanew);
        if(peHeader->Signature==IMAGE_NT_SIGNATURE)
        {
            std::cout<<"\n PE Signature (PE) Matched \n";
            sectionHeader = IMAGE_FIRST_SECTION(peHeader);
            UINT nSectionCount = peHeader->FileHeader.NumberOfSections;

            //No of Sections
            std::cout<<"\n No of Sections : "<<nSectionCount<<"  \n";

            //sectionHeader contains pointer to first section
            //sectionHeader++ will move to next section
            for( UINT i=0; i<nSectionCount; ++i, ++sectionHeader )
            {
                std::cout<<"\n-----------------------------------------------\n";
                std::cout<<"\n Section Name : "<<sectionHeader->Name<<" \n";
                //address can be obtained as (PBYTE)lpFileBase+sectionHeader->PointerToRawData
                std::cout<<"\n Size of section data : "<<sectionHeader->Misc.VirtualSize<<" \n";
                std::cout<<"\n-----------------------------------------------\n";
            }

            //Now sectionHeader will have pointer to last section
            //if you add sectionHeader++ in for loop instead of ++sectionHeader it will point to memory after last section

        }
        else
        {
            return 1;
        }
    }
    else
    {
        return 1;
    }
    return 0;
}
清君侧 2025-01-01 14:59:00

你只是以错误的方式做事。
我给你写了一些代码,希望对你有帮助。它可以显示PE文件最后一段的数据。

#include <stdio.h>
#include <malloc.h>
#include <windows.h>

void ShowHexData(BYTE *ptr,DWORD len)
{
    int index = 0;
    int i = 0;
    const int width = 16;
    while(index + width < len)
    {
        int i;
        for(i = 0; i < width; ++i)
        {
            printf(" %02X",ptr[index + i]);
        }
        printf("    \t");
        for(i = 0; i < width; ++i)
        {
            if(ptr[index + i] >= 0x20 &&
                        ptr[index + i] <= 0x7F)
            {
                putchar(ptr[index + i]);
            }else{
                putchar('.');
            }
        }
        index += width;
        putchar('\n');
    }

    for(i = 0; index  + i < len; ++ i)
    {
        printf(" %02X",ptr[index + i]);
    }
    while(i < width)
    {
        printf("   ");
        i += 1;
    }
    printf("    \t");
    for(i = 0; index + i < len; ++ i)
    {
        if(ptr[index + i] >= 0x20 &&
                    ptr[index + i] <= 0x7F)
        {
            putchar(ptr[index + i]);
        }else{
            putchar('.');
        }
    }
    putchar('\n');


}
int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("Usage : %s filename\n",argv[0]);
        return -1;
    }else{
        FILE *fp = fopen(argv[1],"rb");
        IMAGE_DOS_HEADER DosHeader = {0};
        IMAGE_FILE_HEADER FileHeader = {0};
        IMAGE_SECTION_HEADER SectionHeader = {0};
        DWORD Signature = 0;
        DWORD RawPointerToPeHeader = 0, SizeOfFile = 0;
        DWORD SectionCount = 0;
        DWORD ByteCount = 0;
        BYTE *pData = NULL;
        if(!fp)
        {
            perror("");
            return -1;
        }
        fseek(fp,0,SEEK_END);
        SizeOfFile = ftell(fp);
        if(SizeOfFile <
            sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS))
            goto not_pe_file;
        fseek(fp,0,SEEK_SET);
        fread(&DosHeader,1,sizeof DosHeader,fp);
        if(DosHeader.e_magic != 'M' + 'Z' * 256)
            goto not_pe_file;
        RawPointerToPeHeader = DosHeader.e_lfanew;
        if(SizeOfFile <=
            RawPointerToPeHeader + sizeof(IMAGE_NT_HEADERS))
            goto not_pe_file;
        fseek(fp,RawPointerToPeHeader,SEEK_SET);
        fread(&Signature,1,sizeof(DWORD),fp);
        if(Signature != 'P' + 'E' * 256)
            goto not_pe_file;
        fread(&FileHeader,1,sizeof FileHeader,fp);
        if(FileHeader.SizeOfOptionalHeader !=
            sizeof(IMAGE_OPTIONAL_HEADER))
            goto not_pe_file;
        SectionCount = FileHeader.NumberOfSections;
        if(SectionCount == 0)
        {
            printf("No section for this file.\n");
            fclose(fp);
            return -1;
        }
        if(SizeOfFile <=
            RawPointerToPeHeader +
            sizeof(IMAGE_NT_HEADERS) +
            SectionCount * sizeof(IMAGE_SECTION_HEADER))
            goto not_pe_file;
        fseek(fp,
            RawPointerToPeHeader + sizeof(IMAGE_NT_HEADERS) +
            (SectionCount - 1) * sizeof(IMAGE_SECTION_HEADER),
                SEEK_SET);
        fread(&SectionHeader,1,sizeof SectionHeader,fp);

        ByteCount = SectionHeader.Misc.VirtualSize < SectionHeader.PointerToRawData ?
            SectionHeader.Misc.VirtualSize : SectionHeader.PointerToRawData;

        if(ByteCount == 0)
        {
            printf("No data to read for target section.\n");
            fclose(fp);
            return -1;
        }else if(ByteCount + SectionHeader.PointerToRawData > SizeOfFile)
        {
            printf("Bad section data.\n");
            fclose(fp);
            return -1;
        }
        fseek(fp,SectionHeader.PointerToRawData,SEEK_SET);

        pData = (BYTE*)malloc(ByteCount);

        fread(pData,1,ByteCount,fp);

        ShowHexData(pData,ByteCount);
        free(pData);
        fclose(fp);
        return 0;


not_pe_file:
        printf("Not a PE file.\n");
        fclose(fp);
        return -1;
    }


    return 0;
}

简而言之,你不知道数据在哪里,直到你根据文件头分析数据。

You just do it the wrong way.
I wrote some code for you, hope it helps.It can show the data of the last section of a PE file.

#include <stdio.h>
#include <malloc.h>
#include <windows.h>

void ShowHexData(BYTE *ptr,DWORD len)
{
    int index = 0;
    int i = 0;
    const int width = 16;
    while(index + width < len)
    {
        int i;
        for(i = 0; i < width; ++i)
        {
            printf(" %02X",ptr[index + i]);
        }
        printf("    \t");
        for(i = 0; i < width; ++i)
        {
            if(ptr[index + i] >= 0x20 &&
                        ptr[index + i] <= 0x7F)
            {
                putchar(ptr[index + i]);
            }else{
                putchar('.');
            }
        }
        index += width;
        putchar('\n');
    }

    for(i = 0; index  + i < len; ++ i)
    {
        printf(" %02X",ptr[index + i]);
    }
    while(i < width)
    {
        printf("   ");
        i += 1;
    }
    printf("    \t");
    for(i = 0; index + i < len; ++ i)
    {
        if(ptr[index + i] >= 0x20 &&
                    ptr[index + i] <= 0x7F)
        {
            putchar(ptr[index + i]);
        }else{
            putchar('.');
        }
    }
    putchar('\n');


}
int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("Usage : %s filename\n",argv[0]);
        return -1;
    }else{
        FILE *fp = fopen(argv[1],"rb");
        IMAGE_DOS_HEADER DosHeader = {0};
        IMAGE_FILE_HEADER FileHeader = {0};
        IMAGE_SECTION_HEADER SectionHeader = {0};
        DWORD Signature = 0;
        DWORD RawPointerToPeHeader = 0, SizeOfFile = 0;
        DWORD SectionCount = 0;
        DWORD ByteCount = 0;
        BYTE *pData = NULL;
        if(!fp)
        {
            perror("");
            return -1;
        }
        fseek(fp,0,SEEK_END);
        SizeOfFile = ftell(fp);
        if(SizeOfFile <
            sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS))
            goto not_pe_file;
        fseek(fp,0,SEEK_SET);
        fread(&DosHeader,1,sizeof DosHeader,fp);
        if(DosHeader.e_magic != 'M' + 'Z' * 256)
            goto not_pe_file;
        RawPointerToPeHeader = DosHeader.e_lfanew;
        if(SizeOfFile <=
            RawPointerToPeHeader + sizeof(IMAGE_NT_HEADERS))
            goto not_pe_file;
        fseek(fp,RawPointerToPeHeader,SEEK_SET);
        fread(&Signature,1,sizeof(DWORD),fp);
        if(Signature != 'P' + 'E' * 256)
            goto not_pe_file;
        fread(&FileHeader,1,sizeof FileHeader,fp);
        if(FileHeader.SizeOfOptionalHeader !=
            sizeof(IMAGE_OPTIONAL_HEADER))
            goto not_pe_file;
        SectionCount = FileHeader.NumberOfSections;
        if(SectionCount == 0)
        {
            printf("No section for this file.\n");
            fclose(fp);
            return -1;
        }
        if(SizeOfFile <=
            RawPointerToPeHeader +
            sizeof(IMAGE_NT_HEADERS) +
            SectionCount * sizeof(IMAGE_SECTION_HEADER))
            goto not_pe_file;
        fseek(fp,
            RawPointerToPeHeader + sizeof(IMAGE_NT_HEADERS) +
            (SectionCount - 1) * sizeof(IMAGE_SECTION_HEADER),
                SEEK_SET);
        fread(&SectionHeader,1,sizeof SectionHeader,fp);

        ByteCount = SectionHeader.Misc.VirtualSize < SectionHeader.PointerToRawData ?
            SectionHeader.Misc.VirtualSize : SectionHeader.PointerToRawData;

        if(ByteCount == 0)
        {
            printf("No data to read for target section.\n");
            fclose(fp);
            return -1;
        }else if(ByteCount + SectionHeader.PointerToRawData > SizeOfFile)
        {
            printf("Bad section data.\n");
            fclose(fp);
            return -1;
        }
        fseek(fp,SectionHeader.PointerToRawData,SEEK_SET);

        pData = (BYTE*)malloc(ByteCount);

        fread(pData,1,ByteCount,fp);

        ShowHexData(pData,ByteCount);
        free(pData);
        fclose(fp);
        return 0;


not_pe_file:
        printf("Not a PE file.\n");
        fclose(fp);
        return -1;
    }


    return 0;
}

In short, you do not know where the data is, until you analyze the data according to the file header.

晨与橙与城 2025-01-01 14:59:00

节指针:

PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh); // definition in winnt.h

PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)((DWORD)pioh + pifh->SizeOfOptionalHeader);

最后一个节指针是:

PIMAGE_SECTION_HEADER pilsh = &pish[pifh->NumberOfSections-1];

sections pointer:

PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh); // definition in winnt.h

or

PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)((DWORD)pioh + pifh->SizeOfOptionalHeader);

the last section pointer is:

PIMAGE_SECTION_HEADER pilsh = &pish[pifh->NumberOfSections-1];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文