如何編寫能夠監聽特定程序或全系統所有Http請求的.Net程序?

需求就是獲取所有Http請求的目標地址Url即可。

可以是監聽系統內所有程序,或者也可以只監聽特定的應用程序,比如某瀏覽器。

請問.Net環境下如何編碼能夠實現此需求?

最好給出C#代碼示例,謝謝。


要求不高的話,沒那麼複雜,寫個Fiddler的插件就好了。

Fiddler可以攔截絕大多數HTTP請求(因為這貨會修改Internet設置把自己變成代理),還可以自動幫你解壓、HTTPS解密啥的。

絕大多數需要HTTP訪問的軟體,都會遵循Internet設置中的代理設置的,所以Fiddler在大部分情況下是足夠OK的。

當然如果你想要無條件攔截本機發出的所有HTTP請求,去改路由器吧。


.net估計不行,因為你得裝一個驅動進去攔截


參考Fiddler的原理,考慮也是實現Http代理,然後設定目標程序走這個代理訪問外部網路,應該就可以了。

找到這樣一個C#的Http代理示常式序:

Visual C#實現HTTP代理服務程序

用IE改代理接入此程序的監聽埠8000後,測試可以跑起來,也可以截獲訪問目標IP地址,但是好像無法獲取完整的Http網址Url?另外程序內部經常報異常,導致無法正確將請求轉出,繼而IE上訪問什麼都訪問不了。

有待研究修正。

——————————————更新——————————————

修正了原始代碼的多處錯誤,現在可以正確處理代理了,但是處理速度很慢,而且時有訪問不到的情況,什麼遠程伺服器關閉連接之類的,不明所以。

修改後的代碼:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace WebProxy
{
internal class Proxy
{
private Socket clientSocket;
private Byte[] read = new byte[1024];
//定義一個空間,存儲來自客戶端請求數據包
private Byte[] Buffer = null;
private Encoding ASCII = Encoding.UTF8;
//設定編碼
private Byte[] RecvBytes = new Byte[4096];
//定義一個空間,存儲Web伺服器返回的數據

public Proxy(Socket socket)
{
clientSocket = socket;
}

public void Run()
{
try
{
string clientmessage = "";
//存放來自客戶端的HTTP請求字元串

int bytes = ReadMessage(read, ref clientSocket, ref clientmessage);
if (bytes == 0)
{
return;
}

//int index1 = clientmessage.IndexOf(" ");
//int index2 = clientmessage.IndexOf(" ", index1 + 1);
//if ((index1 == -1) || (index2 == -1))
//{
// throw new IOException();
//}
//string part1 = clientmessage.Substring(index1 + 1, index2 - index1);
//int index3 = part1.IndexOf("/", index1 + 8);
//int index4 = part1.IndexOf(" ", index1 + 8);
//int index5 = index4 - index3;
//_URL = part1.Substring(index1 + 4, (part1.Length - index5) - 8);

var url = new Regex(@"GETs+(S+)s+HTTP").Match(clientmessage).Groups[1].Value;
var host = new Regex(@"Host:s*([^s
]+)").Match(clientmessage).Groups[1].Value;
Console.WriteLine($"目標網址:{url} 主機:{host}");
try
{
IPHostEntry IPHost = Dns.Resolve(host);
Console.WriteLine("遠程主機名: " + IPHost.HostName);
string[] aliases = IPHost.Aliases;
IPAddress[] address = IPHost.AddressList;
Console.WriteLine("Web伺服器IP地址:" + address[0]);
//解析出要訪問的伺服器地址
IPEndPoint ipEndpoint = new IPEndPoint(address[0], 80);
Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//創建連接Web伺服器端的Socket對象
IPsocket.Connect(ipEndpoint);
//Socket連Web接伺服器
if (IPsocket.Connected)
Console.WriteLine("Socket 正確連接!");
string GET = clientmessage;
Byte[] ByteGet = ASCII.GetBytes(GET);
IPsocket.Send(ByteGet, ByteGet.Length, 0);
//代理訪問軟體對伺服器端傳送HTTP請求命令
Int32 rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
//代理訪問軟體接收來自Web伺服器端的反饋信息
Console.WriteLine("接收位元組數:" + rBytes.ToString());
String strRetPage = null;
strRetPage = ASCII.GetString(RecvBytes, 0, rBytes);
while (rBytes &> 0)
{
rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
}
IPsocket.Shutdown(SocketShutdown.Both);
IPsocket.Close();
SendMessage(clientSocket, strRetPage);
//代理服務軟體往客戶端傳送接收到的信息
}
catch (Exception exc2)
{
Console.WriteLine(exc2.ToString());
}
}
catch (Exception te)
{
Console.WriteLine(te);
}
}

//接收客戶端的HTTP請求數據
private int ReadMessage(byte[] ByteArray, ref Socket s, ref String clientmessage)
{
int bytes = s.Receive(ByteArray, 1024, 0);
string messagefromclient = Encoding.ASCII.GetString(ByteArray);
clientmessage = (String)messagefromclient;
return bytes;
}

//傳送從Web伺服器反饋的數據到客戶端
private void SendMessage(Socket s, string message)
{
Buffer = Encoding.UTF8.GetBytes(message);
int length = Buffer.Length;
Console.WriteLine("傳送位元組數:" + length);
s.Send(Buffer, length, 0);
}
}
}

_____________更新_________________

由 張曉彬 提出的 SharpPcap ,測試下來感覺不錯,監聽網卡後,抓取TCP包,已經可以從中分析出正確的Url了,而且效率很高:

但是因為TCP包是會斷開的,一個Http數據可能都會被截斷,目前尚不知TCP包組裝成Http請求的正確邏輯,有待繼續研究。

_________________________更新______________________

已基本搞定了TCP包拼裝成完整Http報文的方法:

主要就是根據 tcpPacket.AcknowledgmentNumber 進行歸檔拼接就可以了

———————————————更新——————————————

寫了兩篇博文加以總結:

http://skyd.sinaapp.com/archives/1169

http://skyd.sinaapp.com/archives/1175


監聽所有可以使用原始套接字,參考fastCSharp的demo.rawSocketListener,你可以針對TCP包做處理(比如GET或者POST開始的)。


WinpCap SDK


看這個呢?

Fiddler

http://www.telerik.com/fiddler


不用winpcap的話可以把自己偽裝代理伺服器,所有需要訪問網路的程序的代理ip埠指向你,.net應該可以做到,只是實現或許有點麻煩,fiddler好像就是這麼乾的。。


fiddle


LSP掛鉤子


全局(IE)代理


推薦閱讀:

C#為什麼Random類不做靜態?
關於 C# 中「string + int」的執行機制的疑惑?
既然在變數前加一個&就可以得到地址,為什麼還需要指針?
有哪些語言可以做到:List<T> 實現介面 I(或繼承某個類)當且僅當 T 實現 I?
關於MSIL中的Nop的問題?

TAG:軟體開發 | 編程 | C# | Dotnet | C#編程 |