2012-01-09 1 views
5

기본적으로, 내가하려는 것은 PE 파일의 마지막 섹션을 찾는 것입니다. 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

어떤 아이디어가 넘는 것으로 나타 납니까? e_lfanew 바이트IMAGE_NT_HEADERS 구조에 오프셋 : 사전

+0

가 - 어떻게 실패하니? –

+0

내가 말했듯이, 섹션의 수가 20k 이상입니다. 따라서, '피쉬 (pish)'프로그램의 역 참조 (dereferencing) 멤버가 충돌 할 때. – Kijan

답변

13

내가 손을 배웅 한 문제가 있습니다에서 감사합니다. 이 바이트 수를 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 16 진 편집기를 열고 모든 바이트 데이터와 실제로 읽은 값을 볼 수 있습니다. http://msdn.microsoft.com/en-us/library/s3aw423e.aspx

+0

글쎄요, 고맙습니다. 문제는 포인터 계산에 대해 아는 것입니다. :) – Kijan

+0

@ jowo는 IMAGE_FILE_HEADER의 'Magic'과 일치하는 'IMAGE_DOS_HEADER'의'e_magic'입니까? 그렇다면 잘못된 행동을하는 이유가 무엇인지 알 수 없습니다. 나는 개체 bytes' ::'표준에 벡터 을 내 EXE로드와'IMAGE_DOS_HEADER * img_dos_header = (IMAGE_DOS_HEADER *) 바이트 [0]을 설정하기 위해 노력했습니다;'하지만 매직 넘버 내'IMAGE_FILE_HEADER * coff_file_header에 부합하지 않는 = (IMAGE_FILE_HEADER *) & bytes [coff_file_header_offset];, 올바른 정보를 확실히로드하고 있습니다. 내가 고칠 필요가있는 어떤 아이디어? 또는 IMAGE_DOS_HEADER을 (를)로드하는 다른 방법은 무엇입니까? –

+0

확인하므로,''IMAGE_DOS_HEADER' 너무 용품 실제로 PE 포맷에 대한 _signature_ 인 '용 e_magic' 바이트 [0]이', BTW 좋은 읽은 0x5A4D' : –

2

당신은 그냥 길을 잘못 수행

여기 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; 
} 

요약하면 파일 헤더에 따라 데이터를 분석 할 때까지는 데이터의 위치를 ​​알 수 없습니다.

0

섹션의 주소와 데이터는 아래의 방법으로 얻을 수 있습니다 다양한 : ". 내 코드가 실패 어디 발견 할 수 없다"

#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; 
}