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!
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. –
@JoachimPileborg Gibt es irgendetwas, was Sie vorschlagen, um es zu reparieren oder sind sie "einfach inkompatibel"? –
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. –