3.ring3-hook的2种基础方式(SetWindowsHookEx、CreateRemoteThread、)

参考:http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces

SetWindowsHookEx 

1.在成功调用 SetWindowsHookEx 后,系统自动映射 DLL 到钩子作用的线程地址空间,但不会立即发生映射,因为 Windows 钩子都是消息,DLL 在消息事件发生前并没有产生实际的映射。

2.为了强制进行映射,在调用 SetWindowsHookEx 之后马上发送一个事件到相关的线程。

SendMessage(hWnd, WM_HOOKEX, 0, 1);
WM_HOOKEX可以在DLL加载时注册,DLLMain:DLL_PROCESS_ATTACH

WM_HOOKEX = ::RegisterWindowMessage("WM_HOOKEX_RK");	
3.钩子会影响性能,所以最好DLL被实际映射的第一时间,也就是在HOOK处理函数中,及时UnhookWindowsHookEx,并LoadLibrary我们的dll,同时SubClass消息

LRESULT HookProc (
				  int code,      
				  WPARAM wParam, 
				  LPARAM lParam  
				  )
{
	if ((pCW->message == WM_HOOKEX)
		&& pCW->lParam) 
	{
		::UnhookWindowsHookEx(g_hHook);

		if (g_bSubclassed) 
		{
			return ::CallNextHookEx(g_hHook, code, wParam, lParam);
		}

		char lib_name[MAX_PATH]; 
		::GetModuleFileName( hDll, lib_name, MAX_PATH );

		if (!::LoadLibrary( lib_name ))
		{
			return ::CallNextHookEx(g_hHook, code, wParam, lParam);
		}

		OldProc = (WNDPROC) 
			::SetWindowLong(g_hWnd, GWL_WNDPROC, (long)NewProc);
		if (OldProc==NULL)	
		{
			::FreeLibrary( hDll );
		}
		else
		{				
			::MessageBeep(MB_OK);	
			g_bSubclassed = true;
		}		
	}
4.上述三点可以实现挂钩后及时脱离,但怎么释放自己的DLL呢,这时就需要再次 SetWindowsHookEx了,同时发送释放自己dll的消息通知,接上述代码

else if (WM_HOOKEX ==pCW->message) 
	{
		::UnhookWindowsHookEx(g_hHook);
		if(!SetWindowLong( g_hWnd, GWL_WNDPROC, (long)OldProc))
		{
		return ::CallNextHookEx(g_hHook, code, wParam, lParam);
		}
		::FreeLibrary( hDll );
		::MessageBeep(MB_OK);
		g_bSubclassed = false;	
	}

CreateRemoteThread 

HMODULE WINAPI LoadLibrary(
  __in          LPCTSTR lpFileName
);
BOOL WINAPI FreeLibrary(
  __in          HMODULE hModule
);
HANDLE WINAPI CreateRemoteThread(
  __in          HANDLE hProcess,
  __in          LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in          SIZE_T dwStackSize,
  __in          LPTHREAD_START_ROUTINE lpStartAddress,
  __in          LPVOID lpParameter,
  __in          DWORD dwCreationFlags,
  __out         LPDWORD lpThreadId
);
typedef DWORD (__stdcall *LPTHREAD_START_ROUTINE) (
        [in] LPVOID lpThreadParameter
);
关键点, LoadLibrary和FreeLibrary都是LPTHREAD_START_ROUTINE函数类型

也就是说,我们可以把LoadLibrary/FreeLibrary 作为到CreateRemoteThread 的线程参数
1. lpStartAddress 参数必须表示远程进程中线程函数的开始地址,这个没问题,因为一般来说kernel32在不同进程中加载位置是相同的,所以LoadLibrary/FreeLibrary 地址可以直接在本进程获取再传给远程进程
2.如果传递到 ThreadFunc 的参数lpParameter 被解释为一个指针。它必须指向远程进程的内存数据,如果被解释成常规的32位数据当然就不考虑了
这里就会有个新问题,LoadLibrary传入的肯定是要注入的dll的路径,所以就是向被注入的进程写数据了
	HMODULE hKernel32 = ::GetModuleHandle("Kernel32");
	void* pLibRemote = ::VirtualAllocEx(hProcess, NULL, nLen, MEM_COMMIT, PAGE_READWRITE );
	if (NULL == pLibRemote)
	{
		return false;
	}

	if (!::WriteProcessMemory(hProcess, pLibRemote, (void*)szDllPath,nLen,NULL))
	{
		return false;
	}

	HANDLE hThread = ::CreateRemoteThread( hProcess, NULL, 0,	
		(LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32,"LoadLibraryA"), 
		pLibRemote, 0, NULL );
	if (NULL == hThread)
	{
		goto JUMP;
	}

	::WaitForSingleObject( hThread, INFINITE );

	// Get handle of loaded module
	::GetExitCodeThread(hThread, &g_hLibModule);
	::CloseHandle(hThread);
//
JUMP:	
	::VirtualFreeEx(hProcess, pLibRemote, sizeof(szDllPath), MEM_RELEASE );
	if (NULL == g_hLibModule)
	{
		return false;
	}

3.退出HOOK
HMODULE hKernel32 = ::GetModuleHandle("Kernel32");
	HANDLE hThread = ::CreateRemoteThread(hProcess,
		NULL, 0,
		(LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32,"FreeLibrary"),
		(void*)g_hLibModule,
		0, NULL );











  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值