1

Ich habe Probleme beim Auflisten von Funktionsnamen in kernel32.dll. Ich habe seine IMAGE_EXPORT_DIRECTORY Struktur abgerufen und ein Array von Zeigern in char-Arrays jedes Funktionsnamens gespeichert: char** name_table = (char**)(image+pExp_dir->AddressOfNames); //pExp_dir is a pointer to the IMAGE_EXPORT_DIRECTORY structure. Ich versuche nun, die Funktionsnamen zu durchlaufen und sie mit einem String zu verbinden, der den Namen der Funktion enthält, deren RVA ich brauche.Probleme beim Iterieren durch AddressOfNames Mitglied der IMAGE_EXPORT_DIRECTORY Struktur

for(int i=0;i<pExp_dir->NumberOfNames;i++) //until i is 1 less than how many names there are to iterate through elements 
    { 
     printf("%s ", (char*)(image+(DWORD)(uintptr_t)name_table[i])); //print the name of each function iterated through, I went back and read through these names and didn't see GetProcAddress anywhere 
     if(proc_name == image+(DWORD)(uintptr_t)name_table[i]) //if(strcmp(proc_name, (const char*)image+(DWORD)(intptr_t)name_table[i]) == 0) //Is it the function we're looking for? 
     { 
      address = (DWORD)(uintptr_t)func_table[ord_table[i]];//If so convert the address of the function into a DWORD(hexadecimal) 
      system("pause"); 
      system("CLS"); //Clear the screen 
      return address; //return the address of the function 
     } 

Aber wenn es die Funktion nicht findet, stürzt das Programm ab. Und nachdem ich in dem Speicherauszug im DBG-Debugger nachgesehen habe, kann ich sehen, dass name_tables alle Funktionsnamen enthält, einschließlich der Funktion, nach der ich suche, aber mein Programm scheint mehrere Elemente zu überspringen, obwohl ich durch seine Elemente eins bei a iteriere Zeit. User Stijn suggested, dass ich intptr_t nicht verwenden sollte char* zu DWORD für Zeigerarithmetik zu verwenden. Also meine Frage ist wirklich über den richtigen Weg, um durch name_table zu iterieren, weil es scheint, als ob dies ein Zeiger-arithmetisches Problem ist. Hier ist die Funktion die Datei Bild und die Funktion zu erhalten, die tatsächlich die RVA bekommt:

void* GetFileImage(char path[]) //Get maps the image of the file into memory and returns the beginning virtual address of the file in memory 
{ 
    HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);//Get a handle to the dll with read rights 
    if(hFile == INVALID_HANDLE_VALUE){printf("Error getting file handle: %d", (int)GetLastError());return NULL;} //Check whether or not CreateFile succeeded 

    HANDLE file_map = CreateFileMapping(hFile, NULL, PAGE_READONLY|SEC_IMAGE, 0, 0, "KernelMap"); //Create file map 
    if(file_map == INVALID_HANDLE_VALUE){printf("Error mapping file: %d", (int)GetLastError());return NULL;} //Did it succeed 

    LPVOID file_image = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 0); //Map it into the virtual address space of my program 
    if(file_image == 0){printf("Error getting mapped view: %d", (int)GetLastError());return NULL;} //Did it succeed 

    return file_image; //return the base address of the image 
} 

DWORD RVAddress(char* image, const char* proc_name) //Gets the relative virtual address of the function and returns a DWORD to be cast to void*. 
{ 
    DWORD address = 0xFFFFFFFF; 

    PIMAGE_DOS_HEADER pDos_hdr = (PIMAGE_DOS_HEADER)image; //Get dos header 
    PIMAGE_NT_HEADERS pNt_hdr = (PIMAGE_NT_HEADERS)(image+pDos_hdr->e_lfanew); //Get PE header by using the offset in dos header + the base address of the file image 
    IMAGE_OPTIONAL_HEADER opt_hdr = pNt_hdr->OptionalHeader; //Get the optional header 
    IMAGE_DATA_DIRECTORY exp_entry = opt_hdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 
    PIMAGE_EXPORT_DIRECTORY pExp_dir = (PIMAGE_EXPORT_DIRECTORY)(image+exp_entry.VirtualAddress); //Get a pointer to the export directory 

    void** func_table = (void**)(image+pExp_dir->AddressOfFunctions); //Get an array of pointers to the functions 
    WORD* ord_table = (WORD*)(image+pExp_dir->AddressOfNameOrdinals); //Get an array of ordinals 
    char** name_table = (char**)(image+pExp_dir->AddressOfNames); //Get an array of function names 

    for(int i=0;i<pExp_dir->NumberOfNames;i++) //until i is 1 less than how many names there are to iterate through elements 
    { 
     printf("%s ", (char*)(image+(DWORD)(uintptr_t)name_table[i])); //print the name of each function iterated through, I went back and read through these names and didn't see GetProcAddress anywhere 
     if(proc_name == image+(DWORD)(uintptr_t)name_table[i]) //if(strcmp(proc_name, (const char*)image+(DWORD)(intptr_t)name_table[i]) == 0) //Is it the function we're looking for? 
     { 
      address = (DWORD)(uintptr_t)func_table[ord_table[i]];//If so convert the address of the function into a DWORD(hexadecimal) 
      system("pause"); 
      system("CLS"); //Clear the screen 
      return address; //return the address of the function 
     } 
    } 

    return (DWORD)0; //Other wise return 0 
} 

Jede Hilfe wäre sehr willkommen!

+0

Nur eine Vermutung hier, aber ich denke, dass es zu dem Problem, das ich beschreibe [in dieser alten Antwort von mir] (http://stackoverflow.com/questions/18440205/casting-void-to-2d-array- von-int-c/18440456 # 18440456). Ein Array von Arrays ist nicht dasselbe wie ein Zeiger auf den Zeiger. –

+0

@JoachimPileborg Gibt es irgendetwas, was Sie vorschlagen, um es zu reparieren oder sind sie "einfach inkompatibel"? –

+0

Ich war falsch, es * ist * ein Array von Zeigern, in denen Zeiger auf Zeiger funktionieren würde. Es scheint jedoch, dass es sich nicht um ein Array von C-artigen Strings handelt, da der Typ (nach [dieser MSDN-Dokumentation] (https://msdn.microsoft.com/en-us/library/ms809762.aspx)) "PDWORD" ist * AddressOfNames'. I.e. Es ist im Grunde ein Array von Zeigern zu 'DWORD'. Ich weiß nichts über das Format, aber Sie könnten immer nur die "Zeiger" ausgeben, um zu sehen, welche Werte sie haben, wenn sie wie Speicherzeiger oder ähnliche Offsets oder etwas anderes aussehen. –

Antwort

0

Docs (Section 6.3) nächste sagen über AddressOfNames Tabelle

Der Export Name Pointer Table ein Array von Adressen (RVAs) ist in die Export-Namentabelle. Die Zeiger sind jeweils 32 Bits und sind relativ zu der Bildbasis. Die Zeiger sind lexikalisch angeordnet, um binäre Suchvorgänge zu ermöglichen.

Und über AddressOfFunctions:

Jeder Eintrag in der Export-Adresstabelle ein Feld, das eine von zwei Formate verwendet, ... Wenn die angegebene Adresse nicht innerhalb des Export Abschnitt (als definiert durch die Adresse und die Länge, die in der Option Kopfzeile angegeben ist), ist das Feld eine Export RVA: eine tatsächliche Adresse in Code oder Daten. Ansonsten ist das Feld eine Forwarder-RVA, die ein Symbol in eine andere DLL nennt.

Ihre Variablen ist nicht void** und char**, aber eigentlich sind alle DWORD* weil diese Tabellen RVA halten. nächsten Code versuchen:

DWORD* func_table = (DWORD*)(image+pExp_dir->AddressOfFunctions); //Get an array of pointers to the functions 
    WORD* ord_table = (WORD*)(image+pExp_dir->AddressOfNameOrdinals); //Get an array of ordinals 
    DWORD* name_table = (DWORD*)(image+pExp_dir->AddressOfNames); //Get an array of function names 

    for(int i=0;i<pExp_dir->NumberOfNames;i++) //until i is 1 less than how many names there are to iterate through elements 
    { 
     printf("%s ", (char*)(image+name_table[i])); //print the name of each function iterated through, I went back and read through these names and didn't see GetProcAddress anywhere 
     if(strcmp(proc_name, (const char*)(image+name_table[i])) == 0) //Is it the function we're looking for? 
     { 
      // TODO should we distinguish between normal and forwarded exports? 
      WORD ordinal_base = 1; // TODO read it from export directory 
      address = func_table[ord_table[i] - ordinal_base];//If so convert the address of the function into a DWORD(hexadecimal) 
      system("pause"); 
      system("CLS"); //Clear the screen 
      return address; //return the address of the function 
     } 
    } 

Also, wenn Ihr Code läuft auf 32-Bit-Maschine sollte es unabhängig von den falschen var Typen arbeiten, aber wenn Sie sind auf 64-Bit - Zeiger sind zweimal länger als DWORD und es wird überspringen ungerade Einträge in Tabellen und geht von Array-Grenze, die Absturz verursachen kann.

P.S. Die Namenstabelle ist geordnet, sodass Sie die binäre Suche verwenden können.

+0

ENDLICH! Ich danke dir sehr! Es ist mir nicht einmal in den Sinn gekommen, ich schätze es liegt daran, dass ich bis vor kurzem auf einem 32-Bit-Laptop programmiert habe. Sehr geschätzt! –