2012-01-09 12 views
5

Zasadniczo próbuję znaleźć ostatnią sekcję pliku PE. Bardzo uważnie czytałem specyfikację PE, ale nie mogę stwierdzić, gdzie mój kod zawodzi.Ładowanie nagłówków 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 jest tablicą bajt zawiera załadowany wykonywalny i pish jest wskaźnikiem do ostatniej sekcji. Z jakiegoś powodu wydaje się, że liczba sekcji przekracza 20 000.

Jakieś pomysły? góry dzięki

+0

- jak to się nie udaje? –

+0

Jak już powiedziałem, liczba sekcji przekracza 20 tys. Tak więc, gdy zakończy się dereferencja członków programu 'pish'. – Kijan

Odpowiedz

13

Jest jeden problem widzę z ręki: e_lfanew jest przesunięcie w strukturze IMAGE_NT_HEADERS w bajtów. Dodajesz tę liczbę bajtów do wskaźnika IMAGE_DOS_HEADER, więc przesuwasz się dalej o sizeof(IMAGE_DOS_HEADER)*pidh->e_lfanew bajtów.

wersji Poprawiono:

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

Najlepszym sposobem, aby debugować problemy jak to jest spadek do kodu z debuggera i przeglądać dane PE się w pamięci. Możesz na przykład otworzyć edytor heksadecymalny Visual Studio i zobaczyć wszystkie dane bajtów oraz wartości, które faktycznie odczytujesz.

Oto kilka informacji na temat wyświetlania pamięci programu w VS 2010: http://msdn.microsoft.com/en-us/library/s3aw423e.aspx

+0

Cóż, dziękuję bardzo, wydaje się, że problem leży w mojej (nie) znajomości arytmetyki wskaźnikowej. :) – Kijan

+0

@jowo to 'e_magic' z' IMAGE_DOS_HEADER' ma pasować do 'Magic' z' IMAGE_FILE_HEADER'? Jeśli tak, nie wiem, dlaczego otrzymuję nieprawidłowe zachowanie. Załadowałem mój EXE do obiektu 'std :: vector bytes' i spróbowałem ustawić' IMAGE_DOS_HEADER * img_dos_header = (IMAGE_DOS_HEADER *) & bajty [0]; 'ale magiczne liczby nie są wyrównane z moim' IMAGE_FILE_HEADER * coff_file_header = (IMAGE_FILE_HEADER *) & bajty [coff_file_header_offset]; ', który z pewnością ładuje prawidłowe informacje. Jakiś pomysł, co muszę naprawić? Lub alternatywny sposób ładowania IMAGE_DOS_HEADER? –

+0

Ok, więc "e_magic" dla 'IMAGE_DOS_HEADER' jest w rzeczywistości _signature_ dla formatu PE ... więc' & bytes [0] 'było właściwie poprawne, oceniając na' 0x5A4D' :) –

2

po prostu zrobić to w niewłaściwy sposób. Napisałem dla ciebie kod, mam nadzieję, że pomoże. Może pokazać dane ostatniej sekcji pliku 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; 
} 

Krótko mówiąc, nie wiesz, gdzie znajdują się dane, dopóki nie przeanalizujesz danych zgodnie z nagłówkiem pliku.

0

Różne adres sekcja i dane można uzyskać przez poniższy sposób również: „Nie mogę odkryć, gdzie mój kod nie”

#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; 
} 
Powiązane problemy