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拦截及更改(下)

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页