【发布时间】:2016-11-09 08:54:21
【问题描述】:
我正在尝试获取 kernel32.dll 中特定函数的 RVA,因此我可以在指定进程中使用 RVA 作为与 kernel32.dll 基地址的偏移量,以获取我需要注入的函数的 VA我的dll。我已经找不到LoadLibrary,但我确实找到了LoadLibraryExA,并将其用于我的dll注入器,但是我现在找不到GetProcAddress,我将用它来定位我的函数的VA ThreadProc 函数。因此,如果我找不到它,这意味着我将不得不计算并存储我需要的每个函数的 VA,并将其放入一个结构中以传递给 ThreadProc 的 LPVOID lpParam 参数,这并不理想.
这里是所有相关函数:
void* GetFileImage(char path[])
{
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)
{
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
BYTE** name_table = (BYTE**)(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 ", (BYTE*)image+(DWORD)(intptr_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(strcmp(proc_name, (const char*)(BYTE*)image+(DWORD)(intptr_t)name_table[i]) == 0) //Is it the function we're looking for?
{
address = (DWORD)(intptr_t)func_table[ord_table[i]];//If so convert the address of the function into a DWORD(hexadecimal)
system("CLS"); //Clear the screen
return address; //return the address of the function
}
}
return (DWORD)0; //Other wise return 0
}
DWORD GetRemoteFunctionAddress(DWORD dwPid, char* kernel_path, char* function_name)
{
HANDLE hSnapshot = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
me32.dwSize = sizeof(MODULEENTRY32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32, dwPid); //Get a snapshot of all the modules in the program(64 and 32 bit, 32 since kernel is 32)
if(hSnapshot == INVALID_HANDLE_VALUE){printf("Snapshot failed");return 0;} //Snapshot not created
if(!(Module32First(hSnapshot, &me32))) //Don't care about it because it will be the exe of the process
{
printf("Mod32First failed");
return 0;
}
while(Module32Next(hSnapshot, &me32)) //Iterate through until...
{
if(me32.szModule == "kernel32.dll"||me32.szModule == "KERNEL32.DLL") //we find kernel32.dll
{
CloseHandle(hSnapshot);
break;
}
}
printf("\nBase address: 0x%08X\n", (DWORD)(intptr_t)me32.modBaseAddr); //Used this for CheatEngine
DWORD RVA = (DWORD_PTR)RVAddress((char*)GetFileImage(kernel_path), function_name); //Get the relative virtual address of the function
DWORD Load = (DWORD_PTR)me32.modBaseAddr+(DWORD_PTR)RVA; //Add the base address of kernel32.dll and the RVA of the function to get a DWORD representation of the address of the function in the remote process
return Load; //return the address of the function in the remote process
}
任何帮助将不胜感激。
【问题讨论】:
-
now can't find GetProcAddress 你的代码有问题,因为 GetProcAddress 肯定在 kernel32.dll 中。可能是这样的功能(获取地址,注入,.. .) 已经由其他人编写并打包在库中,所以找到并使用它可能会更省力?
-
@stijn 我很确定这不是我的程序。我的一个预感是,函数名称可能被破坏了,因为它们是在 C++ 编译器中定义的,该编译器会将符号变成特殊的文本数据,而不是像 C 编译器那样仅通过函数名称来识别它们。但我不知道。
-
@stijn 如果您发现我的代码有任何问题,请随时指出。
-
GetProcAddress 是一个纯 C 函数,因此没有名称修改.. 例如在 powershell 中:
dumpbin.exe /exports C:\Windows\System32\kernel32.dll | sls procadd输出588 24B 00022070 GetProcAddress。我没有时间浏览您的代码,但是您自己尝试过吗?在调试器下运行它,在该循环中放置一个断点并查看 name_table 中的内容。一方面,像(BYTE*)image+(DWORD)(intptr_t)这样的东西看起来很奇怪。至少不需要这些演员中的一个。不知道这是否是罪魁祸首。 -
@stijn 在内存转储中查看它之后,它看起来确实包含
GetProcAddress和许多其他函数,它显然被跳过了。然而,我不知道为什么。难道是我在检索名称时错误地进行了指针运算?
标签: c++11 dll export portable-executable kernel32