C/C++:Windows編程—Hook IE瀏覽器實現URL攔截及更改(上)

Hook IE瀏覽器實現URL攔截及更改(上)

前言+思路

筆者這裏有個需求,針對IE瀏覽器 用戶訪問URL 做一個判斷,是否爲 限制訪問的url,如果是 在另一個軟件上給與警告提示。筆者在拿到這個需求的時候也是網上一頓找,在csdn上找到一篇 hook IE 總結。這篇文章給我一些思路,獲取IE瀏覽器訪問的URL 那麼需要知道 IE瀏覽器訪問URL 用的那種方式,從這文章提示使用 WININET.dll庫中的方法。

然後我在一個windows開發羣 提問題,有網友指點說,在ring3級別下最底層的網絡數據都會到達Ntdll.dll 中 NtDeviceIoControlFile這個方法。然後筆者當然 繼續搜索唄。在 網路上搜索到 看雪論壇上的一篇文章 另類掛鉤-RING3數據包監視 。筆者 當然如獲至寶呀,代碼都現成 拿過改改 不就行了?日期顯示代碼 是10年前的,使用的是 IAT HOOK的方式,代碼完全拿過來 稍微改了一點點 在WriteProcessMemory前後添加VirtualProtect 針對內存頁保護模式的修改,居然還能正常運行。最後測試結果 IE上的請求數據都能攔截到,但是 只有訪問http請求的時候 能看到數據的明文,此時能看到HTTP請求的URL,如果是HTTPS請求攔截到的數據都是經過加密的,如果自己來解密的話應該是相當地麻煩。所以還是不符合筆者的期望,況且 筆者不需要那麼底層的數據,只要在用戶在地址欄 訪問後立馬攔截到就可以了。 此路不通,筆者只能再換一條路了。

經過漫長的搜索,沒有太多線索,筆者決定用OllyDbg斷點調試下 看能否發現線索。前面網上提示說IE瀏覽器 網絡請求用的WININET.dll庫,所以筆者在OD上 將 WININET.dll下與什麼url、request、Internet相關的方法都打上斷點(這裏筆者是在win7 x86 上調試IE進程,OD目前只能調試32位程序)。先將IE瀏覽器打開 然後用OD 附件到進程,讓後ctrl + g 輸入對應的方法,跟蹤表達式到達指定的位置然後f2打上斷點。

在這裏插入圖片描述

然後筆者在瀏覽器地址欄上輸入 www.baidu.com 然後回車,果然奇蹟出現了 斷點 在WinInet.dll的InternetConnectW方法處停住了。
在這裏插入圖片描述

而且參數2 爲URL!筆者趕緊查了下 InternetConnectW方法說明,在調此函數之前會調用一個InternetOpen函數,但是此函數沒有url相關參數。然後筆者 f9 繼續往後走,在一些方法的斷點也會停住 有url參數 也可以看到url的明文,所以從這裏可以斷定 在進行網絡請求的時候 InternetConnectW方法已經是比較靠前的了!所以在這裏hook 可以拿到訪問的URL 也比較符合筆者的期望。筆者在hook的時候 還走一點小彎路,因爲之前用IAT hook的方式能hook到NtDeviceIoControlFile 筆者想 那我就用IAT hook的方式 來hook WININET.dll不就得了!但是是不行的 IAT方式是讀取PE頭,這種方式不能hook 動態加載的DLL!所以筆者使用 Inline hook的方式。因爲要想運行我們自己的邏輯 要麼代碼注入 要 DLL注入,DLL注入肯定少不了 。

實現效果

先看效果,csdn如果看不清 可以這個地址觀看https://www.bilibili.com/video/av81160225

HOOK IE瀏覽器攔截URL效果

代碼實現

這裏先說下,筆者的運行環境,win10-64位+VS2010+IE11

由於筆者之前寫過 DLL注入的例子(Windows編程—DLL注入與卸載 ) 和 Inline Hook的例子(Windows編程—Inline Hook內聯鉤子(下) ),所以直接把之前的代碼拿過 稍微改改就能用了。這裏我們驗證 還用到了另外2個軟件 Process Explorer (該軟件能查看當前進程所有的DLL,等會用來查看DLL注入和卸載是否成功),DebugView(我們注入的DLL中使用OutputDebugString這種方式打印日誌,可以通過DebugView工具查看),示例demo可以在這裏下載也可在github下載最新代碼,如果可以的話,幫忙點個星星喲。

我們要注入的DLL代碼。其實代碼很簡單就是 DLL注入和Inline Hook的結合,基礎牢固,思路正確,做起來還是比較容易的。

#include "stdafx.h"
#include <Windows.h>
#include <Wininet.h>
#pragma comment(lib,"wininet.lib")

#include "InlineHook7.h"

CInlineHook7 g_inlineHookObj7;

typedef HINTERNET ( WINAPI *InternetConnectWFunc)(
	HINTERNET     hInternet,
	LPCWSTR       lpszServerName,
	INTERNET_PORT nServerPort,
	LPCWSTR       lpszUserName,
	LPCWSTR       lpszPassword,
	DWORD         dwService,
	DWORD         dwFlags,
	DWORD_PTR     dwContext
	);

HINTERNET WINAPI MyInternetConnectW(
	HINTERNET     hInternet,
	LPCWSTR       lpszServerName,
	INTERNET_PORT nServerPort,
	LPCWSTR       lpszUserName,
	LPCWSTR       lpszPassword,
	DWORD         dwService,
	DWORD         dwFlags,
	DWORD_PTR     dwContext
	)
{
	g_inlineHookObj7.UnHook(); // 必須先卸載鉤子 再纔可以再次調用被Hook的函數,不然會進入死循環
	HINTERNET ret = NULL;
	CString temp;
	temp.Format(_T("攔截到url:%s"),lpszServerName);
	CString url = lpszServerName;
	if(url.Find(_T("baidu.com")) >= 0)
	{
		url = _T("www.sogou.com");
	}

	OutputDebugString(temp);
	// 這裏要用已經存在的庫,不要再在自己的庫中鏈接WININET.dll庫去使用
	//ret = ::InternetConnectW(hInternet, lpszServerName, nServerPort, lpszUserName, lpszPassword,  dwService,  dwFlags,  dwContext);

	HMODULE hModule = GetModuleHandle(_T("WININET.dll"));
	if(hModule == NULL)
	{
		OutputDebugString(_T("GetModuleHandle false"));
		goto end;
	}
	InternetConnectWFunc func = (InternetConnectWFunc)GetProcAddress(hModule,"InternetConnectW");
	if(func == NULL)
	{
		OutputDebugString(_T("GetProcAddress false"));
		goto end;
	}
	ret = func(hInternet, url, nServerPort, lpszUserName, lpszPassword,  dwService,  dwFlags,  dwContext);
	
end:
	g_inlineHookObj7.ReHook();
	return ret;
}


VOID InlineHookIE()
{
	OutputDebugString(_T("InlineHookIE into"));
	g_inlineHookObj7.Hook("WININET.dll","InternetConnectW",(FARPROC)MyInternetConnectW);
	return;
}

VOID UnInlineHookIE()
{
	OutputDebugString(_T("UnInlineHookIE into"));
	g_inlineHookObj7.UnHook();
	return;
}

// DLL 入口
BOOL APIENTRY DllMain( HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
	)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		{
			InlineHookIE();
		}
		break;
	case DLL_PROCESS_DETACH:
		UnInlineHookIE();
		break;
	}
	return TRUE;
}



待優化部分

這個demo,只能在IE瀏覽器打開後,再點注入到hook 纔會注入到運行的ie進程中。後續會優化成 我們的demo程序只要運行了,當IE瀏覽器被打開,demo程序自動注入DLL,後面當用戶 再次打開新的標籤頁或者IE進程我們也自動注入我們寫的DLL 這樣纔是最完美的。
============== 待優化部分已經下面這篇博客寫了 ==================
C/C++:Windows編程—Hook IE瀏覽器實現URL攔截及更改(下)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章