From f7da7007fcb89b269dab2fcb337695575a642119 Mon Sep 17 00:00:00 2001 From: "fatih.bulut" Date: Thu, 25 Jun 2026 02:30:37 +0300 Subject: [PATCH] fix(clone-app): Unity XAPK detection, mono DLL path, game-assets manifest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- plugins/clone-app/skills/clone-app/SKILL.md | 15 ++++++++++----- .../skills/clone-app/scripts/detect-unity.sh | 15 +++++++++++++++ .../skills/clone-app/scripts/extract-design.py | 2 +- plugins/clone-app/tests/test-detect-unity.sh | 11 +++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/plugins/clone-app/skills/clone-app/SKILL.md b/plugins/clone-app/skills/clone-app/SKILL.md index 8026baa..817ceae 100644 --- a/plugins/clone-app/skills/clone-app/SKILL.md +++ b/plugins/clone-app/skills/clone-app/SKILL.md @@ -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" "$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`. diff --git a/plugins/clone-app/skills/clone-app/scripts/detect-unity.sh b/plugins/clone-app/skills/clone-app/scripts/detect-unity.sh index 1f38bb7..fdc65b1 100755 --- a/plugins/clone-app/skills/clone-app/scripts/detect-unity.sh +++ b/plugins/clone-app/skills/clone-app/scripts/detect-unity.sh @@ -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 diff --git a/plugins/clone-app/skills/clone-app/scripts/extract-design.py b/plugins/clone-app/skills/clone-app/scripts/extract-design.py index 5aa6833..c1c1fa2 100644 --- a/plugins/clone-app/skills/clone-app/scripts/extract-design.py +++ b/plugins/clone-app/skills/clone-app/scripts/extract-design.py @@ -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): diff --git a/plugins/clone-app/tests/test-detect-unity.sh b/plugins/clone-app/tests/test-detect-unity.sh index e593ac3..cfcf4a7 100644 --- a/plugins/clone-app/tests/test-detect-unity.sh +++ b/plugins/clone-app/tests/test-detect-unity.sh @@ -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"