Python distorm3.Decompose() Examples
The following are 28
code examples of distorm3.Decompose().
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example.
You may also want to check out all available functions/classes of the module
distorm3
, or try the search function
.
Example #1
Source File: Instruction.py From VMAttack with MIT License | 6 votes |
def __init__(self, offset, code, type = distorm3.Decode32Bits, feature = 0): """ @param offset Address of the instruction @param code Opcode bytes of the instruction @param type Dissassemble 32 or 64 bit code @param feature Possible settings for distrom3 not used at the moment """ self.valid = False if SV.dissassm_type == 64: type = distorm3.Decode64Bits else: type = distorm3.Decode32Bits inst = distorm3.Decompose(offset, code, type, feature) if len(inst) == 1: self.Instruction = inst[0] if self.Instruction.valid: self.valid = True self.opcode_len = len(code) self.opcode_bytes = [] self.addr = offset for x in code: self.opcode_bytes.append(ord(x)) self._len = len(self.Instruction.operands) + 1
Example #2
Source File: code_parser.py From writeups with GNU General Public License v3.0 | 6 votes |
def find_rr_writes_distorm3(address, data): writes = [] for insn in distorm3.Decompose(address, data, type=distorm3.Decode64Bits): if insn.mnemonic[:3] == 'RET': break if insn.mnemonic[:3] != 'MOV': continue # potential write opnd = insn.operands[0] if opnd.type != 'AbsoluteMemory' or opnd.index is None: continue # Absolute mov, with target that is register-based if distorm3.Registers[opnd.index] != 'RIP': continue # RIP-relative write, this is what we are looking for # distorm3 opnd.size is measured in bits, need to adjust to bytes writes.append((insn.address + insn.size + opnd.disp, opnd.size / 8)) return writes # Find rip-relative mov using capstone
Example #3
Source File: static_deobfuscate.py From VMAttack with MIT License | 5 votes |
def get_distorm_info(inst_addr): """ @brief Prints whole distrom3 info of the given instruction @param inst_addr Address of instruction """ size = ItemSize(inst_addr) inst_bytes = GetManyBytes(inst_addr, size) inst = distorm3.Decompose(inst_addr, inst_bytes, distorm3.Decode64Bits, 0) print inst[0] i = inst[0] print 'InstBytes ', i.instructionBytes print 'Opcode ', i.opcode for o in i.operands: print 'operand ', o print 'operand type', o.type for f in i.flags: print 'flag ', f print 'raw_flags ', i.rawFlags print 'inst_class ', i.instructionClass print 'flow_control ', i.flowControl print 'address ', i.address print 'size ', i.size print 'dt ', i.dt print 'valid ', i.valid print 'segment ', i.segment print 'unused_Prefixes ', i.unusedPrefixesMask print 'mnemonic ', i.mnemonic print 'inst_class ', i.instructionClass
Example #4
Source File: apihooks_kernel.py From DAMM with GNU General Public License v2.0 | 5 votes |
def isPrologInlined(self, model, distorm_mode, func_addr): ##check if function prologs are modified inlined = False content = self.addr_space.read(func_addr, 24) op_cnt = 1 for op in distorm3.Decompose(func_addr, content, distorm_mode): if op_cnt == 2: if model == "32bit": if (op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].type == "Register" and op.operands[1].type == "Register" and op.operands[0].name == "EBP" and op.operands[1].name == "ESP" and prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "EBP"): pass else: inlined = True elif model == "64bit": if (op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].type == "Register" and op.operands[1].type == "Register" and op.operands[0].name == "RBP" and op.operands[1].name == "RSP" and prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "RBP"): pass elif (prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "RBP" and op.mnemonic == "PUSH" and len(op.operands) == 1 and op.operands[0].type == "Register" and op.operands[0].name in ["RSP","RBX","R12","R13","R14","R15"]): # Registers preserved across calls, http://people.freebsd.org/~lstewart/references/amd64.pdf pass else: inlined = True break prev_op = op op_cnt += 1 return inlined # NOTES FROM ANDREW # This function orignally checked for any call outside the kernel module # This produces too many false positives so its modified to check if the call # is to a known module or a kernel symbol
Example #5
Source File: check_syscall.py From DAMM with GNU General Public License v2.0 | 5 votes |
def _get_table_info_distorm(self): """ Find the size of the system call table by disassembling functions that immediately reference it in their first isntruction This is in the form 'cmp reg,NR_syscalls' """ table_size = 0 if not has_distorm: return table_size memory_model = self.addr_space.profile.metadata.get('memory_model', '32bit') if memory_model == '32bit': mode = distorm3.Decode32Bits func = "sysenter_do_call" else: mode = distorm3.Decode64Bits func = "system_call_fastpath" func_addr = self.addr_space.profile.get_symbol(func) if func_addr: data = self.addr_space.read(func_addr, 6) for op in distorm3.Decompose(func_addr, data, mode): if not op.valid: continue if op.mnemonic == 'CMP': table_size = (op.operands[1].value) & 0xffffffff break return table_size
Example #6
Source File: check_syscall.py From aumfor with GNU General Public License v3.0 | 5 votes |
def _get_table_info_distorm(self): """ Find the size of the system call table by disassembling functions that immediately reference it in their first isntruction This is in the form 'cmp reg,NR_syscalls' """ table_size = 0 if not has_distorm: return table_size memory_model = self.addr_space.profile.metadata.get('memory_model', '32bit') if memory_model == '32bit': mode = distorm3.Decode32Bits func = "sysenter_do_call" else: mode = distorm3.Decode64Bits func = "system_call_fastpath" func_addr = self.addr_space.profile.get_symbol(func) if func_addr: data = self.addr_space.read(func_addr, 6) for op in distorm3.Decompose(func_addr, data, mode): if not op.valid: continue if op.mnemonic == 'CMP': table_size = (op.operands[1].value) & 0xffffffff break return table_size
Example #7
Source File: apihooks_kernel.py From vortessence with GNU General Public License v2.0 | 5 votes |
def isPrologInlined(self, model, distorm_mode, func_addr): ##check if function prologs are modified inlined = False content = self.addr_space.read(func_addr, 24) op_cnt = 1 for op in distorm3.Decompose(func_addr, content, distorm_mode): if op_cnt == 2: if model == "32bit": if (op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].type == "Register" and op.operands[1].type == "Register" and op.operands[0].name == "EBP" and op.operands[1].name == "ESP" and prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "EBP"): pass else: inlined = True elif model == "64bit": if (op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].type == "Register" and op.operands[1].type == "Register" and op.operands[0].name == "RBP" and op.operands[1].name == "RSP" and prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "RBP"): pass elif (prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "RBP" and op.mnemonic == "PUSH" and len(op.operands) == 1 and op.operands[0].type == "Register" and op.operands[0].name in ["RSP","RBX","R12","R13","R14","R15"]): # Registers preserved across calls, http://people.freebsd.org/~lstewart/references/amd64.pdf pass else: inlined = True break prev_op = op op_cnt += 1 return inlined # NOTES FROM ANDREW # This function orignally checked for any call outside the kernel module # This produces too many false positives so its modified to check if the call # is to a known module or a kernel symbol
Example #8
Source File: check_syscall.py From vortessence with GNU General Public License v2.0 | 5 votes |
def _get_table_info_distorm(self): """ Find the size of the system call table by disassembling functions that immediately reference it in their first isntruction This is in the form 'cmp reg,NR_syscalls' """ table_size = 0 if not has_distorm: return table_size memory_model = self.addr_space.profile.metadata.get('memory_model', '32bit') if memory_model == '32bit': mode = distorm3.Decode32Bits func = "sysenter_do_call" else: mode = distorm3.Decode64Bits func = "system_call_fastpath" func_addr = self.addr_space.profile.get_symbol(func) if func_addr: data = self.addr_space.read(func_addr, 6) for op in distorm3.Decompose(func_addr, data, mode): if not op.valid: continue if op.mnemonic == 'CMP': table_size = (op.operands[1].value) & 0xffffffff break return table_size
Example #9
Source File: check_syscall.py From volatility with GNU General Public License v2.0 | 5 votes |
def _get_table_info_distorm(self): """ Find the size of the system call table by disassembling functions that immediately reference it in their first isntruction This is in the form 'cmp reg,NR_syscalls' """ table_size = 0 if not has_distorm: return table_size memory_model = self.addr_space.profile.metadata.get('memory_model', '32bit') if memory_model == '32bit': mode = distorm3.Decode32Bits func = "sysenter_do_call" else: mode = distorm3.Decode64Bits func = "system_call_fastpath" func_addr = self.addr_space.profile.get_symbol(func) if func_addr: data = self.addr_space.read(func_addr, 6) for op in distorm3.Decompose(func_addr, data, mode): if not op.valid: continue if op.mnemonic == 'CMP': table_size = (op.operands[1].value) & 0xffffffff break return table_size
Example #10
Source File: apihooks_kernel.py From volatility with GNU General Public License v2.0 | 5 votes |
def isPrologInlined(self, model, distorm_mode, func_addr): ##check if function prologs are modified inlined = False content = self.addr_space.read(func_addr, 24) op_cnt = 1 for op in distorm3.Decompose(func_addr, content, distorm_mode): if op_cnt == 2: if model == "32bit": if (op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].type == "Register" and op.operands[1].type == "Register" and op.operands[0].name == "EBP" and op.operands[1].name == "ESP" and prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "EBP"): pass else: inlined = True elif model == "64bit": if (op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].type == "Register" and op.operands[1].type == "Register" and op.operands[0].name == "RBP" and op.operands[1].name == "RSP" and prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "RBP"): pass elif (prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "RBP" and op.mnemonic == "PUSH" and len(op.operands) == 1 and op.operands[0].type == "Register" and op.operands[0].name in ["RSP","RBX","R12","R13","R14","R15"]): # Registers preserved across calls, http://people.freebsd.org/~lstewart/references/amd64.pdf pass else: inlined = True break prev_op = op op_cnt += 1 return inlined # NOTES FROM ANDREW # This function orignally checked for any call outside the kernel module # This produces too many false positives so its modified to check if the call # is to a known module or a kernel symbol
Example #11
Source File: apihooks_kernel.py From volatility with GNU General Public License v2.0 | 5 votes |
def isPrologInlined(self, model, distorm_mode, func_addr): ##check if function prologs are modified inlined = False content = self.addr_space.read(func_addr, 24) op_cnt = 1 for op in distorm3.Decompose(func_addr, content, distorm_mode): if op_cnt == 2: if model == "32bit": if (op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].type == "Register" and op.operands[1].type == "Register" and op.operands[0].name == "EBP" and op.operands[1].name == "ESP" and prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "EBP"): pass else: inlined = True elif model == "64bit": if (op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].type == "Register" and op.operands[1].type == "Register" and op.operands[0].name == "RBP" and op.operands[1].name == "RSP" and prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "RBP"): pass elif (prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "RBP" and op.mnemonic == "PUSH" and len(op.operands) == 1 and op.operands[0].type == "Register" and op.operands[0].name in ["RSP","RBX","R12","R13","R14","R15"]): # Registers preserved across calls, http://people.freebsd.org/~lstewart/references/amd64.pdf pass else: inlined = True break prev_op = op op_cnt += 1 return inlined # NOTES FROM ANDREW # This function orignally checked for any call outside the kernel module # This produces too many false positives so its modified to check if the call # is to a known module or a kernel symbol
Example #12
Source File: check_syscall.py From volatility with GNU General Public License v2.0 | 5 votes |
def _get_table_info_distorm(self): """ Find the size of the system call table by disassembling functions that immediately reference it in their first isntruction This is in the form 'cmp reg,NR_syscalls' """ table_size = 0 if not has_distorm: return table_size memory_model = self.addr_space.profile.metadata.get('memory_model', '32bit') if memory_model == '32bit': mode = distorm3.Decode32Bits funcs = ["sysenter_do_call"] else: mode = distorm3.Decode64Bits funcs = ["system_call_fastpath", "do_int80_syscall_32"] for func in funcs: func_addr = self.addr_space.profile.get_symbol(func) if func_addr: data = self.addr_space.read(func_addr, 64) for op in distorm3.Decompose(func_addr, data, mode): if not op.valid: continue if op.mnemonic == 'CMP': table_size = (op.operands[1].value) & 0xffffffff break break return table_size
Example #13
Source File: apihooks_kernel.py From aumfor with GNU General Public License v3.0 | 5 votes |
def isPrologInlined(self, model, distorm_mode, func_addr): ##check if function prologs are modified inlined = False content = self.addr_space.read(func_addr, 24) op_cnt = 1 for op in distorm3.Decompose(func_addr, content, distorm_mode): if op_cnt == 2: if model == "32bit": if (op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].type == "Register" and op.operands[1].type == "Register" and op.operands[0].name == "EBP" and op.operands[1].name == "ESP" and prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "EBP"): pass else: inlined = True elif model == "64bit": if (op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].type == "Register" and op.operands[1].type == "Register" and op.operands[0].name == "RBP" and op.operands[1].name == "RSP" and prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "RBP"): pass elif (prev_op.mnemonic == "PUSH" and len(prev_op.operands) == 1 and prev_op.operands[0].type == "Register" and prev_op.operands[0].name == "RBP" and op.mnemonic == "PUSH" and len(op.operands) == 1 and op.operands[0].type == "Register" and op.operands[0].name in ["RSP","RBX","R12","R13","R14","R15"]): # Registers preserved across calls, http://people.freebsd.org/~lstewart/references/amd64.pdf pass else: inlined = True break prev_op = op op_cnt += 1 return inlined # NOTES FROM ANDREW # This function orignally checked for any call outside the kernel module # This produces too many false positives so its modified to check if the call # is to a known module or a kernel symbol
Example #14
Source File: apihooks_kernel.py From volatility with GNU General Public License v2.0 | 4 votes |
def isCallReferenceModified(self, model, distorm_mode, func_addr, kernel_syms, kmods): # check if CALL targets are within the kernel/kext range to detect possible call reference modification modified = False #modified malware/apihooks.py/check_inline function data = self.addr_space.read(func_addr, 750) # Number of instructions disassembled so far n = 0 # Destination address of hooks d = None # Save the last PUSH before a CALL push_val = None # Save the general purpose registers regs = {} ops = [] for op in distorm3.Decompose(func_addr, data, distorm_mode): ops.append(op) for op in distorm3.Decompose(func_addr, data, distorm_mode): # Quit when a decomposition error is encountered # or when reach function end if not op.valid or op.mnemonic == "NOP": break if op.flowControl == 'FC_CALL': # Clear the push value if push_val: push_val = None if op.mnemonic == "CALL" and op.operands[0].type == 'AbsoluteMemoryAddress': # Check for CALL [ADDR] if model == '32bit': const = op.operands[0].disp & 0xFFFFFFFF d = obj.Object("unsigned int", offset = const, vm = self.addr_space) else: const = op.operands[0].disp d = obj.Object("unsigned long long", offset = const, vm = self.addr_space) if self.outside_module(d, kernel_syms, kmods): break elif op.operands[0].type == 'Immediate': # Check for CALL ADDR d = op.operands[0].value if self.outside_module(d, kernel_syms, kmods): break elif op.operands[0].type == 'Register': # Check for CALL REG d = regs.get(op.operands[0].name) if d and self.outside_module(d, kernel_syms, kmods): break n += 1 # filtering out false positives due to structs, you can tweak this as needed if d and self.outside_module(d, kernel_syms, kmods) == True and str(ops[n+1].mnemonic) not in ["DB 0xff", "ADD", "XCHG", "OUTS"]: modified = True return (modified, d)
Example #15
Source File: callbacks.py From DAMM with GNU General Public License v2.0 | 4 votes |
def get_registry_callbacks_legacy(nt_mod): """ Enumerate registry change callbacks. This method of finding a global variable via disassembly of the CmRegisterCallback function is only for XP systems. If it fails on XP you can still find the callbacks using PoolScanGenericCallback. On Vista and Windows 7, these callbacks are registered using the CmRegisterCallbackEx function. """ if not has_distorm3: return symbol = "CmRegisterCallback" # Get the RVA of the symbol from NT's EAT symbol_rva = nt_mod.getprocaddress(symbol) if symbol_rva == None: return # Absolute VA to the symbol code symbol_address = symbol_rva + nt_mod.DllBase # Read the function prologue data = nt_mod.obj_vm.zread(symbol_address, 200) c = 0 vector = None # Looking for MOV EBX, CmpCallBackVector # This may be the first or second MOV EBX instruction for op in distorm3.Decompose(symbol_address, data, distorm3.Decode32Bits): if (op.valid and op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].name == 'EBX'): vector = op.operands[1].value if c == 1: break else: c += 1 # Can't find the global variable if vector == None: return # The vector is an array of 100 _EX_FAST_REF objects addrs = obj.Object("Array", count = 100, offset = vector, vm = nt_mod.obj_vm, targetType = "_EX_FAST_REF") for addr in addrs: callback = addr.dereference_as("_EX_CALLBACK_ROUTINE_BLOCK") if callback: yield symbol, callback.Function, None
Example #16
Source File: check_syscall_shadow.py From volatility with GNU General Public License v2.0 | 4 votes |
def shadowedSyscalls(self, model, distorm_mode, sysents_addr): #looks like these syscall functions end with a call to _thread_exception_return thread_exc_ret_addr = self.addr_space.profile.get_symbol('_thread_exception_return') prev_op = None sysent_funcs = ['_unix_syscall_return', '_unix_syscall64', '_unix_syscall'] for func in sysent_funcs: func_addr = self.addr_space.profile.get_symbol(func) content = self.addr_space.read(func_addr, 1024) for op in distorm3.Decompose(func_addr, content, distorm_mode): if not op.valid: break if op.mnemonic == "CALL" and op.operands[0].value == thread_exc_ret_addr: break if model == "64bit": #callp = &sysent[63] OR &sysent[code] OR callp == sysent if op.mnemonic in ['ADD','CMP'] and op.operands[0].type == 'Register' and op.operands[0].name in ["RSP","RBX","R12","R13","R14","R15"] and 'FLAG_RIP_RELATIVE' in op.flags: #compare actual sysent tbl address to the one in the instruction, calculated per distorm3 INSTRUCTION_GET_RIP_TARGET op_sysent_ptr = obj.Object('Pointer', offset = (op.address + op.operands[1].disp + op.size), vm = self.addr_space) if sysents_addr != op_sysent_ptr.v(): print "not same: %x | %x" % (sysents_addr, op_sysent_ptr.v()) yield (op_sysent_ptr.v(), func, op) elif model == "32bit": #LEA EAX, [EAX*8+0x82ef20] if op.mnemonic == 'LEA' and op.operands[0].type == 'Register' and op.operands[0].name in ['EDI','EAX'] and distorm3.Registers[op.operands[1].index] == "EAX" and op.operands[1].scale == 8: if op.operands[1].disp != sysents_addr: shadowtbl_addr = op.operands[1].disp yield (shadowtbl_addr, func, op) break #CMP EAX, 0x82ef20 elif op.mnemonic == 'CMP' and op.operands[0].type == 'Register' and op.operands[0].name in ['EDI','EAX'] and prev_op.mnemonic in ['LEA','MOV'] and self.addr_space.is_valid_address(op.operands[1].value) == True: if op.operands[1].value != sysents_addr: shadowtbl_addr = op.operands[1].value yield (shadowtbl_addr, func, op) #CMP DWORD [EBP-0x20], 0x82ef20 elif op.mnemonic == 'CMP' and op.operands[0].index != None and distorm3.Registers[op.operands[0].index] == "EBP" and op.operands[0].disp == -32 and op.operands[0].type == "Immediate": if op.operands[1].value != sysents_addr: shadowtbl_addr = op.operands[1].value yield (shadowtbl_addr, func, op) prev_op = op
Example #17
Source File: callbacks.py From volatility with GNU General Public License v2.0 | 4 votes |
def get_registry_callbacks_legacy(nt_mod): """ Enumerate registry change callbacks. This method of finding a global variable via disassembly of the CmRegisterCallback function is only for XP systems. If it fails on XP you can still find the callbacks using PoolScanGenericCallback. On Vista and Windows 7, these callbacks are registered using the CmRegisterCallbackEx function. """ if not has_distorm3: return symbol = "CmRegisterCallback" # Get the RVA of the symbol from NT's EAT symbol_rva = nt_mod.getprocaddress(symbol) if symbol_rva == None: return # Absolute VA to the symbol code symbol_address = symbol_rva + nt_mod.DllBase # Read the function prologue data = nt_mod.obj_vm.zread(symbol_address, 200) c = 0 vector = None # Looking for MOV EBX, CmpCallBackVector # This may be the first or second MOV EBX instruction for op in distorm3.Decompose(symbol_address, data, distorm3.Decode32Bits): if (op.valid and op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].name == 'EBX'): vector = op.operands[1].value if c == 1: break else: c += 1 # Can't find the global variable if vector == None: return # The vector is an array of 100 _EX_FAST_REF objects addrs = obj.Object("Array", count = 100, offset = vector, vm = nt_mod.obj_vm, targetType = "_EX_FAST_REF") for addr in addrs: callback = addr.dereference_as("_EX_CALLBACK_ROUTINE_BLOCK") if callback: yield symbol, callback.Function, None
Example #18
Source File: check_syscall_shadow.py From DAMM with GNU General Public License v2.0 | 4 votes |
def shadowedSyscalls(self, model, distorm_mode, sysents_addr): #looks like these syscall functions end with a call to _thread_exception_return thread_exc_ret_addr = self.addr_space.profile.get_symbol('_thread_exception_return') prev_op = None sysent_funcs = ['_unix_syscall_return', '_unix_syscall64', '_unix_syscall'] for func in sysent_funcs: func_addr = self.addr_space.profile.get_symbol(func) content = self.addr_space.read(func_addr, 1024) for op in distorm3.Decompose(func_addr, content, distorm_mode): if not op.valid: break if op.mnemonic == "CALL" and op.operands[0].value == thread_exc_ret_addr: break if model == "64bit": #callp = &sysent[63] OR &sysent[code] OR callp == sysent if op.mnemonic in ['ADD','CMP'] and op.operands[0].type == 'Register' and op.operands[0].name in ["RSP","RBX","R12","R13","R14","R15"] and 'FLAG_RIP_RELATIVE' in op.flags: #compare actual sysent tbl address to the one in the instruction, calculated per distorm3 INSTRUCTION_GET_RIP_TARGET op_sysent_ptr = obj.Object('Pointer', offset = (op.address + op.operands[1].disp + op.size), vm = self.addr_space) if sysents_addr != op_sysent_ptr.v(): print "not same: %x | %x" % (sysents_addr, op_sysent_ptr.v()) yield (op_sysent_ptr.v(), func, op) elif model == "32bit": #LEA EAX, [EAX*8+0x82ef20] if op.mnemonic == 'LEA' and op.operands[0].type == 'Register' and op.operands[0].name in ['EDI','EAX'] and distorm3.Registers[op.operands[1].index] == "EAX" and op.operands[1].scale == 8: if op.operands[1].disp != sysents_addr: shadowtbl_addr = op.operands[1].disp yield (shadowtbl_addr, func, op) break #CMP EAX, 0x82ef20 elif op.mnemonic == 'CMP' and op.operands[0].type == 'Register' and op.operands[0].name in ['EDI','EAX'] and prev_op.mnemonic in ['LEA','MOV'] and self.addr_space.is_valid_address(op.operands[1].value) == True: if op.operands[1].value != sysents_addr: shadowtbl_addr = op.operands[1].value yield (shadowtbl_addr, func, op) #CMP DWORD [EBP-0x20], 0x82ef20 elif op.mnemonic == 'CMP' and op.operands[0].index != None and distorm3.Registers[op.operands[0].index] == "EBP" and op.operands[0].disp == -32 and op.operands[0].type == "Immediate": if op.operands[1].value != sysents_addr: shadowtbl_addr = op.operands[1].value yield (shadowtbl_addr, func, op) prev_op = op
Example #19
Source File: check_syscall_shadow.py From vortessence with GNU General Public License v2.0 | 4 votes |
def shadowedSyscalls(self, model, distorm_mode, sysents_addr): #looks like these syscall functions end with a call to _thread_exception_return thread_exc_ret_addr = self.addr_space.profile.get_symbol('_thread_exception_return') prev_op = None sysent_funcs = ['_unix_syscall_return', '_unix_syscall64', '_unix_syscall'] for func in sysent_funcs: func_addr = self.addr_space.profile.get_symbol(func) content = self.addr_space.read(func_addr, 1024) for op in distorm3.Decompose(func_addr, content, distorm_mode): if not op.valid: break if op.mnemonic == "CALL" and op.operands[0].value == thread_exc_ret_addr: break if model == "64bit": #callp = &sysent[63] OR &sysent[code] OR callp == sysent if op.mnemonic in ['ADD','CMP'] and op.operands[0].type == 'Register' and op.operands[0].name in ["RSP","RBX","R12","R13","R14","R15"] and 'FLAG_RIP_RELATIVE' in op.flags: #compare actual sysent tbl address to the one in the instruction, calculated per distorm3 INSTRUCTION_GET_RIP_TARGET op_sysent_ptr = obj.Object('Pointer', offset = (op.address + op.operands[1].disp + op.size), vm = self.addr_space) if sysents_addr != op_sysent_ptr.v(): print "not same: %x | %x" % (sysents_addr, op_sysent_ptr.v()) yield (op_sysent_ptr.v(), func, op) elif model == "32bit": #LEA EAX, [EAX*8+0x82ef20] if op.mnemonic == 'LEA' and op.operands[0].type == 'Register' and op.operands[0].name in ['EDI','EAX'] and distorm3.Registers[op.operands[1].index] == "EAX" and op.operands[1].scale == 8: if op.operands[1].disp != sysents_addr: shadowtbl_addr = op.operands[1].disp yield (shadowtbl_addr, func, op) break #CMP EAX, 0x82ef20 elif op.mnemonic == 'CMP' and op.operands[0].type == 'Register' and op.operands[0].name in ['EDI','EAX'] and prev_op.mnemonic in ['LEA','MOV'] and self.addr_space.is_valid_address(op.operands[1].value) == True: if op.operands[1].value != sysents_addr: shadowtbl_addr = op.operands[1].value yield (shadowtbl_addr, func, op) #CMP DWORD [EBP-0x20], 0x82ef20 elif op.mnemonic == 'CMP' and op.operands[0].index != None and distorm3.Registers[op.operands[0].index] == "EBP" and op.operands[0].disp == -32 and op.operands[0].type == "Immediate": if op.operands[1].value != sysents_addr: shadowtbl_addr = op.operands[1].value yield (shadowtbl_addr, func, op) prev_op = op
Example #20
Source File: apihooks_kernel.py From DAMM with GNU General Public License v2.0 | 4 votes |
def isCallReferenceModified(self, model, distorm_mode, func_addr, kernel_syms, kmods): # check if CALL targets are within the kernel/kext range to detect possible call reference modification modified = False #modified malware/apihooks.py/check_inline function data = self.addr_space.read(func_addr, 750) # Number of instructions disassembled so far n = 0 # Destination address of hooks d = None # Save the last PUSH before a CALL push_val = None # Save the general purpose registers regs = {} ops = [] for op in distorm3.Decompose(func_addr, data, distorm_mode): ops.append(op) for op in distorm3.Decompose(func_addr, data, distorm_mode): # Quit when a decomposition error is encountered # or when reach function end if not op.valid or op.mnemonic == "NOP": break if op.flowControl == 'FC_CALL': # Clear the push value if push_val: push_val = None if op.mnemonic == "CALL" and op.operands[0].type == 'AbsoluteMemoryAddress': # Check for CALL [ADDR] if model == '32bit': const = op.operands[0].disp & 0xFFFFFFFF d = obj.Object("unsigned int", offset = const, vm = self.addr_space) else: const = op.operands[0].disp d = obj.Object("unsigned long long", offset = const, vm = self.addr_space) if self.outside_module(d, kernel_syms, kmods): break elif op.operands[0].type == 'Immediate': # Check for CALL ADDR d = op.operands[0].value if self.outside_module(d, kernel_syms, kmods): break elif op.operands[0].type == 'Register': # Check for CALL REG d = regs.get(op.operands[0].name) if d and self.outside_module(d, kernel_syms, kmods): break n += 1 # filtering out false positives due to structs, you can tweak this as needed if d and self.outside_module(d, kernel_syms, kmods) == True and str(ops[n+1].mnemonic) not in ["DB 0xff", "ADD", "XCHG", "OUTS"]: modified = True return (modified, d)
Example #21
Source File: callbacks.py From vortessence with GNU General Public License v2.0 | 4 votes |
def get_registry_callbacks_legacy(nt_mod): """ Enumerate registry change callbacks. This method of finding a global variable via disassembly of the CmRegisterCallback function is only for XP systems. If it fails on XP you can still find the callbacks using PoolScanGenericCallback. On Vista and Windows 7, these callbacks are registered using the CmRegisterCallbackEx function. """ if not has_distorm3: return symbol = "CmRegisterCallback" # Get the RVA of the symbol from NT's EAT symbol_rva = nt_mod.getprocaddress(symbol) if symbol_rva == None: return # Absolute VA to the symbol code symbol_address = symbol_rva + nt_mod.DllBase # Read the function prologue data = nt_mod.obj_vm.zread(symbol_address, 200) c = 0 vector = None # Looking for MOV EBX, CmpCallBackVector # This may be the first or second MOV EBX instruction for op in distorm3.Decompose(symbol_address, data, distorm3.Decode32Bits): if (op.valid and op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].name == 'EBX'): vector = op.operands[1].value if c == 1: break else: c += 1 # Can't find the global variable if vector == None: return # The vector is an array of 100 _EX_FAST_REF objects addrs = obj.Object("Array", count = 100, offset = vector, vm = nt_mod.obj_vm, targetType = "_EX_FAST_REF") for addr in addrs: callback = addr.dereference_as("_EX_CALLBACK_ROUTINE_BLOCK") if callback: yield symbol, callback.Function, None
Example #22
Source File: apihooks_kernel.py From vortessence with GNU General Public License v2.0 | 4 votes |
def isCallReferenceModified(self, model, distorm_mode, func_addr, kernel_syms, kmods): # check if CALL targets are within the kernel/kext range to detect possible call reference modification modified = False #modified malware/apihooks.py/check_inline function data = self.addr_space.read(func_addr, 750) # Number of instructions disassembled so far n = 0 # Destination address of hooks d = None # Save the last PUSH before a CALL push_val = None # Save the general purpose registers regs = {} ops = [] for op in distorm3.Decompose(func_addr, data, distorm_mode): ops.append(op) for op in distorm3.Decompose(func_addr, data, distorm_mode): # Quit when a decomposition error is encountered # or when reach function end if not op.valid or op.mnemonic == "NOP": break if op.flowControl == 'FC_CALL': # Clear the push value if push_val: push_val = None if op.mnemonic == "CALL" and op.operands[0].type == 'AbsoluteMemoryAddress': # Check for CALL [ADDR] if model == '32bit': const = op.operands[0].disp & 0xFFFFFFFF d = obj.Object("unsigned int", offset = const, vm = self.addr_space) else: const = op.operands[0].disp d = obj.Object("unsigned long long", offset = const, vm = self.addr_space) if self.outside_module(d, kernel_syms, kmods): break elif op.operands[0].type == 'Immediate': # Check for CALL ADDR d = op.operands[0].value if self.outside_module(d, kernel_syms, kmods): break elif op.operands[0].type == 'Register': # Check for CALL REG d = regs.get(op.operands[0].name) if d and self.outside_module(d, kernel_syms, kmods): break n += 1 # filtering out false positives due to structs, you can tweak this as needed if d and self.outside_module(d, kernel_syms, kmods) == True and str(ops[n+1].mnemonic) not in ["DB 0xff", "ADD", "XCHG", "OUTS"]: modified = True return (modified, d)
Example #23
Source File: callbacks.py From volatility with GNU General Public License v2.0 | 4 votes |
def get_registry_callbacks_legacy(nt_mod): """ Enumerate registry change callbacks. This method of finding a global variable via disassembly of the CmRegisterCallback function is only for XP systems. If it fails on XP you can still find the callbacks using PoolScanGenericCallback. On Vista and Windows 7, these callbacks are registered using the CmRegisterCallbackEx function. """ if not has_distorm3: return symbol = "CmRegisterCallback" # Get the RVA of the symbol from NT's EAT symbol_rva = nt_mod.getprocaddress(symbol) if symbol_rva == None: return # Absolute VA to the symbol code symbol_address = symbol_rva + nt_mod.DllBase # Read the function prologue data = nt_mod.obj_vm.zread(symbol_address, 200) c = 0 vector = None # Looking for MOV EBX, CmpCallBackVector # This may be the first or second MOV EBX instruction for op in distorm3.Decompose(symbol_address, data, distorm3.Decode32Bits): if (op.valid and op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].name == 'EBX'): vector = op.operands[1].value if c == 1: break else: c += 1 # Can't find the global variable if vector == None: return # The vector is an array of 100 _EX_FAST_REF objects addrs = obj.Object("Array", count = 100, offset = vector, vm = nt_mod.obj_vm, targetType = "_EX_FAST_REF") for addr in addrs: callback = addr.dereference_as("_EX_CALLBACK_ROUTINE_BLOCK") if callback: yield symbol, callback.Function, None
Example #24
Source File: check_syscall_shadow.py From volatility with GNU General Public License v2.0 | 4 votes |
def shadowedSyscalls(self, model, distorm_mode, sysents_addr): #looks like these syscall functions end with a call to _thread_exception_return thread_exc_ret_addr = self.addr_space.profile.get_symbol('_thread_exception_return') prev_op = None sysent_funcs = ['_unix_syscall_return', '_unix_syscall64', '_unix_syscall'] for func in sysent_funcs: func_addr = self.addr_space.profile.get_symbol(func) content = self.addr_space.read(func_addr, 1024) for op in distorm3.Decompose(func_addr, content, distorm_mode): if not op.valid: break if op.mnemonic == "CALL" and op.operands[0].value == thread_exc_ret_addr: break if model == "64bit": #callp = &sysent[63] OR &sysent[code] OR callp == sysent if op.mnemonic in ['ADD','CMP'] and op.operands[0].type == 'Register' and op.operands[0].name in ["RSP","RBX","R12","R13","R14","R15"] and 'FLAG_RIP_RELATIVE' in op.flags: #compare actual sysent tbl address to the one in the instruction, calculated per distorm3 INSTRUCTION_GET_RIP_TARGET op_sysent_ptr = obj.Object('Pointer', offset = (op.address + op.operands[1].disp + op.size), vm = self.addr_space) if sysents_addr != op_sysent_ptr.v(): print "not same: %x | %x" % (sysents_addr, op_sysent_ptr.v()) yield (op_sysent_ptr.v(), func, op) elif model == "32bit": #LEA EAX, [EAX*8+0x82ef20] if op.mnemonic == 'LEA' and op.operands[0].type == 'Register' and op.operands[0].name in ['EDI','EAX'] and distorm3.Registers[op.operands[1].index] == "EAX" and op.operands[1].scale == 8: if op.operands[1].disp != sysents_addr: shadowtbl_addr = op.operands[1].disp yield (shadowtbl_addr, func, op) break #CMP EAX, 0x82ef20 elif op.mnemonic == 'CMP' and op.operands[0].type == 'Register' and op.operands[0].name in ['EDI','EAX'] and prev_op.mnemonic in ['LEA','MOV'] and self.addr_space.is_valid_address(op.operands[1].value) == True: if op.operands[1].value != sysents_addr: shadowtbl_addr = op.operands[1].value yield (shadowtbl_addr, func, op) #CMP DWORD [EBP-0x20], 0x82ef20 elif op.mnemonic == 'CMP' and op.operands[0].index != None and distorm3.Registers[op.operands[0].index] == "EBP" and op.operands[0].disp == -32 and op.operands[0].type == "Immediate": if op.operands[1].value != sysents_addr: shadowtbl_addr = op.operands[1].value yield (shadowtbl_addr, func, op) prev_op = op
Example #25
Source File: apihooks_kernel.py From volatility with GNU General Public License v2.0 | 4 votes |
def isCallReferenceModified(self, model, distorm_mode, func_addr, kernel_syms, kmods): # check if CALL targets are within the kernel/kext range to detect possible call reference modification modified = False #modified malware/apihooks.py/check_inline function data = self.addr_space.read(func_addr, 750) # Number of instructions disassembled so far n = 0 # Destination address of hooks d = None # Save the last PUSH before a CALL push_val = None # Save the general purpose registers regs = {} ops = [] for op in distorm3.Decompose(func_addr, data, distorm_mode): ops.append(op) for op in distorm3.Decompose(func_addr, data, distorm_mode): # Quit when a decomposition error is encountered # or when reach function end if not op.valid or op.mnemonic == "NOP": break if op.flowControl == 'FC_CALL': # Clear the push value if push_val: push_val = None if op.mnemonic == "CALL" and op.operands[0].type == 'AbsoluteMemoryAddress': # Check for CALL [ADDR] if model == '32bit': const = op.operands[0].disp & 0xFFFFFFFF d = obj.Object("unsigned int", offset = const, vm = self.addr_space) else: const = op.operands[0].disp d = obj.Object("unsigned long long", offset = const, vm = self.addr_space) if self.outside_module(d, kernel_syms, kmods): break elif op.operands[0].type == 'Immediate': # Check for CALL ADDR d = op.operands[0].value if self.outside_module(d, kernel_syms, kmods): break elif op.operands[0].type == 'Register': # Check for CALL REG d = regs.get(op.operands[0].name) if d and self.outside_module(d, kernel_syms, kmods): break n += 1 # filtering out false positives due to structs, you can tweak this as needed if d and self.outside_module(d, kernel_syms, kmods) == True and str(ops[n+1].mnemonic) not in ["DB 0xff", "ADD", "XCHG", "OUTS"]: modified = True return (modified, d)
Example #26
Source File: callbacks.py From aumfor with GNU General Public License v3.0 | 4 votes |
def get_registry_callbacks_legacy(nt_mod): """ Enumerate registry change callbacks. This method of finding a global variable via disassembly of the CmRegisterCallback function is only for XP systems. If it fails on XP you can still find the callbacks using PoolScanGenericCallback. On Vista and Windows 7, these callbacks are registered using the CmRegisterCallbackEx function. """ if not has_distorm3: return symbol = "CmRegisterCallback" # Get the RVA of the symbol from NT's EAT symbol_rva = nt_mod.getprocaddress(symbol) if symbol_rva == None: return # Absolute VA to the symbol code symbol_address = symbol_rva + nt_mod.DllBase # Read the function prologue data = nt_mod.obj_vm.zread(symbol_address, 200) c = 0 vector = None # Looking for MOV EBX, CmpCallBackVector # This may be the first or second MOV EBX instruction for op in distorm3.Decompose(symbol_address, data, distorm3.Decode32Bits): if (op.valid and op.mnemonic == "MOV" and len(op.operands) == 2 and op.operands[0].name == 'EBX'): vector = op.operands[1].value if c == 1: break else: c += 1 # Can't find the global variable if vector == None: return # The vector is an array of 100 _EX_FAST_REF objects addrs = obj.Object("Array", count = 100, offset = vector, vm = nt_mod.obj_vm, targetType = "_EX_FAST_REF") for addr in addrs: callback = addr.dereference_as("_EX_CALLBACK_ROUTINE_BLOCK") if callback: yield symbol, callback.Function, None
Example #27
Source File: check_syscall_shadow.py From aumfor with GNU General Public License v3.0 | 4 votes |
def shadowedSyscalls(self, model, distorm_mode, sysents_addr): #looks like these syscall functions end with a call to _thread_exception_return thread_exc_ret_addr = self.addr_space.profile.get_symbol('_thread_exception_return') prev_op = None sysent_funcs = ['_unix_syscall_return', '_unix_syscall64', '_unix_syscall'] for func in sysent_funcs: func_addr = self.addr_space.profile.get_symbol(func) content = self.addr_space.read(func_addr, 1024) for op in distorm3.Decompose(func_addr, content, distorm_mode): if not op.valid: break if op.mnemonic == "CALL" and op.operands[0].value == thread_exc_ret_addr: break if model == "64bit": #callp = &sysent[63] OR &sysent[code] OR callp == sysent if op.mnemonic in ['ADD','CMP'] and op.operands[0].type == 'Register' and op.operands[0].name in ["RSP","RBX","R12","R13","R14","R15"] and 'FLAG_RIP_RELATIVE' in op.flags: #compare actual sysent tbl address to the one in the instruction, calculated per distorm3 INSTRUCTION_GET_RIP_TARGET op_sysent_ptr = obj.Object('Pointer', offset = (op.address + op.operands[1].disp + op.size), vm = self.addr_space) if sysents_addr != op_sysent_ptr.v(): print "not same: %x | %x" % (sysents_addr, op_sysent_ptr.v()) yield (op_sysent_ptr.v(), func, op) elif model == "32bit": #LEA EAX, [EAX*8+0x82ef20] if op.mnemonic == 'LEA' and op.operands[0].type == 'Register' and op.operands[0].name in ['EDI','EAX'] and distorm3.Registers[op.operands[1].index] == "EAX" and op.operands[1].scale == 8: if op.operands[1].disp != sysents_addr: shadowtbl_addr = op.operands[1].disp yield (shadowtbl_addr, func, op) break #CMP EAX, 0x82ef20 elif op.mnemonic == 'CMP' and op.operands[0].type == 'Register' and op.operands[0].name in ['EDI','EAX'] and prev_op.mnemonic in ['LEA','MOV'] and self.addr_space.is_valid_address(op.operands[1].value) == True: if op.operands[1].value != sysents_addr: shadowtbl_addr = op.operands[1].value yield (shadowtbl_addr, func, op) #CMP DWORD [EBP-0x20], 0x82ef20 elif op.mnemonic == 'CMP' and op.operands[0].index != None and distorm3.Registers[op.operands[0].index] == "EBP" and op.operands[0].disp == -32 and op.operands[0].type == "Immediate": if op.operands[1].value != sysents_addr: shadowtbl_addr = op.operands[1].value yield (shadowtbl_addr, func, op) prev_op = op
Example #28
Source File: apihooks_kernel.py From aumfor with GNU General Public License v3.0 | 4 votes |
def isCallReferenceModified(self, model, distorm_mode, func_addr, kernel_syms, kmods): # check if CALL targets are within the kernel/kext range to detect possible call reference modification modified = False #modified malware/apihooks.py/check_inline function data = self.addr_space.read(func_addr, 750) # Number of instructions disassembled so far n = 0 # Destination address of hooks d = None # Save the last PUSH before a CALL push_val = None # Save the general purpose registers regs = {} ops = [] for op in distorm3.Decompose(func_addr, data, distorm_mode): ops.append(op) for op in distorm3.Decompose(func_addr, data, distorm_mode): # Quit when a decomposition error is encountered # or when reach function end if not op.valid or op.mnemonic == "NOP": break if op.flowControl == 'FC_CALL': # Clear the push value if push_val: push_val = None if op.mnemonic == "CALL" and op.operands[0].type == 'AbsoluteMemoryAddress': # Check for CALL [ADDR] if model == '32bit': const = op.operands[0].disp & 0xFFFFFFFF d = obj.Object("unsigned int", offset = const, vm = self.addr_space) else: const = op.operands[0].disp d = obj.Object("unsigned long long", offset = const, vm = self.addr_space) if self.outside_module(d, kernel_syms, kmods): break elif op.operands[0].type == 'Immediate': # Check for CALL ADDR d = op.operands[0].value if self.outside_module(d, kernel_syms, kmods): break elif op.operands[0].type == 'Register': # Check for CALL REG d = regs.get(op.operands[0].name) if d and self.outside_module(d, kernel_syms, kmods): break n += 1 # filtering out false positives due to structs, you can tweak this as needed if d and self.outside_module(d, kernel_syms, kmods) == True and str(ops[n+1].mnemonic) not in ["DB 0xff", "ADD", "XCHG", "OUTS"]: modified = True return (modified, d)