diff options
| author | serpilliere <devnull@localhost> | 2012-07-30 09:38:20 +0200 |
|---|---|---|
| committer | serpilliere <devnull@localhost> | 2012-07-30 09:38:20 +0200 |
| commit | a95d1b7bd1d8e8ca349c45fb83987a4baaf99025 (patch) | |
| tree | 9884a7372c86e42dd39aeb98e864e89830581777 | |
| parent | 13fa70f83bfb3ece9f435bf6802311312fa272de (diff) | |
| parent | 42ec230c4206014badae38f03c82d0e4b5e351e1 (diff) | |
| download | miasm-a95d1b7bd1d8e8ca349c45fb83987a4baaf99025.tar.gz miasm-a95d1b7bd1d8e8ca349c45fb83987a4baaf99025.zip | |
merge
| -rwxr-xr-x | example/disas_and_graph.py | 20 | ||||
| -rw-r--r-- | miasm/arch/arm_arch.py | 6 | ||||
| -rw-r--r-- | miasm/arch/ia32_arch.py | 28 | ||||
| -rw-r--r-- | miasm/arch/java_arch.py | 62 | ||||
| -rw-r--r-- | miasm/arch/ppc_arch.py | 5 | ||||
| -rw-r--r-- | miasm/core/asmbloc.py | 69 | ||||
| -rw-r--r-- | miasm/tools/codenat.py | 12 | ||||
| -rwxr-xr-x | miasm/tools/func_analyser.py | 106 | ||||
| -rwxr-xr-x | miasm/tools/hook_helper.py | 62 | ||||
| -rw-r--r-- | miasm/tools/pe_helper.py | 20 | ||||
| -rw-r--r-- | miasm/tools/seh_helper.py | 44 | ||||
| -rw-r--r-- | miasm/tools/win_api.py | 64 |
12 files changed, 270 insertions, 228 deletions
diff --git a/example/disas_and_graph.py b/example/disas_and_graph.py index 71f943ec..124b8f4a 100755 --- a/example/disas_and_graph.py +++ b/example/disas_and_graph.py @@ -162,19 +162,21 @@ for (n,f), ads in dll_dyn_funcs.items(): def my_disasm_callback(ad): - admode = opmode = u32 - kargs = {} - if options.machine_options: - if options.machine_options in ['u16', 'u32']: - admode = opmode = options.machine_options - kargs = {"admode":admode, "opmode":admode} - else: - raise ValueError('bad machine options') + attrib = {} + if mnemo == ia32_arch.x86_mn: + if options.machine_options: + if options.machine_options in ['u16', 'u32']: + admode = opmode = u32 + admode = opmode = options.machine_options + attrib = {"admode":admode, "opmode":admode} + else: + raise ValueError('bad machine options') + all_bloc = asmbloc.dis_bloc_all(mnemo, in_str, ad, set(), symbol_pool=symbol_pool, dontdis_retcall = options.dontdiscallret, follow_call = options.followcall, - **kargs) + attrib = attrib) g = asmbloc.bloc2graph(all_bloc) open('graph.txt', 'w').write(g) if mnemo == ia32_arch.x86_mn: diff --git a/miasm/arch/arm_arch.py b/miasm/arch/arm_arch.py index 1bc1fc53..9b446334 100644 --- a/miasm/arch/arm_arch.py +++ b/miasm/arch/arm_arch.py @@ -613,7 +613,7 @@ class arm_mnemo_metaclass(type): raise ValueError('ambiquity %s'%str(ret)) - def dis(cls, bin, amode = None, sex = None): + def dis(cls, bin, attrib = {}): if type(bin) == str: bin = bin_stream(bin) elif not isinstance(bin, bin_stream): @@ -907,6 +907,10 @@ class arm_mn(object): self.parse_args(full_mnemo) + def get_attrib(self): + return {} + + def parse_opts(self, rest): pass def str2name(self, n): diff --git a/miasm/arch/ia32_arch.py b/miasm/arch/ia32_arch.py index 3c1906a2..41577bcc 100644 --- a/miasm/arch/ia32_arch.py +++ b/miasm/arch/ia32_arch.py @@ -1278,18 +1278,17 @@ x86mndb = x86allmncs() class x86_mnemo_metaclass(type): rebuilt_inst = True - def dis(cls, op, admode = u32, opmode = u32, sex = 0): + + def dis(cls, op, attrib = {}): i = cls.__new__(cls) - i.__init__(admode, opmode, sex) - i.opmode = opmode - i.admode = admode + i.__init__(attrib) u = i._dis(op) if not u: return None return i def asm(cls, l, symbol_off = []): i = cls.__new__(cls) - i.__init__(admode = u32, opmode = u32, sex = 0) + i.__init__() # admode = u32, opmode = u32, sex = 0) return i._asm(l, symbol_off) @@ -1357,12 +1356,17 @@ class x86_mnemo_metaclass(type): class x86_mn: __metaclass__ = x86_mnemo_metaclass - def __init__(self, admode = u32, opmode = u32, sex = 0): - self.admode = admode - self.opmode = opmode + def __init__(self, attrib = {}): + self.opmode = attrib.get('opmode', u32) + self.admode = attrib.get('opmode', u32) self.mnemo_mode = self.opmode self.cmt = "" + + def get_attrib(self): + return {"opmode":self.opmode, + "admode":self.admode} + @classmethod def prefix2hex(self, prefix): return reduce(lambda x,y:x+chr(y), prefix, "") @@ -1458,14 +1462,9 @@ class x86_mn: raise ValueError('unknown mnemo mode %s'%str(im)) def _dis(self, bin): - - - if type(bin) == str: from miasm.core.bin_stream import bin_stream - bin = bin_stream(bin) - init_offset = bin.offset try: @@ -2295,8 +2294,7 @@ if __name__ == '__main__': instr = x86mnemo.dis('0fa9'.replace(' ', '').decode('hex'), - admode=x86_afs.u16, - opmode=x86_afs.u16) + {"admode":x86_afs.u16,"opmode":x86_afs.u16}) print instr print instr.arg print instr.l diff --git a/miasm/arch/java_arch.py b/miasm/arch/java_arch.py index 3672b778..fe673513 100644 --- a/miasm/arch/java_arch.py +++ b/miasm/arch/java_arch.py @@ -392,25 +392,25 @@ mnemonic('iflt', 155, 3, "if 'value' is less than 0, branch to the 16-bit instru class java_mnemo_metaclass(type): rebuilt_inst = False - - def dis(cls, op, admode=None, sex=0, offset=0, ): + + def dis(cls, op, attrib = {} ): i = cls.__new__(cls) - i.__init__(sex) - u = i._dis(op, offset) + i.__init__(0) + u = i._dis(op) if not u: return None return i - + def asm(cls, l, symbol_reloc_off={}, sex=0, address=0): i = cls.__new__(cls) i.__init__(sex) return i._asm(l, symbol_reloc_off, address=address) - + def asm_instr(cls, l, sex=0): i = cls.__new__(cls) i.__init__(sex) i._asm_instr(l) return i - + def fix_symbol(cls, a, symbol_pool = None): if not AFS_symb in a: return a cp = a.copy() @@ -420,9 +420,9 @@ class java_mnemo_metaclass(type): cp[AFS_imm] = 0 return cp raise Exception('.fix_symbol() cannot handle that for now (and should not have too do so).') - + def is_mem(cls, a): return False - + def get_label(cls, a): if not AFS_symb in a: return None @@ -433,22 +433,22 @@ class java_mnemo_metaclass(type): if n[k] != 1: return None return k - + def has_symb(cls, a): return AFS_symb in a - + def get_symbols(cls, a): if AFS_symb in a: return a[AFS_symb].items() return None - + def names2symbols(cls, a, s_dict): all_s = a[AFS_symb] for name, s in s_dict.items(): count = all_s[name] del(all_s[name]) all_s[s] = count - + def parse_address(cls, a): if a.isdigit(): return {AFS_imm: int(a)} return {AFS_symb: {a: 1}} @@ -457,18 +457,20 @@ class java_mnemo_metaclass(type): class java_mn: __metaclass__ = java_mnemo_metaclass def __init__(self, sex=0): - self.sex = sex - + self.sex = 0 + def get_attrib(self): + return {} + def breakflow(self): return self.m.breakflow def splitflow(self): return self.m.splitflow def dstflow(self): return self.m.dstflow - + def getnextflow(self): return self.offset + self.m.size - + def getdstflow(self): if len(self.arg) == 1: dsts = [ self.arg[0] ] @@ -485,7 +487,7 @@ class java_mn: else: out.append(d) return out - + def setdstflow(self, dst): if len(self.arg) == 1: self.arg = [{AFS_symb:{dst[0]:1}}] @@ -493,7 +495,7 @@ class java_mn: self.arg = [dst[0], self.arg[1], self.arg[2]] + dst[1:] elif self.m.name == 'lookupswitch': self.arg = [dst[0], self.arg[1]] + reduce(lambda x, y: x+y, [ [self.arg[2*i+2], dst[i+1]] for i in range(len(dst)-1) ]) - + def fixdst(self, lbls, my_offset, is_mem): dsts = [0] if self.m.name == 'tableswitch': @@ -510,20 +512,20 @@ class java_mn: self.fixsize() newarg.append({AFS_imm:offset-(my_offset)+self.m.size}) self.arg = newarg - + def fixsize(self): if self.m.name.endswith('switch'): self.size = 4 * len(self.arg) + 1 # opcode + args self.size += ((4 - ((self.offset+1) % 4)) % 4) # align else: raise ValueError(".fixsize() should not be called for %s." % self.m.name) - + def set_args_symbols(self, cpsymbols={}): self.arg = self.m.argfmt.resolve(self.arg, cpsymbols=cpsymbols) - + def is_subcall(self): return self.m.name.startswith('jsr') or self.m.name.startswith('invoke') - + def __str__(self): arg = [] for a in self.arg: @@ -550,21 +552,21 @@ class java_mn: out += "\n".join([" %-8s %s" % (str(arg[2*i+2])+':', arg[2*i+3]) for i in range(len(arg)/2-1) ]) return out return "%-15s" % self.m.name + " ".join(map(str, arg)) - - def _dis(self, bin, offset=0): + + def _dis(self, bin): if type(bin) is str: from miasm.core.bin_stream import bin_stream bin = bin_stream(bin) - self.offset = bin.offset + offset + self.offset = bin.offset try: self.m = mnemo_db[ord(bin.readbs(1))] self.arg = self.m.argfmt.get(bin, sex=self.sex, address=self.offset) - self.l = bin.offset + offset - self.offset + self.l = bin.offset - self.offset except Exception as e: log.warning(e.message) return False return True - + @classmethod def parse_mnemo(cls, txt): if ';' in txt: txt = txt[:txt.index(';')] @@ -579,13 +581,13 @@ class java_mn: t.append(r+l) r = '' return None, t[0], t[1:] - + def _asm_instr(self, txt, address=0): p, mn, t = self.parse_mnemo(txt) self.m = mnemo_db_name[mn] self.arg = t self.offset = address - + def _asm(self, txt, symbol_reloc_off={}, address=0): p, mn, t = self.parse_mnemo(txt) mnemo = mnemo_db_name[mn] diff --git a/miasm/arch/ppc_arch.py b/miasm/arch/ppc_arch.py index 94c564ad..455dbebf 100644 --- a/miasm/arch/ppc_arch.py +++ b/miasm/arch/ppc_arch.py @@ -443,7 +443,7 @@ class ppc_mnemo_metaclass(type): raise ValueError('ambiquity %s'%str(ret)) - def dis(cls, bin, *kargs): + def dis(cls, bin, attrib = {}): if type(bin) == str: bin = bin_stream(bin) elif not isinstance(bin, bin_stream): @@ -786,6 +786,9 @@ class ppc_mn(object): self.parse_args(full_mnemo) + def get_attrib(self): + return {} + def parse_opts(self, rest): if rest: raise ValueError('should not have rest here ', rest) diff --git a/miasm/core/asmbloc.py b/miasm/core/asmbloc.py index b18c331a..e68d89ff 100644 --- a/miasm/core/asmbloc.py +++ b/miasm/core/asmbloc.py @@ -49,12 +49,11 @@ class asm_label: def __init__(self, name = "", offset = None): self.next = "next" - self.noattrib = "noattrib" self.fixedblocs = False if is_int(name): name = "loc_%.16X"%(int(name)&0xFFFFFFFFFFFFFFFF) self.name = name - self.attrib = self.noattrib + self.attrib = None if offset == None: self.offset = offset else: @@ -144,18 +143,38 @@ class asm_symbol_pool: self.s = {} self.s_offset = {} - - def remove(self, l): - if l.name in self.s: - del(self.s[l.name]) - if l.offset != None and l.offset in self.s_offset: - del(self.s_offset[l.offset]) - - def add(self, l): - if l.name in self.s: - raise ValueError('symbol already exist %r'%l) - self.s[l.name] = l - self.s_offset[l.offset] = l + def add(self, obj): + """ + obj can be an asm_label or an offset + """ + if not isinstance(obj, asm_label): + # whatever obj is, it will be an offset + offset = int(obj) + if offset in self.s_offset: + raise ValueError('symbol offset already exist %r'%offset) + obj = asm_label(offset, offset) + if obj.name in self.s: + raise ValueError('symbol already exist %r'%obj) + self.s[obj.name] = obj + if obj.offset != None: + self.s_offset[obj.offset] = obj + + def remove(self, obj): + """ + obj can be an asm_label or an offset + """ + if isinstance(obj, asm_label): + if obj.name in self.s: + del(self.s[obj.name]) + if obj.offset != None and obj.offset in self.s_offset: + del(self.s_offset[obj.offset]) + else: + offset = int(obj) + if offset in self.s_offset: + obj = self.s_offset[offset] + del(self.s_offset[offset]) + if obj.name in self.s: + del(self.s[obj.name]) def del_offset(self, l = None): if l: @@ -204,6 +223,20 @@ class asm_symbol_pool: def __str__(self): return reduce(lambda x,y: x+str(y)+'\n', [self.s[l] for l in self.s], "") + def __in__(self, obj): + if obj in self.s: + return True + if obj in self.s_offset: + return True + return False + def __getitem__(self, item): + if item in self.s: + return self.s[item] + if item in self.s_offset: + return self.s_offset[item] + raise KeyError('unknown symbol %r'%item) + + class interval(): # addrs represent interval using the form: # [start_addr1, stop_addr1[ U [start_addr2, stop_addr2[ U ... @@ -222,7 +255,7 @@ def dis_bloc(mnemo, pool_bin, cur_bloc, offset, job_done, symbol_pool, dont_dis = [], follow_call = False, patch_instr_symb = True, dontdis_retcall = False, lines_wd = None, dis_bloc_callback = None, dont_dis_nulstart_bloc = False, - **kargs): + attrib = {}): pool_bin.offset = offset lines_cpt = 0 while True: @@ -259,7 +292,7 @@ def dis_bloc(mnemo, pool_bin, cur_bloc, offset, job_done, symbol_pool, break try: - instr = mnemo.dis(pool_bin, **kargs) + instr = mnemo.dis(pool_bin, attrib) except StandardError, e: log_asmbloc.warning(e) instr = None @@ -355,7 +388,7 @@ def dis_bloc_all(mnemo, pool_bin, offset, job_done, symbol_pool, dont_dis = [], follow_call = False, patch_instr_symb = True, dontdis_retcall = False, bloc_wd = None, lines_wd = None, all_bloc = None, dis_bloc_callback = None, dont_dis_nulstart_bloc = False, - **kargs): + attrib = {}): log_asmbloc.info("dis bloc all") if all_bloc == None: all_bloc = [] @@ -394,7 +427,7 @@ def dis_bloc_all(mnemo, pool_bin, offset, job_done, symbol_pool, dont_dis = [], dis_bloc_callback = dis_bloc_callback, lines_wd = lines_wd, dont_dis_nulstart_bloc = dont_dis_nulstart_bloc, - **kargs) + attrib = attrib) all_bloc.append(cur_bloc) diff --git a/miasm/tools/codenat.py b/miasm/tools/codenat.py index 6eebeef3..dc934e4c 100644 --- a/miasm/tools/codenat.py +++ b/miasm/tools/codenat.py @@ -21,7 +21,7 @@ from hashlib import md5 from ctypes import * from miasm.tools.to_c_helper import * -from miasm.tools.emul_lib import libcodenat_interface +from miasm.tools.emul_lib import libcodenat_interface # interrupt with eip update after instr @@ -71,7 +71,7 @@ class bloc_nat: blocs_nat = {} def gen_C_module(c_source): - + lib_name = 'emul_cache/out_'+md5(c_source).hexdigest() lib_dir = os.path.dirname(os.path.realpath(__file__)) lib_dir = os.path.join(lib_dir, 'emul_lib') @@ -82,7 +82,7 @@ def gen_C_module(c_source): a = cdll.LoadLibrary('./%s.so'%lib_name) except: a = None - if a == None: + if a == None: open(lib_name+'.c', 'w').write(c_source) gcc_opts = " -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes " @@ -93,7 +93,7 @@ def gen_C_module(c_source): gcc_opts += ' -L%s -lcodenat '%lib_dir gcc_opts_end = ' -Wl,-rpath,%s '%lib_dir os.system('gcc ' + gcc_opts + '%s.o -o %s.so '%(lib_name, lib_name) + gcc_opts_end) - + a = cdll.LoadLibrary('%s.so'%lib_name) return a @@ -106,14 +106,14 @@ def del_bloc_in_range(known_blocs, ad1, ad2): # XXX no lines in bloc? if not bn.b.lines: continue - + if bn.b.lines[0].offset>=ad2 or bn.b.lines[-1].offset + bn.b.lines[-1].l <= ad1: #bloc_out.append(b) bloc_out[ad] = bn else: #print 'inv bloc', bn.b.label pass - + return bloc_out diff --git a/miasm/tools/func_analyser.py b/miasm/tools/func_analyser.py index aa34964b..2b801358 100755 --- a/miasm/tools/func_analyser.py +++ b/miasm/tools/func_analyser.py @@ -68,7 +68,7 @@ def read_dll_export(dll_name, func_name): if not fname in dll_pe_cache: print 'not loaded dll' init_dll_cache(fname) - + pe = dll_pe_cache[fname] """ pe = pefile.PE(fname) @@ -88,7 +88,7 @@ def read_dll_export(dll_name, func_name): symbol_pool_tmp = asm_symbol_pool() all_bloc_tmp = dis_bloc_all(x86mnemo, in_str_tmp, in_str_tmp.offset, [], symbol_pool_tmp, follow_call = False) ret = quick_ret_analyse(offset, all_bloc_tmp) - + return ret @@ -130,23 +130,23 @@ def dump_pool(p): for x in p: print x, p[x] print '\\_____________/' - + def hook_mem_read(evaluator, src): evaluator.log.warn('mem read %s'%str(src)) src_address = evaluator.eval_expr(src.arg, {}) src_address = evaluator.simp_full_exp(src_address) src_address = evaluator.simp_expr_arith_final(src_address) - + print 'test read',src_address, evaluator.simp_expr_arith_final(src_address) dump_pool(evaluator.pool[MEM_GLOB]) - + if not str(src_address) in evaluator.pool[MEM_GLOB]: evaluator.log.warning('unkown read address:%s'%src_address) return ExprMem(src_address, size = src.size) return evaluator.pool[MEM_GLOB][str(src_address)] - + def hook_mem_write(evaluator, dst, src, pool_out): evaluator.log.warn("mem write: %s %s"%(str(dst), str(src))) @@ -160,8 +160,8 @@ def hook_mem_write(evaluator, dst, src, pool_out): dump_pool(evaluator.pool[MEM_GLOB]) - - + + #set unkown stack for all blocks for b in all_bloc: b.eval_start,b.eval_stop = None, None @@ -170,27 +170,27 @@ for b in all_bloc: l.stack_h_after = None - + #first bloc start at 0 #esp_init_arg= 0x1000 evaluator = eval_int({esp:esp_i, ebp:ebp_i, eax:eax_i, ebx:ebx_i, ecx:ecx_i, edx:edx_i, esi:esi_i, edi:edi_i, cs:9, - zf : 0, - nf : 0, - pf : 0, - of : 0, - cf : 0, - tf : 0, - i_f: 0, - df : 0, - af : 0, + zf : 0, + nf : 0, + pf : 0, + of : 0, + cf : 0, + tf : 0, + i_f: 0, + df : 0, + af : 0, iopl: 3, - nt : 0, - rf : 0, - vm : 0, - ac : 0, - vif: 0, - vip: 0, + nt : 0, + rf : 0, + vm : 0, + ac : 0, + vif: 0, + vip: 0, i_d: 0, MEM_GLOB:{}, }, @@ -231,7 +231,7 @@ def is_func_wrapper(ad, pool_import_func = {}): print instr if instr.m.name in ['jmp'] and is_address(instr.arg[0]): return True - + return False #is simply import call? @@ -260,14 +260,14 @@ def is_import_call(offset, eval_arg, symbol_pool, pool_import_func = {}): evaluator_tmp.eval_instr(e) if eip in evaluator_tmp.pool: - n_eip = evaluator_tmp.pool[eip] + n_eip = evaluator_tmp.pool[eip] if type(n_eip) in [int, long]: offset = n_eip continue if not isinstance(n_eip, ExprMem): return False, None ad = evaluator_tmp.eval_expr(n_eip.arg, {}) - + if not type(ad) in [int, long]: return False, None if not ad in pool_import_func: @@ -283,11 +283,11 @@ def is_import_call(offset, eval_arg, symbol_pool, pool_import_func = {}): unstack = read_dll_export(dll_name, func_name) print "result:",unstack #unstack = known_func[pool_import_func[ad].name].unstack - + return True, unstack iiiopop #offset = in_str_tmp.offset - + def stack_h(b, symbol_pool, pool_import_func = {}): @@ -298,10 +298,10 @@ def stack_h(b, symbol_pool, pool_import_func = {}): #m.stack_h = evaluator_tmp.pool[esp] m.stack_h = evaluator.simp_expr_arith_final(evaluator_tmp.pool[esp]) print hex(m.offset), m.stack_h, str(m) - - + + if m.m.name in ['call']: - + """ #hack call next code if m.offset+m.l == s.offset: @@ -324,13 +324,13 @@ def stack_h(b, symbol_pool, pool_import_func = {}): if not s: return None - + if is_func_wrapper(s): return evaluator_tmp - + in_str_tmp = bin_stream(f, s.offset) - + job_done_tmp = [] symbol_pool_tmp = asm_symbol_pool() all_bloc_tmp = dis_bloc_all(x86mnemo, in_str_tmp, in_str_tmp.offset, job_done_tmp, symbol_pool_tmp, follow_call = False) @@ -347,20 +347,20 @@ def stack_h(b, symbol_pool, pool_import_func = {}): ret = e else: return None - + #decal found int if type(ret) in [int, long]: evaluator_tmp.pool[esp]=evaluator_tmp.eval_expr(ExprOp('+', evaluator_tmp.pool[esp], ret), {}) return evaluator_tmp - + if m.m.name in jcc: continue args = [dict_to_Expr(x, m.m.modifs) for x in m.arg] - + e = mnemo_func[m.m.name](*args) - + print "exprs:" for x in e: print x @@ -370,8 +370,8 @@ def stack_h(b, symbol_pool, pool_import_func = {}): ret = evaluator_tmp.eval_expr(eip, {}) if ret == 'ret_addr': m.stack_h_after = evaluator.simp_expr_arith_final(evaluator_tmp.pool[esp]) - - + + return evaluator_tmp @@ -383,9 +383,9 @@ def get_expr_diff(evaluator, a, b): if not type(a_e) in [int, long] or not type(b_e) in [int, long]: return None return b_e-a_e - - - + + + def resolve_func(all_bloc_arg, symbol_pool, pool_import_func): @@ -400,16 +400,16 @@ def resolve_func(all_bloc_arg, symbol_pool, pool_import_func): if next.label in all_bloc_dict and all_bloc_dict[next.label].eval_start!=None: b.eval_stop = all_bloc_dict[next.label].eval_start force_stack_h = True - + for x in b.bto: if x.label in all_bloc_dict and all_bloc_dict[x.label].eval_start==None: all_bloc_dict[x.label].eval_start = all_bloc_dict[next.label].eval_start fini = False - + if b.eval_start == None and b.eval_stop != None: #try to find stack decal and inform start print "tttt", hex(b.lines[0].offset) - + b.eval_start = b.eval_stop tmp = stack_h(b, symbol_pool, pool_import_func) print '_____',tmp @@ -426,10 +426,10 @@ def resolve_func(all_bloc_arg, symbol_pool, pool_import_func): b.eval_start = tmp print 'decal found ', b.label, decal fini = False - + if b.eval_start == None: continue - + if b.eval_stop != None and not force_stack_h: continue @@ -444,10 +444,10 @@ def resolve_func(all_bloc_arg, symbol_pool, pool_import_func): print next all_bloc_dict[next.label].eval_start = b.eval_stop fini = False - + if fini: break - + lines = reduce(lambda x,y:x+y.lines, all_bloc_arg, []) return None @@ -461,7 +461,7 @@ for b in all_bloc: if not b.eval_stop or not b.eval_start: print b.label, 'unresolved bloc' continue - + #print b.label, esp_init-b.eval_start.pool[esp] #if eip in b.eval_stop.pool: # print 'end at:', b.eval_stop.pool[eip], esp_init-b.eval_stop.pool[esp] @@ -475,7 +475,7 @@ for o, l in lines: print "%-20s"%str(l.stack_h), "%-20s"%str(l.stack_h_after), l #print "%-5s"%str(l.stack_h) #print l.arg - + """ for b in all_bloc: for l in b.lines: diff --git a/miasm/tools/hook_helper.py b/miasm/tools/hook_helper.py index 3caca584..da740e02 100755 --- a/miasm/tools/hook_helper.py +++ b/miasm/tools/hook_helper.py @@ -29,14 +29,14 @@ import sys class hooks(): def name2str(self, n): return "str_%s"%n - + def __init__(self, in_str, symbol_pool, gen_data_log_code = True): self.in_str = in_str self.all_bloc = [[]] self.symbol_pool = symbol_pool if gen_data_log_code: self.all_bloc, self.symbol_pool = parse_asm.parse_txt(x86mnemo,''' - + f_name: .string "out.txt" f_handle: @@ -47,15 +47,15 @@ class hooks(): .long 0xDEADBEEF mtick: .long 0xdeadbeef - - + + log_name_data_len: push ebp mov ebp, esp pushad - - - + + + mov eax, [f_handle] test eax, eax jnz write_file_2 @@ -70,22 +70,22 @@ class hooks(): push ebx call [CreateFileA] mov [f_handle], eax - + ;; create lock push my_critic_sec call [InitializeCriticalSection] - + write_file_2: ;; lock push my_critic_sec call [EnterCriticalSection] - - + + ;; write log name push [ebp+8] call [lstrlenA] inc eax - + push 0 lea ebx, [write_ret] push ebx @@ -93,7 +93,7 @@ class hooks(): push [ebp+8] push [f_handle] call [WriteFile] - + ;; write tickcount call [GetTickCount] @@ -106,8 +106,8 @@ class hooks(): push ebx push [f_handle] call [WriteFile] - - + + ;; write data size push 0 lea ebx, [write_ret] @@ -117,8 +117,8 @@ class hooks(): push ebx push [f_handle] call [WriteFile] - - + + ;;write data push 0 lea ebx, [write_ret] @@ -127,26 +127,26 @@ class hooks(): push [ebp+0xc] push [f_handle] call [WriteFile] - + ;; unlock push my_critic_sec call [LeaveCriticalSection] - - + + popad mov esp, ebp pop ebp ret 0xc - + ''', symbol_pool = symbol_pool) - - + + def add_hook(self, hook_ad, args_to_hook = {}, vars_decl = [], func_code = "", post_hook = ""): wrapper_name = "wrapper_%.8X"%hook_ad wrapper_log_name = "wrapper_log_%.8X"%hook_ad patch_name = "patch_%.8X"%hook_ad patch_end_name = "patch_end_%.8X"%hook_ad - + log_name = "log_%.8X"%hook_ad string_decl = [] @@ -158,7 +158,7 @@ class hooks(): continue string_decl.append('%s:\n.string "%s"'%(self.name2str(s), s)) string_decl = "\n".join(string_decl) - + lines, total_bytes = asmbloc.steal_bytes(self.in_str, x86_mn, hook_ad, 5) erased_asm = "\n".join([str(l) for l in lines]) @@ -191,7 +191,7 @@ class hooks(): %s: push ebp mov ebp, esp - + '''%(log_name) asm_s += func_code +'\n' @@ -215,7 +215,7 @@ class hooks(): asm_s +=""" pop ebp ret %d - + """%(len(to_hook)*4) asm_s +=""" @@ -224,13 +224,13 @@ class hooks(): %s: .split """%(patch_name, wrapper_name, patch_end_name) - + #print asm_s all_bloc, self.symbol_pool = parse_asm.parse_txt(x86mnemo,asm_s, symbol_pool = self.symbol_pool) self.all_bloc[0] += all_bloc[0] return log_name - - - + + + diff --git a/miasm/tools/pe_helper.py b/miasm/tools/pe_helper.py index 21e06d2b..9c600165 100644 --- a/miasm/tools/pe_helper.py +++ b/miasm/tools/pe_helper.py @@ -37,7 +37,7 @@ from collections import defaultdict pe_cache = {} def pe_from_name(n): global pe_cache - + my_path = 'win_dll/' all_pe = os.listdir(my_path) if not n in all_pe: @@ -88,10 +88,10 @@ def guess_func_destack_dis(e, ad): job_done = set() symbol_pool = asmbloc.asm_symbol_pool() in_str = bin_stream(e.virt) - + all_bloc = asmbloc.dis_bloc_all(x86_mn, in_str, ad, job_done, symbol_pool, follow_call = False, patch_instr_symb = False) return guess_func_destack(all_bloc) - + def guess_imports_ret_unstack(e): unresolved = set() @@ -100,13 +100,13 @@ def guess_imports_ret_unstack(e): for i,s in enumerate(e.DirImport.impdesc): l = "%2d %-25s %s"%(i, repr(s.dlldescname) ,repr(s)) libname = s.dlldescname.name - - + + for ii, f in enumerate(s.impbynames): print '_'*20 funcname = f.name - - + + my_e, ret = func_from_import(libname.lower(), funcname) if ret: func_addr = my_e.rva2virt(ret.rva) @@ -114,14 +114,14 @@ def guess_imports_ret_unstack(e): else: print 'not found' continue - + #XXX python int obj len zarb bug imgb = my_e.NThdr.ImageBase if imgb>0x80000000: imgb-=0x40000000 func_addr-=0x40000000 my_e.NThdr.ImageBase = imgb - + if not is_rva_in_code_section(my_e, ret.rva): print "not in code section" continue @@ -290,6 +290,7 @@ def code_is_jmp_imp(e, ad, imp_d): return is_jmp_imp(l, imp_d) + # giving e and address in function guess function start def guess_func_start(in_str, line_ad, max_offset = 0x200): ad = line_ad+1 @@ -330,7 +331,6 @@ def guess_func_start(in_str, line_ad, max_offset = 0x200): if func_addrs.issubset(job_done): return ad_found - def get_nul_term(e, ad): out = "" while True: diff --git a/miasm/tools/seh_helper.py b/miasm/tools/seh_helper.py index 6b0fc9de..141df78d 100644 --- a/miasm/tools/seh_helper.py +++ b/miasm/tools/seh_helper.py @@ -218,7 +218,7 @@ def build_fake_inordermodule(modules_name): return o - + all_seh_ad = dict([(x, None) for x in xrange(FAKE_SEH_B_AD, FAKE_SEH_B_AD+0x1000, 0x20)]) #http://blog.fireeye.com/research/2010/08/download_exec_notes.html def init_seh(): @@ -275,16 +275,16 @@ def ctxt2regs(ctxt): ctxt = ctxt[4:] #regs['seg_ds'] = updw(ctxt[:4]) ctxt = ctxt[4:] - + regs['edi'], regs['esi'], regs['ebx'], regs['edx'], regs['ecx'], regs['eax'], regs['ebp'], regs['eip'] = struct.unpack('I'*8, ctxt[:4*8]) ctxt = ctxt[4*8:] #regs['seg_cs'] = updw(ctxt[:4]) ctxt = ctxt[4:] - + #regs['eflag'] = updw(ctxt[:4]) ctxt = ctxt[4:] - + regs['esp'] = updw(ctxt[:4]) ctxt = ctxt[4:] @@ -320,30 +320,30 @@ def fake_seh_handler(except_code): regs = vm_get_gpreg() print '-> exception at', hex(regs['eip']), seh_count seh_count += 1 - + # Help lambda p = lambda s: struct.pack('I', s) - + dump_gpregs_py() # Forge a CONTEXT ctxt = '\x00\x00\x00\x00' + '\x00\x00\x00\x00' * 6 + '\x00' * 112 + '\x00\x00\x00\x00' + '\x3b\x00\x00\x00' + '\x23\x00\x00\x00' + '\x23\x00\x00\x00' + p(regs['edi']) + p(regs['esi']) + p(regs['ebx']) + p(regs['edx']) + p(regs['ecx']) + p(regs['eax']) + p(regs['ebp']) + p(regs['eip']) + '\x23\x00\x00\x00' + '\x00\x00\x00\x00' + p(regs['esp']) + '\x23\x00\x00\x00' #ctxt = regs2ctxt(regs) - + # Find a room for seh #seh = (get_memory_page_max_address_py()+0x1000)&0xfffff000 # Get current seh (fs:[0]) seh_ptr = vm_read_dword(tib_address) - + # Retrieve seh fields old_seh, eh, safe_place = struct.unpack('III', vm_get_str(seh_ptr, 0xc)) - + print '-> seh_ptr', hex(seh_ptr), '-> { old_seh', hex(old_seh), 'eh', hex(eh), 'safe_place', hex(safe_place), '}' #print '-> write SEH at', hex(seh&0xffffffff) - + # Write current seh #vm_add_memory_page(seh, PAGE_READ | PAGE_WRITE, p(old_seh) + p(eh) + p(safe_place) + p(0x99999999)) - + # Write context vm_set_mem(context_address, ctxt) @@ -351,7 +351,7 @@ def fake_seh_handler(except_code): """ #http://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx - + typedef struct _EXCEPTION_RECORD { DWORD ExceptionCode; DWORD ExceptionFlags; @@ -361,7 +361,7 @@ def fake_seh_handler(except_code): ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; } EXCEPTION_RECORD, *PEXCEPTION_RECORD; """ - + vm_set_mem(exception_record_address, p(except_code) + p(0) + p(0) + p(regs['eip']) + p(0) + p(0) ) # Prepare the stack @@ -369,29 +369,29 @@ def fake_seh_handler(except_code): vm_push_uint32_t(seh_ptr) # SEH vm_push_uint32_t(exception_record_address) # ExceptRecords vm_push_uint32_t(return_from_exception) # Ret address - - - + + + # Set fake new current seh for exception fake_seh_ad = get_free_seh_place() print hex(fake_seh_ad) vm_set_mem(fake_seh_ad, p(seh_ptr) + p(0xaaaaaaaa) + p(0xaaaaaabb) + p(0xaaaaaacc)) vm_set_mem(tib_address, p(fake_seh_ad)) - + dump_seh() - + print '-> jumping at', hex(eh) to_c_helper.vm_reset_exception() - - + + regs = vm_get_gpreg() #XXX set ebx to nul? regs['ebx'] = 0 vm_set_gpreg(regs) - + return eh - + fake_seh_handler.base = FAKE_SEH_B_AD diff --git a/miasm/tools/win_api.py b/miasm/tools/win_api.py index ce46094c..741f1c7f 100644 --- a/miasm/tools/win_api.py +++ b/miasm/tools/win_api.py @@ -288,53 +288,53 @@ def kernel32_GetCurrentProcessId(): process_list = [ [ - 0x40, #DWORD dwSize; - 0, #DWORD cntUsage; - winobjs.dw_pid_dummy1, #DWORD th32ProcessID; - 0x11111111, #ULONG_PTR th32DefaultHeapID; - 0x11111112, #DWORD th32ModuleID; - 1, #DWORD cntThreads; + 0x40, #DWORD dwSize; + 0, #DWORD cntUsage; + winobjs.dw_pid_dummy1, #DWORD th32ProcessID; + 0x11111111, #ULONG_PTR th32DefaultHeapID; + 0x11111112, #DWORD th32ModuleID; + 1, #DWORD cntThreads; winobjs.dw_pid_explorer, #DWORD th32ParentProcessID; - 0xbeef, #LONG pcPriClassBase; - 0x0, #DWORD dwFlags; + 0xbeef, #LONG pcPriClassBase; + 0x0, #DWORD dwFlags; "dummy1.exe" #TCHAR szExeFile[MAX_PATH]; ], [ - 0x40, #DWORD dwSize; - 0, #DWORD cntUsage; - winobjs.dw_pid_explorer, #DWORD th32ProcessID; - 0x11111111, #ULONG_PTR th32DefaultHeapID; - 0x11111112, #DWORD th32ModuleID; - 1, #DWORD cntThreads; + 0x40, #DWORD dwSize; + 0, #DWORD cntUsage; + winobjs.dw_pid_explorer, #DWORD th32ProcessID; + 0x11111111, #ULONG_PTR th32DefaultHeapID; + 0x11111112, #DWORD th32ModuleID; + 1, #DWORD cntThreads; 4, #DWORD th32ParentProcessID; - 0xbeef, #LONG pcPriClassBase; - 0x0, #DWORD dwFlags; + 0xbeef, #LONG pcPriClassBase; + 0x0, #DWORD dwFlags; "explorer.exe" #TCHAR szExeFile[MAX_PATH]; ], [ - 0x40, #DWORD dwSize; - 0, #DWORD cntUsage; - winobjs.dw_pid_dummy2, #DWORD th32ProcessID; - 0x11111111, #ULONG_PTR th32DefaultHeapID; - 0x11111112, #DWORD th32ModuleID; - 1, #DWORD cntThreads; + 0x40, #DWORD dwSize; + 0, #DWORD cntUsage; + winobjs.dw_pid_dummy2, #DWORD th32ProcessID; + 0x11111111, #ULONG_PTR th32DefaultHeapID; + 0x11111112, #DWORD th32ModuleID; + 1, #DWORD cntThreads; winobjs.dw_pid_explorer, #DWORD th32ParentProcessID; - 0xbeef, #LONG pcPriClassBase; - 0x0, #DWORD dwFlags; + 0xbeef, #LONG pcPriClassBase; + 0x0, #DWORD dwFlags; "dummy2.exe" #TCHAR szExeFile[MAX_PATH]; ], [ - 0x40, #DWORD dwSize; - 0, #DWORD cntUsage; - winobjs.dw_pid_cur, #DWORD th32ProcessID; - 0x11111111, #ULONG_PTR th32DefaultHeapID; - 0x11111112, #DWORD th32ModuleID; - 1, #DWORD cntThreads; + 0x40, #DWORD dwSize; + 0, #DWORD cntUsage; + winobjs.dw_pid_cur, #DWORD th32ProcessID; + 0x11111111, #ULONG_PTR th32DefaultHeapID; + 0x11111112, #DWORD th32ModuleID; + 1, #DWORD cntThreads; winobjs.dw_pid_explorer, #DWORD th32ParentProcessID; - 0xbeef, #LONG pcPriClassBase; - 0x0, #DWORD dwFlags; + 0xbeef, #LONG pcPriClassBase; + 0x0, #DWORD dwFlags; winobjs.module_name #TCHAR szExeFile[MAX_PATH]; ], |