1

I recently bought a book to start playing around a bit with python and one of the scripts is the following:

#!/usr/bin/python2.7
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
    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
    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
    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() 

I have debugged the script and try to run it in terminal but it looks like it hangs for a while and then I get the following error:

./bhnet.py: line 10: listen: command not found
./bhnet.py: line 11: =: command not found
./bhnet.py: line 12: upload: command not found
./bhnet.py: line 13: execute: command not found
./bhnet.py: line 14: target: command not found
./bhnet.py: line 15: upload_destination: command not found
./bhnet.py: line 16: port: command not found
./bhnet.py: line 19: syntax error near unexpected token `('
./bhnet.py: line 19: `def run_command(command):'

I checked the code with the one in the book and even have the actual code so I tried that as well but still nothing. I wish I could be more specific than that. Any suggestions would be appreciated. Thanks.

John
  • 61
  • 1
  • 2
  • 13

2 Answers2

4

This isn't really in my expertise, but I'll try to shed some light on it.

Background information

When you run a script in a Unix-like system, typically you can call the interpreter program with the path to the script passed as an argument, e.g. python bhnet.py.

However, if you have things configured appropriately, you can also run your script as a standalone executable: ./bhnet.py. In order to do this, you generally need to:

  1. Make sure execute permissions are turned on (chmod +x or equivalent).

  2. Start the first line in the script with the symbols #! (called a "shebang") followed by the path to the interpreter to use.

Your case

The first line in your file is #!/usr/bin/python2.7, which seems plausible enough. What should happen when you run ./bhnet.py is that the interpreter at /usr/bin/python2.7 should get used to run your script. As long as /usr/bin/python2.7 is a Python interpreter, it should be ok...

However, what appears to be happening is that whatever interpreter is being called when you run ./bhnet.py is trying to run the script as a shell script rather than as Python. Perhaps whatever is actually at the path /usr/bin/python2.7 is not Python for some reason. Or perhaps your file doesn't actually start with what you pasted in the question, but maybe you accidentally overwrote the first line in your file with a different interpreter directive, like #!/bin/sh? There are probably other things that could cause this, too.

In any case, whatever is your default python seems to be working fine. (To see what your default points to, you can run which python.)

Recommendation

If you want to run the file as a standalone executable (i.e. ./bhnet.py), try changing the first line to:

#!/usr/bin/env python

This seems to be the recommended shebang line for Python, and it should work fine in your case. But I'd still be interested to know what happened to your /usr/bin/python2.7.

Community
  • 1
  • 1
leekaiinthesky
  • 5,413
  • 4
  • 28
  • 39
  • 1
    It seemed something along those lines but thanks for confirming that for me and also for the great level of detail. I will test it out when I get the chance and post the results. – John May 21 '15 at 11:19
  • 1
    Perhaps see also [Python or Python3. What is the difference?](https://stackoverflow.com/questions/64801225/python-or-python3-what-is-the-difference) – tripleee Dec 30 '21 at 06:18
-3

If the file was created on Windows, try running dos2unix before running on a UNIX-like system.

cMonster
  • 17
  • 1
  • 6