def __extract_member_from_pointer(self, cexpr, obj): parents_type = map(lambda x: idaapi.get_ctype_name(x.cexpr.op), list(self.parents)[:0:-1]) parents = map(lambda x: x.cexpr, list(self.parents)[:0:-1]) logger.debug("Parsing expression {}. Parents - {}".format( obj.name, parents_type)) # Extracting offset and removing expression parents making this offset if parents_type[0] in ('idx', 'add'): # `obj[idx]' or `(TYPE *) + x' if parents[0].y.op != idaapi.cot_num: # There's no way to handle with dynamic offset return offset = parents[0].y.numval() * cexpr.type.get_ptrarr_objsize() cexpr = self.parent_expr() if parents_type[0] == 'add': del parents_type[0] del parents[0] elif parents_type[0:2] == ['cast', 'add']: # (TYPE *)obj + offset or (TYPE)obj + offset if parents[1].y.op != idaapi.cot_num: return if parents[0].type.is_ptr(): size = parents[0].type.get_ptrarr_objsize() else: size = 1 offset = parents[1].theother(parents[0]).numval() * size cexpr = parents[1] del parents_type[0:2] del parents[0:2] else: offset = 0 return self.__extract_member(cexpr, obj, offset, parents, parents_type)
def __extract_member_from_xword(self, cexpr, obj): parents_type = [idaapi.get_ctype_name(x.cexpr.op) for x in list(self.parents)[:0:-1]] parents = [x.cexpr for x in list(self.parents)[:0:-1]] logger.debug("Parsing expression {}. Parents - {}".format(obj.name, parents_type)) if parents_type[0] == 'add': if parents[0].theother(cexpr).op != idaapi.cot_num: return offset = parents[0].theother(cexpr).numval() cexpr = self.parent_expr() del parents_type[0] del parents[0] else: offset = 0 return self.__extract_member(cexpr, obj, offset, parents, parents_type)
def __extract_member_from_xword(self, cexpr, obj): parents_type = map(lambda x: idaapi.get_ctype_name(x.cexpr.op), list(self.parents)[:0:-1]) #0为null,所以需跳过 parents = map(lambda x: x.cexpr, list(self.parents)[:0:-1]) logger.debug("Parsing expression {}. Parents - {}".format( obj.name, parents_type)) if parents_type[0] == 'add': ocexptr = parents[0].theother(cexpr) if ocexptr.op != idaapi.cot_num: return offset = ocexptr.numval() cexpr = self.parent_expr() del parents_type[0] del parents[0] else: offset = 0 return self.__extract_member(cexpr, obj, offset, parents, parents_type)
def check_member_assignment(self, expression, index): """ We are now in cexpr_t == idaapi.cot_var. This function checks if expression is part of member assignment statement. Returns None if not. :param expression: idaapi.cexpr_t :param index: int :return: Structures.AbstractField """ parents_type = map(lambda x: idaapi.get_ctype_name(x.cexpr.op), list(self.parents)[:0:-1]) parents = map(lambda x: x.cexpr, list(self.parents)[:0:-1]) for parent in parents: if parent.ea != idaapi.BADADDR: self.expression_address = parent.ea break else: self.expression_address = idaapi.BADADDR offset = 0 if parents_type[0:2] == ['asg', 'expr']: if parents[0].y == expression: # Assignment like (v1 = v2) where v2 is scanned variable if parents[0].x.op == idaapi.cot_var: self.add_variable(parents[0].x.v.idx) return else: # if expression is (var = something), we have to explore whether continue to scan this variable or not if parents[0].y.op != idaapi.cot_num: if parents[0].y.op == idaapi.cot_call: # Check if expression: var = function((TYPE) var, ...) or var = function(var, ...) args = parents[0].y.a if args and ((args[0].op == idaapi.cot_cast and args[0].x.op == idaapi.cot_var and args[0].x.v.idx == index) or (args[0].op == idaapi.cot_var and args[0].v.idx == index)): return try: self.protected_variables.remove(index) except KeyError: print "[Info] Remove variable {0} from scan list, address: 0x{1:08X}".format( index, self.expression_address) self.variables.pop(index) return # Assignment like v1 = (TYPE) v2 where TYPE is one the supported types elif parents_type[0:3] == ['cast', 'asg', 'expr']: if parents[1].x.op == idaapi.cot_var: if filter(lambda x: x.equals_to(parents[0].type), Const.LEGAL_TYPES): self.add_variable(parents[1].x.v.idx) return # Universal call with no cast conversion and offsets: call(..., this, ...) if parents_type[0] == 'call': arg_index, _ = Helper.get_func_argument_info( parents[0], expression) if SCAN_ALL_ARGUMENTS or not arg_index: self.scan_function(parents[0].x.obj_ea, 0, arg_index) return # -------------------------------------------------------------------------------------------- # When variable is DWORD, int, __int64 etc # -------------------------------------------------------------------------------------------- elif self.variables[index].equals_to(Const.X_WORD_TINFO): if parents_type[0:2] == ['add', 'cast']: if parents[0].theother(expression).op != idaapi.cot_num: return offset = parents[0].theother(expression).numval() if parents_type[2] == 'ptr': if parents_type[3] == 'asg': if parents[3].x == parents[2]: # *(TYPE *)(var + x) = ??? return self.get_member( offset, index, object=parents[3].y, default=parents[1].type.get_pointed_object()) if parents[3].x.op == idaapi.cot_var: # other_var = *(TYPE *)(var + x) return self.create_member(offset, index, parents[3].x.type) return self.create_member( offset, index, parents[1].type.get_pointed_object()) elif parents_type[2] == 'call': # call(..., (TYPE)(var + x), ...) if parents[0].theother(expression).op != idaapi.cot_num: return offset = parents[0].theother(expression).numval() return self.get_member(offset, index, call=parents[2], arg=parents[1]) elif parents_type[2] == 'asg': # other_var = (LEGAL TYPE) (var + offset) if parents[2].y == parents[1] and parents[ 2].x.op == idaapi.cot_var: if filter(lambda x: x.equals_to(parents[1].type), Const.LEGAL_TYPES): self.scan_function(self.function.entry_ea, offset, parents[2].x.v.idx) return cast_type = parents[1].type if cast_type.is_ptr(): return self.create_member(offset, index, cast_type.get_pointed_object()) elif parents_type[0:2] == ['cast', 'ptr']: if parents_type[2] == 'asg' and parents[2].x == parents[1]: # *(TYPE *)var = ??? return self.get_member( 0, index, object=parents[2].y, default=parents[0].type.get_pointed_object()) return self.create_member(0, index, parents[0].type.get_pointed_object()) elif parents_type[0:2] == ['cast', 'call']: # call(..., (TYPE)(var + x), ...) return self.get_member(0, index, call=parents[1], arg=parents[0]) elif parents_type[0] == 'add': # call(..., var + x, ...) if parents[0].theother(expression).op != idaapi.cot_num: return offset = parents[0].theother(expression).numval() if parents_type[1] == 'call': return self.get_member(offset, index, call=parents[1], arg=parents[0]) elif parents_type[1] == 'asg': if parents[1].y == parents[0] and parents[ 1].x.op == idaapi.cot_var: self.scan_function(self.function.entry_ea, offset, parents[1].x.v.idx) return elif parents_type[0] == 'asg': # var = (int)&Some_object if parents[0].y.op == idaapi.cot_cast and parents[ 0].y.x.op == idaapi.cot_ref: return self.create_member( 0, index, parents[0].y.x.type.get_pointed_object()) # -------------------------------------------------------------------------------------------- # When variable is void *, PVOID, DWORD *, QWORD * etc # -------------------------------------------------------------------------------------------- else: # print "[DEBUG] D* Parents:", parents_type offset = 0 if parents_type[0] == 'idx': if parents[0].y.op != idaapi.cot_num: # There's no way to handle with dynamic offset return None offset = parents[0].y.numval( ) * self.variables[index].get_ptrarr_objsize() if parents_type[1] == 'asg' and parents[1].x == parents[0]: # var[idx] = ??? return self.get_member( offset, index, object=parents[1].y, default=self.variables[index].get_pointed_object()) elif parents_type[1] == 'cast': # (TYPE) var[idx] return self.create_member(offset, index, parents[1].type) return self.create_member(offset, index, Const.X_WORD_TINFO) elif parents_type[0:2] == ['ptr', 'asg']: # *var = ??? return self.get_member( 0, index, object=parents[1].y, default=self.variables[index].get_pointed_object()) else: if parents_type[0:2] == ['cast', 'ptr']: if parents_type[2] == 'call': # call(..., *(TYPE *) var, ...) return self.get_member(0, index, call=parents[2], arg=parents[1]) elif parents_type[2] == 'asg' and parents[2].x == parents[ 1]: # *(TYPE *) var = ??? return self.get_member( 0, index, object=parents[2].y, default=parents[0].type.get_pointed_object()) elif parents_type[0:2] == ['cast', 'add']: if parents[1].theother(parents[0]).op != idaapi.cot_num: return None offset = parents[1].theother(parents[0]).numval() offset *= parents[0].type.get_ptrarr_objsize( ) if parents[0].type.is_ptr() else 1 if parents_type[2] == 'ptr': if parents_type[3] == 'asg' and parents[ 3].x == parents[2]: # *((TYPE *)var + x) = ??? return self.get_member( offset, index, object=parents[3].y, default=parents[0].type.get_pointed_object()) return self.create_member( offset, index, parents[0].type.get_pointed_object()) elif parents_type[2] == 'call': # call(..., (TYPE)var + offset, ...) return self.get_member(offset, index, call=parents[2], arg=parents[1]) elif parents_type[2] == 'cast' and parents[2].type.is_ptr( ): if parents_type[3] == 'call': # call(..., (TYPE *) ((TYPE *)var + x), ...) # Where argument type is not the same as cast type. Ida has a bug here choosing sometimes # wrong pointer type idx, tinfo = Helper.get_func_argument_info( parents[3], parents[2]) return self.create_member( offset, index, tinfo.get_pointed_object()) # (TYPE *) ((TYPE *)var + x) return self.create_member( offset, index, parents[2].type.get_pointed_object()) elif parents_type[0:2] == ['add', 'cast']: if parents[0].theother(expression).op != idaapi.cot_num: return None offset = parents[0].theother(expression).numval( ) * self.variables[index].get_ptrarr_objsize() if parents_type[2] == 'call': # call(..., (TYPE)(var + x), ...) return self.get_member(offset, index, call=parents[2], arg=parents[1]) elif parents_type[2] == 'asg': if parents[2].y == parents[1] and parents[ 2].x.op == idaapi.cot_var: if filter(lambda x: x.equals_to(parents[1].type), Const.LEGAL_TYPES): self.scan_function(self.function.entry_ea, offset, parents[2].x.v.idx) return else: return self.create_member( offset, index, parents[1].type.get_pointed_object()) elif parents_type[0] == 'add': # call(..., var + offset, ...) if parents[0].theother(expression).op != idaapi.cot_num: return None offset = parents[0].theother(expression).numval( ) * self.variables[index].get_ptrarr_objsize() if parents_type[1] == 'call': return self.get_member(offset, index, call=parents[1], arg=parents[0]) if parents_type[1] == 'asg': # other_var = var + offset if parents[1].y == parents[0] and parents[ 1].x.op == idaapi.cot_var: self.scan_function(self.function.entry_ea, offset, parents[1].x.v.idx) return elif parents_type[0:2] == ['cast', 'call']: # call(..., (TYPE) var, ...) return self.get_member(0, index, call=parents[1], arg=parents[0]) elif parents_type[0] == 'ptr': if parents_type[1] == 'cast': # (TYPE) *var return self.create_member(0, index, parents[0].type) # *var return self.create_member( 0, index, self.variables[index].get_pointed_object()) elif parents_type[0] == 'asg': return if 'return' not in parents_type[0:2] and parents_type[0] not in ( 'if', 'band', 'eq', 'ne', 'cast'): print "[DEBUG] Unhandled type", self.variables[index].dstr(), \ "Index:", index, \ "Offset:", offset, \ "Function:", idaapi.get_ea_name(self.function.entry_ea), \ "Address: 0x{0:08X}".format(expression.ea), \ "Parents:", parents_type