├── .gitignore ├── libzpy ├── .hgignore ├── README ├── __init__.py ├── fmt │ ├── __init__.py │ ├── citadel.py │ ├── citadel.py.1 │ ├── kins.py │ ├── powerzeus.py │ ├── vmzeus2.py │ ├── vmzeus20.py │ ├── zeus.py │ └── zeus.py.old ├── libs │ ├── UCL.py │ ├── __init__.py │ ├── basecfg.py │ ├── binPCRE.py │ ├── cr_tools.py │ ├── fmt.py │ ├── ida.py │ ├── libucl_i368.so │ ├── libucl_x64.so │ ├── rtb.py │ ├── storage.py │ ├── structure.py │ ├── vmzeus.py │ └── xstream.py ├── modules │ ├── __init__.py │ ├── chthonic.py │ ├── citadel.py │ ├── conf.py │ ├── flokibot.py │ ├── kins.py │ ├── misc.py │ ├── mmbb.py │ ├── p2p.py │ ├── powerzeus.py │ ├── template.py │ ├── torment.py │ ├── vmzeus.py │ ├── vmzeus2.py │ ├── vmzeus20.py │ └── zeus.py └── structs │ ├── __init__.py │ ├── chthonic.py │ ├── citadel.py │ ├── kins.py │ ├── powerzeus.py │ ├── vmzeus2.py │ ├── vmzeus20.py │ └── zeus.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .idea/ 3 | dist/ 4 | libzpy.egg* -------------------------------------------------------------------------------- /libzpy/.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | 3 | *~ 4 | *.pyc 5 | _local/* 6 | -------------------------------------------------------------------------------- /libzpy/README: -------------------------------------------------------------------------------- 1 | read me 2 | -------------------------------------------------------------------------------- /libzpy/__init__.py: -------------------------------------------------------------------------------- 1 | import sys,os 2 | #from contextlib import contextmanager 3 | 4 | def get_mydir(): 5 | p = os.path.abspath(__file__) 6 | dir_path = os.path.dirname(p) 7 | return dir_path 8 | 9 | #@contextmanager 10 | def get_parser(m): 11 | 12 | mod = __import__('.'.join(['libzpy.modules',m])) 13 | return getattr(mod.modules,m) 14 | 15 | def show_version(v): 16 | return "%02d.%02d.%02d.%02d"%(v>>24,(v>>16)&0xff,(v>>8)&0xff,v&0xff) 17 | -------------------------------------------------------------------------------- /libzpy/fmt/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /libzpy/fmt/citadel.py: -------------------------------------------------------------------------------- 1 | import libzpy.fmt.zeus as zeus 2 | 3 | 4 | class fmt(zeus.fmt): 5 | 6 | def __init__(self,*args,**kwargs): 7 | super(fmt,self).__init__(*args,**kwargs) 8 | # self._wf_butify['#'] = 'MOVIE' 9 | fmts = self._formats[:4] 10 | fmts += ['webinj_url','cmds','keyloger','video','httpvip','dns_filter'] 11 | fmts += self._formats[4:] 12 | self._formats = fmts 13 | 14 | 15 | def dns_filter(self): 16 | return self._list('DNS_FILTERS','dns_filter') 17 | 18 | def cmds(self): 19 | return self._list('COMANDS_LIST','cmds') 20 | 21 | def keyloger(self): 22 | if 'keyloger' in self.cfg: 23 | return '{{KEYLOGER}}\nTargets: %s\nTime: %d\n{{END_KEYLOGER}}' % (self.cfg['keyloger'],self.cfg['keyloger_time']) 24 | return '' 25 | 26 | def video(self): 27 | if 'video_qual' in self.cfg: 28 | return '{{VIDEO}}\nQuality: %d | Length: %d\n{{END_VIDEO}}' % (self.cfg['video_qual'],self.cfg['video_length']) 29 | return '' 30 | 31 | def httpvip(self): 32 | return self._field('HTTPVIPURLS','httpvi') 33 | 34 | def webinj_url(self): 35 | return self._field('WEBINJECT_URL','webinj_url') 36 | -------------------------------------------------------------------------------- /libzpy/fmt/citadel.py.1: -------------------------------------------------------------------------------- 1 | import libzpy.fmt.zeus as zeus 2 | 3 | 4 | class fmt(zeus.fmt): 5 | 6 | def __init__(self,*args,**kwargs): 7 | super(fmt,self).__init__(*args,**kwargs) 8 | self._wf_butify['#'] = 'MOVIE' 9 | fmts = self._formats[:4] 10 | fmts += ['webinj_url','cmds','keyloger','video','httpvip','dns_filter'] 11 | fmts += self._formats[4:] 12 | self._formats = fmts 13 | 14 | 15 | def dns_filter(self): 16 | return self._list('DNS_FILTERS','dns_filter') 17 | 18 | def cmds(self): 19 | return self._list('COMANDS_LIST','cmds') 20 | 21 | def keyloger(self): 22 | if 'keyloger' in self.cfg: 23 | return '{{KEYLOGER}}\nTargets: %s\nTime: %d\n{{END_KEYLOGER}}' % (self.cfg['keyloger'],self.cfg['keyloger_time']) 24 | return '' 25 | 26 | def video(self): 27 | if 'video_qual' in self.cfg: 28 | return '{{VIDEO}}\nQuality: %d | Length: %d\n{{END_VIDEO}}' % (self.cfg['video_qual'],self.cfg['video_length']) 29 | return '' 30 | 31 | def httpvip(self): 32 | return self._field('HTTPVIPURLS','httpvi') 33 | 34 | def webinj_url(self): 35 | return self._field('WEBINJECT_URL','webinj_url') 36 | -------------------------------------------------------------------------------- /libzpy/fmt/kins.py: -------------------------------------------------------------------------------- 1 | import libzpy.fmt.zeus as zeus 2 | 3 | 4 | class fmt(zeus.fmt): 5 | 6 | # def __init__(self,*args,**kwargs): 7 | # super(fmt,self).__init__(*args,**kwargs) 8 | # self._wf_butify['$'] = 'NOTIFY' 9 | # self._wf_butify['|'] = 'UNKNOWN' ## TODO.... 10 | 11 | def notify_srv(self): 12 | return self._list('{{NOTIFY_SERVERS}}','notify_srv','{{END_NOTIFY_SERVERS}}') 13 | def notify_list(self): 14 | return self._list('{{NOTIFY_LIST}}','notify_lst','{{END_NOTIFY_LIST}}') 15 | 16 | def captcha_list(self): 17 | return self._list('{{CAPTCHA_LIST}}','captcha_lst','{{END_CAPTCHA_LIST}}') 18 | 19 | def captcha_srv(self): 20 | return self._list('{{CAPTCHA_SERVERS}}','captcha_srv','{{END_CAPTCHA_SERVERS}}') 21 | -------------------------------------------------------------------------------- /libzpy/fmt/powerzeus.py: -------------------------------------------------------------------------------- 1 | import libzpy.fmt.zeus as zeus 2 | 3 | 4 | class fmt(zeus.fmt): 5 | 6 | def __init__(self,*args,**kwargs): 7 | super(fmt,self).__init__(*args,**kwargs) 8 | fmts = self._formats[:4] 9 | fmts += ['notify_srv','notify_list','captcha_srv','captcha_list'] 10 | fmts += self._formats[4:] 11 | self._formats = fmts 12 | 13 | 14 | def notify_srv(self): 15 | return self._list('NOTIFY_SERVERS','notify_srv') 16 | def notify_list(self): 17 | return self._list('NOTIFY_LIST','notify_lst') 18 | 19 | def captcha_list(self): 20 | return self._list('CAPTCHA_LIST','captcha_lst') 21 | 22 | def captcha_srv(self): 23 | return self._list('CAPTCHA_SERVERS','captcha_srv') 24 | -------------------------------------------------------------------------------- /libzpy/fmt/vmzeus2.py: -------------------------------------------------------------------------------- 1 | import libzpy.fmt.zeus as zeus 2 | from struct import unpack 3 | from datetime import datetime 4 | 5 | class fmt(zeus.fmt): 6 | 7 | def notify_srv(self): 8 | return self._list('{{NOTIFY_SERVERS}}','notify_srv') 9 | def notify_list(self): 10 | return self._list('{{NOTIFY_LIST}}','notify_lst') 11 | 12 | 13 | def captcha_list(self): 14 | return self._list('{{CAPTCHA_LIST}}','captcha_lst') 15 | 16 | def captcha_srv(self): 17 | return self._list('{{CAPTCHA_SERVERS}}','captcha_srv') 18 | 19 | 20 | def ctime(self): 21 | if 'CFGID_CONFIG_CREATION_TIME' in self.cfg: 22 | return 'Creation Time: %s\n' % datetime.fromtimestamp(unpack('I',self.cfg['CFGID_CONFIG_CREATION_TIME'])[0]) 23 | return '' 24 | 25 | def modvnc(self): 26 | if 'CFGID_VNCDLL_URL' in self.cfg: 27 | return '{{VNCDLL_URL}}\n' +self.cfg['CFGID_VNCDLL_URL'] + "\n{{END_VNCDLL_URL}}\n" 28 | return '' 29 | 30 | def format(self): 31 | r = '' 32 | r += self.version() 33 | r += self.ctime() 34 | r += self.server() 35 | r += self.modvnc() 36 | r += self.binary() 37 | r += self.adv_server() 38 | r += self.notify_srv() 39 | r += self.notify_list() 40 | r += self.captcha_srv() 41 | r += self.captcha_list() 42 | r += self.webfilters() 43 | r += self.injects() 44 | r += self.captures() 45 | return r 46 | -------------------------------------------------------------------------------- /libzpy/fmt/vmzeus20.py: -------------------------------------------------------------------------------- 1 | import libzpy.fmt.zeus as zeus 2 | from struct import unpack 3 | from datetime import datetime 4 | 5 | class fmt(zeus.fmt): 6 | 7 | # def __init__(self,*args,**kwargs): 8 | # super(fmt,self).__init__(*args,**kwargs) 9 | # self._wf_butify['$'] = 'NOTIFY' 10 | 11 | def notify_srv(self): 12 | return self._list('{{NOTIFY_SERVERS}}','notify_srv') 13 | def notify_list(self): 14 | return self._list('{{NOTIFY_LIST}}','notify_lst') 15 | 16 | 17 | def captcha_list(self): 18 | return self._list('{{CAPTCHA_LIST}}','captcha_lst') 19 | 20 | def captcha_srv(self): 21 | return self._list('{{CAPTCHA_SERVERS}}','captcha_srv') 22 | 23 | 24 | def ctime(self): 25 | key = 'CFGID_CONFIG_CREATION_TIME' 26 | if key in self.cfg: 27 | d = unpack('I',self.cfg[key])[0] if type(self.cfg[key]) == str else self.cfg[key] 28 | return 'Creation Time: %s\n' % datetime.fromtimestamp(d) 29 | return '' 30 | 31 | def modvnc(self): 32 | return self._field('VNCDLL_URL','CFGID_VNCDLL_URL',lambda x:x) 33 | 34 | def signature(self): 35 | return self._field('SIGNATURE','CFGID_SIGNATURE',lambda x: x.encode('hex')) 36 | 37 | def format(self): 38 | r = '' 39 | r += self.version() 40 | r += self.ctime() 41 | r += self.server() 42 | r += self.modvnc() 43 | r += self.binary() 44 | r += self.adv_server() 45 | r += self.notify_srv() 46 | r += self.notify_list() 47 | r += self.captcha_srv() 48 | r += self.captcha_list() 49 | r += self.signature() 50 | r += self.webfilters() 51 | r += self.injects() 52 | r += self.captures() 53 | return r 54 | -------------------------------------------------------------------------------- /libzpy/fmt/zeus.py: -------------------------------------------------------------------------------- 1 | 2 | class fmt(object): 3 | _name = 'ZeuS' 4 | _formats = ['version','server','adv_server','webfilters','injects','captures'] 5 | def __init__(self,cfg): 6 | self.cfg = cfg 7 | 8 | # _wf_butify={ 9 | # '@' : 'SCREENSHOT', 10 | # '!' : 'DONT-REPORT', 11 | # '-' : 'SAVE-COOCKIE', 12 | # '^' : 'BLOCK-ACCESS' 13 | # } 14 | 15 | def _butify_wf(self,d): 16 | if len(d['action']) > 3: 17 | return '{{' + d['action'] + '}} ' + d['target'].strip() 18 | return '{{' + 'UNKNOWN-ACCTION('+d['action'] + ')}} ' + d['target'].strip() 19 | 20 | def webfilters(self): 21 | if 'webfilters' in self.cfg: 22 | return "{{WEBFILTERS}}\n" + "\n".join(map(self._butify_wf,self.cfg['webfilters'])) + "\n{{END_WEBFILTERS}}\n\n" 23 | else: 24 | return '' 25 | 26 | def _field(self,name,fname,ppr=str): 27 | if not fname in self.cfg: 28 | return '' 29 | return '{{%s}}\n%s\n{{END_%s}}\n'%(name,ppr(self.cfg[fname]),name) 30 | 31 | def _list(self,name,fname): 32 | if not fname in self.cfg: 33 | return '' 34 | r = '{{%s}}\n'%name 35 | for c in self.cfg[fname]: 36 | if isinstance(c,str): 37 | r += c + "\n" 38 | elif isinstance(c,dict): 39 | for n in c: 40 | r += n.upper() + ':' + c[n] + " " 41 | r += "\n" 42 | return r + "{{END_%s}}\n"%name 43 | 44 | def version(self): 45 | if 'version' in self.cfg: 46 | return "\n\n" + self._name + ': ' + self.cfg['version'] + "\n\n\n" 47 | return '' 48 | 49 | def binary(self): 50 | return self._list('UPDATE_URLS','update') 51 | # def binary(self): 52 | # return self._list("{{UPDATE_URLS}}",'update',"{{END_UPDATE_URLS}}") 53 | 54 | def server(self): 55 | return self._list('SERVER_URLS','server') 56 | 57 | def adv_server(self): 58 | return self._list('ADV_SERVER_URLS','advance') 59 | 60 | def inject_flags(self,inj): 61 | pass 62 | 63 | def injects(self): 64 | r = self._injects_fmt('injects') 65 | return ('{{INJECTS}}' +r + "{{END_INJECTS}}\n") if r else '' 66 | 67 | def captures(self): 68 | r = self._injects_fmt('captures') 69 | return ('{{CAPTURES}}' +r + "{{END_CAPTURES}}\n") if r else '' 70 | 71 | def _injects_fmt(self,t): 72 | r = '' # 73 | for inject in self.cfg['injects']: 74 | if t in inject: 75 | r += '\nTarget: ' + inject['target'] 76 | r += '\nFlags: ' + inject['flags'] 77 | r += '\nMeta: ' 78 | r += "\n" 79 | for inj in inject[t]: 80 | 81 | r += "{{DATA_BEFORE}}"+ (" {{FLAGS: %X}}" % inj['pre_flag']) +"\n" 82 | r += inj['pre'] + "\n" 83 | r += "{{END_DATA_BEFORE}}\n" 84 | r += "{{DATA_AFTER}}" + (" {{FLAGS: %X}}" % inj['post_flag']) + "\n" 85 | r += inj['post'] + "\n" 86 | r += "{{END_DATA_AFTER}}\n" 87 | r += "{{INJECT}}"+ (" {{FLAGS: %X}}" % inj['inj_flag']) +"\n" 88 | r += inj['inj'] + "\n" 89 | r += "{{END_INJECT}}\n\n" 90 | r += '-'*32 91 | r +="\n" 92 | r += '#' * 32 93 | r +="\n" 94 | return r 95 | 96 | def format(self): 97 | r = '' 98 | for fmt in self._formats: 99 | r+=getattr(self,fmt)() 100 | 101 | return r 102 | -------------------------------------------------------------------------------- /libzpy/fmt/zeus.py.old: -------------------------------------------------------------------------------- 1 | from libs.rtb import check_url 2 | 3 | class fmt(object): 4 | _name = 'ZeuS' 5 | def __init__(self,cfg): 6 | self.cfg = cfg 7 | 8 | _wf_butify={ 9 | '@' : 'SCREENSHOT', 10 | '!' : 'DONT-REPORT', 11 | '-' : 'SAVE-COOCKIE', 12 | '^' : 'BLOCK-ACCESS' 13 | } 14 | 15 | def _butify_wf(self,d): 16 | data = d.strip() 17 | if data[0] in self._wf_butify: 18 | return '{{' + self._wf_butify[data[0]] + '}} ' + data[1:] 19 | return data 20 | 21 | def webfilters(self): 22 | if 'webfilters' in self.cfg: 23 | return "{{WEBFILTERS}}\n" + "\n".join(map(self._butify_wf,self.cfg['webfilters'])) + "\n{{END_WEBFILTERS}}\n\n" 24 | else: 25 | return '' 26 | 27 | def _list(self,pre,name,post): 28 | if not name in self.cfg: 29 | return '' 30 | r = pre + "\n" 31 | for c in self.cfg[name]: 32 | if isinstance(c,str): 33 | r += c + "\n" 34 | elif isinstance(c,dict): 35 | for n in c: 36 | r += n.upper() + ':' + c[n] + " " 37 | r += "\n" 38 | return r + post + "\n" 39 | 40 | def version(self): 41 | if 'version' in self.cfg: 42 | return "\n\n" + self._name + ': ' + self.cfg['version'] + "\n\n\n" 43 | return '' 44 | 45 | def binary(self): 46 | return self._list("{{UPDATE_URLS}}",'update',"{{END_UPDATE_URLS}}") 47 | 48 | def server(self): 49 | return self._list("{{SERVER_URLS}}",'server',"{{END_SERVER_URLS}}") 50 | 51 | def adv_server(self): 52 | return self._list("{{ADV_SERVER_URLS}}",'advance',"{{ADV_END_SERVER_URLS}}") 53 | 54 | def inject_flags(self,inj): 55 | pass 56 | 57 | def injects(self): 58 | r = self._injects_fmt('injects') 59 | return ('{{INJECTS}}' +r + "{{END_INJECTS}}\n") if r else '' 60 | 61 | def captures(self): 62 | r = self._injects_fmt('captures') 63 | return ('{{CAPTURES}}' +r + "{{END_CAPTURES}}\n") if r else '' 64 | 65 | def _injects_fmt(self,t): 66 | r = '' # 67 | for inject in self.cfg['injects']: 68 | if t in inject: 69 | r += '\nTarget: ' + inject['target'] 70 | r+= '\nHits: ' + check_url(inject['target']) 71 | r += '\nFlags: ' + inject['flags'] 72 | r += '\nMeta: ' 73 | r += "\n" 74 | for inj in inject[t]: 75 | 76 | r += "{{DATA_BEFORE}}"+ (" {{FLAGS: %X}}" % inj['pre_flag']) +"\n" 77 | r += inj['pre'] + "\n" 78 | r += "{{END_DATA_BEFORE}}\n" 79 | r += "{{DATA_AFTER}}" + (" {{FLAGS: %X}}" % inj['post_flag']) + "\n" 80 | r += inj['post'] + "\n" 81 | r += "{{END_DATA_AFTER}}\n" 82 | r += "{{INJECT}}"+ (" {{FLAGS: %X}}" % inj['inj_flag']) +"\n" 83 | r += inj['inj'] + "\n" 84 | r += "{{END_INJECT}}\n\n" 85 | r += '-'*32 86 | r +="\n" 87 | r += '#' * 32 88 | r +="\n" 89 | return r 90 | 91 | def format(self): 92 | r = '' 93 | r += self.version() 94 | r += self.server() 95 | r += self.binary() 96 | r += self.adv_server() 97 | # r += self.notify_srv() 98 | # r += self.notify_list() 99 | # r += self.captcha_srv() 100 | # r += self.captcha_list() 101 | r += self.webfilters() 102 | r += self.injects() 103 | r += self.captures() 104 | return r 105 | -------------------------------------------------------------------------------- /libzpy/libs/UCL.py: -------------------------------------------------------------------------------- 1 | from ctypes import * 2 | import os 3 | from mlib.compression import lznt1 4 | 5 | 6 | class UCL(object): 7 | def decompress(self,data,size): 8 | try: 9 | return lznt1.decompress(data) 10 | except: 11 | return self.c_decompress(data,size) 12 | 13 | def c_decompress(self,data,size): 14 | compressed = c_buffer(data) 15 | decompressed = c_buffer(size) 16 | decompressed_size = c_int() 17 | result = self.get_ucl().ucl_nrv2b_decompress_le32( 18 | pointer(compressed), 19 | c_int(len(compressed.raw)), 20 | pointer(decompressed), 21 | pointer(decompressed_size)) 22 | return decompressed.raw[:decompressed_size.value] 23 | 24 | def get_ucl(self): 25 | if hasattr(self,'_lib'): 26 | return self._lib 27 | 28 | MYSELF = os.path.abspath(os.path.expanduser(__file__)) 29 | if os.path.islink(MYSELF): 30 | MYSELF = os.readlink(MYSELF) 31 | DIR = os.path.dirname(MYSELF) 32 | if sizeof(c_long) == 8: 33 | UCL = DIR + '/libucl_x64.so' 34 | else: 35 | UCL = DIR + '/libucl_i386.so' 36 | self._lib = cdll.LoadLibrary(UCL) 37 | return self._lib 38 | -------------------------------------------------------------------------------- /libzpy/libs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mak/libzpy/a0a10a091700bf8dcab96fa7ff720db9ea94f819/libzpy/libs/__init__.py -------------------------------------------------------------------------------- /libzpy/libs/basecfg.py: -------------------------------------------------------------------------------- 1 | import re 2 | from struct import unpack 3 | 4 | import libzpy.libs.cr_tools as cry 5 | 6 | 7 | class BaseCfg(object): 8 | 9 | def __init__(self,cfg): 10 | self.cfg = cfg 11 | self.rc4sbox = None 12 | 13 | def get_strings(self): 14 | ss =map(lambda x: x.strip("\x00"),re.findall("[\x1f-\x7e]{6,}\x00", self.cfg)) 15 | if self.urls: 16 | return list(set(ss).difference(set(self.urls))) 17 | return ss 18 | 19 | def get_botname(self): 20 | _max = lambda x : max(x,key=len) if x else '' 21 | return _max(filter(lambda x: x and not "\x00" in x,map(lambda x:x[0].decode('utf-16').strip("\x00"),re.findall("(([\x1f-\x7e]\x00)+)\x00\x00",self.cfg)))) 22 | 23 | 24 | 25 | def get_urls(self): 26 | self.urls = map(lambda x:x.strip("\x00"),re.findall("https?://[\x1f-\x7e]{6,}\x00",self.cfg)) 27 | return self.urls 28 | 29 | def rc4(self,d,k): 30 | return cry.rc4decrypt(d,k) 31 | 32 | def get_rc4(self,pes): 33 | 34 | if type(pes) == int: 35 | ## some time im off few byts, lets try to fix this 36 | rb = self.cfg[pes:pes+0x102] 37 | off1= pes - ( 0x102 - rb.rfind("\x00\x00") -2) 38 | self.rc4sbox = self.cfg[off1:off1+0x102] 39 | return self.rc4sbox 40 | 41 | 42 | mg = len(pes) 43 | 44 | for idx in xrange(len(self.cfg)-0x100): 45 | try: 46 | ss = unpack('I',self.rc4(pes,self.cfg[idx:idx+0x102])[0:4])[0] 47 | 48 | if ss == mg: 49 | print '[+] found rc4key' 50 | self.rc4sbox = self.cfg[idx:idx+0x102] 51 | return self.rc4sbox 52 | 53 | except Exception as e: 54 | print `e` 55 | pass 56 | 57 | def get_basics(self): 58 | if not self.rc4sbox: 59 | raise Exception('parse your shit bro') 60 | 61 | st = {} 62 | st['botname']=self.get_botname() 63 | st['rc4sbox']=self.rc4sbox.encode('hex') 64 | st['urls'] = self.get_urls() 65 | st['strings'] = self.get_strings() 66 | if not st['botname']: 67 | st['botname'] = '*default*' 68 | # if st['urls']: 69 | # st['cfg'] = st['urls'][0] 70 | # else: 71 | # st['cfg'] = '' 72 | return st 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /libzpy/libs/binPCRE.py: -------------------------------------------------------------------------------- 1 | from libzpy.libs.xstream import xstream 2 | 3 | 4 | OPCODES=dict(OP_END = 0,OP_SOD = 1,OP_SOM = 2,OP_SET_SOM = 3,OP_NOT_WORD_BOUNDARY = 4,OP_WORD_BOUNDARY = 5,OP_NOT_DIGIT = 6,OP_DIGIT = 7,OP_NOT_WHITESPACE = 8,OP_WHITESPACE = 9,OP_NOT_WORDCHAR = 10,OP_WORDCHAR = 11,OP_ANY = 12,OP_ALLANY = 13,OP_ANYBYTE = 14,OP_NOTPROP = 15,OP_PROP = 16,OP_ANYNL = 17,OP_NOT_HSPACE = 18,OP_HSPACE = 19,OP_NOT_VSPACE = 20,OP_VSPACE = 21,OP_EXTUNI = 22,OP_EODN = 23,OP_EOD = 24,OP_OPT = 25,OP_CIRC = 26,OP_DOLL = 27,OP_CHAR = 28,OP_CHARNC = 29,OP_NOT = 30,OP_STAR = 31,OP_MINSTAR = 32,OP_PLUS = 33,OP_MINPLUS = 34,OP_QUERY = 35,OP_MINQUERY = 36,OP_UPTO = 37,OP_MINUPTO = 38,OP_EXACT = 39,OP_POSSTAR = 40,OP_POSPLUS = 41,OP_POSQUERY = 42,OP_POSUPTO = 43,OP_NOTSTAR = 44,OP_NOTMINSTAR = 45,OP_NOTPLUS = 46,OP_NOTMINPLUS = 47,OP_NOTQUERY = 48,OP_NOTMINQUERY = 49,OP_NOTUPTO = 50,OP_NOTMINUPTO = 51,OP_NOTEXACT = 52,OP_NOTPOSSTAR = 53,OP_NOTPOSPLUS = 54,OP_NOTPOSQUERY = 55,OP_NOTPOSUPTO = 56,OP_TYPESTAR = 57,OP_TYPEMINSTAR = 58,OP_TYPEPLUS = 59,OP_TYPEMINPLUS = 60,OP_TYPEQUERY = 61,OP_TYPEMINQUERY = 62,OP_TYPEUPTO = 63,OP_TYPEMINUPTO = 64,OP_TYPEEXACT = 65,OP_TYPEPOSSTAR = 66,OP_TYPEPOSPLUS = 67,OP_TYPEPOSQUERY = 68,OP_TYPEPOSUPTO = 69,OP_CRSTAR = 70,OP_CRMINSTAR = 71,OP_CRPLUS = 72,OP_CRMINPLUS = 73,OP_CRQUERY = 74,OP_CRMINQUERY = 75,OP_CRRANGE = 76,OP_CRMINRANGE = 77,OP_CLASS = 78,OP_NCLASS = 79,OP_XCLASS = 80,OP_REF = 81,OP_RECURSE = 82,OP_CALLOUT = 83,OP_ALT = 84,OP_KET = 85,OP_KETRMAX = 86,OP_KETRMIN = 87,OP_ASSERT = 88,OP_ASSERT_NOT = 89,OP_ASSERTBACK = 90,OP_ASSERTBACK_NOT = 91,OP_REVERSE = 92,OP_ONCE = 93,OP_BRA = 94,OP_CBRA = 95,OP_COND = 96,OP_SBRA = 97,OP_SCBRA = 98,OP_SCOND = 99,OP_CREF = 100,OP_NCREF = 101,OP_RREF = 102,OP_NRREF = 103,OP_DEF = 104,OP_BRAZERO = 105,OP_BRAMINZERO = 106,OP_MARK = 107,OP_PRUNE = 108,OP_PRUNE_ARG = 109,OP_SKIP = 110,OP_SKIP_ARG = 111,OP_THEN = 112,OP_THEN_ARG = 113,OP_COMMIT = 114,OP_FAIL = 115,OP_ACCEPT = 116,OP_CLOSE = 117,OP_SKIPZERO = 118,OP_TABLE_LENGTH = 119 ) 5 | REV_COEDS = dict((v,k) for k, v in OPCODES.iteritems()) 6 | 7 | 8 | #OPCODES=dict( 9 | OP_END = 0 10 | OP_SOD = 1 11 | OP_SOM = 2 12 | OP_SET_SOM = 3 13 | OP_NOT_WORD_BOUNDARY = 4 14 | OP_WORD_BOUNDARY = 5 15 | OP_NOT_DIGIT = 6 16 | OP_DIGIT = 7 17 | OP_NOT_WHITESPACE = 8 18 | OP_WHITESPACE = 9 19 | OP_NOT_WORDCHAR = 10 20 | OP_WORDCHAR = 11 21 | OP_ANY = 12 22 | OP_ALLANY = 13 23 | OP_ANYBYTE = 14 24 | OP_NOTPROP = 15 25 | OP_PROP = 16 26 | OP_ANYNL = 17 27 | OP_NOT_HSPACE = 18 28 | OP_HSPACE = 19 29 | OP_NOT_VSPACE = 20 30 | OP_VSPACE = 21 31 | OP_EXTUNI = 22 32 | OP_EODN = 23 33 | OP_EOD = 24 34 | OP_OPT = 25 35 | OP_CIRC = 26 36 | OP_DOLL = 27 37 | OP_CHAR = 28 38 | OP_CHARNC = 29 39 | OP_NOT = 30 40 | OP_STAR = 31 41 | OP_MINSTAR = 32 42 | OP_PLUS = 33 43 | OP_MINPLUS = 34 44 | OP_QUERY = 35 45 | OP_MINQUERY = 36 46 | OP_UPTO = 37 47 | OP_MINUPTO = 38 48 | OP_EXACT = 39 49 | OP_POSSTAR = 40 50 | OP_POSPLUS = 41 51 | OP_POSQUERY = 42 52 | OP_POSUPTO = 43 53 | OP_NOTSTAR = 44 54 | OP_NOTMINSTAR = 45 55 | OP_NOTPLUS = 46 56 | OP_NOTMINPLUS = 47 57 | OP_NOTQUERY = 48 58 | OP_NOTMINQUERY = 49 59 | OP_NOTUPTO = 50 60 | OP_NOTMINUPTO = 51 61 | OP_NOTEXACT = 52 62 | OP_NOTPOSSTAR = 53 63 | OP_NOTPOSPLUS = 54 64 | OP_NOTPOSQUERY = 55 65 | OP_NOTPOSUPTO = 56 66 | OP_TYPESTAR = 57 67 | OP_TYPEMINSTAR = 58 68 | OP_TYPEPLUS = 59 69 | OP_TYPEMINPLUS = 60 70 | OP_TYPEQUERY = 61 71 | OP_TYPEMINQUERY = 62 72 | OP_TYPEUPTO = 63 73 | OP_TYPEMINUPTO = 64 74 | OP_TYPEEXACT = 65 75 | OP_TYPEPOSSTAR = 66 76 | OP_TYPEPOSPLUS = 67 77 | OP_TYPEPOSQUERY = 68 78 | OP_TYPEPOSUPTO = 69 79 | OP_CRSTAR = 70 80 | OP_CRMINSTAR = 71 81 | OP_CRPLUS = 72 82 | OP_CRMINPLUS = 73 83 | OP_CRQUERY = 74 84 | OP_CRMINQUERY = 75 85 | OP_CRRANGE = 76 86 | OP_CRMINRANGE = 77 87 | OP_CLASS = 78 88 | OP_NCLASS = 79 89 | OP_XCLASS = 80 90 | OP_REF = 81 91 | OP_RECURSE = 82 92 | OP_CALLOUT = 83 93 | OP_ALT = 84 94 | OP_KET = 85 95 | OP_KETRMAX = 86 96 | OP_KETRMIN = 87 97 | OP_ASSERT = 88 98 | OP_ASSERT_NOT = 89 99 | OP_ASSERTBACK = 90 100 | OP_ASSERTBACK_NOT = 91 101 | OP_REVERSE = 92 102 | OP_ONCE = 93 103 | OP_BRA = 94 104 | OP_CBRA = 95 105 | OP_COND = 96 106 | OP_SBRA = 97 107 | OP_SCBRA = 98 108 | OP_SCOND = 99 109 | OP_CREF = 100 110 | OP_NCREF = 101 111 | OP_RREF = 102 112 | OP_NRREF = 103 113 | OP_DEF = 104 114 | OP_BRAZERO = 105 115 | OP_BRAMINZERO = 106 116 | OP_MARK = 107 117 | OP_PRUNE = 108 118 | OP_PRUNE_ARG = 109 119 | OP_SKIP = 110 120 | OP_SKIP_ARG = 111 121 | OP_THEN = 112 122 | OP_THEN_ARG = 113 123 | OP_COMMIT = 114 124 | OP_FAIL = 115 125 | OP_ACCEPT = 116 126 | OP_CLOSE = 117 127 | OP_SKIPZERO = 118 128 | OP_TABLE_LENGTH = 119 129 | #) 130 | #REV_COEDS = dict((v,k) for k, v in OPCODES.iteritems()) 131 | 132 | def hexx(s): 133 | r = '' 134 | for c in s: r+="%02X " % ord(c) 135 | return r 136 | 137 | def singleByte(b): 138 | if b == OP_ANY or b == OP_ALLANY or b == OP_ANYBYTE: return "." 139 | elif b == OP_ANYNL : return "\\R" 140 | elif b == OP_CIRC : return "^" 141 | elif b == OP_DOLL : return "$" 142 | elif b == OP_DIGIT : return "\\d" 143 | elif b == OP_WHITESPACE : return "\\s" 144 | return None 145 | 146 | def reClass(data,positive): 147 | r = '' 148 | charIndex = 0 149 | for c in data: 150 | nc = ord(c) 151 | cb = 1 152 | for j in range(8): 153 | bit = 1 if nc & cb else 0 154 | cb *= 2 155 | if bit == positive: r+= chr(charIndex) 156 | charIndex += 1 157 | return r 158 | 159 | def readBinary(data): 160 | verbose = False 161 | RET="" 162 | size = len(data) 163 | xs = xstream(data) 164 | hdr_names = ('magic','size','opts','flags','dummy1','top_bracket','top_backref','first_byte','req_byte','name_tbl_off','name_entry_size','name_cnt','ref_cnt') 165 | hdr = xs.readFmt("IIIHHHHHHHHHH", into=hdr_names ) 166 | name_tbl_size = hdr['name_tbl_off'] + hdr['name_entry_size'] * hdr['name_cnt'] 167 | 168 | hdr['names']=dict() 169 | xs.seek(hdr['name_tbl_off']) 170 | for i in range(hdr['name_cnt']): 171 | idx = xs.readOne('>H') 172 | name = xs.readN(hdr['name_entry_size']) 173 | name = name[:name.find("\x00")] 174 | hdr['names'][idx]=name 175 | if verbose: 176 | print hexx(data) 177 | print hdr 178 | print "offset : %d " % name_tbl_size 179 | 180 | xs.seek(name_tbl_size); 181 | pos = name_tbl_size 182 | 183 | while pos < hdr['size']: 184 | opcode = xs.readOne("B") 185 | opsize = 1 186 | 187 | if verbose: 188 | print "%d) %d %x | %s \t| %s" % (xs.tell(),opcode,opcode,REV_COEDS[opcode],RET) 189 | 190 | b1 = singleByte(opcode) 191 | if b1: 192 | RET += b1 193 | elif opcode == OP_END: 194 | if verbose: 195 | print "end<" 196 | break 197 | elif opcode == OP_BRA or opcode == OP_SBRA: 198 | RET+="(?:"; xs.readN(2) 199 | elif opcode == OP_KET: RET+=")"; xs.readN(2) 200 | elif opcode == OP_CBRA or opcode == OP_SCBRA: 201 | v1,v2=xs.readFmt(">HH"); 202 | if v2 in hdr['names']: RET+="(?P<%s>" % hdr['names'][v2] 203 | else: RET+="(" 204 | 205 | elif opcode == OP_ALT: RET+="|"; xs.readN(2) 206 | elif opcode == OP_OPT: xs.readN(1) 207 | elif opcode == OP_CHAR or opcode == OP_CHARNC: 208 | RET+=`xs.readN(1)`.replace("'","") 209 | 210 | 211 | elif opcode == OP_CRSTAR : RET += "*" 212 | elif opcode == OP_CRPLUS : RET += "+" 213 | elif opcode == OP_CRMINPLUS : RET += "+?" 214 | elif opcode == OP_CRMINSTAR : RET += "*?" 215 | elif opcode == OP_CRRANGE : RET+= "{%d,%d}" % xs.readFmt(">HH") 216 | 217 | elif opcode == OP_QUERY : RET += "%s?" % xs.readN(1) 218 | 219 | elif opcode == OP_STAR : RET+= "%s*" % xs.readN(1) 220 | elif opcode == OP_POSSTAR : RET+= "%s*+" % xs.readN(1) 221 | elif opcode == OP_MINSTAR : RET+= "%s*?" % xs.readN(1) 222 | 223 | elif opcode == OP_PLUS : RET+= "%s+" % xs.readN(1) 224 | elif opcode == OP_POSPLUS : RET+= "%s++" % xs.readN(1) 225 | elif opcode == OP_MINPLUS : RET+= "%s+?" % xs.readN(1) 226 | 227 | elif opcode == OP_MINQUERY : RET+= "%s??" % xs.readN(1) 228 | 229 | elif opcode == OP_TYPESTAR : RET+= "%s*" % singleByte( xs.readOne("B") ) 230 | elif opcode == OP_TYPEPOSSTAR : RET+= "%s*+" % singleByte( xs.readOne("B") ) 231 | elif opcode == OP_TYPEMINSTAR : RET+= "%s*?" % singleByte( xs.readOne("B") ) 232 | 233 | elif opcode == OP_TYPEPLUS : RET+= "%s+" % singleByte( xs.readOne("B") ) 234 | elif opcode == OP_TYPEPOSPLUS : RET+= "%s++" % singleByte( xs.readOne("B") ) 235 | elif opcode == OP_TYPEMINPLUS : RET+= "%s+?" % singleByte( xs.readOne("B") ) 236 | 237 | elif opcode == OP_TYPEMINQUERY : RET+= "%s??" % singleByte( xs.readOne("B") ) 238 | 239 | elif opcode == OP_TYPEMINUPTO : RET+= "%(char)s{,%(cnt)d}?" % dict( cnt=xs.readOne(">H"), char=singleByte( xs.readOne("B") ) ) 240 | 241 | elif opcode == OP_CLASS : junk=xs.readN(32); RET+="[%s]" % reClass(junk,1) 242 | elif opcode in [OP_PRUNE]: 243 | pass 244 | else: 245 | if verbose: 246 | print "CODE :%d " % opcode 247 | else: 248 | pass 249 | 250 | 251 | if verbose: 252 | print "\n\nDONE: [%s]\n\n" % RET 253 | return RET 254 | 255 | 256 | 257 | 258 | 259 | -------------------------------------------------------------------------------- /libzpy/libs/cr_tools.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | from Crypto.Cipher import AES 3 | from Crypto.Cipher import ARC4 4 | import argparse,sys,struct 5 | 6 | aparse = argparse.ArgumentParser(description='RC4 decoder') 7 | aparse.add_argument('-f','--file') 8 | aparse.add_argument('-k','--key') 9 | aparse.add_argument('-d','--data') 10 | aparse.add_argument('-v','--visual',action='store_true') 11 | aparse.add_argument('-vv','--vvisual',action='store_true') 12 | aparse.add_argument('-t','--type',help='Type of encryptionk key: bin/string/hex') 13 | aparse.add_argument('-6',action='store_true',default=False,dest='v6') 14 | 15 | 16 | class RC6(object): 17 | def __init__(self, key): 18 | self.state = S = [] 19 | key += "\0" * (4 - len(key) & 3) # pad key 20 | 21 | L = list(struct.unpack("<%sL" % (len(key) / 4), key)) 22 | 23 | S.append(0xb7e15163) 24 | for i in range(43): 25 | S.append(_add(S[i], 0x9e3779b9)) 26 | 27 | v = max(132, len(L) * 3) 28 | 29 | A = B = i = j = 0 30 | 31 | for n in range(v): 32 | A = S[i] = _rol(_add(S[i], A, B), 3) 33 | B = L[j] = _rol(_add(L[j] + A + B), _add(A + B)) 34 | i = (i + 1) % len(S) 35 | j = (j + 1) % len(L) 36 | 37 | def encrypt(self, block): 38 | S = self.state 39 | A, B, C, D = struct.unpack("<4L", block.ljust(16, '\0')) 40 | 41 | B = _add(B, S[0]) 42 | D = _add(D, S[1]) 43 | 44 | for i in range(1, 21): # 1..20 45 | t = _rol(_mul(B, _rol(B, 1) | 1), 5) 46 | u = _rol(_mul(D, _rol(D, 1) | 1), 5) 47 | A = _add(_rol(A ^ t, u), S[2 * i]) 48 | C = _add(_rol(C ^ u, t), S[2 * i + 1]) 49 | 50 | A, B, C, D = B, C, D, A 51 | 52 | A = _add(A, S[42]) 53 | C = _add(C, S[43]) 54 | 55 | return struct.pack("<4L", A, B, C, D) 56 | 57 | def decrypt(self, block,state = None): 58 | S = state if state else self.state 59 | A, B, C, D = struct.unpack("<4L", block.ljust(16,"\0"))# * 16) 60 | 61 | C = _add(C, -S[43]) 62 | A = _add(A, -S[42]) 63 | 64 | for i in range(20,0,-1): # 20..1 65 | A, B, C, D = D, A, B, C 66 | 67 | u = _rol(_mul(D, _add(_rol(D, 1) | 1)), 5) 68 | t = _rol(_mul(B, _add(_rol(B, 1) | 1)), 5) 69 | C = _ror(_add(C, -S[2 * i + 1]), t) ^ u 70 | A = _ror(_add(A, -S[2 * i]), u) ^ t 71 | 72 | D = _add(D, -S[1]) 73 | B = _add(B, -S[0]) 74 | 75 | return struct.pack("<4L", A&0xffffffff, B&0xffffffff, C&0xffffffff, D&0xffffffff)#[A,B,C,D] 76 | 77 | # helper functions for rc6 78 | 79 | def _add(*args): 80 | return sum(args) % 4294967296 81 | 82 | def _rol(x, n): 83 | n = 31 & n 84 | return x << n | 2 ** n - 1 & x >> 32 - n 85 | 86 | def _ror(x, y): # rorororor 87 | return _rol(x, 32 - (31 & y)) 88 | 89 | def _mul(a, b): 90 | return (((a >> 16) * (b & 65535) + (b >> 16) * (a & 65535)) * 65536 + 91 | (a & 65535) * (b & 65535)) % 4294967296 92 | 93 | def rc6decrypt(d,k): 94 | # if args.type == 'str': 95 | # rc = RC6(k) 96 | # ciph = lambda d,k: rc.decrypt(d) 97 | # else: 98 | if type(k) == str: 99 | k = struct.unpack('I'*(len(k)/4),k) 100 | ciph = lambda d,k:RC6('a'*16).decrypt(d,k) 101 | r = '' 102 | for i in range(0,len(d)>>4): 103 | r+=ciph(d[i*16:(i+1)*16],k) 104 | return r 105 | 106 | 107 | def aesdecrypt(d,k,xor): 108 | clean = AES.new(k,AES.MODE_ECB).decrypt(d) 109 | if xor: 110 | xor = map(ord,xor) 111 | lxor = len(xor) 112 | r = '' 113 | for i in xrange(0,len(clean),lxor): 114 | r += ''.join(map(lambda x: chr(ord(x[0])^x[1]),zip(clean[i:i+lxor],xor))) 115 | clean = r 116 | return clean 117 | 118 | 119 | #def rc4init(key, 120 | 121 | def rc4decrypt(data, key,xor=None,mod1=0,mod2=0,raw=False): 122 | 123 | if raw: 124 | cip = ARC4.new(key) 125 | return cip.decrypt(data) 126 | 127 | box = map(ord,key) 128 | x = 0 129 | y = 0 130 | out = [] 131 | idx =0 132 | for byt in data: 133 | x = (x + 1 + mod1 ) % 256 134 | y = (y + box[x] + mod2) % 256 135 | box[x], box[y] = box[y], box[x] 136 | byt = ord(byt) ^ box[(box[x] + box[y]) % 256] 137 | if xor: 138 | byt ^= ord(xor[idx%len(xor)]) 139 | idx+=1 140 | out.append(chr(byt)) 141 | 142 | return ''.join(out) 143 | 144 | def visEncry(datA): 145 | i = len(datA)-1 146 | ret =map(ord,(datA)) 147 | for idx in range(1,len(datA)): 148 | ret[idx] ^= ret[idx-1] 149 | return ''.join(map(chr,ret)) 150 | 151 | 152 | def visDecry(datA): 153 | i = len(datA)-1 154 | ret =map(ord,(datA)) 155 | for idx in range(len(datA)-1,0,-1): 156 | ret[idx] ^= ret[idx-1] 157 | return ''.join(map(chr,ret)) 158 | 159 | def ppr(d): 160 | if args.visual: 161 | sys.stdout.write(visDecry(d)) 162 | else: 163 | sys.stdout.write( d) 164 | 165 | def ciph(d,k): 166 | if args.v6: 167 | return rc6decrypt(d,k) 168 | else: 169 | return rc4decrypt(d,k) 170 | 171 | if __name__ == '__main__': 172 | args = aparse.parse_args() 173 | if args.type == 'bin': 174 | with open(args.key) as f: key = f.read() 175 | elif args.type == 'str': 176 | key = args.key 177 | elif args.type == 'hexstr': 178 | key = args.key.decode('hex') 179 | elif args.type == 'hex': 180 | with open(args.key) as f: key = f.read().replace(' ','').replace('\n','').replace('\r','').decode('hex') 181 | else: 182 | print "Unknown format" 183 | sys.exit(1) 184 | #print `key` 185 | #print len(key) 186 | if args.vvisual: 187 | key = visDecry(key) 188 | 189 | if args.file and args.file != '-': 190 | with open(args.file) as f: 191 | ppr(ciph(f.read(),key)) 192 | elif args.file: 193 | ppr(ciph(sys.stdin.read(),key)) 194 | else: 195 | ppr(ciph(args.data,key)) 196 | -------------------------------------------------------------------------------- /libzpy/libs/fmt.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | 5 | def s2hex(s): return binascii.hexlify(s) 6 | 7 | def hex2s(s): return binascii.unhexlify(s) 8 | 9 | 10 | def NullTermStringList(data): 11 | return data.split(chr(0)) 12 | 13 | 14 | -------------------------------------------------------------------------------- /libzpy/libs/ida.py: -------------------------------------------------------------------------------- 1 | import idc 2 | 3 | 4 | class ifile(object): 5 | def __init__(self,addr,use_debugger=False): 6 | self.off = 0 7 | self.addr = addr 8 | self.dbg = use_debugger 9 | 10 | def byte(self,a=None): 11 | if not a: 12 | a = sefl.addr + self.off 13 | self.off += 1 14 | return DbgByte(a) if self.dbg else Byte(a) 15 | 16 | 17 | def word(self,a=None): 18 | if not a: 19 | a = sefl.addr + self.off 20 | self.off += 2 21 | return DbgWord(a) if self.dbg else Word(a) 22 | 23 | 24 | def dword(self,a=None): 25 | if not a: 26 | a = sefl.addr + self.off 27 | self.off +=4 28 | return DbgDword(a) if self.dbg else Dword(a) 29 | 30 | def bytes(self,n,a=None): 31 | return map(ord,self.bytes(n,a)) 32 | 33 | def read(self,n,a=None): 34 | if not a: 35 | a = sefl.addr + self.off 36 | self.off += n 37 | return ReadManyBytes(a,n,self.dbg) 38 | -------------------------------------------------------------------------------- /libzpy/libs/libucl_i368.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mak/libzpy/a0a10a091700bf8dcab96fa7ff720db9ea94f819/libzpy/libs/libucl_i368.so -------------------------------------------------------------------------------- /libzpy/libs/libucl_x64.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mak/libzpy/a0a10a091700bf8dcab96fa7ff720db9ea94f819/libzpy/libs/libucl_x64.so -------------------------------------------------------------------------------- /libzpy/libs/rtb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | import re,fnmatch 4 | 5 | data = { 6 | 'KB24 - KredytBank': [ 7 | 'https://www.kb24.pl/MonitySterujacy', 8 | 'https://www.kb24.pl/Login', 9 | 'https://www.kb24.pl/ikd/DETAL/PL/_SCR/Logowanie.js' 10 | ], 11 | 'Bank Zagrzebski - grupa unicredit': [ 12 | 'https://www.zaba.hr/ebank/gradjani/Gradjani', 13 | 'https://www.zaba.hr/ezaba/MainServlet', 14 | 'https://www.zaba.hr/ezaba/PlatniPromet', 15 | 'https://www.zaba.hr/ezaba/VA/StanjeIPrometiPregledPrometa', 16 | 'https://www.zaba.hr/ebank/gradjani/JavaScript/gLogin.js' 17 | ], 18 | 'mBank - company': [ 19 | 'https://companynet.mbank.pl/mt/fragments/cua/login.jsp' 20 | ], 21 | 'Alpha Bank Romania': [ 22 | 'https://secure2.alphabank.ro/corporate/CorpOTPLoginLangRom.jsp' 23 | ], 24 | 'Alior' : [ 25 | 'https://aliorbank.pl/hades/do/Login' 26 | ], 27 | 'PBZCOM@NET' : [ 28 | 'https://comnet.pbz.hr/PbzComnetWeb/stateAndTransactions/userAccountState.html', 29 | 'https://comnet.pbz.hr/PbzComnetWeb/kunaBusiness/ordersForSending.html' 30 | ], 31 | 'Pekao S.A. - Biznes ' : [ 32 | 'https://ww.pekaobiznes24.pl/webcorpo/do/desktop', 33 | 'https://ww.pekaobiznes24.pl/webcorpo/do/operationHistory', 34 | 'https://www.pekaofirma24.pl/webcorpo/do/confidentialPhone?open=true', 35 | 'https://www.pekaofirma24.pl/sme/do/confidentialPhone?open=true', 36 | 'https://www.pekaofirma24.pl/sme/do/aggregation', 37 | 'https://www.pekaobiznes24.pl/sme/do/domesticTransfer?open=true' 38 | ], 39 | 'HYPO ALPE-ADRIA-BANK' : [ 40 | 'https://www.hypo.hr/hyponet/Payments/PaymentSubmit?menu=loadPartial', 41 | 'https://www.hypo.hr/hyponet/Payments/PaymentViewSubmit?menu=loadPartial', 42 | 'https://www.hypo.hr/hyponet/Order10/IndexGridPartial' 43 | ], 44 | 'Citibank BG': [ 45 | 'https://online.cibank.bg/EBankCI/', 46 | 'https://online.cibank.bg/EBankCI/Login', 47 | 'https://online.cibank.bg/EBankCI/Home', 48 | 'https://online.cibank.bg/EBankCI/StmtInFilesServlet' 49 | ], 50 | 51 | 'Pekao S.A.' : [ 52 | 'https://www.pekao24.pl', 53 | 'https://www.prepaid.pekao24.pl', 54 | 'https://www.cdm24.pl', 55 | 'https://www.pekaofirma24.pl/do/login;jsessionid=', 56 | 'https://www.pekaobiznes24.pl/do/login' 57 | ], 58 | 'BRD@ffice':[ 59 | 'https://www.brdoffice.ro/smartoffice/index.html' 60 | ], 61 | 'Raiffeisen Bank, Zagreb' : [ 62 | 'https://direkt.rba.hr/cgi-bin/ppz2/app/app_main.jsp', 63 | 'https://direkt.rba.hr/cgi-bin/ppz2/start/rbat.jsp' 64 | ], 65 | 'Erste&Steiermärkische Bank' : [ 66 | 'https://netbanking.erstebank.hr', 67 | 'https://netbanking.erstebank.hr/Prijava/Prijava.aspx', 68 | 'https://netbanking.erstebank.rs/Prijava/Prijava.aspx', 69 | 'https://www.erstebank.rs/en/NetBanking/E-banking/Reta' 70 | ], 71 | 'BGŻ - corpo' : [ 72 | 'https://www.pf.bgz.pl/bgzweb/auth/login/submit', 73 | 'https://www.pf.bgz.pl/bgzweb/auth/login/submit', 74 | 'https://www.ebgzfirma.pl' 75 | ], 76 | 'BGK' : [ 77 | 'https://www.zleceniaplatnosci.bgk.pl/BGKSSO/Login.aspx?redirect', 78 | 'https://www.bgk24biznes.pl/', 79 | 'https://repozytorium.bgk.com.pl/' 80 | ], 81 | 'BOŚ' : [ 82 | 'https://bosbank24.pl/twojekonto', 83 | 'https://bosbank24.pl/iboss', 84 | 'https://bosbank24.pl/bosfaktor/login.jsf' 85 | ], 86 | 'Bank Pocztowy' : [ 87 | 'https://www.pocztowy24.pl/', 88 | 'https://www.pocztowy24biznes.pl/web/guest/home', 89 | 'https://e-wniosek.pocztowy.pl/lokaty-online/index.php' 90 | ], 91 | 'BNP Paribas Bank Polska S.A.' : [ 92 | 'https://planet.bnpparibas.pl/hades/do/Login', 93 | 'https://biznesplanet.bnpparibas.pl/hades/do/Login', 94 | 'https://planet.bnpparibas.pl/hades/do/Login' 95 | ], 96 | 'Credit Agricole Bank Polska S.A.' : [ 97 | 'https://e-bank.credit-agricole.pl/', 98 | 'https://firmabank.credit-agricole.pl/mt-front/' 99 | ], 100 | 'Deutsche Bank' : [ 101 | 'https://ebank.db-pbc.pl/auth/login.jsp', 102 | 'https://ebusinessbank.db-pbc.pl/auth/login.jsp', 103 | 'https://makler.dbmakler.pl/', 104 | 'https://webfaktor.db-pbc.pl/login.jsf', 105 | 'https://autobahn.db.com/', 106 | 'https://db-direct.db.com/u/eb/Login_Main.serv', 107 | 'https://dbdi-mobile.db.com/dbdm/public/crud/core/login/Login/input.xhtml' 108 | ], 109 | 'Euro Euro Bank S.A.' : [ 110 | 'https://online.eurobank.pl/bi/bezpieczenstwo_logowanie.ebk' 111 | ], 112 | 'Polski Bank Przedsiębiorczości S.A' : [ 113 | 'https://bank.fmbank24.pl/' 114 | ], 115 | 'Getin Bank' : [ 116 | 'https://secure.getinbank.pl/' 117 | 'https://korporacja.gb24.pl/ceb-web/pages/login.jsp' 118 | ], 119 | 'Noble Bank' : [ 120 | 'https://secure.noblebank.pl/' 121 | 'https://online.noblesecurities.pl/SidomaLight/pl.pbpolsoft.sidomalight.Start/Start.html?module=login' 122 | ], 123 | 'HSBC Bank Polska S.A.' : [ 124 | 'https://www2.secure.hsbcnet.com/uims/portal/IDV_CAM10_AUTHENTICATION?__cancelLogonUrl=http://www.hsbcnet.com', 125 | 'http://www.hsbcnet.com/displayArticle?cd_doc_path=/gbm/about-us/news/2013/euromoney-awards.html', 126 | 'http://www.hsbcnet.com/gbm/fxcalc-disp', 127 | 'https://www.iif.hsbc.pl/Logon?locale=pl_PL' 128 | ], 129 | 'Idea Bank S.A.' : [ 130 | 'https://secure.ideabank.pl/' 131 | ], 132 | 'ING Bank Śląski S.A.' : [ 133 | 'https://online.ingbank.pl/bskonl/login.html', 134 | 'https://www.ingonline.com/pl/!UPR.Dispatcher?ps_redir_proc=homepage', 135 | 'https://start.ingbusinessonline.pl/ing/do/sms', 136 | 'www.ingbank.pl/ing-businessonline‎', 137 | 'www.ingbank.pl/en-ing-businessonline‎' 138 | ], 139 | 'PLUS BANK S.A.' : [ 140 | 'https://plusbank24.pl/web-client/login!input.action' 141 | ], 142 | 'BZ WBK' : [ 143 | 'https://www.centrum24.pl/centrum24-web/?x=', 144 | 'https://www.centrum24.pl/centrum24-web/login', 145 | 'https://www.centrum24.pl/bzwbkonline/eSmart.html?typ=13&', 146 | 'https://www.centrum24.pl/centrum24-web/login', 147 | 'https://ibiznes24.pl/bzwbk24biznes-client/login.html', 148 | 'https://www.inwestoronline.pl/cbm/', 149 | 'https://www.centrum24.pl/prepaid/index?index=1491', 150 | 'https://www.kb24.pl/', 151 | 'https://www.kbnet.pl/web/guest/login' 152 | ], 153 | 'Raiffeisen Polbank S.A.' : [ 154 | 'https://www.r-bank.pl/newsbi/index.jsp?' 155 | 'https://moj.raiffeisenpolbank.com/', 156 | 'https://moj.raiffeisenpolbank.com/polbank', 157 | 'https://www.polbank24.pl/netbanking/', 158 | 'https://wyciagi.polbank24.pl/Login.aspx?ReturnUrl=' 159 | ], 160 | 'Sygma Banque Societe Anonyme S.A.' : [ 161 | 'https://online.sygmabank.pl/SygmaOnLine/' 162 | ], 163 | 'Volkswagen Bank Polska S.A.' : [ 164 | 'https://login.vwbankdirect.pl/', 165 | 'https://biznesbanking.vwbankdirect.pl/' 166 | ], 167 | 'Podkarpacki Bank Spółdzielczy' : [ 168 | 'https://sbe.pbsbank.pl/' 169 | ], 170 | 'Bank BPH S.A.' : [ 171 | 'https://www.bph.pl/pi/do/Login', 172 | 'https://www.bph.pl/mobile/do/login', 173 | 'https://www.bph.pl/bnlite/spring/authenticate' 174 | ], 175 | 'Bank Millennium S.A.' : [ 176 | 'https://www.bankmillennium.pl/osobiste/Default.qz', 177 | 'https://www.bankmillennium.pl/firmy/Default.qz?' 178 | ], 179 | 'Meritum Bank ICB S.A.' : [ 180 | 'https://www.meritumbank.pl/' 181 | ], 182 | 'NORDEA Bank Polska S.A.' : [ 183 | 'https://netbank.nordea.pl/pnb/login.do', 184 | 'https://atlanticfundservices.eu/int2nordea/tfi/nordea/Login.app?' 185 | ], 186 | 'Bank Polskiej Spółdzielczości S.A.' : [ 187 | 188 | 'https://bps25.pl/', 189 | 'https://ebank.bankbps.pl/bpswarszawa_k', 190 | 'https://ebank.bankbps.pl/bpswroclaw_k', 191 | 'https://ebank.bankbps.pl/bpsolsztyn_k', 192 | 'https://ebank.bankbps.pl/bpskatowice_k', 193 | 'https://ebank.bankbps.pl/bpslublin_k', 194 | 'https://ebank.bankbps.pl/bpskrakow_k', 195 | 'https://ebank.bankbps.pl/bpsrzeszow_k' 196 | ], 197 | 'Giełda Papierów Wartościowych': [ 198 | 'https://4brokernet.gpw.pl/dana-na/auth/url_default/welcome.cgi' 199 | ], 200 | 'Krajowa Izba Rozliczeniowa S.A.' : [ 201 | 'https://pbn.paybynet.com.pl/PayByNet/login.do', 202 | 'http://www.kir.com.pl/main.php?do=login&noreferer' 203 | ], 204 | 'Związek Banków Polskich' : [ 205 | 'https://zbp.pl/logowanie' 206 | ] 207 | } 208 | 209 | 210 | def check_url(rgx) : 211 | def fire(u): 212 | try: 213 | return bool(rgx.search(u)) 214 | except AttributeError: 215 | return bool(re.search(fnmatch.translate(rgx),u)) 216 | 217 | r = [] 218 | for bank in data: 219 | c = 0 220 | 221 | for u in data[bank]: 222 | if fire(u): 223 | c +=1 224 | if c >0: r.append(bank + ' (%d/%d)' % (c,len(data[bank]))) 225 | return ' | '.join(r) 226 | -------------------------------------------------------------------------------- /libzpy/libs/storage.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class storageException(Exception): 4 | pass 5 | 6 | -------------------------------------------------------------------------------- /libzpy/libs/structure.py: -------------------------------------------------------------------------------- 1 | from ctypes import * 2 | #try: 3 | # from cStringIO import StringIO 4 | #except ImportError: 5 | from StringIO import StringIO 6 | 7 | c_word = c_uint16 8 | c_dword = c_uint32 9 | c_qword = c_uint64 10 | 11 | ## i need 32bit wchar... 12 | c_wchar = c_wchar if sizeof(c_wchar) == 2 else (2*c_char) 13 | 14 | class DataStructure(Structure): 15 | _flags = {} 16 | _have_data = True 17 | _sep = ' ' 18 | 19 | def __init__(self,data): 20 | super(DataStructure,self).__init__() 21 | self.feed(data) 22 | 23 | def read(self,data): 24 | if isinstance(data,StringIO): 25 | self.data = data.read(self.size) 26 | else: 27 | self.data = data[sizeof(self):self.size] 28 | 29 | def pack(self): 30 | return buffer(self)[:] 31 | 32 | def feed(self, bytes): 33 | data = bytes 34 | if isinstance(data,StringIO): 35 | data = bytes.read(sizeof(self)) 36 | 37 | memmove(addressof(self), c_char_p(data), sizeof(self)) 38 | if self._have_data: 39 | self.read(bytes) 40 | 41 | def _str_field(self,args): 42 | if type(args) == str: 43 | args = (args,0) 44 | n,t = args 45 | if hasattr(self,'_print_%s' % n): 46 | return (n,getattr(self,'_print_%s' % n)()) 47 | elif t == c_word: 48 | return (n,'0x%04x' % getattr(self,n)) 49 | elif t == c_dword: 50 | return (n,'0x%08x' % getattr(self,n)) 51 | elif getattr(self,n).__class__ == str: 52 | return (n,getattr(self,n).encode('string_escape')) 53 | 54 | def _p_field(self,a): 55 | return '%s: %s' % self._str_field(a) 56 | 57 | def _print_flags(self): 58 | ret = [] 59 | for fl in self._flags: 60 | if self.flags & self._flags[fl]: 61 | ret.append(fl) 62 | try: 63 | return ' | '.join(ret) + "\n" 64 | except: 65 | return '' 66 | 67 | def __str__(self): 68 | return self._sep.join(map(self._p_field,self._fields_)) 69 | 70 | def json(self): 71 | import json 72 | return json.dumps(dict(map(self._str_field,self._fields_))) 73 | 74 | 75 | class StructList(object): 76 | struct = None 77 | 78 | def __init__(self,data): 79 | self.data = data.data if isinstance(data,DataStructure) else data 80 | self.size = data.realSize if isinstance(data,DataStructure) else len(data) 81 | self.off = 0 82 | 83 | def __iter__(self): 84 | return self 85 | 86 | def next(self): 87 | if self.off >= self.size: 88 | raise StopIteration 89 | ib = self.struct(self.data[self.off:]) 90 | self.off += ib.size 91 | return ib 92 | -------------------------------------------------------------------------------- /libzpy/libs/vmzeus.py: -------------------------------------------------------------------------------- 1 | 2 | #!/usr/bin/python 3 | ######################################################################## 4 | # Copyright (c) 2014 5 | # all other co-authors here :) 6 | # Daniel Plohmann gmailcom> 7 | # All rights reserved. 8 | ######################################################################## 9 | # 10 | # This is free software: you can redistribute it and/or modify it 11 | # under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, but 16 | # WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | # General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see 22 | # . 23 | # 24 | ######################################################################## 25 | 26 | import struct 27 | import Crypto.Cipher.ARC4 28 | 29 | # Hexdump 30 | # courtesy of http://code.activestate.com/recipes/142812/ 31 | FILTER = "".join([(len(repr(chr(x))) == 3) and chr(x) or "." for x in range(256)]) 32 | 33 | 34 | def hexdump(src, length=16): 35 | N = 0 36 | result = "" 37 | while src: 38 | s, src = src[:length], src[length:] 39 | hexa = " ".join(["%02X" % ord(ch) for ch in s]) 40 | s = s.translate(FILTER) 41 | result += "%04X %-*s %s\r\n" % (N, length * 3, hexa, s) 42 | N += length 43 | return result 44 | 45 | 46 | class VmContext(object): 47 | 48 | def __init__(self, bytecode, config): 49 | self.bytecode = bytecode 50 | self.config = config 51 | self.eip = 0 52 | self.edi = 0 53 | self.ecx = 0 54 | self.r = [0 for i in xrange(16)] 55 | self.magics = {"nop": {1: 0x32, 2: 0x26, 4: 0xF3}, 56 | "xor": {1: 0xF1, 2: 0xE9, 4: 0x6A}, 57 | "add": {1: 0x73, 2: 0xD9}, 58 | "sub": {1: 0xEB}, 59 | "rol": {1: 0x85}, 60 | "ror": {1: 0xF3, 2: 0xA6}, 61 | "not": {1: 0xE7, 2: 0x8B, 4: 0x24}, 62 | "reorder": 0xBA, 63 | "rc4": 0xE9, 64 | "setecx": {2: 0xDA, 4: 0x70}, 65 | "setedi": 0xC8, 66 | "loop": {1: 0xD0, 2: 0xEC}, 67 | "mov_r_const": {1: 0x0B, 2: 0x0F, 4: 0x70}, 68 | "mov_r_r": {1: 0x46, 2: 0x39, 4: 0x9E}, 69 | "add_r_r": {1: 0x72, 2: 0x5F, 4: 0xF9}, 70 | "sub_r_r": {1: 0x1E, 2: 0xD1, 4: 0xA6}, 71 | "xor_r_r": {1: 0xDB, 2: 0xAC, 4: 0xB7}, 72 | "add_r_const": {1: 0x9D, 2: 0x8f, 4: 0x28}, 73 | "sub_r_const": {1: 0x52, 2: 0x85, 4: 0xD8}, 74 | "xor_r_const": {1: 0xD5, 2: 0x24, 4: 0x2E}, 75 | "stos_add": {1: 0x65, 2: 0x89, 4: 0xDC}, 76 | "stos_sub": {1: 0x1D, 4: 0xA0}, 77 | "stos_xor": {1: 0x41, 2: 0x46, 4: 0x29}, 78 | "lods": {1: 0xB8, 2: 0x68, 4: 0xFD}, 79 | "stos": {1: 0x16, 2: 0xBB, 4: 0xF0} 80 | } 81 | self.instr_table = [self.instr_nop_byte, self.instr_nop_word, self.instr_nop_dword, 82 | self.instr_xor_byte, self.instr_xor_word, self.instr_xor_dword, 83 | self.instr_add_byte, self.instr_add_word, self.instr_add_dword, 84 | self.instr_sub_byte, self.instr_sub_word, self.instr_sub_dword, 85 | self.instr_rol_byte, self.instr_rol_word, self.instr_rol_dword, 86 | self.instr_ror_byte, self.instr_ror_word, self.instr_ror_dword, 87 | self.instr_not_byte, self.instr_not_word, self.instr_not_dword, 88 | self.instr_reorder, 89 | self.instr_rc4, 90 | self.instr_setecx_byte, self.instr_setecx_word, self.instr_setecx_dword, 91 | self.instr_setedi, 92 | self.instr_loop_byte, self.instr_loop_word, 93 | self.instr_mov_r_const_byte, self.instr_mov_r_const_word, self.instr_mov_r_const_dword, 94 | self.instr_mov_r_r_byte, self.instr_mov_r_r_word, self.instr_mov_r_r_dword, 95 | self.instr_add_r_r_byte, self.instr_add_r_r_word, self.instr_add_r_r_dword, 96 | self.instr_sub_r_r_byte, self.instr_sub_r_r_word, self.instr_sub_r_r_dword, 97 | self.instr_xor_r_r_byte, self.instr_xor_r_r_word, self.instr_xor_r_r_dword, 98 | self.instr_add_r_const_byte, self.instr_add_r_const_word, self.instr_add_r_const_dword, 99 | self.instr_sub_r_const_byte, self.instr_sub_r_const_word, self.instr_sub_r_const_dword, 100 | self.instr_xor_r_const_byte, self.instr_xor_r_const_word, self.instr_xor_r_const_dword, 101 | self.instr_stos_add_byte, self.instr_stos_add_word, self.instr_stos_add_dword, 102 | self.instr_stos_sub_byte, self.instr_stos_sub_word, self.instr_stos_sub_dword, 103 | self.instr_stos_xor_byte, self.instr_stos_xor_word, self.instr_stos_xor_dword, 104 | self.instr_lods_byte, self.instr_lods_word, self.instr_lods_dword, 105 | self.instr_stos_byte, self.instr_stos_word, self.instr_stos_dword, 106 | self.instr_leave 107 | ] 108 | self.pack_sizes = {1: "B", 2: "H", 4: "I"} 109 | self.modulus = {1: 0xFF, 2: 0xFFFF, 4: 0xFFFFFFFF} 110 | 111 | def __str__(self): 112 | return "EIP: 0x%08x -> 0x%x | EDI: 0x%08x | ECX: 0x%08x" % (self.eip, ord(self.bytecode[self.eip]), self.edi, self.ecx) 113 | 114 | def _fix_xors(self,xors): 115 | suf = {'byte':1,'word':2,'dword':4} 116 | print 'Instrs: %d' % len(self.instr_table) 117 | print 'Magics %d' % len(xors) 118 | 119 | for idx in xrange(0,len(self.instr_table)-1): 120 | name = self.instr_table[idx].im_func.func_name.split('_') 121 | print 'Updating %s with %x' % (`name`,xors[idx]) 122 | try: 123 | self.magics['_'.join(name[1:-1])][suf[name[-1]]] = xors[idx] 124 | except IndexError: 125 | self.magics[name[1]] = xors[idx] 126 | 127 | except KeyError: 128 | self.magics[name[1]] = xors[idx] 129 | 130 | 131 | def dump_r(self): 132 | output = " Custom Registers: \n" 133 | for i in xrange(4): 134 | line = " " 135 | for j in xrange(4): 136 | line += "%s " % struct.pack("I", self.r[4 * i + j]).encode("hex") 137 | output += line + "\n" 138 | return output 139 | 140 | def run(self): 141 | self.instr_count = 0 142 | print "Decoding BaseConfig. Initial VM state:" 143 | print str(self) + "\n" 144 | stop_exec = False 145 | while not stop_exec and self.eip < len(self.bytecode): 146 | self.instr_count += 1 147 | print "+ fetching opcode [%d]: 0x%02x (%d)" % (self.instr_count, ord(self.bytecode[self.eip]), ord(self.bytecode[self.eip])) 148 | stop_exec = self.instr_table[ord(self.bytecode[self.eip])]() 149 | print " ", str(self) 150 | 151 | ################################ 152 | # opcode handlers 153 | ################################ 154 | def instr_nop_byte(self): 155 | # operand: 0x00 156 | self.instr_nop(1) 157 | 158 | def instr_nop_word(self): 159 | # operand: 0x01 160 | self.instr_nop(2) 161 | 162 | def instr_nop_dword(self): 163 | # operand: 0x02 164 | self.instr_nop(4) 165 | 166 | def instr_nop(self, size): 167 | eip_offset = {1: 0, 2: 1, 4: 1}[size] 168 | bXorKey = self.deref_bytecode(self.eip + eip_offset, 1) ^ self.magics["nop"][size] 169 | self.eip += size 170 | if self.deref_bytecode(self.eip, 1) & 0x80: 171 | self.decode_next_opcode_byte(bXorKey) 172 | print " -> nop_%d" % (size) 173 | 174 | def instr_xor_byte(self): 175 | # operand: 0x03 176 | self.instr_xor(1) 177 | 178 | def instr_xor_word(self): 179 | # operand: 0x04 180 | self.instr_xor(2) 181 | 182 | def instr_xor_dword(self): 183 | # operand: 0x05 184 | self.instr_xor(4) 185 | 186 | def instr_xor(self, size): 187 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["xor"][size] 188 | self.eip += 1 189 | # there is some EDI fuckup here not properly dereferenced? 190 | # also EIP offset has to be adjusted 191 | value = self.deref_bytecode(self.eip, size) ^ self.deref_config(self.edi, size) 192 | replacement = struct.pack(self.pack_sizes[size], value) 193 | self.config = self.replace_in_buffer(self.config, self.edi, replacement) 194 | self.eip += size 195 | self.edi += size 196 | if self.deref_bytecode(self.eip, 1) & 0x80: 197 | self.decode_next_opcode_byte(bXorKey) 198 | print " -> xor_%d 0x%08x" % (size, self.edi - size) 199 | 200 | def instr_add_byte(self): 201 | # operand: 0x09 202 | self.instr_add(1) 203 | 204 | def instr_add_word(self): 205 | # operand: 0x0a 206 | self.instr_add(2) 207 | 208 | def instr_add_dword(self): 209 | # operand: 0x0b 210 | self.instr_add(4) 211 | 212 | def instr_add(self, size): 213 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["add"][size] 214 | self.eip += 1 215 | value = self.deref_config(self.edi, size) + self.deref_bytecode(self.eip, size) 216 | replacement = struct.pack(self.pack_sizes[size], value & self.modulus[size]) 217 | self.config = self.replace_in_buffer(self.config, self.edi, replacement) 218 | self.eip += size 219 | self.edi += size 220 | if self.deref_bytecode(self.eip, 1) & 0x80: 221 | self.decode_next_opcode_byte(bXorKey) 222 | print " -> sub_%d 0x%08x" % (size, self.edi - size) 223 | 224 | def instr_sub_byte(self): 225 | # operand: 0x09 226 | self.instr_sub(1) 227 | 228 | def instr_sub_word(self): 229 | # operand: 0x0a 230 | self.instr_sub(2) 231 | 232 | def instr_sub_dword(self): 233 | # operand: 0x0b 234 | self.instr_sub(4) 235 | 236 | def instr_sub(self, size): 237 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["sub"][size] 238 | self.eip += 1 239 | value = self.deref_config(self.edi, size) - self.deref_bytecode(self.eip, size) 240 | replacement = struct.pack(self.pack_sizes[size], value & self.modulus[size]) 241 | self.config = self.replace_in_buffer(self.config, self.edi, replacement) 242 | self.eip += size 243 | self.edi += size 244 | if self.deref_bytecode(self.eip, 1) & 0x80: 245 | self.decode_next_opcode_byte(bXorKey) 246 | print " -> sub_%d 0x%08x" % (size, self.edi - size) 247 | 248 | def rol(self, buf, size, count): 249 | while count > 0: 250 | buf = (buf << 1 | buf >> (size * 8 - 1)) & self.modulus[size] 251 | count -= 1 252 | return buf 253 | 254 | def instr_rol_byte(self): 255 | # operand: 0x0c 256 | self.instr_rol(1) 257 | 258 | def instr_rol_word(self): 259 | # operand: 0x0d 260 | self.instr_rol(2) 261 | 262 | def instr_rol_dword(self): 263 | # operand: 0x0e 264 | self.instr_rol(4) 265 | 266 | def instr_rol(self, size): 267 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["rol"][size] 268 | count = self.deref_bytecode(self.eip + 1, size) & (size * 8 - 1) 269 | self.eip += 2 270 | dataOffset = self.edi 271 | replacement = struct.pack(self.pack_sizes[size], (self.rol(self.deref_config(dataOffset, size), size, count)) & self.modulus[size]) 272 | self.config = self.replace_in_buffer(self.config, dataOffset, replacement) 273 | self.edi += size 274 | if self.deref_bytecode(self.eip, 1) & 0x80: 275 | self.decode_next_opcode_byte(bXorKey) 276 | print " -> rol_%d 0x%08x" % (size, dataOffset) 277 | 278 | def ror(self, buf, size, count): 279 | while count > 0: 280 | buf = (buf >> 1 | buf << (size * 8 - 1)) & self.modulus[size] 281 | count -= 1 282 | return buf 283 | 284 | def instr_ror_byte(self): 285 | # operand: 0x0f 286 | self.instr_ror(1) 287 | 288 | def instr_ror_word(self): 289 | # operand: 0x10 290 | self.instr_ror(2) 291 | 292 | def instr_ror_dword(self): 293 | # operand: 0x11 294 | self.instr_ror(4) 295 | 296 | def instr_ror(self, size): 297 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["ror"][size] 298 | count = self.deref_bytecode(self.eip + 1, size) & (size * 8 - 1) 299 | self.eip += 2 300 | dataOffset = self.edi 301 | ### print "before: ", struct.pack(self.pack_sizes[size], self.deref_config(dataOffset, size)).encode("hex") 302 | replacement = struct.pack(self.pack_sizes[size], (self.ror(self.deref_config(dataOffset, size), size, count)) & self.modulus[size]) 303 | ### print "after: ", replacement.encode("hex") 304 | self.config = self.replace_in_buffer(self.config, dataOffset, replacement) 305 | self.edi += size 306 | if self.deref_bytecode(self.eip, 1) & 0x80: 307 | self.decode_next_opcode_byte(bXorKey) 308 | print " -> ror_%d 0x%08x" % (size, dataOffset) 309 | 310 | def instr_not_byte(self): 311 | # operand: 0x12 312 | self.instr_not(1) 313 | 314 | def instr_not_word(self): 315 | # operand: 0x13 316 | self.instr_not(2) 317 | 318 | def instr_not_dword(self): 319 | # operand: 0x14 320 | self.instr_not(4) 321 | 322 | def instr_not(self, size): 323 | bXorKey = self.deref_bytecode(self.eip, 1) ^ self.magics["not"][size] 324 | self.eip += 1 325 | valueOffset = self.edi 326 | replacement = struct.pack(self.pack_sizes[size], (~self.deref_config(valueOffset, size)) & self.modulus[size]) 327 | self.config = self.replace_in_buffer(self.config, valueOffset, replacement) 328 | self.edi += size 329 | if self.deref_bytecode(self.eip, 1) & 0x80: 330 | self.decode_next_opcode_byte(bXorKey) 331 | print " -> not_%d 0x%08x" % (size, valueOffset) 332 | 333 | def instr_reorder(self): 334 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["reorder"] 335 | operand = self.deref_bytecode(self.eip + 1, 1) 336 | value = struct.pack(self.pack_sizes[4], self.deref_config(self.edi, 4)) 337 | replacement = [0, 0, 0, 0] 338 | for i in xrange(4): 339 | index = operand & 0x3 340 | replacement[index] = value[i] 341 | operand = operand >> 2 342 | replacement = "".join(replacement) 343 | # after shuffling 344 | self.config = self.replace_in_buffer(self.config, self.edi, replacement) 345 | self.edi += 4 346 | self.eip += 2 347 | if self.deref_bytecode(self.eip, 1) & 0x80: 348 | self.decode_next_opcode_byte(bXorKey) 349 | print " -> reorder 0x%08x" % (self.deref_config(self.edi - 4, 4)) 350 | 351 | def instr_rc4(self): 352 | # operand: 0x16 353 | bXorKey = self.deref_bytecode(self.eip + 3, 1) ^ self.magics["rc4"] 354 | keySize = struct.unpack("B", self.bytecode[self.eip + 1])[0] 355 | dataSize = struct.unpack("B", self.bytecode[self.eip + 2])[0] 356 | # build rc4 key with password given in bytecode 357 | keyOffset = self.eip + 3 358 | rc4Key = self.bytecode[keyOffset:keyOffset + keySize] 359 | dataOffset = self.edi 360 | data = self.config[dataOffset:dataOffset + dataSize] 361 | rc4 = Crypto.Cipher.ARC4.new(rc4Key) 362 | cryptedBin = b"".join(data) 363 | plaintext = rc4.decrypt(cryptedBin) 364 | # insert decrypted part in config 365 | self.config = self.replace_in_buffer(self.config, self.edi, plaintext) 366 | self.edi += dataSize 367 | self.eip += 3 + keySize 368 | if self.deref_bytecode(self.eip, 1) & 0x80: 369 | self.decode_next_opcode_byte(bXorKey) 370 | print " -> rc4 -> offset: 0x%08x (%d bytes), key_offset: 0x%08x (%d bytes)" % (dataOffset, dataSize, keyOffset, keySize) 371 | 372 | def instr_setecx_byte(self): 373 | # operand: 0x17 374 | self.instr_setecx(1) 375 | 376 | def instr_setecx_word(self): 377 | # operand: 0x18 378 | self.instr_setecx(2) 379 | 380 | def instr_setecx_dword(self): 381 | # operand: 0x19 382 | self.instr_setecx(4) 383 | 384 | def instr_setecx(self, size): 385 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["setecx"][size] 386 | self.eip += 1 387 | value = self.deref_bytecode(self.eip, size) 388 | self.ecx += value 389 | self.eip += size 390 | if self.deref_bytecode(self.eip, 1) & 0x80: 391 | self.decode_next_opcode_byte(bXorKey) 392 | print " -> set_%d ecx, 0x%08x" % (size, value) 393 | 394 | def instr_setedi(self): 395 | # operand: 0x1A 396 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["setedi"] 397 | self.eip += 1 398 | self.edi += self.deref_bytecode(self.eip, 2) 399 | self.edi = self.edi & 0xFFFF 400 | self.eip += 2 401 | if self.deref_bytecode(self.eip, 1) & 0x80: 402 | self.decode_next_opcode_byte(bXorKey) 403 | print " -> set edi, 0x%08x" % self.edi 404 | 405 | def instr_loop_byte(self): 406 | # operand: 0x1B 407 | self.instr_loop(1) 408 | 409 | def instr_loop_word(self): 410 | # operand: 0x1C 411 | self.instr_loop(2) 412 | 413 | def instr_loop(self, size): 414 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["loop"][size] 415 | if self.deref_bytecode(self.eip + 1 + size, 1) & 0x80: 416 | self.decode_next_opcode_byte(bXorKey, 1 + size) 417 | self.eip += 1 418 | if self.ecx != 0: 419 | self.ecx -= 1 420 | self.eip = self.eip + size - self.deref_bytecode(self.eip, size) 421 | else: 422 | self.eip += size 423 | print " -> loop_%d 0x%08x" % (size, self.ecx) 424 | 425 | def instr_mov_r_const_byte(self): 426 | # operand: 0x1D 427 | self.instr_mov_r_const(1) 428 | 429 | def instr_mov_r_const_word(self): 430 | # operand: 0x1E 431 | self.instr_mov_r_const(2) 432 | 433 | def instr_mov_r_const_dword(self): 434 | # operand: 0x1F 435 | self.instr_mov_r_const(4) 436 | 437 | def instr_mov_r_const(self, size): 438 | bXorKey = self.deref_bytecode(self.eip + 2, 1) ^ self.magics["mov_r_const"][size] 439 | dst_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 440 | value = self.deref_bytecode(self.eip + 2, 4) & self.modulus[size] 441 | self.r[dst_r_index] = value 442 | self.eip += 2 + size 443 | if self.deref_bytecode(self.eip, 1) & 0x80: 444 | self.decode_next_opcode_byte(bXorKey) 445 | print " -> mov_%d r[%d], 0x%08x" % (size, dst_r_index, value) 446 | print self.dump_r() 447 | 448 | def instr_mov_r_r_byte(self): 449 | # operand: 0x20 450 | self.instr_mov_r_r(1) 451 | 452 | def instr_mov_r_r_word(self): 453 | # operand: 0x21 454 | self.instr_mov_r_r(2) 455 | 456 | def instr_mov_r_r_dword(self): 457 | # operand: 0x22 458 | self.instr_mov_r_r(4) 459 | 460 | def instr_mov_r_r(self, size): 461 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["mov_r_r"][size] 462 | dst_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 463 | src_r_index = self.deref_bytecode(self.eip + 1, 1) >> 4 464 | # according to commentary: "lower than 32 bit size operations do not preserve destination's higher bits, they get set to 0" 465 | self.r[dst_r_index] = self.r[src_r_index] & self.modulus[size] 466 | self.eip += 2 467 | if self.deref_bytecode(self.eip, 1) & 0x80: 468 | self.decode_next_opcode_byte(bXorKey) 469 | print " -> mov_%d r[%d], r[%d]" % (size, dst_r_index, src_r_index) 470 | print self.dump_r() 471 | 472 | def instr_add_r_r_byte(self): 473 | # operand: 0x23 474 | self.instr_add_r_r(1) 475 | 476 | def instr_add_r_r_word(self): 477 | # operand: 0x24 478 | self.instr_add_r_r(2) 479 | 480 | def instr_add_r_r_dword(self): 481 | # operand: 0x25 482 | self.instr_add_r_r(4) 483 | 484 | def instr_add_r_r(self, size): 485 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["add_r_r"][size] 486 | dst_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 487 | src_r_index = self.deref_bytecode(self.eip + 1, 1) >> 4 488 | self.r[dst_r_index] += self.r[src_r_index] & self.modulus[size] 489 | self.r[dst_r_index] = self.r[dst_r_index] & self.modulus[4] 490 | self.eip += 2 491 | if self.deref_bytecode(self.eip, 1) & 0x80: 492 | self.decode_next_opcode_byte(bXorKey) 493 | print " -> add_%d r[%d], r[%d]" % (size, dst_r_index, src_r_index) 494 | print self.dump_r() 495 | 496 | def instr_sub_r_r_byte(self): 497 | # operand: 0x26 498 | self.instr_sub_r_r(1) 499 | 500 | def instr_sub_r_r_word(self): 501 | # operand: 0x27 502 | self.instr_sub_r_r(2) 503 | 504 | def instr_sub_r_r_dword(self): 505 | # operand: 0x28 506 | self.instr_sub_r_r(4) 507 | 508 | def instr_sub_r_r(self, size): 509 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["sub_r_r"][size] 510 | dst_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 511 | src_r_index = self.deref_bytecode(self.eip + 1, 1) >> 4 512 | self.r[dst_r_index] -= self.r[src_r_index] & self.modulus[size] 513 | self.r[dst_r_index] = self.r[dst_r_index] & self.modulus[4] 514 | self.eip += 2 515 | if self.deref_bytecode(self.eip, 1) & 0x80: 516 | self.decode_next_opcode_byte(bXorKey) 517 | print " -> sub_%d r[%d], r[%d]" % (size, dst_r_index, src_r_index) 518 | print self.dump_r() 519 | 520 | def instr_xor_r_r_byte(self): 521 | # operand: 0x29 522 | self.instr_xor_r_r(1) 523 | 524 | def instr_xor_r_r_word(self): 525 | # operand: 0x2A 526 | self.instr_xor_r_r(2) 527 | 528 | def instr_xor_r_r_dword(self): 529 | # operand: 0x2B 530 | self.instr_xor_r_r(4) 531 | 532 | def instr_xor_r_r(self, size): 533 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["xor_r_r"][size] 534 | dst_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 535 | src_r_index = self.deref_bytecode(self.eip + 1, 1) >> 4 536 | dst_value = self.r[dst_r_index] ^ (self.r[src_r_index] & self.modulus[size]) 537 | self.r[dst_r_index] = dst_value 538 | self.eip += 2 539 | if self.deref_bytecode(self.eip, 1) & 0x80: 540 | self.decode_next_opcode_byte(bXorKey) 541 | print " -> xor_%d r[%d], r[%d]" % (size, dst_r_index, src_r_index) 542 | print self.dump_r() 543 | 544 | def instr_add_r_const_byte(self): 545 | # operand: 0x2C 546 | self.instr_add_r_const(1) 547 | 548 | def instr_add_r_const_word(self): 549 | # operand: 0x2D 550 | self.instr_add_r_const(2) 551 | 552 | def instr_add_r_const_dword(self): 553 | # operand: 0x2E 554 | self.instr_add_r_const(4) 555 | 556 | def instr_add_r_const(self, size): 557 | bXorKey = self.deref_bytecode(self.eip + 2, 1) ^ self.magics["add_r_const"][size] 558 | dst_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 559 | value = self.deref_bytecode(self.eip + 2, size) 560 | self.r[dst_r_index] += value 561 | self.r[dst_r_index] = self.r[dst_r_index] & self.modulus[4] 562 | self.eip += 2 + size 563 | if self.deref_bytecode(self.eip, 1) & 0x80: 564 | self.decode_next_opcode_byte(bXorKey) 565 | print " -> add_%d r[%d], 0x%x" % (size, dst_r_index, value) 566 | print self.dump_r() 567 | 568 | def instr_sub_r_const_byte(self): 569 | # operand: 0x2F 570 | self.instr_sub_r_const(1) 571 | 572 | def instr_sub_r_const_word(self): 573 | # operand: 0x30 574 | self.instr_sub_r_const(2) 575 | 576 | def instr_sub_r_const_dword(self): 577 | # operand: 0x31 578 | self.instr_sub_r_const(4) 579 | 580 | def instr_sub_r_const(self, size): 581 | bXorKey = self.deref_bytecode(self.eip + 2, 1) ^ self.magics["sub_r_const"][size] 582 | dst_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 583 | value = self.deref_bytecode(self.eip + 2, size) 584 | self.r[dst_r_index] -= value 585 | self.r[dst_r_index] = self.r[dst_r_index] & self.modulus[4] 586 | self.eip += 2 + size 587 | if self.deref_bytecode(self.eip, 1) & 0x80: 588 | self.decode_next_opcode_byte(bXorKey) 589 | print " -> sub_%d r[%d], 0x%x" % (size, dst_r_index, value) 590 | print self.dump_r() 591 | 592 | def instr_xor_r_const_byte(self): 593 | # operand: 0x32 594 | self.instr_xor_r_const(1) 595 | 596 | def instr_xor_r_const_word(self): 597 | # operand: 0x33 598 | self.instr_xor_r_const(2) 599 | 600 | def instr_xor_r_const_dword(self): 601 | # operand: 0x34 602 | self.instr_xor_r_const(4) 603 | 604 | def instr_xor_r_const(self, size): 605 | bXorKey = self.deref_bytecode(self.eip + 2, 1) ^ self.magics["xor_r_const"][size] 606 | dst_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 607 | value = self.deref_bytecode(self.eip + 2, size) 608 | self.eip += 2 + size 609 | self.r[dst_r_index] ^= value 610 | if self.deref_bytecode(self.eip, 1) & 0x80: 611 | self.decode_next_opcode_byte(bXorKey) 612 | print " -> xor_%d r[%d], 0x%x" % (size, dst_r_index, value) 613 | print self.dump_r() 614 | 615 | def instr_stos_add_byte(self): 616 | # operand: 0x35 617 | self.instr_stos_add(1) 618 | 619 | def instr_stos_add_word(self): 620 | # operand: 0x36 621 | self.instr_stos_add(2) 622 | 623 | def instr_stos_add_dword(self): 624 | # operand: 0x37 625 | self.instr_stos_add(4) 626 | 627 | def instr_stos_add(self, size): 628 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["stos_add"][size] 629 | src_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 630 | self.eip += 2 631 | valueOffset = self.edi 632 | replacement = struct.pack(self.pack_sizes[size], (self.deref_config(valueOffset, size) + self.r[src_r_index]) & self.modulus[size]) 633 | # print self.config[valueOffset:valueOffset + 4].encode("hex") 634 | self.config = self.replace_in_buffer(self.config, valueOffset, replacement) 635 | # print self.config[valueOffset:valueOffset + 4].encode("hex") 636 | self.edi += size 637 | if self.deref_bytecode(self.eip, 1) & 0x80: 638 | self.decode_next_opcode_byte(bXorKey) 639 | print " -> add_%d stos edi, r[%d]" % (size, src_r_index) 640 | print self.dump_r() 641 | 642 | def instr_stos_sub_byte(self): 643 | # operand: 0x38 644 | self.instr_stos_sub(1) 645 | 646 | def instr_stos_sub_word(self): 647 | # operand: 0x39 648 | self.instr_stos_sub(2) 649 | 650 | def instr_stos_sub_dword(self): 651 | # operand: 0x3a 652 | self.instr_stos_sub(4) 653 | 654 | def instr_stos_sub(self, size): 655 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["stos_sub"][size] 656 | src_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 657 | valueOffset = self.edi 658 | replacement = struct.pack(self.pack_sizes[size], (self.deref_config(valueOffset, size) - self.r[src_r_index]) & self.modulus[size]) 659 | self.config = self.replace_in_buffer(self.config, valueOffset, replacement) 660 | self.eip += 2 661 | self.edi += size 662 | if self.deref_bytecode(self.eip, 1) & 0x80: 663 | self.decode_next_opcode_byte(bXorKey) 664 | print " -> sub_%d stos edi, r[%d]" % (size, src_r_index) 665 | print self.dump_r() 666 | 667 | def instr_stos_xor_byte(self): 668 | # operand: 0x3b 669 | self.instr_stos_xor(1) 670 | 671 | def instr_stos_xor_word(self): 672 | # operand: 0x3c 673 | self.instr_stos_xor(2) 674 | 675 | def instr_stos_xor_dword(self): 676 | # operand: 0x3d 677 | self.instr_stos_xor(4) 678 | 679 | def instr_stos_xor(self, size): 680 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["stos_xor"][size] 681 | src_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 682 | self.eip += 2 683 | valueOffset = self.edi 684 | replacement = struct.pack(self.pack_sizes[size], (self.deref_config(valueOffset, size) ^ self.r[src_r_index]) & self.modulus[size]) 685 | self.config = self.replace_in_buffer(self.config, valueOffset, replacement) 686 | self.edi += size 687 | if self.deref_bytecode(self.eip, 1) & 0x80: 688 | self.decode_next_opcode_byte(bXorKey) 689 | print " -> xor_%d stos edi, r[%d]" % (size, src_r_index) 690 | print self.dump_r() 691 | 692 | def instr_lods_byte(self): 693 | # operand: 0x3e 694 | self.instr_lods(1) 695 | 696 | def instr_lods_word(self): 697 | # operand: 0x3f 698 | self.instr_lods(2) 699 | 700 | def instr_lods_dword(self): 701 | # operand: 0x40 702 | self.instr_lods(4) 703 | 704 | def instr_lods(self, size): 705 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["lods"][size] 706 | dst_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 707 | dst_value = self.r[dst_r_index] & (0xFFFFFFFF - self.modulus[size]) 708 | dst_value += self.deref_config(self.edi, size) 709 | self.r[dst_r_index] = dst_value 710 | self.eip += 2 711 | if self.deref_bytecode(self.eip, 1) & 0x80: 712 | self.decode_next_opcode_byte(bXorKey) 713 | print " -> lods_%d edi, r[%d]" % (size, dst_r_index) 714 | print self.dump_r() 715 | 716 | def instr_stos_byte(self): 717 | # operand: 0x41 718 | self.instr_stos(1) 719 | 720 | def instr_stos_word(self): 721 | # operand: 0x42 722 | self.instr_stos(2) 723 | 724 | def instr_stos_dword(self): 725 | # operand: 0x43 726 | self.instr_stos(4) 727 | 728 | def instr_stos(self, size): 729 | bXorKey = self.deref_bytecode(self.eip + 1, 1) ^ self.magics["stos"][size] 730 | src_r_index = self.deref_bytecode(self.eip + 1, 1) & 0xF 731 | replacement = struct.pack(self.pack_sizes[size], (self.r[src_r_index]) & self.modulus[size]) 732 | self.config = self.replace_in_buffer(self.config, self.edi, replacement) 733 | self.eip += 2 734 | self.edi += size 735 | if self.deref_bytecode(self.eip, 1) & 0x80: 736 | self.decode_next_opcode_byte(bXorKey) 737 | print " -> stos_%d edi, r[%d]" % (size, src_r_index) 738 | print self.dump_r() 739 | 740 | def instr_leave(self): 741 | return True 742 | 743 | ################################ 744 | # utility functions 745 | ################################ 746 | 747 | def deref(self, buf, offset, size): 748 | return struct.unpack(self.pack_sizes[size], buf[offset:offset + size])[0] 749 | 750 | def deref_bytecode(self, offset, size): 751 | return self.deref(self.bytecode, offset, size) 752 | 753 | def deref_config(self, offset, size): 754 | return self.deref(self.config, offset, size) 755 | 756 | def decode_next_opcode_byte(self, key, offset=0): 757 | # decode the next opcode byte, depending on the XOR key of the function 758 | # in case of a loop function, the next opcode byte sits beyond an offset, thus the parameter 759 | self.bytecode = self.replace_in_buffer(self.bytecode, 760 | self.eip + offset, 761 | chr((self.deref_bytecode(self.eip + offset, 1) ^ key) & 0x7F) 762 | ) 763 | 764 | def replace_in_buffer(self, buf, pos, bytes): 765 | if len(buf) <= pos: 766 | raise IndexError("buffer to short to replace at position") 767 | return buf[:pos] + \ 768 | bytes + \ 769 | buf[pos + len(bytes):] 770 | 771 | 772 | if __name__ == "__main__": 773 | vm_bytecode = "1ac802960208e2e1916affb18705b70550deea058c2aa150fa055dad0e3ac005cdaad205d901ddcb081d8b060abd01cb9d8caa5e018cbefdee0100ce4bf53676c0035cbb75c4b20d4fbdf40d4ab25875c80d7dc9d3a50d1c4cbe0374c4cf0d95a523e888033d11ac0dd60ca9094af30c30d50ca44d910cce82fa0c131ff218fa09a5d9ba70c90ce84109b5e0c9fd99f40ca40bad00d894e7007ae5d5b0b900d0b0db004895e00000ddce0bdd04e7012860970167bdd604392c4894d404e293dba345271c1013cb2a7352273be735b5ecc487c7178e8263324f7d7161b9d4a87df22e0c9c81651d3c39e398db4af41aa59e6cfb8a5bb149ec940b92e5407d00e741131856d68862343e844e3f9c73ef9cc5831c2f4fffbec2ecbeeff3b2728451b1daaceb937906b8ef92e45e7b0f9fb662fd7d45720f11cac48644206661559f6ca5bdcd45af4bff1892920b6f588ae09b887cd61b01e1f01a1814bb4a958981152db53327ef6f41a89b6be426152e0998d0d1e1faab495818ad83b00ba821993f17b3f98e8d17ad7f37de4c04f2ff1ed5f892d1004ebea08b5788abb1132c97ad1a6cbce006bf5f06b43785d53cbbadb6eceef7633049fcd06414c83cf2448051490f0071a5f1f0c003929efa3082c8f5b9e723f543b69865703e733fee6f4b27cd0c7a914b648682426d591f49fc1db3326ae5874ba14310ba9c1de56a240ee6bc8c6b74b100b16693027296c0597b9628d7dec458dd1627b09f60e235d1b4189d9d67b48b47c07b0a78691dc34c12ad2324a03b6ce06fb3d9fbe74b81d4a11f35a624d0df6411acce0ef80906ccace9a40ebf1be842a50eb2a29f33a80ebe4e1338be0e054453238499e1e9b099830e9bcdba0e6e44b888ef99dd03f18f5123a493a80ea30f048a9049cfda245ab9e9915351a4df1edc08fe078008900d5934bd2d8a87d2dda687b503a50c990851f3b708a59741893950ba4d5e8fa0fb74e9ebccdbe46c48f86123e70802b4a3fc5a2d7f3771b7f90919dd5324763460366a3846626e37f8818a131e456eaac0d9fdf0784d482758909c5ffdca677e743552ad2f6456f3ecbceb3a5bc8bf91543b080c4d2b5da0f2ee34e4a97cfccf2921991e5dbcb841e978e78df70e3deb176990d4f527456d79db177c1f696b739d29811f397ef06556a978c4c62728a00dee0c93f8bfcc94ccd10d1004fe9dedcc93cce00ddfbb0c8d9c4383e10cf9c95693f90d2fac3e6dc40de009f6c90929b279ce990ac4d6f109bfd70524b201687042572daef4ad7d9ff44c38be40e011fac61ef8866c44e26548389e8b79ce0009f32fc85e3c44f8581599cad35915c8cd12d94ddbe732334cb8313796e44bed30ad7438773ed996a3aa612570da48725125c3573f8abac9685f836c8f7820c2fc1d593c79a26324df382afda4ee019d601e02c109b8f8e57dca8ef5af3d59f84fc4018c8fa659494803751a77234e6d37a1023464e4df299c3d56cfffabaeb71cf6e713b74d74967eb11bf49ff5d19e4ccb3e34cc0fe3cb17a84c7e2f5c7fc01e4a08cd20626059167f9e3d5dc2ec36fed990d711fec405869201460a971e8605333b9a013f8a55c005b7f9a0012f85a60521329f0500f3a8a6ea01a1c60104ec05b303239a3b8ace02a88d032e38e015a90290f3034c6c01018a0bb47f8a0bffe55bdf8b0349e00353703280e30ec5cefb038e424bdae60ef78fc1034b30c6b3c602bff7dbb0a70264b2c72e820b27d5ee8b025fe9a98dc903de05e5096ace058ff699b30143e0999b11fc05b9c0054ef091d105f0960586e5bd0ec27cd52d9d0e108105f440e29fbac90bfe077ee80458f4778f47b6b7bcb7cc44d80bfc2bd50b1eb20b3aa9a49ac977de003eea96b0cd04c3ea0bffa2bfd5930b8f03f5086f00cb38a303219a88bf38c5388a032b9b03efdfc88885888e03bacbc0faa003a8eedb850311870184910abd8f9933b50ac6d6d350b7a1d603329c0a3c24bf13e7aafc01b0fd099241ff8cc719d20a23c503f610e00193ec9a9809b552f1ebbaa1c209d8bd03daefe70388f73126fd8d93efefc0e984049bae33b7b18e5580898a36302451a3ac13a0c1f8c7837da666958eed920f0c5b341a540f916dd8e1bd00ca5a359ce477036ab0673c9571555316e33855d2e7e237aec35a2227c225ad56e697966b4166e4eef16a279dfbe838a499ca2bea35d2512ae006333f392e861df9470f7bb5b490c473a43a12b6fe3f46fdedb4f485fd8642367f6280794677c9cf8e205aafc78855d47928c06560e990b43c2b1a9101ece0b023f3b7bf1449de7da80e11ca0a03e270ad83c4e76269e568ef586b624e0e4d41a6a1ced08b8ec0a0fd47a0cff77add896322392f7f10f5d5781a38a3f4aea31ecd4a0c0b3b9af55273e8c9e4880ad2cfcd8d8aaab90af00fb8ad8bc1e1ff880f74c50fc4fdff8e0f10d5bec98c0f872e2e3e82ffd60e6c50d30e3f458e0e3c505801a50fc532dab182a9c63529f17e7ba2f0edb3a4ecdb7b0d86e80096ac06e4f3d1656b47a579660f1f788b2ba860fac75a97b1925938f1b2c01000d70ba0b507fde6d5bbf70408ae04a8ca8174de0b5af7531cdc4bcdb0da0067d40781d30de69904c95ae504ef0461e4d70457d3c0076e1fe604e7cb044fee140da6043095438dc607a1613e97ba00493ac204ec9100fa9e0499ae0a5567c70fae8a0a38c40f58983678ed0501b80517ee0a81b30558bb0f8b21b263f4ff8c5be1a5c80f37de0fcb346994ce548003f408db39a08f9808336cbd388b0b241089d0ff38a10306b86c288ab8f8009f5da78bc00321dab8cd0305c223689f0384f20bd13bb60b8f08b00bba0b916368199c30ef08be30b803b41301f8a8031a3acc0b840372c3b503b9e2cb0be3ecfc01e20ae01cde0138527a38d0015550cf07a9ba9273fdaac401f4f97fcc800139970180828117c8a79017e10779c3b501e3ef97fcc70300cda6e50a27dd10e211418fe7504f1353fc5cfb498b5917da8a85739ae391c8bbcfc21e8640efa9165cda326eccd26a71fc6b56c1e9b75d106f251b661e4b893fc48e41731c92bd33d9b1b0275cb5c494c5b49f65606c1ec20b930f0fac0dbb6b1541438928ad14abdf4c527e8fd70b4f08f62b7d829859f977fad3c8d492f4a90c2babd9054f96dc8aadc01df1436f92fd0e0e5104a29b8b64dfc86e0a31c7579a595cdf177078dcf282308d2cda5341acced0741ef4e4458dec56520b892272d8ca6e59f077a36382d248ed9ce8ddc1b23545adee0d8941f755aa93fb4dcdc431e0d27d600f3dfa2cf10ff90cad818c0ccb947adecc0fa6dffc890fa90191840466a2c60414f401ddb9048b58336bcd052f978615a1158e04d426b1ea08d1eb1013bc0f74cb0fce2475b8c988faffba0afa0dd188e3080586cae0850acd8c831cca0f0deb0ff954f4f6ffffe80f12edaa17e40fe34094edfb0f62fcc0afc60f97cc252cfcb094af05923432d7eaa724dc8d293ba46e205d0c1758c46d7e2939db6e677d3cf857574ee3deec824c50a8bd9783559957277ded905f4de7efb3332cc105144b67612236d7a767c24867c7e0e51da6a1beaa7b23b7e52b00659d1b8337e1ac5af08c3305038ba32d3b011a88581be90a7bd15703acb32c8d40824d3ba36cc50b539203cef55992f0100aafb380b5be30a3b2f56857e6e8f0ff01d306e4089bae2f50c2689c0621c7085aa2acb1d268d806ef7afe84f406d732df068bb588de68f406c805a00cc7d10ec8e7ee810ed63dfe05d759f40523a00727548507e0d6ca7ca905ac95cca00506238e07f0dc056e6eb5578205c8b99b61ce5ed6055a4946fcb305d302e105c588e60263d0025f78e35cd80213ee02d0ad02f98702b685020e90dd798a0206ab057301b502ec0df7dacb0d051c80d6dd0dd0acddab066446da06a68033dfcf0db867908cdc0dcad9f60af7f00574520665d659dd4877ea89e008cc6b389756be182dd3ec18ecca383a86bd3d5c60d07d3d2012feb441b40f3506be26a02be6e3aa03ee3e009b0d0f3f02a91cdf540bf0631a217080372d57e874f31ff82dabdbdc8e403047a53302b71859a5da702681ecf8640d03d9423a88a1ed9d4a33ea9f15d0dd772442bf13f2c751969f37ec8e41bc1cb1067d052dc9c1af3914e661906cdbc15c754002d6bbb94c18a0c0de86d60a9e11bbdb9db2f6e71e83df4a42e9de4bbcaa1d7927a65a0453a6fd9a595845b4a5f2f2722e28c8e87add9d24913c70eaf32e7e80484f5e90e8cce40a4d841ca0caef9e87cc41b18de5b8c68753fe9bb04e14aeadfcd935dc0100cbabb303a50d33348f0322e8b70305c226169c038b02b67ea6079508384ed707f78f025ce8e207cee4d767b522cd0f12a907f25bd222ef0f2d295922a3fa9677ef0a4c619ea0d60258397922d07ac3f289f7e602a47e9b23ac1d60d43c5ef68080f02457cbc66037b299c018c31be4c3c401b37d6fa66093b231645fef7eb495fecbb95df0e9bb0f02251869ea7df0f6f89d9e2526ef1ee74dec60749d008e80ecba892197d16569e26b742f35a88f4e018f44553ef43dfc1b5f67439417a45a496d70f224c4991e4f0c6b3a2c0b9aeca31e214e11f4bb8f4caad90cffccbd35bb466aaf59eaa95606f555764b0c92b6091c3ef82a3a5ce4e7e6da7aaedaefeb63be0d0a15eb63a63bb84fb654907c7dd817ab62aefecc0337f0d3e6b785fae417b42a858e511e5c4c62f832e9700b9b858b48a56301a05d86ecde7914840ca8bd00f06dddc6f40098a906cde3007fdac502a0319b06d783892dc906200a8fccd200ed8a02d0a80cfc94dc0059a160fd00280c4e90c800dd0fef0d7dd80f8bae386684fd820fa178947bca0fe9a9ea5303710015070eee06b8e7135f668b2bc047f048b50ebeacf4191160ff761304c800fc988e22e0c3bc5d85edd450ddaebca114f3ae1ccb92cca1989178b33e7df815e6f1266ae899dd9e0041303f49b3f85bdac8713e7373c8672182ec503a99757ac962db0d9b10d26c5247c28efb6784067698a93cfbc1830837422c6639d750beccb1765b75f4dbaa0e8efa62a0c1dd23b2790723fae500c1deffbdd84f2fdf2e7aadebb7d29e6ea0eafcba0400d9e522b09e8d7315268106158ff1354db5916a524975ee1a2ebfb8729c2940b96fc6a8d7fbc1a3791c03c6acabab4ea13bdc8720a05a2d6a6df9a829079c3a7058746487e146ff789b0aa0945b8d877effe2785e6c246f7751ebae10854d67f5aced5b802ef47c0300751dab0de930dc72234c44b9f21420f7fef5d104ad958e040f8c08ca2ad80261d204870786aa960e92027411d00e68a20972d0078baf0e48cbe0e98c0e11b85aa18f0e039fb40784e1097668df07f2dc076f22ff075a492312c807dc0cd5f10cbcc00cb55039fe80079da50c4d00c607bddc077471eb0cdb9d9b221cb4ac7c7518c71e2a1ea1a0cade6bc6a6cd03bfa759545a82316666c03614748a2c47bfb2065d4b9c237e23c597ab4d2db7688c7b0b9d3f41fa552f83c15fabbf236326c55b43bd20f11e9b29028673f1b9cd3d1dcf682a1240b01ef60a36ba113f11960b37bdb5d99e443d7c12858cc8cbaddacacb409ff25619cf3874af1c35c98fcd1461f789d04acd6250cec13572011bb9465299ca0f44f9d2d78301f00fde587cbc8ffef30fd38b737fd20ee1ae01a888e1c808be30830e09f7e1f9080eee0e42b80fc0aa0ed308e80e318e0822b296adab8ef9eeb308bc0000".decode("hex") 774 | vm_cconfig = "b1a4d432c9e0d7a5a65376312a3aa31d5c0f3d12d85d908ceabaea8138bb66f3e52407d63fd7d46f4e963aaaf99f25c59eab5240802a3872831ff4e7d51b81e1cbf463821da018f084d4474a7bd1f84dcce99a19ecbf7db1815a8bb7a8463f9c404178cf5107951af6ac2af34babc325b9243602f5e6701fd6f3f3465943b69b63698c7c80a45a28d0e1e43a2f9d22fffbbaa8e7970b216b47684b596f748f4010b7406e9365593bd106526b856e4e36103dffee93c463955d9a1732d6b11f9a9bf3a6a8322add2c43c5b4877f991365ecb3a8b6030c4664df321141200ea86ac3caa7ea41359a7184593f9dc8ccc833a06e66099b4d2acd0667d67aee229689ef56382195287ef9ec2635db14b0a4f79daf8f9322885d9db02b81aa6cd8c87ed9f50a6dd2ae5f37e5770871c1f1100ab8604c3533be403594a7f2de364447740f04a4d0cae4ae448fd60bd3d70f5cffd894814f07b050784015f560c0ad26b518895cb5f5310cdb59698e091d98971d411c0c7c8a0002da388af2211b4c6e4e223dec842ab2589c1142d2fbe76fe1b26c25e1a82ccf9b57c96fe71bc772445376c7a774f4dcfcb33cef3272c19d5c2619633a8718c745e219d986ac5090b1d0af9a063f3e80de559938051f26c05d16ab68d5826bcf2149dcf48fcd800a8e4640b559bdda924a5ce620e22d2267183fcd8ceb12d8296ea8ee094e5dee20faa34bc230dbb0cda2860282e39b662f0e94c0a317f39f6a497d58e2f60c796951213512933db8fe31125f6b896c32acf2f514930a9f209ac562e2713abd5c20ec1b99b5963a1e76fcd0e3d4e35e3f895e50a41cda56ffcf349086d270bc0684733c34e1ad96edb1b76272105d083fd62383221bc496a4b410a104ee3e95d07fc85d78e2dcbb4b7cb71875bac53be4996168744bcec430ecd8b7eb9f359c233e836400711a4c0e8f0c818fde7fa2a9d75e40aa8e28199b419ccbdb29c31bc54a5557547667cea73b73ba4c799a791f9b80f59ac0109f6695360f7bf757c759d22035cb4ec11b5f262c71a029bd18d4e11f0e5c101f2b3afecf354eea7940931e13e9dbafbb4f4da37573456eec7115a8fe3887909987a05b6aa96de6b50ee0393d49e9ddae6f27f45e35a41a7b1d9214570532ab53688b672582ffe36c778bbd59bf9c83b22d32e5d198fac241ced87a8d6631a1a58a35c19b37d93e47fd9588e3e10bbccca06ffb6af744246a037f95b85a7371395f363074455ab362511136a1e5547cc84d782d24d9284f2befe59308008408e557fcf6034d72e6d430b4780ab7ac1e404d64c9de6f".decode("hex") 775 | vm_dconfig = "96c73597606994ee41517aa32abff61d376dadfad71f1f4c2e7b2b02b71bd5a42ee14844ad8a17b11586c8ed0a000a001359675049712e0a2fc852621a6a80e1c049ac3c56d85584f5d50a9d42662df14e68f765bb04bc8d214d6f7a696c6c612f352e322028636f6d70617469626c653b204d53494520372e303b2057696e646f7773204e5420362e313b20535631290092b671be8b7381f7e1b33d8ff5213429f110fe475cbc74b3ecd2211f9b33f308fcf536e0d0abc36bd5e7756adefddd7728093730ec339c97313179b9e40e3f8e2a2a5c21f5836bf0d632a750000a00a7f77b44dc700cdd70d8abbfc90c8dde5bc45dcaca2380df4e8c9dbb0e01000083056f0d9411d09e058849db973a39392d00190022812c884da02f9a04f8f134d1fbec799ff7687474703a2f2f6c696c6963383831326173732e696e2f736f6369756d2f0049364586a50e358d4b34be3ba533d4036fae1a4d81e95419e98c1fe63da3e0d230e8fa02624544447d95baf37dab721c4f95d2de9e210117eaa19b3ddaeca989d3a5d05bc9c0c8da554110da0847e004004a6030b8a117162447a626fedeb6b45bf42f588186aa95fcc20f407f1207f3fd1d80118dbb057e8901a86a5182ef9bef5e7fc3339fd3be9aa06e55d911cd63723f9a378695223aea6309d17ddf3c85b86a286286142a9c563082010a0282010100b472d4c02e470e8031b5c604d10baa4c514f35ecb0b2b52abe6a3f36d4330f00201afc78b0077b7cbd87d1764e1c037c12be03ef01c99eac7b076f5c12f630001a88164409e6b45bfe07e23405c352dd31c4456b7ce97f1802bd9833b60dca07842598fc6c9b2b03916bde63e66d8c0fcc8659278fbc8a0178500feba3abf5c76bdbd89b0706f6303490363516cf2ee186734f962ece36aac5f8e67b1cce634ef740a2a95c360ec3dd94b78076a3b9865520ee096b11a039cac7ee4a5efd7cf17034cfe64224c4ad0329294e77b8d66d4a4839e8f0031ffa2e5124751e14bfe75371befc20f2adc378e737702a0995f9977c12e4a86bd425abc4e672cec0b3290203010001f5758c31782de003d8cd04ca2a2262d6cf1cfabd53255f4f95b102cc2817b355fa9f65a133dc32f1603c9f46d1dd20d13fa2dfabb38747006f006c00640041000000b7e8a99a95eb0597b493457191f27eff80a431cca8bd70b24f0042aa585249e2096ea21012d90d07cb194e87be22d35a6511969c351c455bdbc9a160c55f244be49ae6e6b0a3c1b36d3f0000100085db1758aaa166cb6a54b5e84093f956806fcfd63cc3783269c4216f".decode("hex") 776 | print "target from 8fbba8c234bf9fa0c05d4fe2773086a8: " 777 | print hexdump(vm_dconfig) 778 | print "Baseconfig length: 0x%x (%d) bytes\n" % (len(vm_dconfig), len(vm_dconfig)) 779 | ctx = VmContext(vm_bytecode, vm_cconfig) 780 | ctx.run() 781 | if ctx.config == vm_dconfig: 782 | print "Success!" 783 | 784 | -------------------------------------------------------------------------------- /libzpy/libs/xstream.py: -------------------------------------------------------------------------------- 1 | import StringIO 2 | import struct 3 | import string 4 | import os 5 | 6 | 7 | def glue(parts,delim='',preproc=None): 8 | if preproc: 9 | for fn in preproc: 10 | parts = map( fn , parts ) 11 | return delim.join(parts) 12 | 13 | class streamError(Exception): 14 | msg=None 15 | def __init__(self,m=None): 16 | self.msg=m 17 | def __str__(self): 18 | if self.msg: 19 | return "Error: "+self.msg 20 | else: 21 | return "Error: unknow error " 22 | 23 | def unpackEx(fmt,data,into=None): 24 | #print "Will unpackt [%s] [%s]" % (fmt,`data`) 25 | t = struct.unpack(fmt,data) 26 | if not t : 27 | return None 28 | if not into: 29 | return t 30 | if len(t) != len(into): 31 | raise streamError("readFmt into values : size mismatch [%d != %d]" % (len(into),len(t))) 32 | return dict( (into[i],t[i]) for i in range(len(into)) ) 33 | 34 | class xstream(StringIO.StringIO): 35 | 36 | def readN(self,n): 37 | d = self.read(n) 38 | if len(d) < n: 39 | raise streamError("Read error : need %d bytes, got %d " % ( n , len(d) )) 40 | return d 41 | 42 | def readFmt(self,fmt,into=None): 43 | n = struct.calcsize(fmt) 44 | d = self.readN(n) 45 | return unpackEx(fmt,d,into) 46 | 47 | # old code : 48 | t = struct.unpack(fmt,d) 49 | if not t: 50 | return None 51 | if not into: 52 | return t 53 | if len(into) != len(t): 54 | raise streamError("readFmt into values : size mismatch [%d != %d]" % (len(into),len(t))) 55 | D={} 56 | for i in range(len(into)): 57 | D[into[i]] = t[i] 58 | return D 59 | 60 | 61 | def readOne(self,fmt): 62 | d = self.readFmt(fmt) 63 | return None if d is None else d[0] 64 | 65 | def readAll(self): 66 | s = self.getLen() 67 | p = self.getPos() 68 | d = s - p 69 | return self.readN(d) 70 | 71 | 72 | def append(self,data): 73 | p = self.tell() 74 | self.seek(0, os.SEEK_END) 75 | self.write( data ) 76 | self.seek(p) 77 | 78 | def appendFmt(self,fmt,*a): 79 | return self.append(struct.pack(fmt, *a) ) 80 | 81 | def writeFmt(self,fmt,*a): 82 | return self.write( struct.pack(fmt , *a) ) 83 | 84 | def writePascalData(self,data,fmt="!H"): # lol :D 85 | self.writeFmt(fmt,len(data)) 86 | self.write(data) 87 | 88 | def readme(self): 89 | p = self.tell() 90 | self.seek(0) 91 | v = self.read() 92 | self.seep(p) 93 | return v 94 | 95 | def dump(self): 96 | return self.getvalue() 97 | 98 | def getLen(self): 99 | org = self.tell() 100 | self.seek(0, os.SEEK_END) 101 | end = self.tell() 102 | self.seek(org) 103 | return end 104 | 105 | def getPos(self): 106 | return self.tell() 107 | 108 | def availableLen(self): 109 | return self.getLen() - self.getPos() 110 | 111 | def printStatus(self): 112 | print " Len: %d Pos: %d " % ( self.getLen() , self.getPos() ) 113 | 114 | def hexDump(self,inRow=16,title=None,head=True): 115 | S = ' \n' 116 | if head: 117 | if title: 118 | S += " .----[ %s ]----- \n" % title 119 | S += "| offset ascii hex \n" 120 | p = self.tell() # save 121 | self.seek(0) # rewind 122 | fmt = "| 0x%08X %-"+str(inRow)+"s \t %s\n" 123 | while True: 124 | of = self.tell() 125 | chunk = self.read(inRow) 126 | hx = '' 127 | ch = '' 128 | for c in list(chunk): 129 | ch+= c if ord(c)>=32 and ord(c)<127 else '.' 130 | hx += "%02X " % ord(c) 131 | S += fmt % (of,ch,hx) 132 | if len(chunk) < inRow: 133 | break 134 | S+= "| 0x%08X \n" % self.tell() 135 | S+= "`-- \n" 136 | self.seek(p) 137 | return S 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /libzpy/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mak/libzpy/a0a10a091700bf8dcab96fa7ff720db9ea94f819/libzpy/modules/__init__.py -------------------------------------------------------------------------------- /libzpy/modules/chthonic.py: -------------------------------------------------------------------------------- 1 | from Crypto.Cipher import AES 2 | import libzpy.structs.chthonic as cht 3 | import libzpy.fmt.zeus as zeusfmt 4 | from libzpy.libs.basecfg import BaseCfg 5 | from libzpy.libs.vmzeus import VmContext as VM 6 | from libzpy.modules import template as t 7 | from libzpy.modules import zeus as zeus 8 | import mlib.crypto as mc 9 | import json 10 | import re 11 | import sys 12 | import StringIO 13 | import hashlib 14 | import struct 15 | import os 16 | import libzpy.structs.chthonic as chtstruct 17 | 18 | AES_BLOCK_SIZE = 16 19 | 20 | def aes_pad(s): 21 | return s + (AES_BLOCK_SIZE - len(s) % AES_BLOCK_SIZE) * chr(AES_BLOCK_SIZE - len(s) % AES_BLOCK_SIZE) 22 | 23 | def aes_decrypt(data, key): 24 | aes = AES.new(key, AES.MODE_ECB) 25 | data = aes.decrypt(data) 26 | data = mc.visDecry(data) 27 | return data 28 | 29 | def aes_encrypt(data, key): 30 | data = mc.visEncry(data) 31 | aes = AES.new(key, AES.MODE_ECB) 32 | data = aes.encrypt(aes_pad(data)) 33 | return data 34 | 35 | def unpack(data, verb, key): 36 | if key is not None: 37 | data = aes_decrypt(data, key) 38 | 39 | data = t.unpack(data, verb, chtstruct) 40 | 41 | result = [] 42 | items = data["items"] 43 | 44 | for item in items: 45 | if item.id == item._cfgids['CFGID_OUTER_PAYLOAD'] and not item.data.startswith("MZ"): 46 | try: 47 | nested = unpack(item.data, verb, key) 48 | result += nested["items"] 49 | except ValueError: 50 | nested = unpack(item.data, verb, None) 51 | result += nested["items"] 52 | 53 | elif item.id == item._cfgids['CFGID_PAYLOAD'] and item.flags & item._flags['ITEMF_IS_PACKED_CONFIG']: 54 | nested = unpack(item.data, verb, None) 55 | result += nested["items"] 56 | elif item.id == item._cfgids['CFGID_INJECTS']: 57 | nested = unpack(item.data, verb, None) 58 | result += nested["items"] 59 | else: 60 | result.append(item) 61 | 62 | data['items'] = result 63 | 64 | return data 65 | 66 | def pack(data, verb, aes_key): 67 | packet = zeus.pack(data, verb) 68 | packet = aes_encrypt(packet, aes_key) 69 | 70 | return packet 71 | 72 | def parse(data, verb): 73 | ret = t.parse(data, verb, cht) 74 | 75 | for i in data['items']: 76 | if i.data.startswith("MZ"): 77 | ret['PE'] = i.data 78 | return ret 79 | 80 | 81 | def to_str(data, verb): 82 | if not isinstance(data, dict): 83 | verb('I need unpacked data') 84 | return 85 | 86 | fmt = zeusfmt.fmt(data) 87 | fmt._ = 'Cthonic' 88 | return fmt.format() 89 | 90 | def format(data, verb, type='pretty'): 91 | if type == 'pretty': 92 | return to_str(data, verb) 93 | elif type == 'json': 94 | return json.dumps(data) 95 | 96 | def go(data, verb, aeskey): 97 | if not data: 98 | return "" 99 | if len(data) % 16 != 0: 100 | return "" 101 | 102 | data = unpack(data, verb, aeskey) 103 | data = parse(data, verb) 104 | return data 105 | 106 | def get_basecfg(data,verb,*args): 107 | oldstdout = sys.stdout 108 | sys.stdout = StringIO.StringIO() 109 | cfg = None 110 | try: 111 | vmctx = VM(data['code'].decode('hex'),data['data'].decode('hex')) 112 | vmctx._fix_xors(data['magic']) 113 | vmctx.run() 114 | cfg = vmctx.config 115 | 116 | except Exception as e: 117 | import traceback 118 | sys.stdout = oldstdout 119 | print 'VMError: ' + `e` 120 | traceback.print_exc(file=sys.stdout) 121 | 122 | sys.stdout = oldstdout 123 | if not cfg: 124 | print 'Code hash: ' + hashlib.md5(data['code'].decode('hex')).hexdigest() 125 | print 'Data hash: ' + hashlib.md5(data['data'].decode('hex')).hexdigest() 126 | print 'Xors: ' + str(data['magic']) 127 | return cfg 128 | 129 | class ChthonicCfg(BaseCfg): 130 | def __init__(self, cfg): 131 | super(ChthonicCfg, self).__init__(cfg) 132 | self.rc4sbox = 'huh' 133 | 134 | def get_ua(self): 135 | self.ua = re.search("(Moz[^\x00]+)\x00", self.cfg).group(1) 136 | return self.ua 137 | 138 | def get_basics(self): 139 | st = super(ChthonicCfg, self).get_basics() 140 | st['user-agent'] = self.get_ua() 141 | st['aes-key'] = self.aeskey 142 | del st['rc4sbox'] 143 | return st 144 | 145 | def set_aes(self, aeskey): 146 | self.aeskey = aeskey 147 | 148 | def parse_basecfg(basecfg, _args): 149 | cfg = ChthonicCfg(basecfg) 150 | cfg.set_aes(_args['aes-key']) 151 | return cfg.get_basics() 152 | -------------------------------------------------------------------------------- /libzpy/modules/citadel.py: -------------------------------------------------------------------------------- 1 | import json 2 | from hashlib import md5 3 | from struct import unpack,pack 4 | 5 | import libzpy.fmt.citadel as cfmt 6 | import libzpy.structs.citadel as zeus 7 | from libzpy.libs.basecfg import BaseCfg 8 | 9 | import libzpy.libs.cr_tools as cry 10 | from libzpy.modules import template as t 11 | 12 | 13 | class CitaCfg(BaseCfg): 14 | def __init__(self,cfg,lk): 15 | self.lk = lk 16 | self.cfg = cfg 17 | self.rc4sbox = None 18 | 19 | def rc4(self,d,k): 20 | return cry.rc4decrypt(d,k,self.lk) 21 | 22 | def get_rc4(self,off): 23 | self.rc4sbox = self.cfg[off:off+0x102] 24 | 25 | def unpack(data,verb): 26 | return t.unpack(data,verb,zeus) 27 | 28 | def parse(data,verb): 29 | data = t.parse(data,verb,zeus) 30 | #print `data` 31 | for id in range(20009,20021) + range(20101,20204): 32 | if id in data and id == 20009: 33 | d = t.string_list(data[id].data) 34 | data['dns_filter'] =d 35 | del data[id] 36 | 37 | elif id in data and id == 20010: 38 | d = t.string_list(data[id].data) 39 | data['cmds'] =d 40 | del data[id] 41 | elif id in data and id == 20011: 42 | pass 43 | 44 | elif id in data and id == 20012: 45 | pass 46 | elif id in data and id == 20013: 47 | pass 48 | elif id in data and id == 20014: 49 | pass 50 | 51 | elif id in data and id == 20015: 52 | d = data[id].data.strip("\x00") 53 | data['keyloger'] = d 54 | del data[id] 55 | 56 | elif id in data and id == 20016: 57 | d = unpack('I',data[id].data) 58 | data['keyloger_time'] = d 59 | del data[id] 60 | 61 | elif id in data and id == 20017: 62 | pass 63 | 64 | elif id in data and id == 20018: 65 | d = data[id].data.strip("\x00") 66 | data['webinj_url'] = d 67 | del data[id] 68 | 69 | elif id in data and id == 20019: 70 | pass 71 | 72 | elif id in data and id == 20020: 73 | d = t.string_list(data[id].data) 74 | d['httpvip'] = d 75 | del data[id] 76 | 77 | elif id in data and id == 20101: 78 | d = unpack('I',data[id].data) 79 | data['video_length'] = d 80 | del data[id] 81 | 82 | elif id in data and id == 20102: 83 | d = unpack('I',data[id].data) 84 | data['video_qual' ] =d 85 | del data[id] 86 | 87 | return data 88 | 89 | 90 | def to_str(data,verb): 91 | if not isinstance(data,dict): 92 | verb('I need unpacked data') 93 | return 94 | 95 | fmt = cfmt.fmt(data) 96 | fmt._name = 'Citadel' 97 | return fmt.format() + '\n\nUNKNOWN_DATA:\n\n' + '\n'.join(data['unknown']) 98 | 99 | 100 | def json(data): 101 | verb=lambda x:x 102 | data = unpack(data,verb) 103 | data = parse(data,verb) 104 | 105 | return data 106 | 107 | 108 | def go(data,verb): 109 | data = unpack(data,verb) 110 | data = parse(data,verb) 111 | 112 | return to_str(data,verb) 113 | 114 | 115 | def format(data,verb,type='pretty'): 116 | if type == 'pretty': 117 | return to_str(data,verb) 118 | elif type == 'json': 119 | return json.dumps(data) 120 | 121 | 122 | def rc4_init_cit(key, magicKey): 123 | """ Initialize the RC4 keystate """ 124 | 125 | hash = [] 126 | box = [] 127 | keyLength = len(key) 128 | if type(magicKey) == int: 129 | magicKey = pack('I',magicKey) 130 | magicKeyLen = len(magicKey) 131 | 132 | for i in range(0, 256): 133 | hash.append(ord(key[i % keyLength])) 134 | box.append(i) 135 | 136 | y = 0 137 | for i in range(0, 256): 138 | y = (y + box[i] + hash[i]) % 256 139 | tmp = box[i] 140 | box[i] = box[y] 141 | box[y] = tmp; 142 | 143 | y= 0 144 | for i in range(0, 256): 145 | magicKeyPart1 = ord(magicKey[y]) & 0x07; 146 | magicKeyPart2 = ord(magicKey[y]) >> 0x03; 147 | y += 1 148 | if (y == magicKeyLen): 149 | y = 0 150 | 151 | if (magicKeyPart1 == 0): 152 | box[i] = ~box[i] 153 | elif (magicKeyPart1 == 1): 154 | box[i] ^= magicKeyPart2 155 | elif (magicKeyPart1 == 2): 156 | box[i] += magicKeyPart2 157 | elif (magicKeyPart1 == 3): 158 | box[i] -= magicKeyPart2 159 | elif (magicKeyPart1 == 4): 160 | box[i] = box[i] >> (magicKeyPart2 % 8) | (box[i] << (8 - (magicKeyPart2 % 8))) 161 | elif (magicKeyPart1 == 5): 162 | box[i] = box[i] << (magicKeyPart2 % 8) | (box[i] >> (8 - (magicKeyPart2 % 8))) 163 | elif (magicKeyPart1 == 6): 164 | box[i] += 1 165 | elif (magicKeyPart1 == 7): 166 | box[i] -= 1 167 | 168 | box[i] = box[i] & 0xff 169 | 170 | return ''.join([chr(c) for c in box]) 171 | 172 | 173 | 174 | 175 | def parse_basecfg(basecfg,args): 176 | login_key = args['lk'] 177 | salt = args['s'] 178 | off = args['off'] 179 | bc = CitaCfg(basecfg,login_key) 180 | bc.get_rc4(off) 181 | st = bc.get_basics() 182 | aes = bc.rc4(md5(login_key).digest(),bc.rc4sbox) 183 | 184 | comm = rc4_init_cit(aes,salt) 185 | 186 | st['aes-key'] = aes.encode('hex') 187 | st['rc4cfg'] = bc.rc4sbox.encode('hex') 188 | st['rc4sbox'] = (comm+"\x00\x00").encode('hex') 189 | st['login_key'] = login_key 190 | st['cfg'] = st['urls'][0] 191 | if 'aes_xor' in args: 192 | st['aes_xor'] = args['aes_xor'] 193 | 194 | return st 195 | 196 | 197 | ## we allready decode basecfg 198 | def get_basecfg(d,*args): 199 | return d.decode('hex') 200 | 201 | -------------------------------------------------------------------------------- /libzpy/modules/conf.py: -------------------------------------------------------------------------------- 1 | import libzpy.structs.zeus as z 2 | 3 | 4 | def pesettings(data,verb,type): 5 | p = z.PESettings(data) 6 | p._sep = "\n" 7 | print str(p) 8 | return p 9 | 10 | def get_pesettings_size(type,verb): 11 | return 0x1e6 12 | 13 | def pesettings_key(data,verb): 14 | p = z.PESettings(data) 15 | p._sep = "\n" 16 | print p.RC4KEY 17 | -------------------------------------------------------------------------------- /libzpy/modules/flokibot.py: -------------------------------------------------------------------------------- 1 | import libzpy.structs.zeus as zeus 2 | import libzpy.fmt.zeus as zfmt 3 | from libzpy.modules import template as t 4 | 5 | from libzpy.libs.basecfg import BaseCfg 6 | import json 7 | 8 | 9 | def unpack(data,verb,verify=False): 10 | return t.unpack(data,verb,zeus,verify) 11 | 12 | 13 | def parse(data,verb): 14 | return t.parse(data,verb,zeus) 15 | 16 | 17 | def to_str(data,verb): 18 | if not isinstance(data,dict): 19 | verb('I need unpacked data') 20 | return 21 | 22 | fmt = zfmt.fmt(data) 23 | fmt._ = 'flokibot' 24 | return fmt.format() 25 | 26 | 27 | def json(data): 28 | verb=lambda x:x 29 | data = unpack(data,verb,True) 30 | data = parse(data,verb) 31 | return data 32 | 33 | 34 | def go(data,verb): 35 | data = unpack(data,verb) 36 | data = parse(data,verb) 37 | print to_str(data,verb) 38 | 39 | 40 | def format(data,verb,type='pretty'): 41 | if type == 'pretty': 42 | return to_str(data,verb) 43 | elif type == 'json': 44 | return json.dumps(data) 45 | 46 | 47 | def parse_basecfg(basecfg,args): 48 | bc = BaseCfg(basecfg) 49 | bc.get_rc4(581) 50 | res = bc.get_basics() 51 | return res 52 | 53 | 54 | def get_basecfg(d,*args): 55 | return d.decode('hex') 56 | -------------------------------------------------------------------------------- /libzpy/modules/kins.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys,StringIO,re 3 | import libzpy.structs.kins as k 4 | import libzpy.fmt.powerzeus as pzfmt 5 | from libzpy.modules import template as t 6 | from libzpy.libs.vmzeus import VmContext as VM 7 | from libzpy.libs.basecfg import BaseCfg 8 | from ctypes import sizeof 9 | from struct import * 10 | from hashlib import md5 11 | from pprint import pprint 12 | 13 | 14 | class KinsCfg(BaseCfg): 15 | def get_rc4(self): 16 | self.rc4sbox = 'placeholder' 17 | 18 | def get_aes(self,off): 19 | self.get_rc4() 20 | self.aes = self.cfg[off:off+16] 21 | return self.aes 22 | 23 | def get_ua(self): 24 | self.ua = re.search("(Moz[^\x00]+)\x00",self.cfg).group(1) 25 | return self.ua 26 | 27 | def get_basics(self): 28 | st = super(KinsCfg,self).get_basics() 29 | del st['rc4sbox'] 30 | st['aes-key']= self.aes.encode('hex') 31 | st['user-agent']=self.get_ua() 32 | return st 33 | 34 | 35 | 36 | def unpack(data,verb): 37 | return t.unpack(data,verb,k) 38 | def parse(data,verb): 39 | return t.parse(data,verb,k) 40 | 41 | def to_str(data,verb): 42 | if not isinstance(data,dict): 43 | verb('I need unpacked data') 44 | return 45 | 46 | fmt = pzfmt.fmt(data) 47 | fmt._name = 'KiNS' 48 | return fmt.format() 49 | 50 | def go(data,verb): 51 | data = unpack(data,verb) 52 | data = parse(data,verb) 53 | #print `data['injects']` 54 | r = to_str(data,verb) 55 | #print r 56 | return r 57 | 58 | 59 | def get_basecfg(data,verb,*args): 60 | oldstdout = sys.stdout 61 | #fd = open('/tmp/out','w') 62 | # print 'Code hash: ' + md5(data['code'].decode('hex')).hexdigest() 63 | # print 'Data hash: ' + md5(data['data'].decode('hex')).hexdigest() 64 | sys.stdout = StringIO.StringIO() 65 | cfg = None 66 | try: 67 | vmctx = VM(data['code'].decode('hex'),data['data'].decode('hex')) 68 | vmctx._fix_xors(data['magic']) 69 | vmctx.run() 70 | cfg = vmctx.config 71 | 72 | except Exception as e: 73 | import traceback 74 | sys.stdout = oldstdout 75 | print 'VMError: ' + `e` 76 | traceback.print_exc(file=sys.stdout) 77 | 78 | sys.stdout = oldstdout 79 | # fd.close() 80 | if not cfg: 81 | print 'Code hash: ' + md5(data['code'].decode('hex')).hexdigest() 82 | print 'Data hash: ' + md5(data['data'].decode('hex')).hexdigest() 83 | print 'Xors: ' + str(data['magic']) 84 | return cfg 85 | 86 | 87 | 88 | 89 | 90 | def parse_basecfg(basecfg,_args): #key,off,verb): 91 | 92 | # print `basecfg` 93 | off=_args['off'] 94 | cfg = KinsCfg(basecfg) 95 | cfg.get_aes(off) 96 | return cfg.get_basics() 97 | -------------------------------------------------------------------------------- /libzpy/modules/misc.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | def dumper(data,verb,byId='-1',mask=0,outfile=None): 5 | if not outfile: 6 | raise Exception("dumper: need outfile !") 7 | 8 | verb("Dumping items : %s " % byId ) 9 | itemsId = map( int , byId.split(',') ) 10 | 11 | for item in data['items']: 12 | if item['recId'] in itemsId : 13 | verb("Found record id=%d " % item['recId']) 14 | with open(outfile,'wb') as f: 15 | f.write(item['data']) 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /libzpy/modules/mmbb.py: -------------------------------------------------------------------------------- 1 | 2 | import libzpy.structs.zeus as zeus 3 | import libzpy.fmt.zeus as zfmt 4 | from libzpy.modules import template as t 5 | 6 | from StringIO import StringIO 7 | from ctypes import sizeof 8 | from libzpy.libs.basecfg import BaseCfg 9 | import json 10 | 11 | 12 | class mmbbCfb(BaseCfg): 13 | 14 | def get_rc4(self,off): 15 | #(4,10,0) 16 | o=self.cfg.find('\x04\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00') 17 | self.aesKey = self.cfg[o+4+off:o+4+off+0x10] 18 | self.rc4sbox = self.cfg[o:] 19 | return self.rc4sbox 20 | 21 | def get_basics(self): 22 | st=super(mmbbCfb,self).get_basics() 23 | st['aes-key'] = self.aesKey.encode('hex') 24 | return st 25 | 26 | def unpack(data,verb,verify=False): 27 | return t.unpack(data,verb,zeus,verify) 28 | 29 | def parse(data,verb): 30 | return t.parse(data,verb,zeus) 31 | 32 | def to_str(data,verb): 33 | if not isinstance(data,dict): 34 | verb('I need unpacked data') 35 | return 36 | 37 | fmt = zfmt.fmt(data) 38 | fmt._ = 'PowerZeus' 39 | return fmt.format() 40 | 41 | 42 | def json(data): 43 | verb=lambda x:x 44 | data = unpack(data,verb,True) 45 | data = parse(data,verb) 46 | return data 47 | 48 | def go(data,verb): 49 | data = unpack(data,verb) 50 | data = parse(data,verb) 51 | #print `data['injects']` 52 | print to_str(data,verb) 53 | 54 | 55 | def format(data,verb,type='pretty'): 56 | if type == 'pretty': 57 | return to_str(data,verb) 58 | elif type == 'json': 59 | return json.dumps(data) 60 | 61 | 62 | def parse_basecfg(basecfg,args): 63 | 64 | off = args['aoff']# 65 | bc = mmbbCfb(basecfg) 66 | bc.get_rc4(off) 67 | return bc.get_basics() 68 | 69 | 70 | ## we allready decode basecfg 71 | def get_basecfg(d,*args): 72 | # print d 73 | return d.decode('hex') 74 | -------------------------------------------------------------------------------- /libzpy/modules/p2p.py: -------------------------------------------------------------------------------- 1 | """Zeus-P2P binstorage parser """ 2 | """ 3 | import os 4 | import sys 5 | import struct 6 | import md5 7 | import zlib 8 | 9 | import json 10 | 11 | from libzpy.libs.storage import storageException 12 | 13 | from libzpy.libs.xstream import xstream 14 | from libzpy.libs import fmt 15 | from libzpy.libs import cr_tools 16 | from libzpy.libs import binPCRE 17 | 18 | #from _local.tmp import zBinStorage 19 | class zBinStorage(object): 20 | pass 21 | 22 | 23 | #from parsers import * 24 | #from libs.cr_tools import xorWithKey 25 | #import libs.binPCRE 26 | #from libs import fmt 27 | 28 | STORAGE_HEADER_SIZE = 48 # 20 + 3*4 + 16 29 | ITEM_HEADER_SIZE = 16 # 4*4 30 | 31 | FLG_ITEM_PACKED = 0x00000001 32 | FLG_ITEM_WEBINJECT = 0x40000000 33 | FLG_ITEM_CONFIG = 0x10000000 34 | 35 | 36 | def decode(): 37 | pass 38 | 39 | def _p2p_inflate(data): 40 | dc = zlib.decompressobj(-15) 41 | d = dc.decompress(data) 42 | return d 43 | 44 | 45 | 46 | 47 | def unpack(data,verb,checkMD5=False,calcMD5=True,showInfo=False): 48 | size = len(data) 49 | if size < STORAGE_HEADER_SIZE + ITEM_HEADER_SIZE : 50 | raise storageException("Not enoungh data (<48) !") 51 | 52 | xs = xstream(data) 53 | RET = dict( head=dict() , items=[] ) 54 | H = xs.readFmt("=20s I I I 16s ",into=('padding','size','unk1','version','md5') ) 55 | H['padding'] = fmt.s2hex(H['padding']) 56 | H['md5'] = fmt.s2hex(H['md5']) 57 | dif = size-H['size'] 58 | if dif < 0: 59 | raise storageException("Data size missmatch ! (%d<->%d) " % (H['size'],size) ) 60 | if dif > 0: 61 | verb( "[Warning] too much data , will truncate (lost %d bytes)" % dif ) 62 | xs.truncate(size - dif ) 63 | 64 | RET['head'] = H 65 | 66 | if checkMD5 or calcMD5: 67 | tmp = xs.getPos() 68 | realMD5 = md5.new( xs.read() ).hexdigest() 69 | xs.seek(tmp) 70 | RET['head']['realMD5'] = realMD5 71 | 72 | if checkMD5: 73 | if RET['head']['md5'] != RET['head']['realMD5'] : 74 | raise storageException("Bad MD5 sum ! [ %s <-> %s ]" % (RET['head']['md5'] , RET['head']['realMD5']) ) 75 | else: 76 | verb("MD5 is OK !") 77 | 78 | version = H['version'] 79 | 80 | while xs.availableLen() > ITEM_HEADER_SIZE : 81 | ih = xs.readFmt("=IIII",into=("recId","recFlag","recSize","realSize")) 82 | verb(`ih`) 83 | key = 0xFFFFFFFF & ( ( 0x0000FFFF & ih['recId'] ) | ( ih['recSize'] << 0x10 ) | ( RET['head']['version'] << 8 ) ) 84 | #print "KEY : %08X " % key 85 | binKey = struct.pack("=I",key) 86 | ic = xs.readN( ih['recSize'] ) 87 | #print `ic` 88 | # decode item 89 | ic = cr_tools.xorWithKey(ic, binKey) 90 | #print `ic` 91 | # unpack 92 | if ih['recFlag'] & FLG_ITEM_PACKED : 93 | ic = _p2p_inflate(ic) 94 | #print `ic` 95 | ih['data'] = ic 96 | RET['items'].append(ih) 97 | 98 | if showInfo: 99 | print RET['head'] 100 | print "Recods : %d " % len(RET['items']) 101 | 102 | return RET 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | class format: 114 | def __init__(self,data,verb,to='json'): 115 | self.verb = verb 116 | for item in data['items']: 117 | item['data'],item['desc'] = self.processItem(item) 118 | if to == 'json': 119 | print json.dumps(data) 120 | 121 | 122 | def processItem(self,i): 123 | F = i['recFlag'] 124 | N = i['recId'] 125 | if F & FLG_ITEM_WEBINJECT: 126 | return self.fmtWebinject(i) 127 | if F & FLG_ITEM_CONFIG: 128 | fn = "config_rec_%d" % N 129 | func = getattr(self,fn) 130 | return func(i) 131 | ## other 132 | return None 133 | 134 | def fmtWebinject(self,i): 135 | data = i['data'] 136 | xs = xstream(data) 137 | PARTS = [] 138 | while xs.availableLen() > 4: 139 | el = xs.readFmt("=IH",into=("size","flag")) 140 | tmp = xs.readN( el['size'] - 6 ) 141 | if tmp[:4] == 'ERCP': 142 | tmp = `binPCRE.readBinary(tmp)` 143 | el['data'] = tmp 144 | PARTS.append(tmp) 145 | return PARTS,"webinject" 146 | 147 | def config_rec_22003(self,i): 148 | l = fmt.NullTermStringList(i['data']) 149 | return l,"Webfilters" 150 | 151 | def config_rec_22004(self,i): 152 | l = fmt.NullTermStringList(i['data']) 153 | return l,"list2" 154 | 155 | def config_rec_22002(self,i): 156 | t = self.rec_22002(i['data']) 157 | return t,'webinject-table' 158 | 159 | 160 | def rec_22002(self,data): 161 | r = [] 162 | xs = xstream( data ) 163 | i=1 164 | while xs.availableLen()>4: 165 | wi = xs.readFmt("=IHH",into=("len","flag","id")) 166 | wi['len'] -= 4 + 2 + 2 167 | entry = xstream( xs.readN(wi['len']) ) 168 | 169 | params='' 170 | for k in wi: params += ' %s=%04X|%d ' % (k,wi[k],wi[k]) 171 | 172 | cond=[] 173 | while entry.availableLen()>4: 174 | cond = entry.readFmt("=III",into=("len","flag1","flag2")) 175 | cond['len'] -= 4*3 176 | cont = entry.readN( cond['len'] ) 177 | if cont[:4] == "ERCP": 178 | cont = `binPCRE.readBinary(cont)` 179 | params = '' 180 | for k in cond: params += ' %s=%04X|%d ' % (k,cond[k],cond[k]) 181 | cond['text'] = cont 182 | 183 | wi['conditions'] = cond 184 | r.append(wi) 185 | i+=1 186 | return r 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | class storage(zBinStorage): 197 | def __init__(self): 198 | zBinStorage.__init__(self) 199 | self.outbuf = '' 200 | 201 | 202 | def parseNullTermStringList(self,data): 203 | r = data.split(chr(0)) 204 | for i in range(len(r)): 205 | self.out( " [%d] %s \n" % (i,r[i]) ) 206 | return r 207 | 208 | def readPCRE(self,data): 209 | txt = libs.binPCRE.readBinary(data) 210 | return txt 211 | 212 | def rec_webinject(self,data): 213 | size = len(data) 214 | xs = xstream(data) 215 | PARTS=[] 216 | while xs.availableLen() > 4: 217 | 218 | entrySize,entryFlag = xs.readFmt("=IH") 219 | entrySize -= 4 + 2 220 | 221 | entryData = xs.readN(entrySize) 222 | self.out( " <<--- DATA : %d | FLAG : %04X --->>\n" % ( entrySize , entryFlag ) ) 223 | 224 | if entryData[:4]=='ERCP': 225 | entryData = self.readPCRE(entryData) 226 | 227 | self.out( `entryData`+"\n" ) 228 | 229 | self.out( " <<--- /DATA --->>\n" ) 230 | WI=dict(size=entrySize,flag=entryFlag,data=entryData) 231 | PARTS.append(WI) 232 | return PARTS 233 | 234 | def rec_22003(self,data): 235 | self.out( " \n" ) 236 | r = self.parseNullTermStringList(data) 237 | self.out( " \n" ) 238 | return r 239 | 240 | 241 | 242 | def rec_22004(self,data): 243 | self.out( " \n" ) 244 | r = self.parseNullTermStringList(data) 245 | self.out( " \n" ) 246 | return r 247 | 248 | def rec_22001(self,data): 249 | self.out(" \n") 250 | xs = xstream(data) 251 | #self.out(xs.hexDump()) 252 | r=[] 253 | of = 0 254 | while xs.availableLen()>12: 255 | e = xs.readFmt("=IIH",into=("len","nul1","flag1") ) ;of+=10 256 | e['sub']=[] 257 | self.out(" \n" %(e['len'], e['nul1'], e['flag1'])) 258 | 259 | toRead = e['len'] - 10; 260 | nRead = 0 261 | while nRead < toRead: 262 | sub = xs.readFmt("=IBBBB",into=("size","f1","f2","f3","f4")) ;of+=8; nRead+=8; 263 | sub['content']='' 264 | if sub['size']>0: 265 | data = xs.readN(sub['size']-8) ; of+=sub['size']-8; nRead+=sub['size']-8; 266 | cont = self.readPCRE(data) 267 | sub['content'] = cont 268 | self.out(" %s\n" % (sub['size'],sub['f1'],sub['f2'],sub['f3'],sub['f4'],sub['content'])) 269 | e['sub'].append(sub) 270 | r.append(e) 271 | self.out(" \n\n") 272 | self.out(" \n") 273 | return r 274 | 275 | def rec_22002(self,data): 276 | self.out( " \n" ) 277 | r = [] 278 | xs = xstream( data ) 279 | i=1 280 | while xs.availableLen()>4: 281 | wi = xs.readFmt("=IHH",into=("len","flag","id")) 282 | wi['len'] -= 4 + 2 + 2 283 | entry = xstream( xs.readN(wi['len']) ) 284 | 285 | params='' 286 | for k in wi: params += ' %s=%04X|%d ' % (k,wi[k],wi[k]) 287 | self.out( " \n" % ( i,params) ) 288 | 289 | cond=[] 290 | while entry.availableLen()>4: 291 | cond = entry.readFmt("=III",into=("len","flag1","flag2")) 292 | cond['len'] -= 4*3 293 | cont = entry.readN( cond['len'] ) 294 | if cont[:4] == "ERCP": 295 | cont = self.readPCRE(cont) 296 | params = '' 297 | for k in cond: params += ' %s=%04X|%d ' % (k,cond[k],cond[k]) 298 | self.out(" %s \n" % (params,cont) ) 299 | cond['text'] = cont 300 | 301 | self.out( " \n") 302 | wi['conditions'] = cond 303 | r.append(wi) 304 | i+=1 305 | self.out( " \n" ) 306 | return r 307 | 308 | 309 | def formatRecord(self,RH,data): 310 | rid = RH['recId'] 311 | rflg = RH['recFlag'] 312 | 313 | if rflg & 0x40000000: 314 | fname = "rec_webinject" 315 | else : 316 | fname = "rec_%d" % rid 317 | 318 | if hasattr(self,fname): 319 | func = getattr(self,fname) 320 | fmt=func(data) 321 | return fmt 322 | else : 323 | self.out("< -- NOT IMPLEMENTED ID %d -- >\n" % rid ) 324 | txt = xstream(data).hexDump() ## make nice hexdump :) 325 | self.out(txt) 326 | return txt 327 | 328 | 329 | 330 | 331 | def inflate(self,data,dstSize=0): 332 | dc = zlib.decompressobj(-15) 333 | d = dc.decompress(data) 334 | return d 335 | 336 | def unpack_head(self,data): 337 | 338 | if len(data) < 48: 339 | raise storageException("Need more data (1)") 340 | 341 | xs = xstream(data) 342 | st = xs.readFmt("=20s I I I 16s ",into=('padding','size','cnt1','cnt2','md5') ) 343 | st['padding'] = fmt.s2hex(st['padding']) 344 | st['md5'] = fmt.s2hex(st['md5']) 345 | # convert datetime !? 346 | 347 | self.out("\n junk\t: %s\n size\t: %d\n cnt1\t: %d\n cnt2\t: %d\n MD5\t: %s\n\n\n" % ( st['padding'] ,st['size'],st['cnt1'],st['cnt2'], st['md5'] ) ) 348 | 349 | content = xs.read() 350 | dif = len(content) - ( st['size'] - 48 ) # size of binstorage head 351 | if dif <0 : 352 | raise storageException("Need more data (2)") 353 | if dif > 0: 354 | self.verb("Got spare bytes :%d , truncate !" % dif) 355 | content = content[:-dif] 356 | 357 | m5s = md5.new(content).hexdigest() 358 | st['real-md5'] = m5s 359 | self.out(" %s \n\n" % m5s ) 360 | 361 | return st,content 362 | 363 | 364 | def unpack_recs(self,st,data): 365 | RECS = [] 366 | version = st['cnt2'] # filed 367 | 368 | xs = xstream(data) 369 | while xs.availableLen()>16: 370 | RH = xs.readFmt("=IIII",into=("recId","recFlag","recSize","realSize")) 371 | try: 372 | RD = xs.readN( RH['recSize'] ) 373 | except : 374 | raise storageException("Fail to read record ... corupted data ?") 375 | 376 | self.out( "\n" % ( RH['recId'],RH['recId'],RH['recFlag'],RH['recSize'],RH['realSize']) ) 377 | 378 | rec_key = 0xFFFFFFFF & ( ( 0x0000FFFF & RH['recId']) | ( RH['recSize'] << 0x10 ) | ( version << 8 ) ) 379 | rec_bin = struct.pack("I",rec_key) 380 | self.out( "%08X+%08X+%08X => %08X\n" % (RH['recId'],RH['recSize'],version,rec_key) ) 381 | RD = cr_tools.xorWithKey(RD, rec_bin) 382 | 383 | if RH['recFlag'] & 0x01: ## handle zipped content 384 | RD = self.inflate(RD,RH['realSize']) 385 | 386 | #RH['rawData']=RD 387 | self.dumpRecord(RD) # dump support added :) 388 | 389 | RH['fmtData']=self.formatRecord(RH,RD) 390 | self.out( "\n\n" ) 391 | 392 | RECS.append(RH) 393 | return RECS 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | def pack_rec_default(self,content): 403 | print " >> %s <<" % content 404 | return content 405 | 406 | def pack_nullstr(self,c): 407 | return ''.join( '%s\x00' % str(u) for u in c ) 408 | 409 | def pack_rec_20003(self,c): return self.pack_nullstr(c) 410 | def pack_rec_20005(self,c): return self.pack_nullstr(c) 411 | def pack_rec_20009(self,c): return self.pack_nullstr(c) 412 | def pack_rec_20011(self,c): return self.pack_nullstr(c) 413 | 414 | def pack_rec_20007(self,c): # webi tabe 415 | pass 416 | 417 | def pack_webinject(self,c): 418 | xs = xstream() 419 | for e in c: 420 | l = len(e)+4 421 | xs.writeFmt("I",l) 422 | xs.write(str(e)) 423 | return xs.dump() 424 | 425 | 426 | 427 | def pack_record(self,record): 428 | fields = ("id","content") 429 | for f in fields: 430 | if f not in record: 431 | raise storageException("Missing requred field: [%s]"%f) 432 | return 433 | 434 | flag = 0x0 435 | 436 | opts = record.get("opt",{}) 437 | if opts.get("webinject",None): 438 | fn = "pack_webinject" 439 | flag |= 0x40000000 440 | else: 441 | fn = "pack_rec_%d" % record['id'] 442 | if not hasattr(self,fn): 443 | fn = "pack_rec_default" 444 | 445 | func = getattr(self,fn) 446 | bindata = func(record['content']) 447 | size = len(bindata) 448 | xs = xstream() 449 | xs.writeFmt("=IIII",record['id'],flag,size,size) 450 | xs.write(bindata) 451 | return xs.dump() 452 | 453 | 454 | def pack_recs(self,recList): 455 | recBin = '' 456 | recCnt = 0 457 | for rec in recList: 458 | recBin += self.pack_record(rec) 459 | recCnt += 1 460 | size = len(recBin) 461 | m5s = md5.new(recBin).digest() 462 | 463 | xs = xstream() 464 | xs.write("xpad"*5) 465 | xs.writeFmt("=III",size,recCnt,0) 466 | xs.write(m5s) 467 | xs.write(recBin) 468 | xs.seek(0) 469 | return xs.read() 470 | """ 471 | -------------------------------------------------------------------------------- /libzpy/modules/powerzeus.py: -------------------------------------------------------------------------------- 1 | import libzpy.structs.powerzeus as pz 2 | import libzpy.fmt.powerzeus as pzfmt 3 | from libzpy.modules import template as t 4 | 5 | from StringIO import StringIO 6 | from ctypes import sizeof 7 | import json 8 | 9 | def unpack(data,verb): 10 | return t.unpack(data,verb,pz) 11 | 12 | def parse(data,verb): 13 | return t.parse(data,verb,pz) 14 | 15 | def to_str(data,verb): 16 | if not isinstance(data,dict): 17 | verb('I need unpacked data') 18 | return 19 | 20 | 21 | fmt = pzfmt.fmt(data) 22 | fmt._ = 'PowerZeus' 23 | return fmt.format() 24 | 25 | 26 | def go(data,verb): 27 | data = unpack(data,verb) 28 | data = parse(data,verb) 29 | #print `data['injects']` 30 | print to_str(data,verb) 31 | 32 | 33 | def format(data,verb,type='pretty'): 34 | if type == 'pretty': 35 | return to_str(data,verb) 36 | elif type == 'json': 37 | return json.dumps(data) 38 | -------------------------------------------------------------------------------- /libzpy/modules/template.py: -------------------------------------------------------------------------------- 1 | from StringIO import StringIO 2 | from ctypes import sizeof 3 | from hashlib import md5 4 | 5 | def unpack(data,verb,mod=None,verify=None): 6 | data = StringIO(data) 7 | stor = mod.Header(data) 8 | hash = md5(data.read(stor.size - sizeof(mod.Header))).digest() 9 | data.seek(sizeof(mod.Header),0) 10 | if verify: 11 | # print str(bytearray(stor.md5)).encode('hex') 12 | # print hash.encode('hex') 13 | if hash != str(bytearray(stor.md5)): 14 | print '[-] Hash mismath -- corrupted binstor?' 15 | return None 16 | ret = {} 17 | ret['header'] = stor 18 | ret['items'] = [] 19 | for idx in xrange(stor.count): 20 | itm = mod.Item(data) 21 | ret['items'].append(itm) 22 | return ret 23 | 24 | def string_list(d): 25 | return filter(None,d.split("\x00")) 26 | 27 | 28 | 29 | def parse(data,verb,mod=None): 30 | if not isinstance(data,dict): 31 | verb('I need unpacked data') 32 | return 33 | ret = {} 34 | ret['header'] = data['header'] 35 | ret['unknown'] = {} 36 | injList = [] 37 | injects = [] 38 | 39 | for itm in data['items']: 40 | if itm.is_webfilter(): 41 | if not 'webfilters' in ret: 42 | ret['webfilters'] = [] 43 | for x in filter(None,itm.data.split("\x00")): 44 | ret['webfilters'].append(mod.WebFilter(x).json()) 45 | 46 | elif itm.is_injectlist(): 47 | injList.append(itm) 48 | elif itm.is_inject(): 49 | injects.append(itm) 50 | elif itm.is_update(): 51 | if not 'update' in ret: 52 | ret['update'] = [] 53 | ret['update'].append(itm.data) 54 | elif itm.is_version(): 55 | pv =lambda x:'.'.join(['%.2X'% ord(c) for c in reversed(x)]) 56 | ret['version'] = pv(itm.data) 57 | 58 | elif (hasattr(itm,'is_captchasrv' ) and itm.is_captchasrv()): 59 | 60 | if not 'captcha_srv' in ret: 61 | ret['captcha_srv'] = [] 62 | ret['captcha_srv'].append(itm.data) 63 | 64 | elif (hasattr(itm,'captchalist') and itm.is_captchalist()) : 65 | 66 | if not 'captcha_lst' in ret: 67 | ret['captcha_lst'] = [] 68 | 69 | x = mod.HttpInject_Captcha(itm.data) 70 | u = x.data[x.urlCaptcha:].replace("w\x00\x00","www").strip("\x00") 71 | m = x.data.replace("w\x00\x00","www") 72 | m = m[x.urlHostMask:m.find("\x00")] 73 | ret['captcha_lst'].append({'mask':m,'url':u}) 74 | 75 | elif (hasattr(itm,'notifysrv') and itm.is_notifysrv()): 76 | 77 | if not 'notify_srv' in ret: 78 | ret['notify_srv'] = [] 79 | ret['notify_srv'].append(itm.data) 80 | 81 | 82 | elif itm.is_cfg_url(): 83 | 84 | if not 'server' in ret: 85 | ret['server'] = [] 86 | ret['server'].append(itm.data) 87 | 88 | elif itm.is_acfg_url(): 89 | if not 'advance' in ret: 90 | ret['advance'] = [] 91 | ret['advance'] += itm.data.split("\x00") 92 | 93 | elif itm._str_field('id')[1] != str(itm.id): 94 | # ## we know this type... 95 | ret[itm._str_field('id')[1]] = itm.data 96 | else: 97 | ret['unknown'][itm.id] = itm.data 98 | # ret['unknown'].append( str(itm) + "\n" + `itm.data`) 99 | 100 | ret['injects'] = [] 101 | # print len(injects) 102 | for il in injList: 103 | idx = 0 104 | for ih in mod.HttpInject_HList(il.data): 105 | 106 | rr = {} 107 | rr['flags'] = ih._print_flags().strip() 108 | rr['flags_raw'] = ih.flags 109 | rr['meta'] = {} #{'flags': hex(ih.flags)} 110 | rr['target']=str(ih.data).strip().replace("\x00",'') 111 | 112 | if ih.is_inject(): 113 | t = 'injects' 114 | elif ih.is_capture(): t = 'captures' 115 | else: t='unknown' 116 | 117 | rr[t]= [] 118 | idx2= 0 119 | r = {} 120 | for inj in mod.HttpInject_BList(injects[idx].data): 121 | if idx2 % 3 == 0: 122 | r['pre'] = unicode(inj.data,'utf-8','replace').strip() 123 | r['pre_flag'] = inj.flags 124 | elif idx2 % 3 == 1: 125 | r['post'] = unicode(inj.data,'utf-8','replace').strip() 126 | r['post_flag'] = inj.flags 127 | else: 128 | r['inj'] = unicode(inj.data,'utf-8','replace').strip() 129 | r['inj_flag'] = inj.flags 130 | rr[t].append(r) 131 | r= {} 132 | idx2+=1 133 | idx += 1 134 | ret['injects'].append(rr) 135 | if len(injects) <= idx: 136 | break 137 | return ret 138 | 139 | -------------------------------------------------------------------------------- /libzpy/modules/torment.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import libzpy.fmt.zeus as zfmt 4 | import libzpy.structs.zeus as zeus 5 | 6 | import libzpy.libs.cr_tools as cry 7 | from libzpy.modules import template as t 8 | 9 | 10 | def unpack(data,verb,verify=False): 11 | return t.unpack(data,verb,zeus,verify) 12 | 13 | def parse(data,verb): 14 | return t.parse(data,verb,zeus) 15 | 16 | def to_str(data,verb): 17 | if not isinstance(data,dict): 18 | verb('I need unpacked data') 19 | return 20 | 21 | fmt = zfmt.fmt(data) 22 | fmt._ = 'PowerZeus' 23 | return fmt.format() 24 | 25 | 26 | def json(data): 27 | verb=lambda x:x 28 | data = unpack(data,verb,True) 29 | data = parse(data,verb) 30 | return data 31 | 32 | def go(data,verb): 33 | data = unpack(data,verb) 34 | data = parse(data,verb) 35 | #print `data['injects']` 36 | print to_str(data,verb) 37 | 38 | 39 | def format(data,verb,type='pretty'): 40 | if type == 'pretty': 41 | return to_str(data,verb) 42 | elif type == 'json': 43 | return json.dumps(data) 44 | 45 | 46 | def parse_basecfg(basecfg,args): 47 | data = unpack(basecfg,lambda x: x,verify=False) 48 | data = parse(data,lambda x:x) 49 | botname = data['unknown'][1].strip("\x00") 50 | rc4key = data['unknown'][3].strip("\x00") 51 | urls = data['unknown'][2].split('')[2:-1] 52 | return {'botname': botname, 'rc4key':rc4key,'urls':urls,'cfg':urls[0]} 53 | 54 | 55 | 56 | 57 | ## we allready decode basecfg 58 | def get_basecfg(d,*args): 59 | # if not 'key' in args: 60 | # pass 61 | 62 | k = args[0] 63 | d = d.decode('hex') 64 | return cry.visDecry(cry.rc4decrypt(d,k,raw=True)) 65 | 66 | -------------------------------------------------------------------------------- /libzpy/modules/vmzeus.py: -------------------------------------------------------------------------------- 1 | import sys,StringIO,re 2 | import libzpy.structs.kins as k 3 | import libzpy.fmt.powerzeus as pzfmt 4 | #import libzpy.libs.cr_tools as cry 5 | from libzpy.modules import template as t 6 | from libzpy.libs.vmzeus import VmContext as VM 7 | from libzpy.libs.basecfg import BaseCfg 8 | from ctypes import sizeof 9 | from struct import * 10 | from hashlib import md5 11 | from pprint import pprint 12 | 13 | 14 | class VMZCfg(BaseCfg): 15 | def _get_enc_urls(self,k=None): 16 | d = self.cfg 17 | k = k if k else self.rc4sbox 18 | rk = k[:-2][::-1] 19 | off = d.find(k) 20 | if off == -1: 21 | print 'No key... wrong baseconfig/key?' 22 | return 23 | i = 0 24 | ret =[];els = [] 25 | while i < len(d): 26 | if i == off: 27 | i+= 0x102 28 | else: 29 | dec = self.rc4(d[i:i+0x66],rk) 30 | if dec.find('http') != -1: 31 | ret.append(dec.split("\x00")[0]) 32 | elif re.search("[\x1f-\x7e]{6,}\x00",dec): 33 | els.append( re.search("([\x1f-\x7e]{6,})\x00",dec).group(1) ) 34 | i+=1 35 | self.urls = ret 36 | return ret,els 37 | 38 | def get_urls(self): 39 | if not self.urls: 40 | self._get_enc_urls() 41 | return self.urls 42 | 43 | def get_rc4(self,ks): 44 | ## brutforece to find botnet rc4 key try to find baseurl 45 | ## if succeded its our key - should work well 46 | if type(ks) != list: 47 | self.rc4sbox = ks.decode('hex') 48 | return self.rc4sbox 49 | 50 | r = None 51 | for k in ks: 52 | try: 53 | temp = self._get_enc_urls(k) 54 | if temp and temp != ([],[]) and any(map(lambda u: u.find('http')!=-1,temp[0])): 55 | r = k 56 | except Exception as e: 57 | # import traceback 58 | # print `e` 59 | # traceback.print_exc(file=sys.stdout) 60 | pass 61 | self.rc4sbox = r 62 | return r 63 | 64 | 65 | def unpack(data,verb): 66 | return t.unpack(data,verb,k) 67 | def parse(data,verb): 68 | return t.parse(data,verb,k) 69 | 70 | def to_str(data,verb): 71 | if not isinstance(data,dict): 72 | verb('I need unpacked data') 73 | return 74 | 75 | fmt = pzfmt.fmt(data) 76 | fmt._name = 'VMZeus' 77 | return fmt.format() 78 | 79 | def do_print(data,verb): 80 | print data 81 | 82 | def json(data): 83 | return go(data,lambda x:x) 84 | 85 | def go(data,verb): 86 | data = unpack(data,verb) 87 | data = parse(data,verb) 88 | #print `data['injects']` 89 | return data 90 | 91 | 92 | def vmzeus_dga(key,suff,idx=0): 93 | key = key[::-1][2:] 94 | key = chr(ord(key[0]) + idx) + key[1:] + "\x00\x00" 95 | return 'http://' + md5(key).hexdigest()[:11] + suff 96 | 97 | def parse_basecfg(basecfg,data): 98 | # print `basecfg` 99 | key = data['key'] 100 | rc6k = data.get('off',None) 101 | 102 | bc = VMZCfg(basecfg) 103 | bc.get_rc4(key) 104 | staticcfg = bc.get_basics() 105 | fakeurl = re.search('(http://[a-zA-Z0-9/.]*\x00)',bc.cfg).group(1) 106 | if rc6k: 107 | staticcfg['rc6sbox']= basecfg[rc6k:rc6k+0xb0].encode('hex') 108 | for u in filter(lambda x: x.endswith('.jpg'),bc.urls): 109 | staticcfg['cfg'] =u 110 | 111 | staticcfg['urls'] 112 | staticcfg['fakeurl'] = (fakeurl if fakeurl else '*UNKNOWN*').strip("\x00") 113 | # staticcfg['OtherEncStrings'] = `els` 114 | # staticcfg['OtherStrings']= `othr` 115 | return staticcfg 116 | 117 | # print 'DGA: ' + `[ vmzeus_dga(key,els[0],i) for i in range(0,5)]` 118 | 119 | 120 | def get_basecfg(data,verb,*args): 121 | oldstdout = sys.stdout 122 | #fd = open('/tmp/out','w') 123 | sys.stdout = StringIO.StringIO() 124 | cfg = None 125 | try: 126 | vmctx = VM(data['code'].decode('hex'),data['data'].decode('hex')) 127 | vmctx._fix_xors(data['magic']) 128 | vmctx.run() 129 | cfg = vmctx.config 130 | 131 | except Exception as e: 132 | import traceback 133 | sys.stdout = oldstdout 134 | print 'VMError: ' + `e` 135 | traceback.print_exc(file=sys.stdout) 136 | 137 | sys.stdout = oldstdout 138 | # fd.close() 139 | if not cfg: 140 | print 'Code hash: ' + md5(data['code'].decode('hex')).hexdigest() 141 | print 'Data hash: ' + md5(data['data'].decode('hex')).hexdigest() 142 | print 'Xors: ' + str(data['magic']) 143 | # print `cfg` 144 | return cfg 145 | 146 | # def decrypt_cfg(data,key): 147 | # print 'Data: ' + `data` 148 | # print 'Key: ' + `key` 149 | # data = cry.rc4decrypt(data,key) 150 | # return cry.visDecry(data) 151 | 152 | 153 | -------------------------------------------------------------------------------- /libzpy/modules/vmzeus2.py: -------------------------------------------------------------------------------- 1 | import libzpy.structs.vmzeus2 as k 2 | import libzpy.fmt.vmzeus2 as pzfmt 3 | from libzpy.modules import template as t 4 | 5 | 6 | from ctypes import sizeof 7 | import json 8 | from struct import * 9 | 10 | def _print(data,ver): 11 | import pprint 12 | pprint.pprint(data) 13 | 14 | def do_print(data,verb): 15 | print data 16 | 17 | 18 | def unpack(data,verb): 19 | return t.unpack(data,verb,k) 20 | def parse(data,verb): 21 | return t.parse(data,verb,k) 22 | 23 | def json(data): 24 | verb=lambda x:x 25 | data = unpack(data,verb) 26 | data = parse(data,verb) 27 | return data 28 | 29 | def to_str(data,verb): 30 | if not isinstance(data,dict): 31 | verb('I need unpacked data') 32 | return 33 | 34 | fmt = pzfmt.fmt(data) 35 | fmt._name = 'VMZeus-2.0' 36 | return fmt.format() 37 | 38 | def go(data,verb): 39 | data = unpack(data,verb) 40 | data = parse(data,verb) 41 | #print `data['injects']` 42 | print to_str(data,verb) 43 | -------------------------------------------------------------------------------- /libzpy/modules/vmzeus20.py: -------------------------------------------------------------------------------- 1 | import libzpy.structs.vmzeus20 as k 2 | import libzpy.fmt.vmzeus20 as pzfmt 3 | from libzpy.modules import template as t 4 | 5 | 6 | from ctypes import sizeof 7 | import json,struct 8 | 9 | 10 | def _print(data,ver): 11 | import pprint 12 | pprint.pprint(data) 13 | 14 | def unpack(data,verb): 15 | return t.unpack(data,verb,k) 16 | def parse(data,verb): 17 | return t.parse(data,verb,k) 18 | 19 | def to_str(data,verb): 20 | if not isinstance(data,dict): 21 | verb('I need unpacked data') 22 | return 23 | 24 | fmt = pzfmt.fmt(data) 25 | fmt._name = 'VMZeus-2.0' 26 | return fmt.format() 27 | 28 | 29 | def json(data): 30 | verb=lambda x:x 31 | data = unpack(data,verb) 32 | data = parse(data,verb) 33 | if 'CFGID_SIGNATURE' in data: 34 | data['CFGID_SIGNATURE'] =data['CFGID_SIGNATURE'].encode('hex') 35 | data['CFGID_CONFIG_CREATION_TIME'] = struct.unpack('I',data['CFGID_CONFIG_CREATION_TIME'])[0] 36 | 37 | return data 38 | 39 | def go(data,verb): 40 | data = unpack(data,verb) 41 | data = parse(data,verb) 42 | #print `data['injects']` 43 | print to_str(data,verb) 44 | -------------------------------------------------------------------------------- /libzpy/modules/zeus.py: -------------------------------------------------------------------------------- 1 | import libzpy.structs.zeus as zeus 2 | import libzpy.fmt.zeus as zfmt 3 | from libzpy.modules import template as t 4 | 5 | from StringIO import StringIO 6 | from ctypes import sizeof,cast,c_byte 7 | from libzpy.libs.basecfg import BaseCfg 8 | import json 9 | 10 | def unpack(data,verb,verify=False): 11 | return t.unpack(data,verb,zeus,verify) 12 | 13 | def parse(data,verb): 14 | return t.parse(data,verb,zeus) 15 | 16 | def to_str(data,verb): 17 | if not isinstance(data,dict): 18 | verb('I need unpacked data') 19 | return 20 | 21 | fmt = zfmt.fmt(data) 22 | fmt._ = 'PowerZeus' 23 | return fmt.format() 24 | 25 | 26 | def json(data): 27 | verb=lambda x:x 28 | data = unpack(data,verb,True) 29 | data = parse(data,verb) 30 | return data 31 | 32 | def go(data,verb): 33 | data = unpack(data,verb) 34 | data = parse(data,verb) 35 | #print `data['injects']` 36 | print to_str(data,verb) 37 | 38 | 39 | def format(data,verb,type='pretty'): 40 | if type == 'pretty': 41 | return to_str(data,verb) 42 | elif type == 'json': 43 | return json.dumps(data) 44 | 45 | 46 | def parse_basecfg(basecfg,args): 47 | 48 | off = args['off'] 49 | bc = BaseCfg(basecfg) 50 | bc.get_rc4(off) 51 | return bc.get_basics() 52 | 53 | 54 | ## we allready decode basecfg 55 | def get_basecfg(d,*args): 56 | return d.decode('hex') 57 | 58 | def pack(data,verb,rand=True): 59 | import hashlib 60 | import struct as s 61 | hdr = zeus.Header("\x00"*sizeof(zeus.Header)) 62 | items = [] 63 | for idx in data: 64 | d = data[idx]['data'] 65 | if not isinstance(d,basestring): 66 | d= s.pack('I',d) 67 | itm = zeus.Item("\x00"*sizeof(zeus.Item)) 68 | itm.id = idx 69 | itm.flags = data[idx]['flags'] 70 | itm.size = len(d) 71 | itm.realSize = len(d) 72 | items.append(itm.pack() + d) 73 | 74 | with open('/dev/urandom') as f: rnd=f.read(20) 75 | cnt = ''.join(items) 76 | hsh = hashlib.md5(cnt).digest() 77 | hdr.count = len(data.keys()) 78 | if rand: 79 | hdr.rand = (c_byte*20)(*map(ord,rnd)) 80 | 81 | hdr.flags = 0 82 | hdr.size = len(cnt) + sizeof(zeus.Header) 83 | hdr.md5 =(c_byte*16)(*map(ord,hsh)) 84 | # ctypes.cast(f.fileName, ctypes._char_p) 85 | return hdr.pack() + cnt 86 | 87 | 88 | -------------------------------------------------------------------------------- /libzpy/structs/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /libzpy/structs/chthonic.py: -------------------------------------------------------------------------------- 1 | from libzpy.libs.structure import DataStructure,StructList 2 | from libzpy.libs.structure import c_word 3 | import libzpy.structs.zeus as zeus 4 | 5 | class Header(zeus.Header): 6 | pass 7 | 8 | 9 | class Item(zeus.Item): 10 | def __init__(self,*args,**kwargs): 11 | super(Item,self).__init__(*args,**kwargs) 12 | 13 | self._cfgids['CFGID_OUTER_PAYLOAD'] = 12003 14 | self._cfgids['CFGID_INJECTS'] = 2541227442 15 | self._cfgids['CFGID_PAYLOAD'] = 12000 16 | self._flags['ITEMF_IS_PACKED_CONFIG'] = 0x10000000 17 | 18 | 19 | class HttpInject_HList(zeus.HttpInject_HList): 20 | struct = zeus.HttpInject_Header 21 | 22 | class HttpInject_BList(zeus.HttpInject_BList): 23 | pass 24 | 25 | class HttpInject_Captcha(DataStructure): 26 | _fields_ = [('size',c_word),('urlHostMask',c_word),('urlCaptcha',c_word)] 27 | 28 | class WebFilter(zeus.WebFilter): 29 | def __init__(self,*args,**kwargs): 30 | super(WebFilter,self).__init__(*args,**kwargs) 31 | self._wf['$'] = 'NOTIFY' 32 | self._wf['|'] = 'UNKNOWN' ## TODO.... -------------------------------------------------------------------------------- /libzpy/structs/citadel.py: -------------------------------------------------------------------------------- 1 | from libzpy.libs.structure import DataStructure,StructList 2 | from libzpy.libs.structure import c_word,c_dword,c_byte 3 | import libzpy.structs.zeus as zeus 4 | 5 | class Header(DataStructure): 6 | _have_data=False 7 | _fields_ = [ ('junk',c_byte*12), ('size',c_dword), ('flags',c_dword), ('count',c_dword),('md5',c_byte*0x10)] 8 | 9 | 10 | class Item(zeus.Item): 11 | 12 | def __init__(self,*args,**kwargs): 13 | super(Item,self).__init__(*args,**kwargs) 14 | self._flags['ITEMF_IS_ARGUMENT'] = 0x00100000 15 | self._flags['ITEMF_IS_MODULE_HASH'] = 0x00200000 16 | self._flags['ITEMF_IS_PROC_NAME_HASH'] = 0x00400000 17 | self._cfgids[20009] ='CFGID_DNS_FILTER' 18 | self._cfgids[20010] ='CFGID_CMD_LIST' 19 | self._cfgids[20011] ='CFGID_HTTP_MAGICURI_LIST' 20 | self._cfgids[20012] ='CFGID_FILESEARCH_KEYWORDS' 21 | self._cfgids[20013] ='CFGID_FILESEARCH_EXCLUDES_NAME' 22 | self._cfgids[20014] ='CFGID_FILESEARCH_EXCLUDES_PATH' 23 | self._cfgids[20015] ='CFGID_KEYLOGGER_PROCESSES' 24 | self._cfgids[20016] ='CFGID_KEYLOGGER_TIME' 25 | self._cfgids[20017] ='CFGID_FILESEARCH_MINYEAR' 26 | self._cfgids[20018] ='CFGID_WEBINJECTS_URL' 27 | self._cfgids[20019] ='CFGID_TOKENSPY_URL' 28 | self._cfgids[20020] ='CFGID_HTTPVIP_URLS' 29 | self._cfgids[20101] ='CFGID_VIDEO_QUALITY' 30 | self._cfgids[20102] ='CFGID_VIDEO_LENGTH' 31 | self._cfgids[20201] ='CFGID_MONEY_PARSER_ENABLED' 32 | self._cfgids[20202] ='CFGID_MONEY_PARSER_INCLUDE' 33 | self._cfgids[20203] ='CFGID_MONEY_PARSER_EXCLUDE' 34 | 35 | self._cfgids_n = self._cfgids.__class__(map(reversed, self._cfgids.items())) 36 | 37 | 38 | def is_captchasrv(self): 39 | return self.id == self._cfgids_n['CFGID_CAPTCHA_SERVER'] 40 | 41 | def is_captchalist(self): 42 | return self.id == self._cfgids_n['CFGID_CAPTCHA_LIST'] 43 | def is_notifysrv(self): 44 | return self.id == self._cfgids_n['CFGID_NOTIFY_SERVER'] 45 | 46 | def is_notifylist(self): 47 | return self.id == self._cfgids_n['CFGID_NOTIFY_LIST'] 48 | 49 | _http_inj_flags = { 50 | 'FLAG_IS_INJECT' : 0x0001, 51 | 'FLAG_IS_CAPTURE' : 0x0002, 52 | 'FLAG_REQUEST_POST' : 0x0004, 53 | 'FLAG_REQUEST_GET' : 0x0008, 54 | 'FLAG_ONCE_PER_DAY' : 0x0010, 55 | 'FLAG_CAPTURE_NOTPARSE' : 0x0100, 56 | 'FLAG_CAPTURE_TOFILE' : 0x0200, 57 | 'FLAG_URL_CASE_INSENSITIVE' : 0x1000, 58 | 'FLAG_CONTEXT_CASE_INSENSITIVE' : 0x2000 59 | } 60 | class HttpInject_InjectBlock(zeus.HttpInject_InjectBlock): 61 | _flags = _http_inj_flags 62 | 63 | class HttpInject_Header(DataStructure): 64 | _pack_ = 1 65 | _fields_ = [('flags',c_word),('size',c_word),('urlMask',c_word), 66 | ('postDataBlackMask',c_word),('postDataWhiteMask',c_word), 67 | ('contextMask',c_word) 68 | ] 69 | _flags = _http_inj_flags 70 | 71 | def is_inject(self): 72 | return self.flags & self._flags['FLAG_IS_INJECT'] 73 | def is_capture(self): 74 | return self.flags & self._flags['FLAG_IS_CAPTURE'] 75 | 76 | class HttpInject_HList(zeus.HttpInject_HList): 77 | struct = HttpInject_Header 78 | 79 | class HttpInject_BList(zeus.HttpInject_BList): 80 | pass 81 | 82 | class HttpInject_Captcha(DataStructure): 83 | _fields_ = [('size',c_word),('urlHostMask',c_word),('urlCaptcha',c_word)] 84 | 85 | 86 | class WebFilter(zeus.WebFilter): 87 | def __init__(self,*args,**kwargs): 88 | super(WebFilter,self).__init__(*args,**kwargs) 89 | self._wf['#'] = 'MOVIE' 90 | -------------------------------------------------------------------------------- /libzpy/structs/kins.py: -------------------------------------------------------------------------------- 1 | from libzpy.libs.structure import DataStructure,StructList 2 | from libzpy.libs.structure import c_word 3 | import libzpy.structs.zeus as zeus 4 | 5 | class Header(zeus.Header): 6 | pass 7 | 8 | class Item(zeus.Item): 9 | 10 | def __init__(self,*args,**kwargs): 11 | super(Item,self).__init__(*args,**kwargs) 12 | self._flags['ITEMF_IS_ARGUMENT'] = 0x00100000 13 | self._flags['ITEMF_IS_MODULE_HASH'] = 0x00200000 14 | self._flags['ITEMF_IS_PROC_NAME_HASH'] = 0x00400000 15 | self._cfgids[20009] = 'CFGID_CAPTCHA_SERVER' 16 | self._cfgids[20010] ='CFGID_CAPTCHA_LIST' 17 | self._cfgids[20011] ='CFGID_NOTIFY_SERVER' 18 | self._cfgids[20012] ='CFGID_NOTIFY_LIST' 19 | # self._cfgids[20013] ='CFGID_REFRESH_BLOCK_LIST' 20 | self._cfgids_n = self._cfgids.__class__(map(reversed, self._cfgids.items())) 21 | 22 | 23 | def is_captchasrv(self): 24 | return self.id == self._cfgids_n['CFGID_CAPTCHA_SERVER'] 25 | 26 | def is_captchalist(self): 27 | return self.id == self._cfgids_n['CFGID_CAPTCHA_LIST'] 28 | def is_notifysrv(self): 29 | return self.id == self._cfgids_n['CFGID_NOTIFY_SERVER'] 30 | 31 | def is_notifylist(self): 32 | return self.id == self._cfgids_n['CFGID_NOTIFY_LIST'] 33 | 34 | 35 | # class HttpInject_InjectBlock(zeus.HttpInject_InjectBlock): 36 | # pass 37 | 38 | class HttpInject_HList(zeus.HttpInject_HList): 39 | struct = zeus.HttpInject_Header 40 | 41 | class HttpInject_BList(zeus.HttpInject_BList): 42 | pass 43 | 44 | class HttpInject_Captcha(DataStructure): 45 | _fields_ = [('size',c_word),('urlHostMask',c_word),('urlCaptcha',c_word)] 46 | 47 | class WebFilter(zeus.WebFilter): 48 | def __init__(self,*args,**kwargs): 49 | super(WebFilter,self).__init__(*args,**kwargs) 50 | self._wf['$'] = 'NOTIFY' 51 | self._wf['|'] = 'UNKNOWN' ## TODO.... 52 | -------------------------------------------------------------------------------- /libzpy/structs/powerzeus.py: -------------------------------------------------------------------------------- 1 | from libzpy.libs.structure import DataStructure,StructList 2 | from libzpy.libs.structure import c_word 3 | import libzpy.structs.zeus as zeus 4 | 5 | class Header(zeus.Header): 6 | pass 7 | 8 | class Item(zeus.Item): 9 | 10 | def __init__(self,*args,**kwargs): 11 | super(Item,self).__init__(*args,**kwargs) 12 | self._flags['ITEMF_IS_ARGUMENT'] = 0x00100000 13 | self._flags['ITEMF_IS_MODULE_HASH'] = 0x00200000 14 | self._flags['ITEMF_IS_PROC_NAME_HASH'] = 0x00400000 15 | self._cfgids[20009] = 'CFGID_CAPTCHA_SERVER' 16 | self._cfgids[20010] ='CFGID_CAPTCHA_LIST' 17 | self._cfgids[20011] ='CFGID_NOTIFY_SERVER' 18 | self._cfgids[20012] ='CFGID_NOTIFY_LIST' 19 | self._cfgids[20013] ='CFGID_REFRESH_BLOCK_LIST' 20 | self._cfgids_n = self._cfgids.__class__(map(reversed, self._cfgids.items())) 21 | 22 | 23 | def is_captchasrv(self): 24 | return self.id == self._cfgids_n['CFGID_CAPTCHA_SERVER'] 25 | 26 | def is_captchalist(self): 27 | return self.id == self._cfgids_n['CFGID_CAPTCHA_LIST'] 28 | def is_notifysrv(self): 29 | return self.id == self._cfgids_n['CFGID_NOTIFY_SERVER'] 30 | 31 | def is_notifylist(self): 32 | return self.id == self._cfgids_n['CFGID_NOTIFY_LIST'] 33 | 34 | _http_inj_flags = { 35 | 'FLAG_IS_INJECT' : 0x0001, 36 | 'FLAG_IS_CAPTURE' : 0x0002, 37 | 'FLAG_REQUEST_POST' : 0x0004, 38 | 'FLAG_REQUEST_GET' : 0x0008, 39 | 'FLAG_ONCE_PER_DAY' : 0x0010, 40 | 'FLAG_CAPTURE_NOTPARSE' : 0x0100, 41 | 'FLAG_CAPTURE_TOFILE' : 0x0200, 42 | 'FLAG_URL_CASE_INSENSITIVE' : 0x1000, 43 | 'FLAG_CONTEXT_CASE_INSENSITIVE' : 0x2000 44 | } 45 | class HttpInject_InjectBlock(zeus.HttpInject_InjectBlock): 46 | _flags = _http_inj_flags 47 | 48 | class HttpInject_Header(DataStructure): 49 | _pack_ = 1 50 | _fields_ = [('flags',c_word),('size',c_word),('urlMask',c_word), 51 | ('postDataBlackMask',c_word),('postDataWhiteMask',c_word), 52 | ('contextMask',c_word) 53 | ] 54 | _flags = _http_inj_flags 55 | 56 | def is_inject(self): 57 | return self.flags & self._flags['FLAG_IS_INJECT'] 58 | def is_capture(self): 59 | return self.flags & self._flags['FLAG_IS_CAPTURE'] 60 | 61 | class HttpInject_HList(zeus.HttpInject_HList): 62 | struct = HttpInject_Header 63 | 64 | class HttpInject_BList(zeus.HttpInject_BList): 65 | pass 66 | 67 | class HttpInject_Captcha(DataStructure): 68 | _fields_ = [('size',c_word),('urlHostMask',c_word),('urlCaptcha',c_word)] 69 | 70 | 71 | class WebFilter(zeus.WebFilter): 72 | def __init__(self,*args,**kwargs): 73 | super(WebFilter,self).__init__(*args,**kwargs) 74 | self._wf['$'] = 'NOTIFY' 75 | -------------------------------------------------------------------------------- /libzpy/structs/vmzeus2.py: -------------------------------------------------------------------------------- 1 | from libzpy.libs.structure import DataStructure,StructList 2 | from libzpy.libs.structure import c_dword,c_word 3 | import libzpy.structs.zeus as zeus 4 | 5 | 6 | class Header(DataStructure): 7 | _have_data=False 8 | _fields_ = [ ('unk1',c_dword), ('size',c_dword), ('flags',c_dword), ('unk2',c_dword),('count',c_dword),('checksum',c_dword),('unk3',c_dword)] 9 | 10 | 11 | 12 | class Item(zeus.Item): 13 | 14 | def __init__(self,*args,**kwargs): 15 | super(Item,self).__init__(*args,**kwargs) 16 | self._flags['ITEMF_IS_ARGUMENT'] = 0x00100000 17 | self._flags['ITEMF_IS_MODULE_HASH'] = 0x00200000 18 | self._flags['ITEMF_IS_PROC_NAME_HASH'] = 0x00400000 19 | self._flags['ITEMF_IS_HTTP_INJECT'] = 8 20 | self._cfgids[20009] = 'CFGID_CAPTCHA_SERVER' 21 | self._cfgids[20010] ='CFGID_CAPTCHA_LIST' 22 | self._cfgids[20011] ='CFGID_NOTIFY_SERVER' 23 | self._cfgids[20012] ='CFGID_NOTIFY_LIST' 24 | self._cfgids[20013] ='CFGID_REFRESH_BLOCK_LIST' 25 | self._cfgids[20014] ='CFGID_VNCDLL_URL' 26 | self._cfgids[20015] ='CFGID_MINERDLL_URL' 27 | self._cfgids[20018] ='CFGID_SPAM_TASK' 28 | self._cfgids[20019] ='CFGID_SPAM_TASK_STATUS' 29 | self._cfgids[20020] ='CFGID_SPAM_MODULE_URL' 30 | self._cfgids[20021] ='CFGID_CONFIG_CREATION_TIME' 31 | self._cfgids[20022] ='CFGID_P2P_NODE_INFO' 32 | self._cfgids[20023] ='CFGID_SIGNATURE' 33 | self._cfgids[20024] ='CFGID_FORCED_HOMEPAGE' 34 | 35 | # self._cfgids[20013] ='CFGID_REFRESH_BLOCK_LIST' 36 | self._cfgids_n = self._cfgids.__class__(map(reversed, self._cfgids.items())) 37 | args[0].read(4) 38 | 39 | def is_captchasrv(self): 40 | return self.id == self._cfgids_n['CFGID_CAPTCHA_SERVER'] 41 | 42 | def is_captchalist(self): 43 | return self.id == self._cfgids_n['CFGID_CAPTCHA_LIST'] 44 | def is_notifysrv(self): 45 | return self.id == self._cfgids_n['CFGID_NOTIFY_SERVER'] 46 | 47 | def is_notifylist(self): 48 | return self.id == self._cfgids_n['CFGID_NOTIFY_LIST'] 49 | 50 | def is_ctime(self): 51 | return self.id == self._cfgids_n['CFGID_CONFIG_CREATION_TIME'] 52 | 53 | # class HttpInject_InjectBlock(zeus.HttpInject_InjectBlock): 54 | # pass 55 | 56 | class HttpInject_HList(zeus.HttpInject_HList): 57 | struct = zeus.HttpInject_Header 58 | 59 | class HttpInject_BList(zeus.HttpInject_BList): 60 | pass 61 | 62 | class HttpInject_Captcha(DataStructure): 63 | _fields_ = [('size',c_word),('urlHostMask',c_word),('urlCaptcha',c_word)] 64 | 65 | 66 | class WebFilter(zeus.WebFilter): 67 | def __init__(self,*args,**kwargs): 68 | super(WebFilter,self).__init__(*args,**kwargs) 69 | self._wf['$'] = 'NOTIFY' 70 | -------------------------------------------------------------------------------- /libzpy/structs/vmzeus20.py: -------------------------------------------------------------------------------- 1 | from libzpy.libs.structure import DataStructure,StructList 2 | from libzpy.libs.structure import c_dword,c_word 3 | import libzpy.structs.zeus as zeus 4 | 5 | 6 | class Header(DataStructure): 7 | _have_data=False 8 | _fields_ = [ ('unk1',c_dword), ('size',c_dword), ('flags',c_dword), ('unk2',c_dword),('count',c_dword),('checksum',c_dword),('unk3',c_dword)] 9 | 10 | 11 | 12 | class Item(zeus.Item): 13 | 14 | def __init__(self,*args,**kwargs): 15 | super(Item,self).__init__(*args,**kwargs) 16 | self._flags['ITEMF_IS_ARGUMENT'] = 0x00100000 17 | self._flags['ITEMF_IS_MODULE_HASH'] = 0x00200000 18 | self._flags['ITEMF_IS_PROC_NAME_HASH'] = 0x00400000 19 | self._flags['ITEMF_IS_HTTP_INJECT'] = 8 20 | self._cfgids[20009] = 'CFGID_CAPTCHA_SERVER' 21 | self._cfgids[20010] ='CFGID_CAPTCHA_LIST' 22 | self._cfgids[20011] ='CFGID_NOTIFY_SERVER' 23 | self._cfgids[20012] ='CFGID_NOTIFY_LIST' 24 | self._cfgids[20013] ='CFGID_REFRESH_BLOCK_LIST' 25 | self._cfgids[20014] ='CFGID_VNCDLL_URL' 26 | self._cfgids[20015] ='CFGID_MINERDLL_URL' 27 | self._cfgids[20018] ='CFGID_SPAM_TASK' 28 | self._cfgids[20019] ='CFGID_SPAM_TASK_STATUS' 29 | self._cfgids[20020] ='CFGID_SPAM_MODULE_URL' 30 | self._cfgids[20021] ='CFGID_CONFIG_CREATION_TIME' 31 | self._cfgids[20022] ='CFGID_P2P_NODE_INFO' 32 | self._cfgids[20023] ='CFGID_SIGNATURE' 33 | self._cfgids[20024] ='CFGID_FORCED_HOMEPAGE' 34 | 35 | # self._cfgids[20013] ='CFGID_REFRESH_BLOCK_LIST' 36 | self._cfgids_n = self._cfgids.__class__(map(reversed, self._cfgids.items())) 37 | args[0].read(4) 38 | 39 | def is_captchasrv(self): 40 | return self.id == self._cfgids_n['CFGID_CAPTCHA_SERVER'] 41 | 42 | def is_captchalist(self): 43 | return self.id == self._cfgids_n['CFGID_CAPTCHA_LIST'] 44 | def is_notifysrv(self): 45 | return self.id == self._cfgids_n['CFGID_NOTIFY_SERVER'] 46 | 47 | def is_notifylist(self): 48 | return self.id == self._cfgids_n['CFGID_NOTIFY_LIST'] 49 | 50 | def is_ctime(self): 51 | return self.id == self._cfgids_n['CFGID_CONFIG_CREATION_TIME'] 52 | 53 | # class HttpInject_InjectBlock(zeus.HttpInject_InjectBlock): 54 | # pass 55 | 56 | class HttpInject_HList(zeus.HttpInject_HList): 57 | struct = zeus.HttpInject_Header 58 | 59 | class HttpInject_BList(zeus.HttpInject_BList): 60 | pass 61 | 62 | class HttpInject_Captcha(DataStructure): 63 | _fields_ = [('size',c_word),('urlHostMask',c_word),('urlCaptcha',c_word)] 64 | 65 | 66 | class WebFilter(zeus.WebFilter): 67 | def __init__(self,*args,**kwargs): 68 | super(WebFilter,self).__init__(*args,**kwargs) 69 | self._wf['$'] = 'NOTIFY' 70 | -------------------------------------------------------------------------------- /libzpy/structs/zeus.py: -------------------------------------------------------------------------------- 1 | from libzpy.libs.structure import DataStructure,StructList 2 | from libzpy.libs.structure import c_byte,c_word,c_dword,c_qword,c_wchar,c_char 3 | from libzpy.libs.UCL import UCL 4 | #from ctypes import bytearray 5 | 6 | _UCL = None 7 | def decompress(data,size): 8 | global _UCL 9 | if not _UCL: 10 | _UCL = UCL() 11 | return _UCL.decompress(data,size) 12 | 13 | 14 | class Header(DataStructure): 15 | _have_data = False 16 | _fields_ = [('rand',c_byte*20),('size',c_dword),('flags',c_dword),('count',c_dword),('md5',c_byte*0x10)] 17 | 18 | def _print_md5(self): 19 | ret ='' 20 | for i in range(0,0x10): 21 | ret += '%02x' % self.md5[i] 22 | return ret 23 | 24 | class PESettings(DataStructure): 25 | compId = None 26 | _have_data = False 27 | _pack_ =1 28 | _fields_ = [('size',c_dword),('_compId',c_wchar*60),('guid',c_char*0x10),('_RC4KEY',c_byte*0x102), 29 | ('exeFile',c_char*20),('reportFile',c_char*20),('regKey',c_char*10),('regDynamicConfig',c_char*10), 30 | ('regLocalConfig',c_char*10),('regLocalSettings',c_char*10),('processInfectionId',c_dword),('storageArrayKey',c_dword) 31 | ] 32 | 33 | def _print__compId(self): 34 | return 'compId: ' + self.compId 35 | def _print__RC4KEY(self): 36 | b = bytearray(self._RC4KEY) 37 | return str(b).encode('hex') 38 | 39 | def __getattribute__(self,name): 40 | if name=='compId': 41 | return self._compId if self._compId[0].__class__ == unicode else ''.join(map(lambda x:x[0],self._compId)).strip("\x00") 42 | elif name == 'RC4KEY': 43 | return self._print__RC4KEY() 44 | else: 45 | return object.__getattribute__(self, name) 46 | 47 | class Item(DataStructure): 48 | _flags = { 49 | 'ITEMF_COMPRESSED': 0x00000001, 50 | 'ITEMF_COMBINE_ADD': 0x00010000, 51 | 'ITEMF_COMBINE_OVERWRITE': 0x00020000, 52 | 'ITEMF_COMBINE_REPLACE' : 0x00040000, 53 | 'ITEMF_COMBINE_DELETE' : 0x00080000, 54 | 'ITEMF_IS_OPTION' :0x10000000, 55 | 'ITEMF_IS_SETTING' :0x20000000, 56 | 'ITEMF_IS_HTTP_INJECT' :0x40000000 57 | 58 | } 59 | 60 | _cfgids = { 61 | 20001 :'CFGID_LAST_VERSION', 62 | 20002 :'CFGID_LAST_VERSION_URL', 63 | 20003 :'CFGID_URL_SERVER_0', 64 | 20004 :'CFGID_URL_ADV_SERVERS', 65 | 20005 :'CFGID_HTTP_FILTER', 66 | 20006 :'CFGID_HTTP_POSTDATA_FILTER', 67 | 20007 :'CFGID_HTTP_INJECTS_LIST', 68 | 20008 :'CFGID_DNS_LIST', 69 | } 70 | 71 | _fields_ = [ ('id',c_dword),('flags',c_dword),('size',c_dword),('realSize',c_dword)] 72 | 73 | def __init__(self,*args,**kwargs): 74 | super(Item,self).__init__(*args,**kwargs) 75 | self._cfgids_n = self._cfgids.__class__(map(reversed, self._cfgids.items())) 76 | 77 | def _print_id(self): 78 | if self.id in self._cfgids: 79 | return '%s' % self._cfgids[self.id] 80 | return '%d' % self.id 81 | 82 | def feed(self,data): 83 | super(Item,self).feed(data) 84 | 85 | ## apperently we ca have decompression without changed size... 86 | if self.flags & self._flags['ITEMF_COMPRESSED']: 87 | self.decompress() 88 | 89 | def decompress(self): 90 | self.data = decompress(self.data,self.realSize)#.run(1) 91 | # self.data = unrv2b(self.data,self.realSize).run(1) 92 | 93 | 94 | def is_compresed(self): 95 | return self.flags & self._flags['ITEMF_COMPRESSED'] 96 | 97 | def is_option(self): 98 | return self.flags & self._flags['ITEMF_IS_OPTION'] 99 | 100 | def is_inject(self): 101 | return self.flags & self._flags['ITEMF_IS_HTTP_INJECT'] 102 | 103 | def is_setting(self): 104 | return self.flags & self._flags['ITEMF_IS_SETTING'] 105 | 106 | def is_version(self): 107 | return self.id == self._cfgids_n['CFGID_LAST_VERSION'] 108 | 109 | def is_update(self): 110 | return self.id == self._cfgids_n['CFGID_LAST_VERSION_URL'] 111 | 112 | def is_injectlist(self): 113 | return self.id == self._cfgids_n['CFGID_HTTP_INJECTS_LIST'] 114 | 115 | def is_webfilter(self): 116 | return self.id == self._cfgids_n['CFGID_HTTP_FILTER'] 117 | 118 | def is_cfg_url(self): 119 | return self.id == self._cfgids_n['CFGID_URL_SERVER_0'] 120 | 121 | def is_acfg_url(self): 122 | return self.id == self._cfgids_n['CFGID_URL_ADV_SERVERS'] 123 | 124 | def is_dnslist(self): 125 | return self.id == self._cfgids_n['CFGID_DNS_LIST'] 126 | 127 | def is_dnsfilter(self): 128 | return self.id == self._cfgids_n['CFGID_DNS_FILTER'] 129 | 130 | def is_cmdlist(self): 131 | return self.id == self._cfgids_n['CFGID_CMD_LIST'] 132 | 133 | 134 | 135 | _http_inj_Flags ={ 136 | 'FLAG_IS_FAKE' : 0x0001, 137 | 'FLAG_IS_MIRRORFAKE' : 0x0002, 138 | 'FLAG_IS_INJECT' : 0x0004, 139 | 'FLAG_IS_CAPTURE' : 0x0008, 140 | 141 | 'FLAG_ONCE_PER_DAY' : 0x0010, 142 | 'FLAG_REQUEST_POST' : 0x0020, 143 | 'FLAG_REQUEST_GET' : 0x0040, 144 | 145 | 'FLAG_CAPTURE_NOTPARSE' : 0x0100, 146 | 'FLAG_CAPTURE_TOFILE' : 0x0200, 147 | 148 | 'FLAG_URL_CASE_INSENSITIVE' : 0x1000, 149 | 'FLAG_CONTEXT_CASE_INSENSITIVE' : 0x2000 150 | } 151 | 152 | class HttpInject_InjectBlock(DataStructure): 153 | _fields_ = [('size',c_word),('flags',c_word)] 154 | _flags = _http_inj_Flags 155 | 156 | def _print_flags(self): 157 | return '%x' % self.flags 158 | 159 | class HttpInject_BList(StructList): 160 | struct = HttpInject_InjectBlock 161 | 162 | 163 | class HttpInject_Header(DataStructure): 164 | _pack_ = 1 165 | _fields_ = [('flags',c_word),('size',c_word),('urlMask',c_word),('fakeUrl',c_word), 166 | ('postDataBlackMask',c_word),('postDataWhiteMask',c_word), 167 | ('blockOnUrl',c_word),('contextMask',c_word) 168 | ] 169 | _flags = _http_inj_Flags 170 | 171 | def is_inject(self): 172 | return self.flags & self._flags['FLAG_IS_INJECT'] 173 | 174 | def is_capture(self): 175 | return self.flags & self._flags['FLAG_IS_CAPTURE'] 176 | 177 | class HttpInject_HList(StructList): 178 | struct = HttpInject_Header 179 | 180 | 181 | class WebFilter(object): 182 | _wf = { 183 | '@' : 'SCREENSHOT', 184 | '!' : 'DONT-REPORT', 185 | '-' : 'SAVE-COOCKIE', 186 | '^' : 'BLOCK-ACCESS' 187 | } 188 | def __init__(self,d): 189 | self.act = d[0] 190 | self.trg = d[1:] 191 | if 0x61 < ord(self.act) < 0x7a: 192 | ## some strange shit... 193 | self.trg = self.act + self.trg 194 | self.act = "" 195 | 196 | 197 | def __getitem__(self,x): 198 | if x in self._wf: 199 | return self._wf[x] 200 | return x 201 | 202 | def json(self): 203 | return {'action':self[self.act],'target':self.trg} 204 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | try: 4 | from setuptools import setup 5 | except ImportError: 6 | from distutils.core import setup 7 | 8 | setup(name="libzpy", 9 | version="0.0.6", 10 | description="zeus-like things", 11 | author="mak", 12 | packages=['libzpy', 'libzpy.fmt', 'libzpy.libs', 'libzpy.modules', 'libzpy.structs'], 13 | package_data={'libzpy.libs':['libucl_i368.so','libucl_x64.so']}, 14 | include_package_data=True, 15 | install_requires=[ 16 | "pycrypto", 17 | "mlib" 18 | ]) 19 | 20 | --------------------------------------------------------------------------------