Skip to content

Commit 343f777

Browse files
committed
Initial commit of project files. Welcome emissary!
1 parent 5310166 commit 343f777

File tree

6 files changed

+1039
-0
lines changed

6 files changed

+1039
-0
lines changed

README.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
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

Comments
 (0)