开发者

Delphi hook to redirect to different ip

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.


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:

if pIPHeader.DestIp = inet_addr('66.220.146.11') then
  pIPHeader.DestIp := inet_addr('127.0.0.1');


Use the OS's HOSTS file instead. It is meant for exactly this purpose, and no code is needed.


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!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜