Delphi hook для перенаправления на разные ip - PullRequest
0 голосов
/ 19 мая 2010

Каков наилучший способ перенаправить ЛЮБОЙ браузер на другой 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.

Ответы [ 3 ]

1 голос
/ 21 мая 2010

Поскольку вы уже знаете, как читать IP-адрес назначения из каждого пакета, и знаете, какой IP-адрес вы хотите перенаправить, просто сохраните новый IP-адрес в пакете, прежде чем передать его в функции SendPacketTo ... (). , т.е.:

if pIPHeader.DestIp = inet_addr('66.220.146.11') then
  pIPHeader.DestIp := inet_addr('127.0.0.1');
0 голосов
/ 06 мая 2016

Прежде всего, локальный IP-адрес 127.0.0.1 не имеет никакого смысла для драйвера NDIS. Поэтому не меняйте адрес назначения на 127.0.0.1. Вместо этого вы должны сделать следующее:

Допустим, пользователь открывает www.stackoverflow.com в браузере. Для простоты мы предполагаем, что мы только перенаправляем соединения, предназначенные для порта 80.

Действия для исходящего пакета TCP SYN и последующего пакета в этом направлении:

1) Заголовок Ethernet: поменяйте местами назначения и MAC-адреса источника 2) 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. Этот пакет предназначен для IP-адреса www.stackoverflow.com, но порт назначения TCP отличается от порта 80, и это фактически порт источника соединения, которое мы перенаправили. Итак:

1) Заголовок Ethernet: поменяйте местами назначения и MAC-адреса источника 2) IP-заголовок: измените IP-адрес назначения на IP-адрес вашего локального интерфейса. В этом случае вы можете просто поменять IP-адреса источника и назначения. 3) Заголовок TCP: измените порт назначения на исходный порт исходного пакета, измените исходный порт на 80. 4) Пересчитать контрольные суммы TCP / IP. 5) Вместо отправки пакета в сеть - перешлите его вверх по сетевому стеку (SendPacketToMstcp).

Если вы выполните все манипуляции правильно, у вас будет локальный прозрачный HTTP-прокси!

0 голосов
/ 20 мая 2010

Вместо этого используйте файл ОС HOSTS. Он предназначен именно для этой цели, и никакой код не требуется.

...