Skip to content

Commit

Permalink
Merge pull request #19 from ohreteam/koki
Browse files Browse the repository at this point in the history
tac builders, DCE add, local module load support

tac builders
DCE add
local module load support
field-related enhancement
recursive bug fix, but some still remained
  • Loading branch information
kokifish authored Feb 15, 2025
2 parents 18e32f5 + d54fe52 commit f729e7b
Show file tree
Hide file tree
Showing 17 changed files with 646 additions and 304 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ poetry.lock
diff.diff
bin/
pyvenv.cfg
test.py


# Byte-compiled / optimized / DLL files
Expand Down
29 changes: 15 additions & 14 deletions examples/dis_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
print(f">> {asmstr}")

# === reverse truly START
FUNC_IDX = 12 # 5: onWindowStageCreate, call loadContent and pass a mothod as para; 7: mothod that used as para
FUNC_IDX = 12
# print(f">> before CF {dis_file.methods[FUNC_IDX]._debug_vstr()}")
panda_re.split_native_code_block(FUNC_IDX)
# print(f">> CF built {panda_re.dis_file.methods[FUNC_IDX]._debug_vstr()}")
Expand All @@ -53,19 +53,19 @@
panda_re._code_lifting_algorithms(FUNC_IDX)
print(f">> after lifting {panda_re.dis_file.methods[FUNC_IDX]._debug_vstr()}")

# nac_total = panda_re.get_insts_total()
# for idx in range(panda_re.method_len()):
# panda_re.split_native_code_block(idx)
# print(f">> [{idx}/{panda_re.method_len()}] CF built {panda_re.dis_file.methods[idx]}")
# panda_re.trans_NAC_to_TAC(method_id=idx)
# tac_total = panda_re.get_insts_total()
# for idx in range(panda_re.method_len()):
# panda_re._code_lifting_algorithms(method_id=idx)
# print(f">> [{idx}/{panda_re.method_len()}] after lift {panda_re.dis_file.methods[idx]._debug_vstr()}")
# todo_tac = panda_re.get_tac_unknown_count()
# final_tac_total = panda_re.get_insts_total()
# print(f"todo_tac {todo_tac}/{tac_total} {todo_tac/tac_total:.4f} /nac /{nac_total} {todo_tac/nac_total:.4f}")
# print(f"lifting_algorithms {final_tac_total}/{tac_total} {final_tac_total/tac_total:.4f}")
nac_total = panda_re.get_insts_total()
for idx in range(panda_re.method_len()):
panda_re.split_native_code_block(idx)
panda_re.trans_NAC_to_TAC(method_id=idx)
tac_total = panda_re.get_insts_total()
for idx in range(panda_re.method_len()):
panda_re._code_lifting_algorithms(method_id=idx)
print(f">> [{idx}/{panda_re.method_len()}] after lift {panda_re.dis_file.methods[idx]._debug_vstr()}")
todo_tac, tac_opstr_set = panda_re.get_tac_unknown_count()
final_tac_total = panda_re.get_insts_total()
print(f"todo_tac {todo_tac}/{tac_total} {todo_tac/tac_total:.4f} /nac /{nac_total} {todo_tac/nac_total:.4f}")
print(f"lifting_algorithms {final_tac_total}/{tac_total} {final_tac_total/tac_total:.4f}")
print(f"tac_opstr_set {len(tac_opstr_set)} {tac_opstr_set}")

panda_re._module_analysis_algorithms()
print(f"\n\n panda_re.dis_file.modulevar_d {panda_re.dis_file.modulevar_d}")
Expand All @@ -75,5 +75,6 @@
content = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "\n\n"
for idx in range(panda_re.method_len()):
content += f">> [{idx}/{panda_re.method_len()}] after lift \n{panda_re.dis_file.methods[idx]._debug_vstr()}\n\n"
content += f"tac_opstr_set {len(tac_opstr_set)} {tac_opstr_set}"
file.write(content)
file.close()
108 changes: 77 additions & 31 deletions ohre/abcre/dis/AsmArg.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@

class AsmArg(DebugBase):
def __init__(self, arg_type: AsmTypes = AsmTypes.UNKNOWN,
name: str = "", value=None, ref_base=None, paras_len: int = None):
name="", value=None, ref_base=None, paras_len: int = None):
self.type = arg_type
# name: e.g. for v0, type is VAR, name is v0(stored without truncating the prefix v)
self.name: str = name
# type is FIELD/OBJECT: name maybe str or AsmArg
self.name: Union[str, AsmArg] = name
# value: may be set in the subsequent analysis
# type is ARRAY: value is list[AsmArg]
# type is OBJECT: value is list[AsmArg]: AsmArg(name:key, value:any value)
self.value = value
# type is OBJECT: value is dict str->AsmArg: key: str, value: AsmArg
self.value: Union[int, float, str, List[AsmArg], Dict[str, AsmArg]] = value
self.ref_base = ref_base # AsmArg
self.paras_len: Union[int, None] = paras_len # for method object, store paras len here
if (self.is_value_valid() == False):
Expand Down Expand Up @@ -65,25 +66,34 @@ def obj_has_key(self, key) -> bool:
key_name_str = key
else:
Log.error(f"ERROR! obj_has_key key {type(key)} {key}")
for arg in self.value:
if (key_name_str == arg.name):
for name in self.value.keys():
if (key_name_str == name):
return True
return False

def set_object_key_value(self, key: str, value: str, create=False) -> bool:
def set_object_key_value(self, key: str, value_arg, create=False) -> bool:
# value_arg: a AsmArg
if (not isinstance(value_arg, AsmArg)):
return False
if (self.type != AsmTypes.OBJECT):
return False
for arg in self.value:
if (key == arg.name):
arg.value = value
for name, arg in self.value.items():
if (key == name):
self.value[name] = value_arg
return True
if (create):
self.value[name] = value_arg
return True
return False

def set_ref(self, ref_ed_arg):
self.ref_base = ref_ed_arg
def set_ref(self, ref_ed_arg) -> bool:
if (isinstance(ref_ed_arg, AsmArg)):
self.ref_base = ref_ed_arg
return True
return False

def has_ref(self) -> bool:
if (self.ref_base is not None):
if (self.ref_base is not None and isinstance(self.ref_base, AsmArg)):
return True
else:
return False
Expand Down Expand Up @@ -125,23 +135,38 @@ def build_arr(cls, args: List, name: str = ""): # element of args should be Asm
return AsmArg(AsmTypes.ARRAY, name=name, value=list(args))

@classmethod
def build_object(cls, in_kv: Dict = None, name: str = "", ref_base=None): # element of args should be AsmArg
obj_value_l: List[AsmArg] = list()
def build_object(cls, in_kv: Dict = None, name: str = "", ref_base=None):
obj_value_d: Dict[str, AsmArg] = dict()
if (isinstance(in_kv, Iterable)):
for k, v in in_kv.items():
if (isinstance(v, int)):
obj_value_l.append(AsmArg(AsmTypes.IMM, name=k, value=v))
obj_value_d[k] = AsmArg(AsmTypes.IMM, value=v)
elif (isinstance(v, float)):
obj_value_l.append(AsmArg(AsmTypes.IMM, name=k, value=v))
obj_value_d[k] = AsmArg(AsmTypes.IMM, value=v)
elif (isinstance(v, str)):
obj_value_l.append(AsmArg(AsmTypes.FIELD, name=k, value=v))
obj_value_d[k] = AsmArg(AsmTypes.FIELD, value=v)
elif (v is None):
obj_value_l.append(AsmArg(AsmTypes.UNDEFINED, name=k, value=None))
obj_value_d[k] = AsmArg(AsmTypes.NULL)
else:
obj_value_d[k] = AsmArg(AsmTypes.UNDEFINED, value=v)
Log.error(f"ERROR! build_object k {k} {type(k)} v {v} {type(v)} name {name}")
if (len(obj_value_l) == 0):
obj_value_l = None
return AsmArg(AsmTypes.OBJECT, name=name, value=obj_value_l, ref_base=ref_base)
if (len(obj_value_d) == 0):
obj_value_d = None
return AsmArg(AsmTypes.OBJECT, name=name, value=obj_value_d, ref_base=ref_base)

@classmethod
def build_object_with_asmarg(cls, in_kv: Dict = None, name: str = "", ref_base=None):
# in_kv : k str, v AsmArg
obj_value_d: Dict[str, AsmArg] = dict()
if (isinstance(in_kv, Iterable)):
for k, v in in_kv.items():
if (isinstance(v, AsmArg)):
obj_value_d[k] = v
else:
Log.error(f"ERROR! build_object_with_asmarg k {k} {type(k)} v {v} {type(v)} v is not AsmArg")
if (len(obj_value_d) == 0):
obj_value_d = None
return AsmArg(AsmTypes.OBJECT, name=name, value=obj_value_d, ref_base=ref_base)

@classmethod
def build_FunctionObject(cls):
Expand All @@ -158,6 +183,20 @@ def build_this(cls):
# this always stored at a2
return AsmArg(AsmTypes.ARG, name="this")

@classmethod
def build_with_type(cls, ty: str, value: str):
if (AsmTypes.is_str(ty)):
return AsmArg(AsmTypes.STR, value=value)
if (AsmTypes.is_int(ty)):
if (value.isdigit()):
return AsmArg(AsmTypes.IMM, value=int(value))
if (AsmTypes.is_float(ty)):
if (utils.is_float(value)):
return AsmArg(AsmTypes.IMM, value=float(value))
if (ty == "null_value" and value == "0"):
return AsmArg(AsmTypes.NULL)
return AsmArg(AsmTypes.UNKNOWN, value=value)

def is_arg_this(self) -> bool:
if (self.type == AsmTypes.ARG and self.name == "this"):
return True
Expand Down Expand Up @@ -187,7 +226,7 @@ def is_value_valid(self) -> bool:
return True
return False
if (self.type == AsmTypes.OBJECT):
if (isinstance(self.value, Iterable)):
if (isinstance(self.value, dict)):
return True
return False
if (self.type == AsmTypes.FIELD):
Expand All @@ -205,7 +244,8 @@ def is_value_valid(self) -> bool:
if (isinstance(self.value, int)):
return True
return False
Log.error(f"is_value_valid NOT supported logic type {self.type_str} value {type(self.value)} {self.value}")
if (self.type != AsmTypes.UNKNOWN):
Log.error(f"is_value_valid NOT supported logic type {self.type_str} value {type(self.value)} {self.value}")
return True

def is_acc(self) -> bool:
Expand Down Expand Up @@ -292,7 +332,7 @@ def get_all_args_recursively(self, include_self: bool = True) -> List:

def _common_error_check(self):
if (self.type == AsmTypes.FIELD):
if (len(self.name) == 0):
if (isinstance(self.name, str) and len(self.name) == 0):
Log.error(f"[ArgCC] A filed name len==0: name {self.name} len {len(self.name)}")
if (self.type == AsmTypes.MODULE):
if (len(self.name) == 0):
Expand All @@ -307,23 +347,29 @@ def _common_error_check(self):
if (len(self.name) != 0 or (not isinstance(self.value, str))):
Log.error(f"[ArgCC] A str with name: {self.name} or value not str: {type(self.value)} {self.value}")

def _debug_str_obj(self, detail: bool = False, print_ref: bool = True) -> str:
def _debug_str_obj(self, detail: bool = False, print_ref: bool = True, visited=None) -> str:
visited = visited or set()
if id(self) in visited:
return "[Circular]"
visited.add(id(self))
out = ""
if (print_ref and self.ref_base is not None):
out += f"{self.ref_base}."
if (detail):
out += f"OBJ:{self.name}"
else:
out += f"{self.name}"
if (isinstance(self.value, Iterable)):
if (isinstance(self.value, dict)):
out += "{"
for i in range(len(self.value)):
if (isinstance(self.value[i].value, str)):
out += f"{self.value[i].name}:\"{self.value[i].value}\""
i = 0
for name, arg in self.value.items():
if (detail):
out += f"{name}: {arg._debug_vstr()}"
else:
out += f"{self.value[i].name}:{self.value[i].value}"
out += f"{name}: {arg}"
if (i < len(self.value) - 1):
out += ", "
i += 1
out += "}"
elif (self.value is not None):
if (isinstance(self.value, str)):
Expand Down
Loading

0 comments on commit f729e7b

Please sign in to comment.