feat: Add support for local APKs, multi-device workflows, and anti-tampering detection

This change introduces the ability to patch local APK files or directories, support for separate source and target devices, and detection of common anti-tampering libraries.

Key changes:
- **Local APK Support**: Added `--apk <path>` flag to use local `.apk` files or split-APK directories instead of pulling from a device.
- **Two-Device Workflow**: Added `--source <serial>` flag to pull an APK from one device (e.g., a Play Store emulator) and install the patched version on another (e.g., a `userdebug` emulator).
- **Anti-Tampering Detection**: The patching script now scans for known integrity-protection libraries (e.g., PairIP, DexGuard, Bangcle) and issues a warning if detected.
- **Improved Disassembly**: Introduced a `--no-res` optimization when user certificate trust is not required, avoiding common `apktool` resource decoding errors.
- **Package Name Extraction**: Integrated `aapt2` to automatically detect package names from local APK files for cleaner uninstalls.
- **Enhanced Device Selection**: Updated the interactive menu to handle source/target selection and filter unauthorized devices more effectively.
- **Documentation**: Updated `README.md` and `CLAUDE.md` with new usage examples and information regarding anti-tampering limitations.
This commit is contained in:
benjamin-luescher 2026-03-05 08:58:43 +01:00
parent 0c5c835263
commit 86d8393dd4
4 changed files with 339 additions and 32 deletions

View file

@ -225,6 +225,47 @@ inject_network_security_config() {
fi
}
# Check for anti-tampering / integrity-protection libraries
check_anti_tampering() {
local found=()
# Library filename:protection name pairs (Bash 3.2 compatible — no associative arrays)
local pairs=(
"libpairipcore.so:PairIP"
"libDexHelper.so:DexGuard"
"libDexHelper-x86.so:DexGuard"
"libjiagu.so:360 Jiagu"
"libjiagu_art.so:360 Jiagu"
"libsecexe.so:Bangcle"
"libsecmain.so:Bangcle"
"libtosprotection.so:Tencent Legu"
"libexec.so:Baidu"
"libexecmain.so:Baidu"
)
for pair in "${pairs[@]}"; do
local lib_name="${pair%%:*}"
local protection="${pair#*:}"
if find "$WORK_DIR/lib" -name "$lib_name" 2>/dev/null | grep -q .; then
found+=("$protection ($lib_name)")
fi
done
if [[ ${#found[@]} -gt 0 ]]; then
echo ""
print_warning "Anti-tampering protection detected!"
echo -e " ${YELLOW}This app uses native integrity checks that will likely crash${NC}"
echo -e " ${YELLOW}after patching because the APK signature has changed.${NC}"
echo ""
for item in "${found[@]}"; do
echo -e " ${RED}${NC} $item"
done
echo ""
echo -e " The patched APK will still be created, but the app may crash on launch."
echo ""
fi
}
# Process a single APK (make debuggable)
process_single_apk() {
local input_apk="$1"
@ -238,7 +279,18 @@ process_single_apk() {
# Step 1: Disassemble
print_step "Disassembling APK..."
$APKTOOL d -f -o "$WORK_DIR" "$input_apk"
if [[ "$TRUST_USER_CERTS" == true ]]; then
# Full resource decode needed so we can inject/overwrite network_security_config.xml
$APKTOOL d -f -o "$WORK_DIR" "$input_apk"
else
# --no-res: skip resource decoding — we only need AndroidManifest.xml.
# This avoids aapt2 "private resource" errors (e.g. android:style/TextAppearance.*)
# that occur when the app references private Android framework styles/resources.
$APKTOOL d -f --no-res -o "$WORK_DIR" "$input_apk"
fi
# Step 1b: Check for anti-tampering protections
check_anti_tampering
# Step 2: Make debuggable
print_step "Making APK debuggable..."