-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodule_conflict_check.py
More file actions
92 lines (77 loc) · 2.91 KB
/
Copy pathmodule_conflict_check.py
File metadata and controls
92 lines (77 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/env python3
"""
module_conflict_check.py -- Detect LSPosed module conflicts
Analyzes hooked classes to find overlapping patches.
Usage: python3 module_conflict_check.py [--export csv]
"""
import subprocess, re, json, argparse, sys
from collections import defaultdict
def adb(cmd):
r = subprocess.run(f"adb shell {cmd}", shell=True, capture_output=True, text=True)
return r.stdout.strip()
def get_lsposed_modules():
"""List active LSPosed modules"""
out = adb("pm dump | grep -A 20 'LSPosed'")
# Parse module names from logcat or dumpsys
modules = []
for line in out.splitlines():
if "module" in line.lower():
m = re.search(r"package:([a-z0-9_.]+)", line)
if m:
modules.append(m.group(1))
return modules
def analyze_hooks(module_pkg):
"""Extract hooked classes from module DEX"""
# This is a simplified check — real analysis needs DEX parsing
out = adb(f"pm dump {module_pkg} | grep -i hook")
hooks = []
for line in out.splitlines():
m = re.search(r"(L[a-z0-9_/]+;)", line)
if m:
hooks.append(m.group(1))
return hooks
def find_conflicts(modules_hooks):
"""Find overlapping hooks between modules"""
conflicts = defaultdict(list)
all_hooks = {}
for mod, hooks in modules_hooks.items():
for hook in hooks:
if hook in all_hooks:
conflicts[hook].append((all_hooks[hook], mod))
else:
all_hooks[hook] = mod
return {h: mods for h, mods in conflicts.items() if len(mods) > 1}
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--export", help="Export to CSV or JSON")
args = parser.parse_args()
print("🔍 LSPosed Module Conflict Checker")
print("=" * 50)
modules = get_lsposed_modules()
if not modules:
print("No LSPosed modules found.")
return
print(f"Found {len(modules)} active modules\n")
modules_hooks = {}
for mod in modules:
hooks = analyze_hooks(mod)
modules_hooks[mod] = hooks
print(f" {mod.split('.')[-1]:<30} {len(hooks)} hooks")
conflicts = find_conflicts(modules_hooks)
if conflicts:
print(f"\n⚠️ Found {len(conflicts)} potential conflicts:\n")
for hook, hooked_by in conflicts.items():
print(f" {hook}")
for mod1, mod2 in hooked_by:
print(f" ↔ {mod1} ↔ {mod2}")
print("\n💡 Try disabling one module to see if conflicts resolve.")
else:
print("\n✅ No conflicts detected!")
if args.export:
data = {"total_modules": len(modules), "conflicts": conflicts}
ext = args.export.split('.')[-1]
with open(args.export, 'w') as f:
json.dump(data, f, indent=2) if ext == 'json' else f.write(str(data))
print(f"Exported to {args.export}")
if __name__ == "__main__":
main()