[原创] Ring3挂钩实现网址过滤、重定向——《另类挂钩-RING3数据包监视》应用
转一份本地备份,原帖发在看雪的:http://bbs.pediy.com/showthread.php?t=100847
这份代码演示了如何根据黑名单过滤指定URL(可以实现简单的网页防火墙),并且演示了一种最容易实现的页面劫持方法(重定向)。当然,使用这个方法钓鱼是绝对禁止的,出了任何问题都与本人无关
实现原理:
1. 网址的黑名单过滤最简单,如果不需要模式匹配的话可以直接 Pos() 查找Buffer中是否包含指定字符串,有则直接返回失败(例如0xC0000001),让系统不发送这个请求包。
2. 页面劫持就是指将一个网站(或页面)的访问重定向到我们指定的网址上,这个电信以前干得比较多,他们是通过DNS实现的。这里通过修改服务器的返回数据,替换成 HTTP/1.1 301 来欺骗浏览器,比直接修改GET报文更方便,而且可以跨站。
都在原来代码的基础上修改而来,完整工程见文章末尾,下面是新增的处理部分:
// 过滤参数
Block_Filter = 'google.com'; // 阻止所有对 google.com 的请求
// 重定向参数
URL_Filter = 'bbs.pediy.com'; // 要重定向的URL (小写)
Redirect_String: AnsiString = // 重定向字符串(使用 HTTP 301)
'HTTP/1.1 301 Moved Permanently'#13#10'Location: ' +
'http://www.baidu.com/search/error.html' +
#0;
in function NewNtDeviceIoControlFile():
case IoControlCode of
AFD_SEND:
if ( LookupSendPacket(Buffer, Len) ) then
begin
// 输出包内容
OutputDebugString(PChar(Format('[HTTP Send] Handle = %0.8X, Length = %d', [FileHandle, Len])));
OutputDebugString(PChar(Format('%s', [StrPas(Buffer)])));
tmpStr := LowerCase(String(StrPas(Buffer)));
{ 网址过滤实现 }
if (Pos(Block_Filter, tmpStr) > 0) then
begin
OutputDebugString(PChar(Format('>>> "%s" was blocked.', [Block_Filter])));
Result := $C0000001; // 返回失败让系统丢掉这个包
end;
{ 重定向实现 }
// 查找发送的数据中是否包含 URL_Filter 中的字符串
if (Pos(URL_Filter, tmpStr) > 0) then
begin
// 匹配到 URL_Filter,将Handle加入 SessionList
tmpStr := IntToHex(FileHandle, 8);
if (SessionList.IndexOf(tmpStr) = -1) then // 如果没有这个Handle
SessionList.Add(tmpStr);
end;
end;
AFD_RECV:
if ( LookupRecvPacket(Buffer, Len) ) then
begin
// 输出包内容
OutputDebugString(PChar(Format('[HTTP Recv] Handle = %0.8X, Length = %d', [FileHandle, Len])));
OutputDebugString(PChar(Format('%s', [StrPas(Buffer)])));
{ 重定向实现 }
// 在SessionList查找Handle,找到则进行重定向
tmpStr := IntToHex(FileHandle, 8);
Index := SessionList.IndexOf(tmpStr);
if (Index >= 0) then
begin
SessionList.Delete(Index);
// 修改缓冲区内容为重定向字符串
if (Len >= DWORD(Length(Redirect_String))) then
CopyMemory(Buffer, @Redirect_String[1], Length(Redirect_String));
OutputDebugString(PChar(Format('>>> Redirect "%s" to a new page.', [URL_Filter])));
end;
end;
end;
Block_Filter = 'google.com'; // 阻止所有对 google.com 的请求
// 重定向参数
URL_Filter = 'bbs.pediy.com'; // 要重定向的URL (小写)
Redirect_String: AnsiString = // 重定向字符串(使用 HTTP 301)
'HTTP/1.1 301 Moved Permanently'#13#10'Location: ' +
'http://www.baidu.com/search/error.html' +
#0;
in function NewNtDeviceIoControlFile():
case IoControlCode of
AFD_SEND:
if ( LookupSendPacket(Buffer, Len) ) then
begin
// 输出包内容
OutputDebugString(PChar(Format('[HTTP Send] Handle = %0.8X, Length = %d', [FileHandle, Len])));
OutputDebugString(PChar(Format('%s', [StrPas(Buffer)])));
tmpStr := LowerCase(String(StrPas(Buffer)));
{ 网址过滤实现 }
if (Pos(Block_Filter, tmpStr) > 0) then
begin
OutputDebugString(PChar(Format('>>> "%s" was blocked.', [Block_Filter])));
Result := $C0000001; // 返回失败让系统丢掉这个包
end;
{ 重定向实现 }
// 查找发送的数据中是否包含 URL_Filter 中的字符串
if (Pos(URL_Filter, tmpStr) > 0) then
begin
// 匹配到 URL_Filter,将Handle加入 SessionList
tmpStr := IntToHex(FileHandle, 8);
if (SessionList.IndexOf(tmpStr) = -1) then // 如果没有这个Handle
SessionList.Add(tmpStr);
end;
end;
AFD_RECV:
if ( LookupRecvPacket(Buffer, Len) ) then
begin
// 输出包内容
OutputDebugString(PChar(Format('[HTTP Recv] Handle = %0.8X, Length = %d', [FileHandle, Len])));
OutputDebugString(PChar(Format('%s', [StrPas(Buffer)])));
{ 重定向实现 }
// 在SessionList查找Handle,找到则进行重定向
tmpStr := IntToHex(FileHandle, 8);
Index := SessionList.IndexOf(tmpStr);
if (Index >= 0) then
begin
SessionList.Delete(Index);
// 修改缓冲区内容为重定向字符串
if (Len >= DWORD(Length(Redirect_String))) then
CopyMemory(Buffer, @Redirect_String[1], Length(Redirect_String));
OutputDebugString(PChar(Format('>>> Redirect "%s" to a new page.', [URL_Filter])));
end;
end;
end;
为了方便实现,利用了 TStringList.IndefOf() 查找Socket句柄,考虑效率的话建议自己实现查询算法。
注入dll到浏览器后就能看到效果,这段代码会阻止所有对 google.com 的访问,并且将看雪论坛的请求全部重定向到百度的错误页面上。