Delphi钩子重定向到不同的ip
将任何浏览器重定向到特定站点的不同 IP 的最佳方法是什么? 例如,如果用户在任何浏览器中输入 www.facebook.com,他将被重定向到 127.0.0.1。如果他输入 66.220.146.11,也会发生同样的情况。
到目前为止我所拥有的是: 使用 winpkfilter 我能够拦截端口 80 上的所有流量,类型(输入或输出)、源 ip、目标 ip 和数据包。我的问题是以某种方式修改数据包,以便浏览器被重定向。
这是我现在拥有的代码:
program Pass;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows,
Winsock,
winpkf,
iphlp;
var
iIndex, counter : DWORD;
hFilt : THANDLE;
Adapts : TCP_AdapterList;
AdapterMode : ADAPTER_MODE;
Buffer, ParsedBuffer : INTERMEDIATE_BUFFER;
ReadRequest : ETH_REQUEST;
hEvent : THANDLE;
hAdapter : THANDLE;
pEtherHeader : TEtherHeaderPtr;
pIPHeader : TIPHeaderPtr;
pTcpHeader : TTCPHeaderPtr;
pUdpHeader : TUDPHeaderPtr;
SourceIP, DestIP : TInAddr;
thePacket : PChar;
f : TextFile;
SourceIpString, DestinationIpString : string;
SourceName, DestinationName : string;
function IPAddrToName(IPAddr : string) : string;
var
SockAddrIn : TSockAddrIn;
HostEnt : PHostEnt;
WSAData : TWSAData;
begin
WSAStartup($101, WSAData);
SockAddrIn.sin_addr.s_addr := inet_addr(PChar(IPAddr));
HostEnt := gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
if HostEnt <> nil then
begin
result := StrPas(Hostent^.h_name)
end
else
begin
result := '';
end;
end;
procedure ReleaseInterface();
begin
// Restore default mode
AdapterMode.dwFlags := 0;
AdapterMode.hAdapterHandle := hAdapter;
SetAdapterMode(hFilt, @AdapterMode);
// Set NULL event to release previously set event object
SetPacketEvent(hFilt, hAdapter, 0);
// Close Event
if hEvent <> 0 then
CloseHandle(hEvent);
// Close driver object
CloseFilterDriver(hFilt);
// Release NDISAPI
FreeNDISAPI();
end;
begin
// Check the number of parameters
if ParamCount() < 2 then
begin
Writeln('Command line syntax:');
Writeln(' PassThru.exe index num');
Writeln(' index - network interface index.');
Writeln(' num - number or packets to filter');
Writeln('You can use ListAdapters to determine correct index.');
Exit;
end;
// Initialize NDISAPI
InitNDISAPI();
// Create driver object
hFilt := OpenFilterDriver('NDISRD');
if IsDriverLoaded(hFilt) then
begin
// Get parameters from command line
iIndex := StrToInt(ParamStr(1));
counter := StrToInt(ParamStr(2));
// Set exit procedure
ExitProcessProc := ReleaseInterface;
// Get TCP/IP bound interfaces
GetTcpipBoundAdaptersInfo(hFilt, @Adapts);
// Check paramer values
if iIndex > Adapts.m_nAdapterCount then
begin
Writeln('There is no network interface with such index on this system.');
Exit;
end;
hAdapter := Adapts.m_nAdapterHandle[iIndex];
AdapterMode.dwFlags := MSTCP_FLAG_SENT_TUNNEL or MSTCP_FLAG_RECV_TUNNEL;
AdapterMode.hAdapterHandle := hAdapter;
// Create notification event
hEvent := CreateEvent(nil, TRUE, FALSE, nil);
if hEvent <> 0 then
if SetPacketEvent(hFilt, hAdapter, hEvent) <> 0 then
begin
// Initialize request
ReadRequest.EthPacket.Buffer := @Buffer;
ReadRequest.hAdapterHandle := hAdapter;
SetAdapterMode(hFilt, @AdapterMode);
counter := 0;
//while counter <> 0 do
while true do
begin
WaitForSingleObject(hEvent, INFINITE);
while ReadPacket(hFilt, @ReadRequest) <> 0 do
begin
//dec(counter);
pEtherHeader := TEtherHeaderPtr(@Buffer.m_IBuffer);
if ntohs(pEtherHeader.h_proto) = ETH_P_IP then
begin
pIPHeader := TIPHeaderPtr(Integer(pEtherHeader) +
SizeOf(TEtherHeader));
SourceIP.S_addr := pIPHeader.SourceIp;
DestIP.S_addr := pIPHeader.DestIp;
if pIPHeader.Protocol = IPPROTO_TCP then
begin
pTcpHeader := TTCPHeaderPtr(Integer(pIPHeader) +
(pIPHeader.VerLen and $F) * 4);
if (pTcpHeader.SourcePort = htons(80)) or
(pTcpHeader.DestPort = htons(80)) then
begin
inc(counter);
if Buffer.m_dwDeviceFlags = PACKET_FLAG_ON_SEND
then
Writeln(counter, ') - MSTCP --> Interface')
else
Writeln(counter, ') - Interface --> MSTCP');
Writeln(' Packet size = ',
Buffer.m_Length);
Writeln(Format(' IP %.3u.%.3u.%.3u.%.3u --> %.3u.%.3u.%.3u.%.3u PROTOCOL: %u',
[byte(SourceIP.S_un_b.s_b1),
byte(SourceIP.S_un_b.s_b2),
byte(SourceIP.S_un_b.s_b3),
byte(SourceIP.S_un_b.s_b4),
byte(DestIP.S_un_b.s_b1),
byte(DestIP.S_un_b.s_b2),
byte(DestIP.S_un_b.s_b3),
byte(DestIP.S_un_b.s_b4),
byte(pIPHeader.Protocol)]
));
Writeln(Format(' TCP SRC PORT: %d DST PORT: %d',
[ntohs(pTcpHeader.SourcePort),
ntohs(pTcpHeader.DestPort)]));
//get the data
thePacket := pchar(pEtherHeader) +
(sizeof(TEtherHeaderPtr) + pIpHeader.VerLen * 4
+ pTcpHeader.Offset * 4);
{
SourceIpString :=
IntToStr(byte(SourceIP.S_un_b.s_b1)) + '.' +
IntToStr(byte(SourceIP.S_un_b.s_b2)) + '.' +
IntToStr(byte(SourceIP.S_un_b.s_b3)) + '.' +
IntToStr(byte(SourceIP.S_un_b.s_b4));
DestinationIpString :=
IntToStr(byte(DestIP.S_un_b.s_b1)) + '.' +
IntToStr(byte(DestIP.S_un_b.s_b2)) + '.' +
IntToStr(byte(DestIP.S_un_b.s_b3)) + '.' +
IntToStr(byte(DestIP.S_un_b.s_b4));
}
end;
end;
end;
// if ntohs(pEtherHeader.h_proto) = ETH_P_RARP then
// Writeln(' Reverse Addr Res packet');
// if ntohs(pEtherHeader.h_proto) = ETH_P_ARP then
// Writeln(' Address Resolution packet');
//Writeln('__');
if Buffer.m_dwDeviceFlags = PACKET_FLAG_ON_SEND then
// Place packet on the network interface
SendPacketToAdapter(hFilt, @ReadRequest)
else
// Indicate packet to MSTCP
SendPacketToMstcp(hFilt, @ReadRequest);
{
if counter = 0 then
begin
Writeln('Filtering complete');
readln;
break;
end;
}
end;
ResetEvent(hEvent);
end;
end;
end;
end.
What is the best way to redirect ANY browser to a different ip for specific sites?
For example if the user will type www.facebook.com in any browser he will be redirected to 127.0.0.1. Also the same should happen if he will type 66.220.146.11.
What I have until now is this:
using the winpkfilter I am able to intercept all the traffic on port 80, with type(in or out), source ip, destination ip and packet. My problem is to modify somehow the packet so the browser will be redirected.
This is the code that i have right now:
program Pass;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows,
Winsock,
winpkf,
iphlp;
var
iIndex, counter : DWORD;
hFilt : THANDLE;
Adapts : TCP_AdapterList;
AdapterMode : ADAPTER_MODE;
Buffer, ParsedBuffer : INTERMEDIATE_BUFFER;
ReadRequest : ETH_REQUEST;
hEvent : THANDLE;
hAdapter : THANDLE;
pEtherHeader : TEtherHeaderPtr;
pIPHeader : TIPHeaderPtr;
pTcpHeader : TTCPHeaderPtr;
pUdpHeader : TUDPHeaderPtr;
SourceIP, DestIP : TInAddr;
thePacket : PChar;
f : TextFile;
SourceIpString, DestinationIpString : string;
SourceName, DestinationName : string;
function IPAddrToName(IPAddr : string) : string;
var
SockAddrIn : TSockAddrIn;
HostEnt : PHostEnt;
WSAData : TWSAData;
begin
WSAStartup($101, WSAData);
SockAddrIn.sin_addr.s_addr := inet_addr(PChar(IPAddr));
HostEnt := gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
if HostEnt <> nil then
begin
result := StrPas(Hostent^.h_name)
end
else
begin
result := '';
end;
end;
procedure ReleaseInterface();
begin
// Restore default mode
AdapterMode.dwFlags := 0;
AdapterMode.hAdapterHandle := hAdapter;
SetAdapterMode(hFilt, @AdapterMode);
// Set NULL event to release previously set event object
SetPacketEvent(hFilt, hAdapter, 0);
// Close Event
if hEvent <> 0 then
CloseHandle(hEvent);
// Close driver object
CloseFilterDriver(hFilt);
// Release NDISAPI
FreeNDISAPI();
end;
begin
// Check the number of parameters
if ParamCount() < 2 then
begin
Writeln('Command line syntax:');
Writeln(' PassThru.exe index num');
Writeln(' index - network interface index.');
Writeln(' num - number or packets to filter');
Writeln('You can use ListAdapters to determine correct index.');
Exit;
end;
// Initialize NDISAPI
InitNDISAPI();
// Create driver object
hFilt := OpenFilterDriver('NDISRD');
if IsDriverLoaded(hFilt) then
begin
// Get parameters from command line
iIndex := StrToInt(ParamStr(1));
counter := StrToInt(ParamStr(2));
// Set exit procedure
ExitProcessProc := ReleaseInterface;
// Get TCP/IP bound interfaces
GetTcpipBoundAdaptersInfo(hFilt, @Adapts);
// Check paramer values
if iIndex > Adapts.m_nAdapterCount then
begin
Writeln('There is no network interface with such index on this system.');
Exit;
end;
hAdapter := Adapts.m_nAdapterHandle[iIndex];
AdapterMode.dwFlags := MSTCP_FLAG_SENT_TUNNEL or MSTCP_FLAG_RECV_TUNNEL;
AdapterMode.hAdapterHandle := hAdapter;
// Create notification event
hEvent := CreateEvent(nil, TRUE, FALSE, nil);
if hEvent <> 0 then
if SetPacketEvent(hFilt, hAdapter, hEvent) <> 0 then
begin
// Initialize request
ReadRequest.EthPacket.Buffer := @Buffer;
ReadRequest.hAdapterHandle := hAdapter;
SetAdapterMode(hFilt, @AdapterMode);
counter := 0;
//while counter <> 0 do
while true do
begin
WaitForSingleObject(hEvent, INFINITE);
while ReadPacket(hFilt, @ReadRequest) <> 0 do
begin
//dec(counter);
pEtherHeader := TEtherHeaderPtr(@Buffer.m_IBuffer);
if ntohs(pEtherHeader.h_proto) = ETH_P_IP then
begin
pIPHeader := TIPHeaderPtr(Integer(pEtherHeader) +
SizeOf(TEtherHeader));
SourceIP.S_addr := pIPHeader.SourceIp;
DestIP.S_addr := pIPHeader.DestIp;
if pIPHeader.Protocol = IPPROTO_TCP then
begin
pTcpHeader := TTCPHeaderPtr(Integer(pIPHeader) +
(pIPHeader.VerLen and $F) * 4);
if (pTcpHeader.SourcePort = htons(80)) or
(pTcpHeader.DestPort = htons(80)) then
begin
inc(counter);
if Buffer.m_dwDeviceFlags = PACKET_FLAG_ON_SEND
then
Writeln(counter, ') - MSTCP --> Interface')
else
Writeln(counter, ') - Interface --> MSTCP');
Writeln(' Packet size = ',
Buffer.m_Length);
Writeln(Format(' IP %.3u.%.3u.%.3u.%.3u --> %.3u.%.3u.%.3u.%.3u PROTOCOL: %u',
[byte(SourceIP.S_un_b.s_b1),
byte(SourceIP.S_un_b.s_b2),
byte(SourceIP.S_un_b.s_b3),
byte(SourceIP.S_un_b.s_b4),
byte(DestIP.S_un_b.s_b1),
byte(DestIP.S_un_b.s_b2),
byte(DestIP.S_un_b.s_b3),
byte(DestIP.S_un_b.s_b4),
byte(pIPHeader.Protocol)]
));
Writeln(Format(' TCP SRC PORT: %d DST PORT: %d',
[ntohs(pTcpHeader.SourcePort),
ntohs(pTcpHeader.DestPort)]));
//get the data
thePacket := pchar(pEtherHeader) +
(sizeof(TEtherHeaderPtr) + pIpHeader.VerLen * 4
+ pTcpHeader.Offset * 4);
{
SourceIpString :=
IntToStr(byte(SourceIP.S_un_b.s_b1)) + '.' +
IntToStr(byte(SourceIP.S_un_b.s_b2)) + '.' +
IntToStr(byte(SourceIP.S_un_b.s_b3)) + '.' +
IntToStr(byte(SourceIP.S_un_b.s_b4));
DestinationIpString :=
IntToStr(byte(DestIP.S_un_b.s_b1)) + '.' +
IntToStr(byte(DestIP.S_un_b.s_b2)) + '.' +
IntToStr(byte(DestIP.S_un_b.s_b3)) + '.' +
IntToStr(byte(DestIP.S_un_b.s_b4));
}
end;
end;
end;
// if ntohs(pEtherHeader.h_proto) = ETH_P_RARP then
// Writeln(' Reverse Addr Res packet');
// if ntohs(pEtherHeader.h_proto) = ETH_P_ARP then
// Writeln(' Address Resolution packet');
//Writeln('__');
if Buffer.m_dwDeviceFlags = PACKET_FLAG_ON_SEND then
// Place packet on the network interface
SendPacketToAdapter(hFilt, @ReadRequest)
else
// Indicate packet to MSTCP
SendPacketToMstcp(hFilt, @ReadRequest);
{
if counter = 0 then
begin
Writeln('Filtering complete');
readln;
break;
end;
}
end;
ResetEvent(hEvent);
end;
end;
end;
end.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
由于您已经知道如何从每个数据包中读取目标 IP,并且知道要重定向到哪个 IP,因此只需将新 IP 存储回数据包,然后再将其传递给 SendPacketTo...() 函数即可,即:
Since You already know how to read the destination IP from each packet, and you know which IP you want to redirect to, simply store the new IP back to the packet before you pass it to the SendPacketTo...() functions, ie:
请改用操作系统的 HOSTS 文件。它正是用于此目的,并且不需要任何代码。
Use the OS's HOSTS file instead. It is meant for exactly this purpose, and no code is needed.
首先,本地主机 IP 地址 127.0.0.1 对于 NDIS 驱动程序没有任何意义。因此,请勿将目标地址更改为 127.0.0.1。相反,您应该执行以下操作:
假设用户在浏览器中打开 www.stackoverflow.com。为简单起见,我们假设仅重定向发往端口 80 的连接。
传出 TCP SYN 数据包和此方向上的后续数据包的操作:
1) 以太网标头:交换目标和源 MAC 地址
2) IP 标头:将目标 IP 地址更改为您的本地接口 IP 地址。在这种情况下,您只需交换源 IP 和目标 IP 即可。
3) TCP 标头:将目标端口更改为您的代理端口。
4) 重新计算 TCP/IP 校验和。
5) 不是将数据包发送到网络,而是将其转发到网络堆栈 (SendPacketToMstcp)。
您的代理将从 www.stackoverflow.com 获取传入连接,其中 TCP 源端口与 www.stackoverflow.com 的原始连接的源端口相匹配。所以代理甚至知道原始目标IP(可以从客户端套接字信息中获取)和原始目标端口(我们仅拦截端口80,见上文)。因此代理拥有建立与 www.stackoverflow.com 的连接所需的所有信息。请注意,您必须通过重定向器传递来自代理的连接。
传出 SYN-ACK 和后续数据包的操作:
当您的代理接受重定向连接时,它会发送 TCP SYN-ACK 数据包。该数据包的目的地是 www.stackoverflow.com 的 IP,但目标 TCP 端口与端口 80 不同,这实际上是我们重定向的连接的源端口。所以:
1)以太网报头:交换目标和源MAC地址
2) IP 标头:将目标 IP 地址更改为您的本地接口 IP 地址。在这种情况下,您只需交换源 IP 和目标 IP 即可。
3)TCP头:将目的端口更改为原始数据包源端口,将源端口更改为80。
4) 重新计算 TCP/IP 校验和。
5) 不是将数据包发送到网络,而是将其转发到网络堆栈 (SendPacketToMstcp)。
如果您正确执行所有操作,您将拥有一个本地透明 HTTP 代理!
First of all localhost IP address 127.0.0.1 does not make any sense for the NDIS driver. So don't change destination address to 127.0.0.1. Instead you should do the following:
Lets say user opens www.stackoverflow.com in the browser. For the simplicity we assume that we only redirect connections destined to port 80.
Actions for the outgoing TCP SYN packet and follow up packet in this direction:
1) Ethernet header: Swap destination and source MAC addresses
2) IP header: Change destination IP address to your local interface IP address. In this case you can just swap source and destination IPs.
3) TCP header: change destination port to your proxy port.
4) Recalculate TCP/IP checksums.
5) Instead of sending packet to the network - forward it up the network stack (SendPacketToMstcp).
You proxy will get the incoming connection from the www.stackoverflow.com, with the TCP source port matching the source port of the original connection to www.stackoverflow.com. So proxy even knows the original destination IP (can get it from the client socket information) and original destination port (we intercept only port 80, see above). So proxy have all required information to establish the connection to www.stackoverflow.com. Just note, that you have to pass connections from your proxy through the redirector.
Actions for outgoing SYN-ACK and follow up packets:
When your proxy accepts the redirected connection it send TCP SYN-ACK packet. This packet is destined to IP of www.stackoverflow.com but destination TCP port differs from port 80 and this is actually the source port of the connection we redirected. So:
1) Ethernet header: Swap destination and source MAC addresses
2) IP header: Change destination IP address to your local interface IP address. In this case you can just swap source and destination IPs.
3) TCP header: change destination port to the original packet source port, change source port to 80.
4) Recalculate TCP/IP checksums.
5) Instead of sending packet to the network - forward it up the network stack (SendPacketToMstcp).
If you do all manipulations properly you will have a local transparent HTTP proxy!