Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 加载PE头_C_Winapi_Portable Executable - Fatal编程技术网

C 加载PE头

C 加载PE头,c,winapi,portable-executable,C,Winapi,Portable Executable,基本上,我要做的是找到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;

基本上,我要做的是找到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
是指向最后一节的指针。由于某种原因,似乎有超过20000个部门

有什么想法吗?
提前感谢

我马上看到一个问题:e\u lfanew是
图像\u NT\u头
结构的偏移量,以字节为单位。您正在将此数量的字节添加到
IMAGE\u DOS\u头
指针,因此您将通过
sizeof(IMAGE\u DOS\u头)*pidh->e\u 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数据。例如,您可以打开VisualStudioHex编辑器,查看所有字节数据以及实际读取的值

以下是有关在VS 2010中查看程序内存的一些信息:
我马上看到一个问题:e\u lfanew是
图像\u NT\u头的偏移量,以字节为单位。您正在将此数量的字节添加到
IMAGE\u DOS\u头
指针,因此您将通过
sizeof(IMAGE\u DOS\u头)*pidh->e\u 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数据。例如,您可以打开VisualStudioHex编辑器,查看所有字节数据以及实际读取的值

以下是有关在VS 2010中查看程序内存的一些信息:
你只是用了错误的方法。 我为你写了一些代码,希望对你有所帮助。它可以显示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;
}
#包括
#包括
#包括
void ShowHexData(字节*ptr,DWORD len)
{
int指数=0;
int i=0;
const int width=16;
而(索引+宽度<长度)
{
int i;
对于(i=0;i=0x20&&
ptr[index+i]=0x20&&

ptr[index+i]你只是用了错误的方法。 我为你写了一些代码,希望对你有所帮助。它可以显示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;
}
#包括
#包括
#包括
void ShowHexData(字节*ptr,DWORD len)
{
int指数=0;
int i=0;
const int width=16;
而(索引+宽度<长度)
{
int i;
对于(i=0;i=0x20&&
ptr[index+i]=0x20&&

ptr[index+i]各种区段地址和数据也可以通过以下方式获得:

#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;
}
#包括
#包括
int main()
{
LPCSTR fileName=“inputFile.exe”;
处理文件;
处理文件映射;
LPVOID lpFileBase;
PIMAGE_DOS_HEADER DOS HEADER;
PIMAGE\u NT\u头peHeader;
PIMAGE_SECTION_SECTION SECTION HEADER;
hFile=CreateFileA(文件名,通用读取,文件共享读取,NULL,打开现有,文件属性正常,0);
if(hFile==无效的句柄值)
{

std::cout还可以通过以下方式获得各种区段地址和数据:

#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;
}
#包括
#包括
int main()
{
LPCSTR fileName=“inputFile.exe”;
处理文件;
处理文件映射;
LPVOID lpFileBase;
PIMAGE_DOS_HEADER DOS HEADER;
PIMAGE\u NT\u头peHeader;
PIMAGE_SECTION_SECTION SECTION HEADER;
hFile=CreateFileA(文件名,通用读取,文件共享读取,NULL,打开现有,文件属性正常,0);
if(hFile==无效的句柄值)
{
标准::coutsections指针:

PIMAGE_SECTION_HEADER pish=IMAGE_FIRST_SECTION(pinh);//定义 在温特

PIMAGE_SECTION_HEADER pish=(PIMAGE_SECTION_HEADER)((字节*)pioh+ pifh->SizeOfOptionalHeader)

最后一节指针是:

PIMAGE\u SECTION\u HEADER pilsh=&pish[pifh->NumberOfSections-1]

节指针:

PIMAGE_SECTION_HEADER pish=IMAGE_FIRST_SECTION(pinh);//定义 在温特

PIMAGE_SECTION_HEADER pish=(PIMAGE_SECTION_HEADER)((字节*)pioh+ pifh->SizeOfOptionalHeader)

最后一节指针是:

PIMAGE\u SECTION\u HEADER pilsh=&pish[pifh->NumberOfSections-1]


“我无法发现我的代码在哪里失败。”-它是如何失败的?正如我所说,节数超过20k。因此,当取消对
pish
程序成员的引用时,“我无法发现我的代码在哪里失败。”-它是如何失败的?正如我所说,节数超过20k。因此,当取消对
pish
程序成员的引用时,程序崩溃。非常感谢,问题似乎在于我(不)知道指针算法。:)@jowo是来自
IMAGE\u DOS\u HEADER
e\u magic
应该与
IMAGE\u FILE\u HEADER
magic
匹配?如果是这样,我不知道为什么会出现错误行为。我已将我的EXE加载到
std::vector bytes
对象中,并尝试设置
IMAGE\u DOS\u HEADER*img\u DOS\u HEADER=(IMAGE\u HEADER*)&字节[0];
但是幻数与我的
IMAGE\u FILE\u HEADER*coff\u FILE\u HEADER=(IMAGE\u FILE\u HEADER*)和bytes[coff\u FILE\u HEADER\u offset]不对齐
,这肯定是加载了正确的信息。知道我需要修复什么吗?或者加载图像\u DOS\u头的另一种方法吗?好吧,那么,
e\u magic
for
图像\u DOS\u头实际上是PE格式的签名……所以
字节[0]
实际上是正确的,计算结果为
0x5A4D
:)这本书读得很好,顺便说一句:好的,最后一个问题^ ^ ^你为什么在获得时将
pidh
转换为
(BYTE*)