关于qihoocom大侠的 另类挂钩-RING3数据包监视 相信很多人都看过了。不过明明不是我写的代码,这已经是第四个人问我这个代码应该怎么改了,而且基本都是类似的要求URL过滤或者拦截指定数据包。
也许是太简单了,没见MJ在博客和论坛谈论这个代码的具体应用,不过不得不承认Hook NtDeviceIoControlFile应用还是相当广泛的。
比如我这里演示的两个功能:过滤URL 和 页面劫持(重定向)


1. 过滤包含指定URL的访问最简单,匹配到这样的 GET/POST请求后,直接返回错误就OK了。
2. 页面劫持就是通过 HTTP 301 消息,伪造页面被移走的假象来欺骗浏览器,当然这个要实现的话,需要浏览器支持重定向功能。

代码依然在原来的基础上修改来的,主要修改如下:

代码:
  // 过滤参数
  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;

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);
            // 修改缓冲区内容为重定向字符串,
            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句柄,为了效率建议自己实现查询。另外很多地方没有完善的判断,比如直接
  CopyMemory(Buffer, @Redirect_String[1], Length(Redirect_String));
可能导致溢出,需要首先 if (Len > Length(Redirect_String)) then 再去修改缓冲区。

完整工程文件见附件。注入dll到浏览器后就能看到效果,这段代码会阻止所有对 google.com 的访问,并且将看雪论坛的请求全部重定向到百度的那个地址上
上传的附件 r3_Hook_NtDeviceIoControl_301_src.rar