fix(clone-app): Unity XAPK detection, mono DLL path, game-assets manifest

- detect-unity.sh: handle XAPK bundles by extracting nested *.apk entries
  to a mktemp dir and merging their listings before grepping; /dev/stdin
  pipe approach is unreliable on macOS (unzip central-dir seek fails)
- tests/test-detect-unity.sh: add xapk il2cpp fixture — outer xapk wraps
  a Unity base.apk; asserts classification returns il2cpp
- SKILL.md mono branch: replace hardcoded $WORK/output/Managed/ path (jadx
  never creates it) with correct extract-from-APK step into $WORK/managed/;
  mirrors the il2cpp branch wording and adds XAPK note
- SKILL.md il2cpp+mono branches: add game-assets/manifest.json inventory
  step after unity-assets.sh so re-digest-contract.md claim is satisfied
- extract-design.py: remove unused imports sys and re

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
fatih.bulut 2026-06-25 02:30:37 +03:00
parent b4072218fd
commit f7da7007fc
4 changed files with 37 additions and 6 deletions

View File

@ -103,12 +103,17 @@ Tell the subagent its clone-app scripts dir is
- **Unity (`il2cpp`):** locate `libil2cpp.so` + `global-metadata.dat` under
`$WORK/output` (or unzip from `$APK`); run
`bash "$CA/il2cpp-dump.sh" <so> <metadata> "$WORK/unity-out"` and
`bash "$CA/unity-assets.sh" "$APK" "$WORK/game-assets"`; write
`bash "$CA/unity-assets.sh" "$APK" "$WORK/game-assets"`; inventory
`$WORK/game-assets/` into `$WORK/game-assets/manifest.json` (a JSON list
of `{"path": ..., "type": ...}` entries for every extracted file); write
`$WORK/unity-digest.md` (type model + netcode) per `unity-re-guide.md`.
- **Unity (`mono`):** decompile the managed assemblies with
`ilspycmd "$WORK/output/Managed/Assembly-CSharp.dll" -o "$WORK/unity-out"`
(repeat for other `Managed/*.dll` of interest; near-source C#), plus
`bash "$CA/unity-assets.sh" "$APK" "$WORK/game-assets"`; write
- **Unity (`mono`):** extract `assets/bin/Data/Managed/*.dll` from `$APK`
(for an XAPK, from the nested `base.apk`) into `$WORK/managed/`, then
`ilspycmd "$WORK/managed/Assembly-CSharp.dll" -o "$WORK/unity-out"`
(repeat for other DLLs of interest; near-source C#), plus
`bash "$CA/unity-assets.sh" "$APK" "$WORK/game-assets"`; inventory
`$WORK/game-assets/` into `$WORK/game-assets/manifest.json` (a JSON list
of `{"path": ..., "type": ...}` entries for every extracted file); write
`$WORK/unity-digest.md` per `unity-re-guide.md`.
- If a Unity tool exits 3 (missing), continue with a partial digest and set
`RE Method: limited: unity-no-tools`.

View File

@ -1,5 +1,6 @@
#!/usr/bin/env bash
# Classify an APK/XAPK as a Unity build: il2cpp | mono | none.
# Handles XAPK bundles by also scanning nested base.apk / split apks.
set -uo pipefail
APK="${1:-}"
@ -11,6 +12,20 @@ fi
listing="$(unzip -Z1 "$APK" 2>/dev/null)" || {
echo "ERROR: cannot read zip: $APK" >&2; exit 2; }
# XAPK: top-level *.apk entries are inner packages — scan their contents too.
nested_apks="$(grep -E '\.apk$' <<<"$listing" || true)"
if [[ -n "$nested_apks" ]]; then
INNER_TMP="$(mktemp -d)"
trap 'rm -rf "$INNER_TMP"' EXIT
while IFS= read -r inner; do
[[ -z "$inner" ]] && continue
inner_path="$INNER_TMP/$(basename "$inner")"
unzip -p "$APK" "$inner" > "$inner_path" 2>/dev/null || continue
inner_listing="$(unzip -Z1 "$inner_path" 2>/dev/null || true)"
listing="$listing"$'\n'"$inner_listing"
done <<<"$nested_apks"
fi
if grep -q 'global-metadata\.dat' <<<"$listing" \
&& grep -qi 'libil2cpp\.so' <<<"$listing"; then
echo il2cpp; exit 0

View File

@ -10,7 +10,7 @@ layer (confidence high); Compose keeps tokens in res/values but no layouts
(med); Flutter/React Native keep almost nothing in Android res (low) so the
caller leans on screenshots. Pass --framework to override the auto guess.
"""
import sys, os, json, re, argparse, glob
import os, json, argparse, glob
import xml.etree.ElementTree as ET
def _find_res_dirs(root):

View File

@ -25,9 +25,20 @@ mkzip "$TMP/il2cpp.apk" "lib/arm64-v8a/libil2cpp.so" "assets/bin/Data/Managed/Me
mkzip "$TMP/mono.apk" "assets/bin/Data/Managed/Assembly-CSharp.dll"
mkzip "$TMP/plain.apk" "classes.dex" "AndroidManifest.xml"
# Build XAPK fixture: inner Unity il2cpp base.apk wrapped in an xapk
mkzip "$TMP/base.apk" "lib/arm64-v8a/libil2cpp.so" "assets/bin/Data/Managed/Metadata/global-metadata.dat"
python3 - "$TMP/unity.xapk" "$TMP/base.apk" <<'PY'
import sys, zipfile, os
out, inner = sys.argv[1], sys.argv[2]
with zipfile.ZipFile(out, "w") as z:
z.write(inner, arcname="base.apk")
z.writestr("manifest.json", "{}")
PY
check "il2cpp" "il2cpp" "$(bash "$SCRIPT" "$TMP/il2cpp.apk")"
check "mono" "mono" "$(bash "$SCRIPT" "$TMP/mono.apk")"
check "none" "none" "$(bash "$SCRIPT" "$TMP/plain.apk")"
check "xapk il2cpp" "il2cpp" "$(bash "$SCRIPT" "$TMP/unity.xapk")"
bash "$SCRIPT" >/dev/null 2>&1; rc=$?
check "usage exit 2" "2" "$rc"