我想调用一个函数在我做了一个DLL注入的远程进程。
我已经成功地注入我的DLL有:
CreateRemoteThread(pHandle, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA"), pLibRemote, 0, NULL);
该DllMain的执行和DLL是在待机模式下运行。 我想这样做是有点调用远程加载的DLL,以做一些工作。
我曾尝试导出这样的功能:
extern "C" __declspec(dllexport) void MyFunc(void)
然后执行这样的功能:
CreateRemoteThread(pHandle, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("mydll"), "MyFunc"), NULL, 0, NULL);
但它会导致崩溃。
我该如何解决这个问题?
调用GetModuleHandle
你有它映射到进程(如果有的话)将得到DLL的基地。 所以,你需要做的是首先要确保导出函数的DLL。 你可以做你做或创建一个.def
文件,如这里 。 此后:
理论上
- 注入DLL到目标进程,并让它在装载基址
- 注入DLL到当前进程。 使用
GetProcAddress
发现导出的函数和DLL的底座之间的偏移。 - 添加该偏移从步骤1中获得的基地址
CreateRemoteThread
在该位置。
在实践中
如果做你的DLL注入,可以让你获得你的DLL加载到目标的基础。
HMODULE hInjected;
hThread = CreateRemoteThread( hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)( GetProcAddress( hMod,
"LoadLibraryW" ) ), lpAddress, 0, NULL );
// Locate address our payload was loaded
if( hThread != 0 ) {
WaitForSingleObject( hThread, INFINITE );
GetExitCodeThread( hThread, ( LPDWORD )&hInjected );
CloseHandle( hThread );
}
hInjected
将所注入的DLL的基极。 然后我有另一个功能:
void* GetPayloadExportAddr( LPCWSTR lpPath, HMODULE hPayloadBase, LPCSTR lpFunctionName ) {
// Load payload in our own virtual address space
HMODULE hLoaded = LoadLibrary( lpPath );
if( hLoaded == NULL ) {
return NULL;
} else {
void* lpFunc = GetProcAddress( hLoaded, lpFunctionName );
DWORD dwOffset = (char*)lpFunc - (char*)hLoaded;
FreeLibrary( hLoaded );
return (DWORD)hPayloadBase + dwOffset;
}
}
这样做是第一次加载载荷到我们自己的虚拟地址空间。 之后,我们可以使用GetProcAddress
来获得导出函数的地址。 由此,我们可以得到从DLL的基本偏移功能。 添加这一偏移量与hInjected
我们早点起床会告诉我们在CreateRemoteThread
调用应该进行。 所以,你可以做出像这样的电话:
BOOL InitPayload( HANDLE hProcess, LPCWSTR lpPath, HMODULE hPayloadBase, HWND hwndDlg ) {
void* lpInit = GetPayloadExportAddr( lpPath, hPayloadBase, "Init" );
if( lpInit == NULL ) {
return FALSE;
} else {
HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0,
lpInit, hwndDlg, 0, NULL );
if( hThread == NULL ) {
return FALSE;
} else {
CloseHandle( hThread );
}
}
return TRUE;
}
这是拆出来的所有代码, 旧的项目我有 。 欢迎您乘坐代码,做你想做的事情不管,但我知道,如果我现在要重写代码,我会做很多不同的事情。
小李的回答工作,如果你是注入DLL 32位到32位进程。
如果要注入DLL 64位到64位的过程中,你不能获得DLL的基址GetExitCodeThread
,因为它只会给你的64位地址的低32位。
为了获得在这种情况下,正确的地址,您必须编写的代码到调用进程LoadLibrary
(存储在处理内存中的特定位置的结果),执行的代码块(使用CreateRemoteThread
),然后读回从使用位置的地址ReadProcessMemory
。
你可以找到更多细节在这里(包括PowerShell和ASM代码)在这里: http://clymb3r.wordpress.com/2013/05/26/implementing-remote-loadlibrary-and-remote-getprocaddress-using-powershell-and -部件/
然后,您可以计算偏移量导出的函数一样迈克介绍,但要小心存放在64位值的差异,而不是在一个DWORD(这是32位)。