collect runtime independant information about reflection
This commit is contained in:
parent
41da375abb
commit
fcba655f82
1 changed files with 60 additions and 8 deletions
|
|
@ -36,10 +36,18 @@ def check_app_result(
|
||||||
summary["nb_failed"] += 1
|
summary["nb_failed"] += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
|
does_reflection = False
|
||||||
|
boot_cl_id = ""
|
||||||
|
for cl in data["classloaders"]:
|
||||||
|
if cl["cname"] == "Ljava/lang/BootClassLoader;":
|
||||||
|
boot_cl_id = cl["id"]
|
||||||
|
|
||||||
reflections = []
|
reflections = []
|
||||||
nb_class_collision_at_invoke = 0
|
nb_class_collision_at_invoke = 0
|
||||||
seen = {}
|
seen = {}
|
||||||
for invoke_data in data["invoke_data"]:
|
for invoke_data in data["invoke_data"]:
|
||||||
|
if invoke_data["caller_cl_id"] != boot_cl_id:
|
||||||
|
does_reflection = True
|
||||||
call_site = (
|
call_site = (
|
||||||
invoke_data["caller_method"],
|
invoke_data["caller_method"],
|
||||||
invoke_data["caller_cl_id"],
|
invoke_data["caller_cl_id"],
|
||||||
|
|
@ -53,10 +61,23 @@ def check_app_result(
|
||||||
if cl not in seen[id_]:
|
if cl not in seen[id_]:
|
||||||
nb_class_collision_at_invoke += 1
|
nb_class_collision_at_invoke += 1
|
||||||
seen[id_].add(cl)
|
seen[id_].add(cl)
|
||||||
reflections.append((*call_site, invoke_data["method"]))
|
|
||||||
|
cl_class = "unknown"
|
||||||
|
if invoke_data["caller_cl_id"] in data["classloaders"]:
|
||||||
|
cl_class = data["classloaders"][invoke_data["caller_cl_id"]]["cname"]
|
||||||
|
reflections.append(
|
||||||
|
(
|
||||||
|
invoke_data["caller_method"],
|
||||||
|
cl_class,
|
||||||
|
invoke_data["addr"],
|
||||||
|
invoke_data["method"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
seen = {}
|
seen = {}
|
||||||
for invoke_data in data["class_new_inst_data"]:
|
for invoke_data in data["class_new_inst_data"]:
|
||||||
|
if invoke_data["caller_cl_id"] != boot_cl_id:
|
||||||
|
does_reflection = True
|
||||||
call_site = (
|
call_site = (
|
||||||
invoke_data["caller_method"],
|
invoke_data["caller_method"],
|
||||||
invoke_data["caller_cl_id"],
|
invoke_data["caller_cl_id"],
|
||||||
|
|
@ -70,10 +91,23 @@ def check_app_result(
|
||||||
if cl not in seen[id_]:
|
if cl not in seen[id_]:
|
||||||
nb_class_collision_at_invoke += 1
|
nb_class_collision_at_invoke += 1
|
||||||
seen[id_].add(cl)
|
seen[id_].add(cl)
|
||||||
reflections.append((*call_site, invoke_data["constructor"]))
|
|
||||||
|
cl_class = "unknown"
|
||||||
|
if invoke_data["caller_cl_id"] in data["classloaders"]:
|
||||||
|
cl_class = data["classloaders"][invoke_data["caller_cl_id"]]["cname"]
|
||||||
|
reflections.append(
|
||||||
|
(
|
||||||
|
invoke_data["caller_method"],
|
||||||
|
cl_class,
|
||||||
|
invoke_data["addr"],
|
||||||
|
invoke_data["constructor"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
seen = {}
|
seen = {}
|
||||||
for invoke_data in data["cnstr_new_inst_data"]:
|
for invoke_data in data["cnstr_new_inst_data"]:
|
||||||
|
if invoke_data["caller_cl_id"] != boot_cl_id:
|
||||||
|
does_reflection = True
|
||||||
call_site = (
|
call_site = (
|
||||||
invoke_data["caller_method"],
|
invoke_data["caller_method"],
|
||||||
invoke_data["caller_cl_id"],
|
invoke_data["caller_cl_id"],
|
||||||
|
|
@ -87,7 +121,18 @@ def check_app_result(
|
||||||
if cl not in seen[id_]:
|
if cl not in seen[id_]:
|
||||||
nb_class_collision_at_invoke += 1
|
nb_class_collision_at_invoke += 1
|
||||||
seen[id_].add(cl)
|
seen[id_].add(cl)
|
||||||
reflections.append((*call_site, invoke_data["constructor"]))
|
|
||||||
|
cl_class = "unknown"
|
||||||
|
if invoke_data["caller_cl_id"] in data["classloaders"]:
|
||||||
|
cl_class = data["classloaders"][invoke_data["caller_cl_id"]]["cname"]
|
||||||
|
reflections.append(
|
||||||
|
(
|
||||||
|
invoke_data["caller_method"],
|
||||||
|
cl_class,
|
||||||
|
invoke_data["addr"],
|
||||||
|
invoke_data["constructor"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
classes_by_cl: dict[str, list[str]] = {}
|
classes_by_cl: dict[str, list[str]] = {}
|
||||||
dyn_load_classes = set()
|
dyn_load_classes = set()
|
||||||
|
|
@ -101,6 +146,9 @@ def check_app_result(
|
||||||
dex_bin = fp.read()
|
dex_bin = fp.read()
|
||||||
classes_by_cl[cl_id].extend(get_bytecode_classes(dex_bin))
|
classes_by_cl[cl_id].extend(get_bytecode_classes(dex_bin))
|
||||||
|
|
||||||
|
if len(data["dyn_code_load"]) != 0:
|
||||||
|
does_reflection = True
|
||||||
|
|
||||||
# Don't do androguard scan when there is no other dynloading
|
# Don't do androguard scan when there is no other dynloading
|
||||||
if len(data["dyn_code_load"]) != 0:
|
if len(data["dyn_code_load"]) != 0:
|
||||||
apk_name = f"{path.name}.apk"
|
apk_name = f"{path.name}.apk"
|
||||||
|
|
@ -123,6 +171,7 @@ def check_app_result(
|
||||||
"nb_class_collision_at_invoke": nb_class_collision_at_invoke,
|
"nb_class_collision_at_invoke": nb_class_collision_at_invoke,
|
||||||
"nb_ref": len(reflections),
|
"nb_ref": len(reflections),
|
||||||
"reflections": reflections,
|
"reflections": reflections,
|
||||||
|
"does_reflection": does_reflection,
|
||||||
}
|
}
|
||||||
if not keep_ref_data:
|
if not keep_ref_data:
|
||||||
summary["apks"][path.name]["reflections"] = None
|
summary["apks"][path.name]["reflections"] = None
|
||||||
|
|
@ -145,12 +194,15 @@ def run(folder: Path, app_folder: Path):
|
||||||
for p in folder.iterdir():
|
for p in folder.iterdir():
|
||||||
if p.is_dir():
|
if p.is_dir():
|
||||||
check_app_result(p, app_folder, summary, keep_ref_data=True)
|
check_app_result(p, app_folder, summary, keep_ref_data=True)
|
||||||
apk_data = summary["apks"]
|
|
||||||
assert isinstance(apk_data, dict)
|
|
||||||
|
|
||||||
summary["baseline_reflection"] = list(
|
# Strange, looks like there is no baseline? This need investigation
|
||||||
set.intersection(*map(lambda x: set(x["reflections"]), apk_data.values()))
|
# apk_data = summary["apks"]
|
||||||
)
|
# assert isinstance(apk_data, dict)
|
||||||
|
#
|
||||||
|
# summary["baseline_reflection"] = list(
|
||||||
|
# set.intersection(*map(lambda x: set(x["reflections"]), apk_data.values()))
|
||||||
|
# )
|
||||||
|
|
||||||
print(json.dumps(summary, indent=" "))
|
print(json.dumps(summary, indent=" "))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue