转一份本地备份,原帖发在看雪的: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 的访问,并且将看雪论坛的请求全部重定向到百度的错误页面上。