|
| 1 | +## Emissary - A generic TCP payload proxy |
| 2 | +This is a simple but flexible generic TCP payload proxy. The reasoning behind its creation was to have something similar to Portswigger's Burp Proxy, for TCP instead of just HTTP. Currently there is no GUI and it is just a command-line based application. Upon starting the proxy, you are presented with an IPython shell and you can manipulate various settings on the fly, such as search and replace operations, the level of information displayed, etc. Lots of work needs to be done, but it's a functional and useful tool at the moment. |
| 3 | + |
| 4 | +The socket connections are managed by the asyncore module, and the proxy can handle truly asynchronous connections, and it seems to do so with quite good performance (I don't have any numbers at the moment - but I don't notice any performance hits when passing any interactive traffic through it such as HTTP, RDP, SSH, etc.) |
| 5 | + |
| 6 | +Aside from some custom fuzzing and data logging code that I have not yet released, I believe IPython (>= 0.11) is the only dependency for this code to run outside of standard Python modules. The custom modules referenced are not loaded by default, so it should not be an issue. I intend the fuzzing and data logging to be modular, so you should be able to fit something in if you need to (I hope to get those components online soon as well, however.) |
| 7 | + |
| 8 | + |
| 9 | +**Basic usage is as follows:** |
| 10 | + |
| 11 | + Usage: emissary.py [options] |
| 12 | + |
| 13 | + Options: |
| 14 | + -h, --help show this help message and exit |
| 15 | + -l LOCAL_ADDR, --local-addr=LOCAL_ADDR |
| 16 | + Local address to bind to |
| 17 | + -p LOCAL_PORT, --local-port=LOCAL_PORT |
| 18 | + Local port to bind to |
| 19 | + -r REMOTE_ADDR, --remote-addr=REMOTE_ADDR |
| 20 | + Remote address to bind to |
| 21 | + -P REMOTE_PORT, --remote-port=REMOTE_PORT |
| 22 | + Remote port to bind to |
| 23 | + --search-request=SEARCH_REQUEST |
| 24 | + String that if found will be replaced by --replace- |
| 25 | + request's value |
| 26 | + --replace-request=REPLACE_REQUEST |
| 27 | + String to replace the value of --search-request |
| 28 | + --search-response=SEARCH_RESPONSE |
| 29 | + String that if found will be replaced by --replace- |
| 30 | + request's value |
| 31 | + --replace-response=REPLACE_RESPONSE |
| 32 | + String to replace the value of --search-request |
| 33 | + --regex-request Requests: Use regular expressions for search and |
| 34 | + replace instead of string constants |
| 35 | + --regex-response Responses: Use regular expressions for search and |
| 36 | + replace instead of string constants |
| 37 | + --fuzz-request Fuzz the request which the proxy gets from the |
| 38 | + connecting client prior to sending it to |
| 39 | + the remote host |
| 40 | + --fuzz-response Fuzz the response which the proxy gets from the remote |
| 41 | + host prior to sending it to the conecting |
| 42 | + client |
| 43 | + -i RUN_INFO, --run-info=RUN_INFO |
| 44 | + Additional information string to add to database |
| 45 | + run_info entry |
| 46 | + -d DEBUG, --debug=DEBUG |
| 47 | + Debug level (0-5, 0: No debugging; 1: Simple |
| 48 | + conneciton information; 2: Simple data |
| 49 | + information; 3: Listener data display; 4: |
| 50 | + Sender data display; 5: All data display) |
| 51 | + |
| 52 | +### Example of setting up a proxy to an SSH server (mine...) |
| 53 | +Below you can see us setting up the proxy to listen on localhost, port 2222, and connect to the host 173.203.94.5 port 22 - the debug level is set to 4, which shows full communication from the "sender" side (the socket that connects to the server): |
| 54 | + |
| 55 | + $ ./emissary.py -l 127.0.0.1 -p 2222 -r 173.203.94.5 -P 22 --debug=4 |
| 56 | + |
| 57 | + Setting up asynch. TCP proxy with the following settings: |
| 58 | + Local binding Address: 127.0.0.1 |
| 59 | + Local binding Port: 2222 |
| 60 | + |
| 61 | + Remote host address: 173.203.94.5 |
| 62 | + Remote host port: 22 |
| 63 | + |
| 64 | + Debug: Level 4 (Show sender data and size of sent/received messages) |
| 65 | + |
| 66 | + Fuzzing <NOTHING> (Maybe you wanted --fuzz-request or --fuzz-response?) |
| 67 | + Listener running... |
| 68 | + |
| 69 | + In [1]: Connection established... |
| 70 | + Sender: 39 bytes read |
| 71 | + 00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f SSH-2.0- OpenSSH_ |
| 72 | + 00000010 35 2e 33 70 31 20 44 65 62 69 61 6e 2d 33 75 62 5.3p1 De bian-3ub |
| 73 | + 00000020 75 6e 74 75 37 0d 0a untu7.. |
| 74 | + Sender: 20 bytes sent |
| 75 | + 00000000 43 6c 69 65 6e 74 2d 62 65 69 6e 67 2d 4d 69 54 Client-b eing-MiT |
| 76 | + 00000010 4d 64 21 0a Md!. |
| 77 | + Sender: 19 bytes read |
| 78 | + 00000000 50 72 6f 74 6f 63 6f 6c 20 6d 69 73 6d 61 74 63 Protocol mismatc |
| 79 | + 00000010 68 2e 0a h.. |
| 80 | + Sender: 0 bytes read |
| 81 | + |
| 82 | + |
| 83 | + |
| 84 | + In [1]: |
| 85 | + |
| 86 | +### Simple search and replace of TCP data |
| 87 | +You can perform simple search and replace operations via the command line, or through the IPython shell. Below, we search for "OpenSSH" in responses from the server, and replace them with "PwnedSSH": |
| 88 | + |
| 89 | + $ python emissary.py -l 127.0.0.1 -p 2222 -r 173.203.94.5 -P 22 --debug=4 --search-response="OpenSSH" --replace-response="PwnedSSH" |
| 90 | + |
| 91 | + Setting up asynch. TCP proxy with the following settings: |
| 92 | + Local binding Address: 127.0.0.1 |
| 93 | + Local binding Port: 2222 |
| 94 | + |
| 95 | + Remote host address: 173.203.94.5 |
| 96 | + Remote host port: 22 |
| 97 | + |
| 98 | + Debug: Level 4 (Show sender data and size of sent/received messages) |
| 99 | + |
| 100 | + Running string search/replace on RESPONSES with search/replace: 's/OpenSSH/PwnedSSH' |
| 101 | + Fuzzing <NOTHING> (Maybe you wanted --fuzz-request or --fuzz-response?) |
| 102 | + Listener running... |
| 103 | + |
| 104 | + In [1]: Connection established... |
| 105 | + Sender: 39 bytes read |
| 106 | + 00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f SSH-2.0- OpenSSH_ |
| 107 | + 00000010 35 2e 33 70 31 20 44 65 62 69 61 6e 2d 33 75 62 5.3p1 De bian-3ub |
| 108 | + 00000020 75 6e 74 75 37 0d 0a untu7.. |
| 109 | + Replacing literal 'OpenSSH' with 'PwnedSSH': |
| 110 | + Sender: 8 bytes sent |
| 111 | + 00000000 4f 68 4e 6f 65 73 21 0a OhNoes!. |
| 112 | + Sender: 19 bytes read |
| 113 | + 00000000 50 72 6f 74 6f 63 6f 6c 20 6d 69 73 6d 61 74 63 Protocol mismatc |
| 114 | + 00000010 68 2e 0a h.. |
| 115 | + Sender: 0 bytes read |
| 116 | + |
| 117 | +This can also be done with regular expressions by adding the argument `--regex-response` - the same holds true for `--search-request` of course. |
| 118 | + |
| 119 | +You can manipulate the search/replace functionality via the interactive shell through the local variable **sr_request** or **sr_response**, respectively. The structure of this variable is a three item array, the first being a boolean that determines if the search/replace is regular expression based or not, the second being the search term, and the third being the replacement. |
| 120 | + |
| 121 | + |
| 122 | +The name _emissary_ was chosen because the internal name of "TcpProxy" was boring, and because it's at least a decent fit considering what the tool does. |
0 commit comments