2012-01-09 31 views
5

Về cơ bản, những gì tôi đang cố gắng làm là tìm phần cuối cùng của tệp PE. Tôi đã đọc đặc điểm kỹ thuật PE rất chăm chú, nhưng tôi không thể phát hiện ra mã của tôi bị lỗi ở đâu.Đang tải các tiêu đề 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)); 

là mảng byte chứa thực thi đã tải và pish là con trỏ đến phần cuối cùng. Vì một lý do nào đó, có vẻ như số lượng phần trên 20 000.

Bất kỳ ý tưởng nào? Cảm ơn trước

+0

- nó hỏng như thế nào? –

+0

Như tôi đã nói, số lượng phần trên 20k. Vì vậy, khi các thành viên dereferencing của chương trình 'pish' bị treo. – Kijan

Trả lời

13

Có một vấn đề tôi gặp phải: e_lfanew là phần bù đắp cho cấu trúc IMAGE_NT_HEADERS trong byte. Bạn đang thêm số byte này vào con trỏ IMAGE_DOS_HEADER, vì vậy bạn đang di chuyển về phía trước bởi sizeof(IMAGE_DOS_HEADER)*pidh->e_lfanew byte.

cố định phiên bản:

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)); 

Cách tốt nhất để gỡ rối các vấn đề như thế này là để thả vào mã với debugger và xem các dữ liệu PE mình trong bộ nhớ. Bạn có thể mở trình soạn thảo hex của Visual Studio chẳng hạn và xem tất cả dữ liệu byte và những giá trị nào bạn thực sự đang đọc.

Dưới đây là một số thông tin về xem bộ nhớ chương trình trong VS 2010: http://msdn.microsoft.com/en-us/library/s3aw423e.aspx

+0

Vâng, cảm ơn bạn rất nhiều, nó xuất hiện rằng vấn đề là trong của tôi (không) biết số học con trỏ. :) – Kijan

+0

@jowo là 'e_magic' từ' IMAGE_DOS_HEADER' được cho là khớp với 'Magic' của' IMAGE_FILE_HEADER'? Nếu vậy, tôi không biết tại sao tôi nhận được hành vi không chính xác. Tôi đã tải EXE của mình vào đối tượng 'std :: vector bytes' và cố gắng đặt' IMAGE_DOS_HEADER * img_dos_header = (IMAGE_DOS_HEADER *) & byte [0]; 'nhưng số ma thuật không phù hợp với' IMAGE_FILE_HEADER * coff_file_header của tôi = (IMAGE_FILE_HEADER *) & byte [coff_file_header_offset]; ', chắc chắn đang tải thông tin chính xác. Bất kỳ ý tưởng những gì tôi cần phải sửa chữa? Hoặc một cách khác để tải IMAGE_DOS_HEADER? –

+0

Ok, do đó, 'e_magic' cho' IMAGE_DOS_HEADER' thực sự là _signature_ cho định dạng PE ... vì vậy '& bytes [0]' thực sự chính xác, đánh giá thành '0x5A4D' :) –

2

Bạn chỉ cần làm điều đó một cách sai lầm. Tôi đã viết một số mã cho bạn, hy vọng nó sẽ giúp. Nó có thể hiển thị dữ liệu của phần cuối cùng của một tệp 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; 
} 

Tóm lại, bạn không biết dữ liệu ở đâu, cho đến khi bạn phân tích dữ liệu theo tiêu đề tệp.

0

Nhiều địa chỉ phần và dữ liệu có thể thu được bằng cách dưới đây cũng: "Tôi không thể khám phá nơi mã của tôi thất bạ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; 
}