2013-04-11 9 views
6

Próbuję utworzyć przeglądarkę PE w C++ i wygląda na to, że się zawiesza, jeśli próbuję wypisać nazwy bibliotek w tabeli katalogu importu. Wygląda na to, że nie otrzymuję poprawnych wskazówek dla bibliotek DLL, które są używane przez program.Jak odczytać tabelę katalogu importowania w C

HANDLE handle = CreateFile("messagebox.exe",GENERIC_READ,0,0,OPEN_EXISTING, 
           FILE_ATTRIBUTE_NORMAL,0); 
DWORD size = GetFileSize(handle,NULL); 
PVOID virtualpointer = VirtualAlloc(NULL,size,MEM_COMMIT,PAGE_READWRITE); 
state = ReadFile(handle,virtualpointer,size,&byteread,NULL); 
CloseHandle(handle); 
PIMAGE_NT_HEADERS ntheaders = PIMAGE_NT_HEADERS(PCHAR(vpointer) + 
            PIMAGE_DOS_HEADER(vpointer)->e_lfanew); 
handle = GetCurrentProcess(); 
DWORD EntryAddr = ntheaders->OptionalHeader.ImageBase + 
         ntheaders->OptionalHeader.AddressOfEntryPoint; 

DWORD importdir = 
     (DWORD) &(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]); 

DWORD va = (DWORD)(ntheaders->OptionalHeader.ImageBase) + 
        ((PIMAGE_DATA_DIRECTORY)dwValueB)->VirtualAddress; 
LPSTR libname[128]; 
int i =0; 
while(((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->Name) 
{ 
     // get DLL name 
     libname[i] = (LPSTR)(nt->OptionalHeader.ImageBase + 
         ((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->Name); 
     i++; 
} 
+0

Niezależnie od reszty, gdzie wprowadzasz 'nt'? –

+0

Przepraszam za to, naprawiłem to teraz – user2272296

+0

Czy możesz podać kompletny kod? W powyższym brakuje pewnej liczby deklaracji zmiennych jako minimum. –

Odpowiedz

9

Aby odczytać nazwy bibliotek w imporcie Informator tabeli, można wykonać następujące czynności:

  1. Uzyskaj adres bazowy w pliku na pamięci odwzorowany.
  2. Pobierz wskaźnik do struktury IMAGE_NT_HEADERS.
  3. Pobierz wskaźnik do struktury IMAGE_SECTION_HEADER.

  4. DataDirectory to końcowe 128 bajtów OptionalHeader, który z kolei jest ostatnim elementem nagłówka PE IMAGE_NT_HEADERS. Struktura składa się z 2 elementów, które zawierają położenie i rozmiar struktury danych.
    Jeśli chcesz wyszukać informacje na temat nazw dll, najpierw znajdź RVA (Relative Virtual Address) z Import Directory z Data Directory, znajdź ten adres w surowych danych sekcji, a teraz masz tablicę IMAGE_IMPORT_DESCRIPTOR. Pobierz element tej tablicy, który odnosi się do zmapowanego obrazu, sprawdzając ciągi wskazane przez pola Nazwa.

Nie będę opisywać strukturę Portable Executable File Format, ale można spojrzeć na poniższe linki:
Peering Inside the PE
Microsoft Systems Journal

Niektóre zmienne w kodzie nie są uznane i to jest mylące, ale przylegając do twojego kodu szkieletu, napisałem go tak, aby spełniał twoje pytanie.

DWORD Rva2Offset(DWORD rva,PIMAGE_SECTION_HEADER psh,PIMAGE_NT_HEADERS pnt); 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
LPCWSTR fNmae=L"C:\\Windows\\system32\\notepad.exe"; 
HANDLE handle=CreateFile(fNmae/*"messagebox.exe"*/, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 
DWORD byteread,size=GetFileSize(handle, NULL); 
PVOID virtualpointer=VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); 
ReadFile(handle, virtualpointer, size, &byteread, NULL); 
CloseHandle(handle); 
// Get pointer to NT header 
PIMAGE_NT_HEADERS   ntheaders=(PIMAGE_NT_HEADERS)(PCHAR(virtualpointer) + PIMAGE_DOS_HEADER(virtualpointer)-> e_lfanew); 
PIMAGE_SECTION_HEADER  pSech=IMAGE_FIRST_SECTION(ntheaders);//Pointer to first section header 
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor; //Pointer to import descriptor 
__try 
{ 
    if(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size != 0)/*if size of the table is 0 - Import Table does not exist */ 
    { 
     pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)virtualpointer +\ 
          Rva2Offset(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,pSech,ntheaders)); 
     LPSTR libname[256]; 
     size_t i=0; 
     // Walk until you reached an empty IMAGE_IMPORT_DESCRIPTOR 
     while(pImportDescriptor->Name != NULL) 
     { 
      printf("Library Name :"); 
      //Get the name of each DLL 
      libname[i]=(PCHAR)((DWORD_PTR)virtualpointer + Rva2Offset(pImportDescriptor->Name,pSech,ntheaders)); 
      printf("%s\n", libname[i]); 
      pImportDescriptor++; //advance to next IMAGE_IMPORT_DESCRIPTOR 
      i++; 

     } 

    } 
    else 
    { 
     printf("No Import Table!\n"); 
     return 1; 
    } 
} 
__except(EXCEPTION_EXECUTE_HANDLER) 
{ 
    if(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode()) 
    { 
     printf("Exception: EXCEPTION_ACCESS_VIOLATION\n"); 
     return 1; 
    } 

} 
if(virtualpointer) 
    VirtualFree(virtualpointer, size, MEM_DECOMMIT); 

return 0; 
} 
/*Convert Virtual Address to File Offset */ 
DWORD Rva2Offset(DWORD rva,PIMAGE_SECTION_HEADER psh,PIMAGE_NT_HEADERS pnt) 
{ 
    size_t i = 0; 
    PIMAGE_SECTION_HEADER pSeh; 
    if(rva == 0) 
    { 
      return (rva); 
    } 
    pSeh = psh; 
    for(i = 0; i < pnt->FileHeader.NumberOfSections; i++) 
    { 
      if(rva >= pSeh->VirtualAddress && rva < pSeh->VirtualAddress + 
       pSeh->Misc.VirtualSize) 
      { 
        break; 
      } 
      pSeh++; 
    } 
    return (rva - pSeh->VirtualAddress + pSeh->PointerToRawData); 
} 
+2

'Rva2Offset' jest wart milion! Wielkie dzięki! –

+1

Btw, można uzyskać zarchiwizowane Microsoft Systems Journal od marca 1994 r. Dla artykułu PE w tym bezpośrednim łączu (http://download.microsoft.com/download/0/6/7/0678184e-905e-4783-9511-d4dca1f492b4 /MSJMAR94.exe), i to do przeglądania reszty (https://www.microsoft.com/msj/backissues86.aspx); nie musisz, ale na wypadek, gdybyś kiedykolwiek chciał wskoczyć do wehikułu czasu ... –

+0

Wiem, że to jest stare. Ale chciałem wiedzieć, dlaczego potrzebujemy 'rva - pSeh-> VirtualAddress + pSeh-> PointerToRawData'. Czy nie możemy po prostu dodać 'rva' do adresu podstawowego obrazu? –

Powiązane problemy