现在的位置: 首页 > 综合 > 正文

Windows核心编程Dll注入之远程线程

2018年02月24日 ⁄ 综合 ⁄ 共 1904字 ⁄ 字号 评论关闭

        为了让某个进程运行我们的Dll,可以使用远程线程来达到目的。

为了达到这个目的,我们必须让该进程调用我们的Dll。怎样才能让目标进程来调用我们的DLL呢?首先不可能是隐式的,因为隐式调用Dll的名字必须要在进程的导入表中出现,修改程序的导入表将非常麻烦(有空偶再研究一下)。最直接的方式就是显式的调用LoadLibrary函数来调用我们的Dll。好主意!但是我们怎么样才能让目标进程去执行该动作呢,也就是去调用LoadLibrary函数呢?我们不可能去修改源代码来增加一个线程来执行吧。幸好,windows提供了一个API——CreateRemoteThread,他可以让目标进程创建一个线程!太神奇了!也就是说只要获取到了目标进程的进程句柄(这个容易实现)就可以给他创建一个线程。Good!然后在线程函数中执行调用我们Dll的代码,像这样

CreateRemoteThread(hRemoteProcess, NULL, 0, LoadLibraryW, "C:\\MyDll.dll", 0, NULL) ;慢着,有两个小问题。首先,目标进程真的会执行LoadLibraryW吗?不会!!!在编译和链接一个程序的时候,生成的二进制文件中会包含一个导入段,这个导入段由一些列转换函数(thunk)构成,这些转换函数用来跳转到导入的函数。因此,在代码调用诸如LoadLibraryW之类的函数时,链接器会生成一个调用,来调用我们模块中导入段中的一个转换函数,这个转换函数然后会跳到实际的函数,所以调用CreateRemoteThread时线程函数的地址是我们模块导入段的LoadLibraryW转换函数的地址,我们必须通过下面的方式来得到LoadLibraryW的地址。

GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryW")

因为每个程序到需要调用Kernel32.dll,所以这个方法是可以的。还一个问题是你给线程函数的参数传入"C:\\MyDll.dll"就行啦?当然不行!"C:\\MyDll.dll"是这个进程中的字符串地址,而不是目标进程中的地址!我们必须传递目标进程中该字符串的地址。这两个函数VirtualAllocEx,WriteProcessMemory可以解决问题,一个用来在目标进程中分配地址,一个用来给地址赋值,正好,呵呵。然后调用CreateRemoteThread就OK了,下面给出完整代码:

#include "stdafx.h"
#include <Windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
	HWND hwndTarget = FindWindow(NULL, _T("TestDllInj")) ;
	if(hwndTarget == NULL){
		printf("could not find the window!!!\n") ;
		return 1 ;
	}
	DWORD dwTargetProId ;
	GetWindowThreadProcessId(hwndTarget, &dwTargetProId) ;
	HANDLE hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwTargetProId) ;

	PVOID pMemRomote = VirtualAllocEx(hRemoteProcess, 0, 1024, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE) ;

	if(WriteProcessMemory(hRemoteProcess, pMemRomote, _T("C:\\MyDll.dll"), 1024, NULL) == NULL){
		printf("can not write to mem of the remote process!!!\n") ;
		return 3;
	}
	PTHREAD_START_ROUTINE pfnAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryW") ;
	HANDLE thrd = CreateRemoteThread(hRemoteProcess, NULL, 0, pfnAddr, pMemRomote, 0, NULL) ;
	if(thrd == NULL){
		printf("create remote thread failed!!!\n") ;
	}
	else{
		printf("Inject dll sucessed!!!\n") ;
	}

	return 0;
}


抱歉!评论已关闭.