본문으로 건너뛰기
5분 AI.
GITHUB TRENDING SHELL DAILY #4 딥다이브 · 2026-10-23 분석

android-reverse-engineering-skill 딥다이브
— APK를 읽는 순서까지 코드로 만드는 법

스킬·스크립트

빠른 판단

무엇
APK 분류·디컴파일·Kotlin 이름 복원·HTTP API 추적 절차를 연결하는 Claude Code 역공학 스킬
이럴 때
분석 권한이 있는 Android 패키지의 구조·호출 경로를 조사하고 근거 파일을 연결해 문서화할 때
입력
APK·XAPK·JAR·AAR와 분석 범위
결과
디컴파일·이름 복원·API 추적 결과와 근거 문서
Android 앱의 실행 파일을 읽기 쉬운 코드로 바꾸고, 화면에서 HTTP API까지 이어지는 흐름을 찾도록 Claude Code를 안내하는 플러그인입니다. 핵심은 새로운 디컴파일 엔진보다 분류 → 도구 선택 → 증거 검색 → 문서화라는 분석 절차에 있습니다. Bash 1,967줄과 PowerShell 1,035줄을 따라가며, 초보 개발자도 도구 조합·오류 처리·정규식의 한계를 배울 수 있습니다. 저장소 SimoneAvogadro/android-reverse-engineering-skill · 스타 8,268 · 포크 936 · Apache-2.0 · 2026-10-23 GitHub 기준, 소스 해설은 커밋 0c7cf89 기준입니다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

실행 파일을 분석 자료로 바꾸는 도구 상자와 작업 지침

android-reverse-engineering-skill은 APK·XAPK·JAR·AAR를 분석하는 Claude Code용 스킬입니다. 이미 있는 분석 도구에 무엇을 맡기고, 그 결과에서 무엇을 읽어야 하는지까지 연결합니다. 디컴파일은 jadx나 Vineflower가 담당하고, 스킬은 분석 순서와 결과를 해석하는 기준을 제공합니다.

용어 먼저
역공학과 디컴파일
역공학은 완성된 결과물에서 내부 구조와 동작을 추론하는 일입니다. 디컴파일은 그중 실행용 코드를 사람이 읽기 쉬운 소스 형태로 바꾸는 과정입니다. 원본 프로젝트 복원과는 다릅니다. 주석·원래 변수명·빌드 설정까지 되살아나는 것은 아닙니다.
한 문장 비유

디컴파일러가 분해 공구라면, 이 스킬은 “어디부터 열고 무엇을 기록할지” 알려주는 정비 매뉴얼입니다

상자를 열었다고 부품의 역할까지 곧바로 알 수는 없습니다. 먼저 제품 종류를 확인하고, 알맞은 공구를 고르고, 부품 사이 연결을 따라가야 합니다. 이 저장소의 SKILL.md가 그 순서를 정합니다.

Shell 스크립트는 반복 작업을 맡습니다. 파일을 풀고, 외부 도구를 부르고, URL이나 클래스 이름의 흔적을 모읍니다. 흔적이 실제로 어떤 기능을 뜻하는지 판단하는 단계에는 코드 읽기와 추가 확인이 필요합니다.

1-1. 입력과 출력부터 구분하기

구분구체적인 대상초보자가 알아둘 점
APKAndroid 설치 패키지DEX 코드·리소스·네이티브 라이브러리가 함께 들어갈 수 있습니다.
XAPK여러 APK와 부가 자료를 담은 ZIP 묶음기본 앱과 기기별 분할 패키지를 함께 살펴봐야 합니다.
JAR / AARJVM 코드 또는 Android 라이브러리 묶음AAR와 APK의 내부 코드 포맷은 같지 않을 수 있습니다.
스크립트 출력Java 소스·리소스·이름 매핑·검색 결과기계가 만든 중간 증거입니다.
스킬의 목표구조 요약·API 목록·호출 흐름 문서에이전트가 증거를 읽어 작성하도록 지시하는 결과물입니다.

이 구분은 중요합니다. find-api-calls.sh가 완성된 OpenAPI 명세를 생성하지는 않습니다. 대부분의 출력은 파일:줄:일치 내용 형식입니다. SKILL.md의 Phase 5는 이를 바탕으로 전체 엔드포인트 목록과 중요한 API의 상세 설명을 작성하라고 안내합니다.

1-2. 사용자가 만나는 두 입구

# README의 Claude Code 명령 예
/decompile path/to/owned-demo.apk

# 자연어로 분석 목표를 구체화하는 예
이 앱의 로그인 화면에서 네트워크 요청까지 호출 흐름을 설명해 줘.
각 결론에 근거 파일과 줄 번호를 붙여 줘.

위 예시의 대상은 직접 만든 앱이나 분석 권한이 있는 자료로 한정하면 됩니다. 이 글의 실습은 정적 읽기와 가짜 예제로 구성합니다. 실제 API에 접속하거나 인증 문자열을 사용해야 할 이유는 없습니다.

배울 핵심
자동화할 일과 판단할 일을 구분하는 설계

압축 해제·도구 실행·문자열 검색은 반복 가능하게 만들고, 프레임워크 판별과 호출 관계 해석은 근거를 남기며 진행합니다. 이 경계를 읽어내면 보안 분석뿐 아니라 로그 조사와 레거시 코드 이해에도 응용할 수 있습니다.

2왜 주목받는가

인기의 관측값과, 소스에서 읽히는 매력은 구분해서 보기

2026-10-23 GitHub 기준 스타는 8,268개, 포크는 936개이며, GitHub Trending의 Shell 일간 목록에서 4위로 선정됐습니다. 이 수치는 관심의 크기를 보여주지만, 특정 게시물이나 사건이 상승을 일으켰다는 인과관계까지 증명하지는 않습니다.

소스에서 확인할 수 있는 매력은 분명합니다. 디컴파일 명령 하나를 알려주는 데서 더 나아가, 처음 보는 앱을 분류하고, 난독화된 이름을 보완하고, HTTP 흔적을 모으는 작업을 하나의 학습 흐름으로 연결합니다. 명령어를 아는 것과 분석 순서를 아는 것 사이의 간격을 줄이는 프로젝트입니다.

2-1. 기존 도구와 무엇이 다른가

도구 / 방식주요 역할이 저장소와의 관계
jadx 단독DEX·APK 등을 Java 형태로 해석하고 리소스 확인기본 엔진입니다. 이 스킬이 명령 구성과 후속 분석 순서를 보탭니다.
Vineflower 단독JVM 바이트코드를 Java로 해석대체 엔진입니다. --engine both로 결과를 나란히 비교합니다.
ApktoolAndroid 리소스와 smali 중심의 해석선택 의존성으로 검사하지만, 핵심 래퍼가 직접 실행하지는 않습니다.
일회성 AI 질문그때그때 코드 설명과 검색 요청스킬은 단계·검색 기준·출력 형식을 파일로 남겨 재사용합니다.
이 저장소도구 호출·증거 수집·분석 지침의 연결엔진의 정확도를 대체하지 않고, 분석 절차를 정리합니다.

위 비교는 기능과 설계의 비교입니다. 처리 속도나 복원 정확도의 순위를 매긴 벤치마크는 아닙니다. jadx 자체도 모든 코드를 완전하게 디컴파일할 수 없다고 설명합니다. jadx 공식 저장소의 경고를 읽으면 결과 대조가 필요한 이유를 이해할 수 있습니다.

2-2. “일단 전부 디컴파일” 전에 갈림길을 둔다

fingerprint.sh는 libflutter.so, libhermes.so, assets/www/index.html 같은 흔적으로 앱의 종류를 추정합니다. Flutter나 React Native 앱에서는 Java 호스트 외부에 주요 로직이 있을 수 있으므로, 다른 분석 도구를 고려하라고 출력합니다.

다만 이것은 안내입니다. 스크립트가 Flutter 분석 도구를 설치하거나 Dart 코드를 해석하는 것은 아닙니다. SKILL.md는 해당 프레임워크라면 후속 Java/Kotlin 분석 단계를 멈추고 도구를 바꾸라고 지시합니다.

2-3. 현대 Kotlin 앱을 읽으려는 확장

Bash 검색기에는 Retrofit·OkHttp뿐 아니라 Ktor·Apollo·Koin·HMAC 관련 패턴이 들어 있습니다. recover-kotlin-names.sh는 코루틴 디버그 정보와 Kotlin 메타데이터에서 이름 후보를 추출합니다. 이 조합은 낯선 짧은 클래스 이름 속에서 의미 있는 탐색 지점을 찾도록 돕습니다.

비유

길 이름이 지워진 지도라도 가게 간판과 버스 정류장이 남아 있으면 위치를 추정할 수 있습니다. 이 도구는 남은 간판을 모읍니다. 다만 간판 하나가 그 건물의 원래 이름을 보장하지는 않으므로, 이웃한 코드도 읽어야 합니다.

3기술 스택 전체 지도

서버 중심의 앱이 아닌, 로컬 CLI와 에이전트 지침 중심의 구성

3-1. 백엔드에 해당하는 실행 계층

HTTP 서버·DB·사용자 계정 백엔드는 없습니다. 실행 계층은 외부 CLI를 호출하는 Bash와 PowerShell입니다. 스크립트의 공통 경로는 plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/입니다. 아래에서 파일 이름만 적은 스크립트는 이 디렉터리의 파일을 가리킵니다.

계층실제 파일 / 도구담당하는 작업
실행 조합Bash 7개·PowerShell 4개의존성 검사·설치·디컴파일·검색을 나눠 처리합니다.
데이터 가공두 Bash 파일 안의 Python 3이름 매핑을 JSON·TSV로 저장하고 역색인을 만듭니다.
기본 엔진jadx소스와 Android 리소스를 출력합니다.
대체 엔진Vineflower / FernflowerJAR 입력을 Java 소스로 바꿉니다.
중간 변환dex2jarAPK의 DEX를 JVM 쪽에서 읽을 JAR로 변환하는 경로에 사용됩니다.
파일 탐색grep·awk·sed·find·sort·unzip·strings압축 목록·문자열·파일 위치를 조합해 후보를 좁힙니다.

3-2. 프론트엔드에 해당하는 사용자 접점

React·Vue 같은 웹 UI는 없습니다. 사용자 접점은 Claude Code의 대화와 plugins/android-reverse-engineering/commands/decompile.md에 정의된 /decompile입니다. 이 Markdown 파일의 프런트매터에는 user-invocable: true와 입력 인자 설명이 들어 있습니다.

plugins/android-reverse-engineering/skills/android-reverse-engineering/SKILL.md는 단계별 행동과 참고 문서를 연결합니다. 코드가 화면을 렌더링하는 구조 대신, 에이전트가 지침을 읽고 로컬 도구와 파일 읽기를 조합하는 구조입니다.

용어 먼저
매니페스트와 프런트매터
매니페스트는 플러그인의 이름·버전·구성 경로를 적은 설명서입니다. 프런트매터는 Markdown 맨 위의 구분선 사이에 적는 설정입니다. 둘 다 실행 알고리즘보다 호스트 프로그램이 내용을 발견하고 불러오는 방식을 설명합니다.

3-3. 인프라·빌드와 실제 버전

이 커밋에는 package.json, Cargo.toml, pyproject.toml, go.mod, Dockerfile, 잠금 파일, .github/workflows/가 없습니다. 따라서 일반 앱처럼 패키지 매니저 의존성 목록이나 CI 빌드 파이프라인을 설명할 근거도 없습니다. 버전의 근거는 두 플러그인 JSON과 설치·검사 스크립트에서 찾아야 합니다.

항목확인한 값정확한 의미
카탈로그 버전1.5.0.claude-plugin/marketplace.json의 metadata.version과 플러그인 항목의 버전입니다.
플러그인 버전1.5.0plugins/android-reverse-engineering/.claude-plugin/plugin.json의 값입니다.
GitHub 릴리스v1.1.0 · 2026-04-272026-10-23 GitHub 기준 최신 릴리스입니다. 매니페스트 버전과 별개의 기록입니다.
Java 검사 기준REQUIRED_JAVA_MAJOR=17Bash·PowerShell 검사기가 요구하는 최소 주 버전입니다.
jadx / Vineflower버전 고정 없음설치기는 패키지 매니저 또는 GitHub 최신 릴리스 조회를 사용합니다.
dex2jar 대체 태그2.4.35Bash·PowerShell 설치기의 빈 태그 대체값입니다. PowerShell은 조회 예외에도 사용하며, 전체 설치 버전을 고정하지는 않습니다.
Python / Shellpython3 / bash언어의 세부 버전은 고정하지 않습니다. 문법과 유틸리티 호환성은 별도 점검 대상입니다.

버전을 적어 두는 것과 실행 환경을 재현 가능하게 고정하는 것은 서로 다른 일입니다. gh_latest_tag()가 호출 시점의 최신 버전을 선택하므로 같은 커밋의 스크립트도 날짜에 따라 다른 도구를 설치할 수 있습니다. 재현 실험에서는 엔진 버전과 입력 파일 해시도 함께 기록해야 합니다.

# plugin.json의 구성 일부
{
  "name": "android-reverse-engineering",
  "version": "1.5.0",
  "skills": "./skills/",
  "commands": "./commands/"
}

위의 ./skills/와 ./commands/는 매니페스트 안의 설정값입니다. 브라우저 링크가 아니라, 플러그인 루트에서 구성 요소를 찾기 위한 경로입니다.

3-4. 코드 규모를 숫자로 읽기

종류파일 수 / 줄 수집계 범위
Bash7개 / 1,967줄.sh 전체, 빈 줄·주석·내장 Python 포함
PowerShell4개 / 1,035줄.ps1 전체, 빈 줄·주석 포함
내장 Python2블록 / 147줄복원기 93줄 + 조회기 54줄, Bash 집계와 중복
Markdown11개 / 1,686줄README·스킬·명령·참고 문서·정책 포함
JSON / 텍스트2개 / 45줄 · 1개 / 122줄매니페스트 2개와 호스트 분류 목록
전체28파일 / 텍스트 5,054줄Git 내부 제외, 텍스트 27개와 아이콘 PNG 1개

줄 수는 줄바꿈 문자 수 기준입니다. 전체에는 LICENSE와 .gitattributes도 포함합니다. 이 수치는 코드의 복잡도나 품질 점수가 아니라, 읽을 분량을 가늠하는 지도입니다.

4아키텍처 심화 분석

지침이 제어하고, 스크립트가 실행하고, 파일이 단계를 연결한다
사용자: 분석할 파일 + 알고 싶은 기능 | v Claude Code: /decompile 명령 또는 스킬의 작업 지침 | +-- SKILL.md Phase 0: 앱 종류 판별 권고 | `-- fingerprint.sh: ZIP 목록 + DEX 문자열 | `-- Flutter/RN/Cordova/Xamarin: Phase 1~5 중단, 도구 전환 | +-- Phase 1: check-deps.sh / .ps1 | `-- INSTALL_REQUIRED / INSTALL_OPTIONAL | `-- 필요 시 설치기: 외부 다운로드 | +-- Phase 2: decompile.sh / .ps1 | +-- jadx --------------------> 소스 + 리소스 | `-- Vineflower ---------------> 소스 (APK/AAR는 dex2jar 경유, JAR는 직접 입력) | +-- Phase 3 / 3.5: 구조 읽기 + Kotlin 이름 후보 | `-- mapping.tsv / mapping.json / by_package/ | +-- Phase 4: 호출 흐름을 코드에서 추적 | `-- lookup-name.sh: 검색 결과에 이름 덧붙이기 | `-- Phase 5: find-api-calls.sh / .ps1 + 증거 검토 `-- 전체 API 목록 + 중요 흐름 상세 문서

이 그림은 SKILL.md에 적힌 권장 작업 흐름입니다. 모든 단계를 한 번에 호출하는 단일 실행 파일이 있는 것은 아닙니다. 특히 plugins/android-reverse-engineering/commands/decompile.md의 실제 지침은 의존성 검사 → 디컴파일 → 초기 구조 요약을 중심으로 하며, Phase 0의 판별기를 직접 호출하라고 적지는 않습니다. 명령 하나가 전체 분석을 항상 끝낸다고 이해하면 범위를 과대평가하게 됩니다.

여기서 명령 파일의 저장소 루트 기준 경로는 plugins/android-reverse-engineering/commands/decompile.md입니다. 전체 흐름의 근거는 plugins/android-reverse-engineering/skills/android-reverse-engineering/SKILL.md입니다.

4-1. 설계 패턴 ① 단계별 분류와 조기 방향 전환

fingerprint.sh의 has()는 압축 파일의 목록과 DEX에서 추출한 클래스 문자열을 함께 봅니다. 파일 이름만 보면 드러나지 않는 Ktor·Koin 같은 라이브러리도 DEX 문자열에서 찾으려는 설계입니다. 프레임워크 판별은 if / elif 순서로 진행하며, 처음 맞는 조건이 결과를 결정합니다.

# fingerprint.sh의 실제 핵심 함수
has() { grep -qE "$1" "$LISTING" || grep -qE "$1" "$DEX_STRINGS"; }

# 실제 판별에 쓰는 흔적의 예
'^lib/[^/]+/libflutter\.so$'
'^assets/index\.android\.bundle$'
'^META-INF/.*\.kotlin_module$'

DEX에서 문자열을 뽑는 파이프라인은 unzip -p → strings -n 8 → grep → sed입니다. Lcom/example/Foo; 같은 타입 표기에서 맨 앞 L과 마지막 ;를 없애 com/example/Foo를 검색 자료로 남깁니다.

설계 용어
휴리스틱
항상 맞는 증명 대신, 자주 맞는 단서로 빠르게 판단하는 규칙입니다. libflutter.so가 있으면 Flutter일 가능성을 높게 보는 식입니다. 복합 앱·특수 패키징·제거된 흔적에서는 틀릴 수 있으므로, 판정과 함께 어떤 흔적이 있었는지 기록해야 합니다.

좋은 학습 지점은 결과와 근거를 함께 출력한다는 것입니다. FRAMEWORK와 RATIONALE를 따로 보관해 “무엇으로 분류했는가”와 “왜 그렇게 봤는가”를 구분합니다. 다만 여러 프레임워크가 함께 있으면 우선순위에 따라 한 종류만 대표로 표시됩니다.

4-2. 설계 패턴 ② 공통 호출 방식과 교체 가능한 엔진

decompile.sh의 decompile_single()은 ENGINE 값으로 분기해 run_jadx()와 run_fernflower()를 선택합니다. 객체지향 클래스 없이도 같은 목적의 작업을 함수 두 개로 분리한 전략 패턴의 형태를 읽을 수 있습니다.

함수입력 처리와 옵션맞춰 주는 출력
run_jadx()-d, 선택적 --deobf·--no-res, 항상 --show-bad-codesources/와 필요 시 resources/
run_fernflower()필요 시 dex2jar, -dgs=1·-mpm=60, 선택적 -ren=1출력 JAR 또는 직접 생성된 폴더에서 sources/로 정리
decompile_single()jadx·fernflower·both 중 선택두 엔진 모드에서는 하위 폴더를 나눠 보관
# 두 엔진 모드의 결과 배치 예시
owned-demo-decompiled/
├── jadx/
│   ├── sources/
│   └── resources/
└── fernflower/
    └── sources/

후속 검색기는 엔진 이름보다 sources/라는 경로를 기준으로 동작할 수 있습니다. 서로 다른 도구의 출력 차이를 래퍼가 흡수하는 셈입니다. 다만 두 결과가 자동 병합되거나, 더 정확한 클래스가 자동 선택되지는 않습니다. 파일 수와 jadx 경고가 있는 파일 수를 비교해 보여줍니다.

엔진 함수가 입력 파일을 인자로 모두 받지는 않는다는 점도 볼 만합니다. decompile_single()은 전역 INPUT_FILE_ABS와 ext_lower를 잠시 바꾸고, 정상·부분 성공 경로에서 복원합니다. 실패로 조기 반환하면 복원문에 도달하지 않습니다. 간단한 직렬 실행에는 쓸 수 있지만, 병렬 실행이나 독립 테스트로 확장하려면 상태를 명시적 인자로 옮기는 편이 읽기 쉽습니다.

4-3. 설계 패턴 ③ 결과물을 확인하는 부분 성공 처리

외부 명령이 실패했는지만 보지 않고, 읽을 만한 결과물을 남겼는지도 확인합니다. run_jadx()는 종료 코드를 저장한 뒤 sources/의 Java 파일 수를 셉니다. 원래 명령의 종료 코드와 래퍼 함수가 반환하는 의미를 분리한 것입니다.

# run_jadx()의 실제 반환 분기
if [[ $jadx_status -eq 0 ]]; then
  return 0
fi

if [[ $count -gt 0 ]]; then
  echo "Warning: jadx exited with status $jadx_status after writing $count Java files; treating this as partial success." >&2
  return 2
fi

# 결과 소스도 없다면 실패
return 1
함수 반환값의미호출자의 반응
0외부 명령이 성공으로 끝남다음 단계로 진행합니다.
2명령은 비정상 종료했지만 Java 출력이 존재경고를 남기고 분석을 계속합니다.
1도구 부재 또는 사용 가능한 소스가 없는 실패해당 디컴파일 흐름을 중단합니다.

이 값은 엔진 함수 내부의 계약입니다. decompile_single()이 부분 성공을 받아 계속하므로, 최종 셸 프로세스가 반드시 2로 끝나는 것은 아닙니다. 또 install-dep.sh의 종료 코드 2는 “수동 설치 조치 필요”라는 다른 의미입니다.

both 모드에서도 jadx가 1을 반환하면 Vineflower 실행 전에 중단합니다. 따라서 두 엔진 실행은 “첫 엔진이 완전히 실패해도 두 번째로 복구하는 경로”까지 구현한 것은 아닙니다. 정상 종료 역시 코드 정확도를 증명하지는 않습니다. 이 로직은 처리 지속 여부를 정하는 장치입니다.

4-4. 설계 패턴 ④ 증거를 파일로 남기고 조회를 분리

recover-kotlin-names.sh 안의 Python은 Java 파일을 걸으며 다음 순서로 이름 후보를 고릅니다. @DebugMetadata.c → @Metadata.d2의 첫 적합한 타입 → jadx의 renamed from 주석입니다. 각 파일에서 하나의 후보를 정해 매핑을 만듭니다.

# 내장 Python의 실제 정규식과 후보 정리 일부
RE_DEBUG = re.compile(r'@DebugMetadata\([^)]*?c\s*=\s*"([^"]+)"', re.S)
RE_LCLASS = re.compile(r'L([A-Za-z][\w/$]+);')

# 코루틴 내부 클래스의 접미사를 제거
real = m.group(1).split("$", 1)[0]

# 결과를 조회용 사전으로 보관
mapping[obf] = real

결과는 mapping.json, 근거 파일 경로를 담은 mapping.tsv, 패키지별 목록 by_package/입니다. 원본 Java 파일 이름을 직접 바꾸지는 않습니다. “원래 코드를 보존한 상태에서 이름 해석을 덧붙이는 방식”을 배울 수 있습니다.

lookup-name.sh의 search()는 복원 이름의 부분 문자열을 찾고, by_obf()는 난독화된 이름 하나를 풀어 봅니다. grep_annot()는 subprocess.run()으로 grep을 실행하고, 매핑이 있는 파일의 일치 줄에만 이름 후보를 덧붙입니다.

비유

자료 원문을 고쳐 쓰는 대신 옆에 색인 카드를 만드는 방식입니다. 같은 원래 클래스에서 나온 코루틴 파일 여러 개가 같은 이름으로 연결될 수 있으므로, 조회기는 역방향 목록도 만들어 관련 파일을 함께 보여줍니다.

5디렉토리 구조 해부

설치용 설명과 실제 학습 내용을 나누어 찾는 법
android-reverse-engineering-skill/ ├── .claude-plugin/ │ └── marketplace.json 카탈로그와 플러그인 위치 ├── .gitattributes 줄바꿈을 LF로 정규화 ├── README.md 기능·사용법·주의사항 ├── PRIVACY.md 로컬 처리와 Claude 처리 범위 ├── THIRD_PARTY_NOTICES.md 외부 도구와 라이선스 안내 ├── LICENSE 저장소 자체의 Apache-2.0 └── plugins/ └── android-reverse-engineering/ ├── .claude-plugin/ │ ├── plugin.json 이름·버전·구성 경로 │ └── icon.png 플러그인 아이콘 ├── commands/ │ └── decompile.md 사용자 명령의 작업 지침 └── skills/ └── android-reverse-engineering/ ├── SKILL.md 전체 분석 절차 ├── scripts/ │ ├── fingerprint.sh │ ├── check-deps.sh / check-deps.ps1 │ ├── install-dep.sh / install-dep.ps1 │ ├── decompile.sh / decompile.ps1 │ ├── find-api-calls.sh / find-api-calls.ps1 │ ├── recover-kotlin-names.sh │ └── lookup-name.sh └── references/ ├── setup-guide.md ├── jadx-usage.md ├── fernflower-usage.md ├── api-extraction-patterns.md ├── call-flow-analysis.md ├── kotlin-name-recovery.md └── third_party_hosts.txt

5-1. 같은 이름의 설정 폴더가 두 번 등장하는 이유

루트의 .claude-plugin/marketplace.json은 설치 가능한 플러그인 목록을 설명합니다. 그 안의 source 값은 ./plugins/android-reverse-engineering입니다. 실제 플러그인 내부의 .claude-plugin/plugin.json은 해당 플러그인 한 개의 구성을 설명합니다.

앞쪽은 매장 진열표, 뒤쪽은 개별 제품의 설명서로 생각하면 됩니다. 버전 정보가 두 곳에 있으므로 배포할 때 서로 일치하는지 확인해야 합니다. 이 커밋에서는 둘 다 1.5.0입니다.

5-2. 참고 문서도 실행 설계의 일부다

파일 이름읽어야 하는 순간배울 내용
setup-guide.md도구 설치·환경 오류를 이해할 때PATH, Java, 외부 엔진 위치와 문제 해결
jadx-usage.md기본 디컴파일 옵션을 고를 때리소스·난독화·부분 결과 읽기
fernflower-usage.md복잡한 Java 출력을 대조할 때변환 경로와 엔진별 옵션
api-extraction-patterns.mdHTTP 흔적을 찾을 때라이브러리별 검색 패턴과 문서화 항목
call-flow-analysis.md검색 결과를 기능과 연결할 때Manifest·생명주기·DI·호출자 추적
kotlin-name-recovery.md짧은 클래스 이름이 읽기를 막을 때메타데이터에서 이름 후보를 찾는 원리
third_party_hosts.txtURL 결과의 잡음을 줄일 때외부 SDK 호스트를 정규식으로 분류하는 기준

참고 파일들은 plugins/android-reverse-engineering/skills/android-reverse-engineering/references/에 있습니다. SKILL.md가 단계별로 해당 파일을 가리키므로, 필요할 때 세부 지식을 찾아 읽는 구조입니다. 모든 설명을 하나의 거대한 지침에 넣지 않는 문서 구성도 학습 대상입니다.

5-3. 처음 읽을 때의 권장 순서

  1. plugin.json으로 무엇이 연결되는지 확인합니다.
  2. SKILL.md와 명령 파일을 비교해 전체 절차와 명령의 범위를 구분합니다.
  3. decompile.sh의 run_jadx()부터 외부 명령 호출을 읽습니다.
  4. find-api-calls.sh에서 입력·검색 조건·출력 형식을 따라갑니다.
  5. 이름 복원기와 조회기를 읽으며 JSON 매핑이 어떻게 활용되는지 확인합니다.

처음부터 모든 설치 분기를 외울 필요는 없습니다. 입력 하나가 어느 함수와 파일을 거쳐 어떤 결과를 남기는지 먼저 그리면, 나머지 옵션이 붙는 위치도 자연스럽게 보입니다.

6학습 포인트 (기술별)

잘된 구조와 불완전한 경계를 함께 읽어야 실력이 된다

6-1. Bash: 인자는 배열로 만들고 실패는 구분한다

run_jadx()는 옵션을 긴 문자열 하나로 조립하지 않고 args 배열에 넣습니다. 마지막에 jadx "${args[@]}"로 전달하므로 공백이 있는 파일 경로도 하나의 인자로 유지할 수 있습니다. 반면 echo "Running: ..."는 사람에게 보여주는 로그이지, 다시 평가할 명령문은 아닙니다.

# decompile.sh에서 발췌한 인자 구성
local args=()
args+=("-d" "$out_dir")
[[ "$DEOBF" == true ]] && args+=("--deobf")
[[ "$NO_RES" == true ]] && args+=("--no-res")
args+=("--show-bad-code")
args+=("$INPUT_FILE_ABS")

set -euo pipefail은 오류를 드러내는 기본 장치입니다. 그러나 grep은 일치가 없어도 종료 코드 1을 돌려주므로, 예상된 빈 결과에는 || true를 붙이는 코드가 나옵니다. 다만 이 처리로 grep의 다른 오류도 숨겨질 수 있으므로, 빈 결과만으로 “일치 없음”과 “처리 실패”를 구분할 수는 없습니다.

실습 아이디어: 종이에 owned demo.apk라는 경로가 들어갈 때의 배열 요소를 적어 보세요. 파일 경로 한 개가 인자 몇 개로 전달되는지 설명할 수 있으면 인용부호의 역할을 이해한 것입니다.

6-2. 정규식: 검색 결과는 후보 집합이다

find-api-calls.sh의 run_grep()는 Java와 Kotlin 파일을 재귀 검색합니다. Retrofit은 @GET 같은 애너테이션을, OkHttp는 Request.Builder 같은 호출 흔적을 찾습니다. 컴파일러의 문법 트리를 분석하는 방식은 아니므로, 주석·샘플 코드·사용하지 않는 문자열도 잡힐 수 있습니다.

--paths는 난독화로 호출 형태가 바뀌어도 문자열 경로는 남을 수 있다는 점을 이용합니다. SEG와 ROOT로 패턴을 만들고 MIME 형식과 일부 시스템 경로를 제외합니다. 결과가 어떻게 달라지는지 가짜 문자열로 생각해 볼 수 있습니다.

가짜 입력 문자열경로 검색의 예상이유
"/v1/profile"후보에 포함두 구간 이상의 절대 경로 형태입니다.
"api/v1/items"후보에 포함알려진 시작 단어 api 뒤에 경로가 이어집니다.
"/login"이 패턴에서는 누락절대 경로의 구간이 하나뿐입니다.
"image/png"중복 제거 목록에서 제외MIME 유형으로 걸러내는 규칙이 있습니다.
"/proc/self"중복 제거 목록에서 제외운영체제 경로를 제외하는 규칙이 있습니다.

검색 결과가 있다는 사실과 실제로 호출되는 API라는 결론 사이에는 코드 검토가 필요합니다. 경로 문자열을 찾았다면 호스트 설정·HTTP 메서드·호출자·인증 헤더를 따로 확인해야 합니다. 경로만으로 GET인지 POST인지 채워 넣으면 문서가 잘못됩니다.

6-3. URL 분류: 중복 제거와 출현 빈도는 다르다

--urls는 엄격한 URL 패턴과 awk 필터를 거쳐 문자열 잡음을 줄입니다. 이어 third_party_hosts.txt의 정규식에 맞는 호스트를 외부 서비스 후보로 묶습니다. “자사 후보”라는 표시가 호스트 소유권을 증명하는 것은 아닙니다.

특히 출력 제목의 frequency-sorted를 해석할 때 주의해야 합니다. URL 추출 직후 sort -u를 하므로 뒤에서 세는 숫자는 대체로 그 호스트의 서로 다른 URL 문자열 수입니다. 같은 URL이 소스 100곳에 나온다고 해서 100으로 세지 않습니다.

전체 검색의 요약부는 한 번의 grep 결과를 여러 분류로 셉니다. 하지만 상세 항목에서는 다시 검색합니다. “단일 순회”는 요약 집계에 해당하며, 도구 전체가 파일을 단 한 번만 읽는다는 뜻은 아닙니다.

실습 아이디어: 가짜 URL 3개 중 2개를 같게 적고, 중복 제거 전후에 호스트별 수가 어떻게 달라지는지 표로 비교하세요. 실제 요청 횟수와 정적 문자열 수가 다른 지표라는 것도 함께 설명해 보세요.

6-4. Python: 사전과 역색인으로 코드 읽기 보조하기

복원기는 mapping[난독화 이름] = 이름 후보를 저장합니다. 조회기는 같은 후보로 연결되는 파일이 여럿일 수 있어서 REV.setdefault(r, []).append(o)로 역방향 목록을 만듭니다. 사전 하나와 리스트만으로 다대일 관계를 탐색하는 작은 예제입니다.

# 구조를 설명하기 위한 가짜 매핑
{
  "a.b.c": "com.example.account.AccountRepository",
  "a.b.d": "com.example.account.AccountRepository"
}

# 역방향으로 보면 같은 원래 클래스의 후보 파일을 함께 찾을 수 있음
com.example.account.AccountRepository
    a.b.c
    a.b.d

코드를 더 자세히 보면 개선점도 보입니다. TSV에는 파일 경로가 있지만 JSON에는 이름 쌍만 있습니다. 후보를 얻은 방식은 전체 건수로만 집계합니다. 신뢰도를 더 잘 보여주려면 매핑마다 debug_meta·d2·renamed 같은 근거 유형을 함께 보관할 수 있습니다.

6-5. Kotlin 메타데이터: 원리와 복원 보장은 구분한다

README와 참고 문서는 Kotlin 메타데이터를 제거할 수 없다는 강한 표현과 높은 복원율을 제시합니다. 그러나 이 커밋에는 그 수치를 검증하는 샘플 데이터나 평가 코드가 없습니다. 스크립트 자체도 d2 배열에서 첫 적합한 타입을 고를 뿐, 그 타입이 반드시 파일의 선언 클래스인지 검증하지 않습니다.

Kotlin 공식 문서는 메타데이터가 클래스·함수·프로퍼티 같은 정보를 담고, 전용 라이브러리로 읽을 수 있다고 설명합니다. 반면 ProGuard 공식 문서는 일반 앱에서 메타데이터를 제거할 수 있으며, 리플렉션이나 라이브러리 용도에 따라 보존이 필요하다고 설명합니다. 보존된 메타데이터의 이름도 난독화된 클래스 이름에 맞춰 바뀔 수 있으므로, “원래 이름은 항상 남는다”고 일반화하면 안 됩니다. 근거: Kotlin 메타데이터 문서, ProGuard Kotlin 안내.

이 스크립트가 복원하는 대상은 클래스 이름 후보입니다. 메서드·필드 이름 복원은 구현하지 않습니다. 이는 스크립트의 범위에 대한 설명이며, Kotlin 메타데이터 전체가 클래스 이름만 담는다는 뜻은 아닙니다.

6-6. 이식성: 같은 이름의 파일도 동작은 다를 수 있다

확인 지점소스에서 읽히는 차이학습할 질문
Bash와 PowerShellPowerShell 검색기에는 Ktor·Apollo·경로 목록·호스트 분류 옵션이 없습니다.플랫폼 지원과 기능 동등성을 따로 적었는가?
이름 복원·판별대응하는 .ps1 파일 없이 Bash 파일만 있습니다.Windows 사용자가 기대할 수 있는 범위는 어디까지인가?
Vineflower 탐색Bash 검사기는 CLI와 사용자 로컬 JAR를 찾지만, 실행기의 JAR 탐색 목록은 더 좁습니다.검사 통과와 실행 가능성이 같은 조건인가?
AAR 경로Fernflower 경로는 AAR도 dex2jar에 직접 넘기며, classes.jar를 꺼내는 별도 분기가 없습니다.확장자가 다른 컨테이너를 같은 방식으로 처리해도 되는가?
분할 APK 재탐색바깥 출력의 sources/와 resources/가 있어야 조건을 검사합니다.both나 --no-res에서도 같은 경로가 존재하는가?

이 차이들은 실행 결과를 측정한 결론이 아니라 코드 경로에서 확인한 조건과 점검할 위험입니다. 특히 README가 권하는 AAR·Fernflower 조합은 입력 구조와 외부 도구 버전에 따른 검증이 필요합니다. README도 Windows 지원을 실험적이라고 표시합니다.

7하드웨어 / 시스템 요구사항

저장소의 명시 요구와 학습용 권장을 나누어 준비하기

README 기준 필수 도구는 Java JDK 17 이상과 jadx입니다. 검사 코드는 java 버전과 jadx 존재를 확인하며, javac 등 JDK 구성 요소는 검사하지 않습니다. CPU 코어 수·RAM 최소량·디스크 최소량은 저장소에 정해져 있지 않습니다. 아래의 하드웨어 수치는 보장 사양이 아닌, 작은 학습용 자료를 다룰 때의 시작 권장입니다.

항목확인된 요구 / 지원학습용 준비 기준
CPU최소 코어 수 명시 없음일반 64비트 PC·노트북으로 시작하고 입력 크기에 따라 시간을 관찰합니다.
RAM최소량 명시 없음8GB 정도에서 작은 예제로 시작하고, 큰 앱·두 엔진 비교에는 16GB 이상을 고려합니다.
디스크최소량 명시 없음입력 ZIP·압축 해제·중간 JAR·소스 결과를 위해 수 GB의 여유 공간을 준비합니다.
Java검사기의 최소 주 버전 17JDK와 실행 중인 java의 PATH가 일치하는지 확인합니다.
Python이름 복원·조회에서 python3 호출표준 라이브러리만 사용하지만, 검사기가 Python 존재를 확인하지는 않습니다.
Bash배열·연관 배열·문자열 소문자화 사용문법 기준 Bash 4 이상이 필요하며, Bash 3.2를 사용하는 macOS 환경은 별도 점검합니다.
WindowsPowerShell 스크립트 4개, README상 실험적 지원PowerShell 최소 버전은 명시되지 않았고, Bash판과 기능 차이가 있습니다.
GPU / 기기전용 GPU·에뮬레이터 필수 요구 없음정적 읽기에는 Android 폰이 없어도 됩니다. adb는 선택 도구입니다.

7-1. 운영체제 이름보다 실제 유틸리티 옵션을 확인한다

install-dep.sh는 macOS와 Linux를 나누고 brew·apt·dnf·pacman을 찾습니다. 그러나 설치 분기가 있다는 사실만으로 모든 분석 명령이 해당 OS 기본 도구에서 호환된다고 보장되지는 않습니다.

예를 들어 print_structure()는 find -printf를, XAPK 목록은 sort -z를 사용합니다. macOS 기본 BSD 유틸리티와 차이가 있을 수 있습니다. declare -A와 ${INPUT,,}도 오래된 Bash에서 사용할 수 없습니다.

준비 원칙
검사기가 확인하는 목록 밖에도 의존성이 있다

check-deps.sh는 Java·jadx와 선택 엔진 등을 확인합니다. 하지만 Python·Bash 버전·unzip·strings·GNU 옵션 지원을 모두 검사하지 않습니다. 검사 결과를 “시스템 전체 호환성 인증”으로 해석하지 않는 것이 좋습니다.

7-2. 시간 제한은 조건부로 적용된다

run_fernflower()의 전체 제한은 FERNFLOWER_TIMEOUT_SECONDS이며 기본값은 900초입니다. 다만 timeout 명령이 존재하고 설정값이 양의 정수일 때만 적용됩니다. 그 외에는 일반 java -jar 실행으로 진행합니다.

별도로 넘기는 -mpm=60은 메서드 단위 제한 옵션입니다. 전체 프로세스 제한과 구분해야 합니다. 큰 앱에 두 엔진을 사용하면 출력 공간과 처리 시간이 모두 늘어납니다.

7-3. 네트워크와 데이터의 경계

PRIVACY.md는 작성자가 운영하는 서버나 원격 측정 기능이 없다고 설명합니다. 설치기는 GitHub나 패키지 저장소에 접속하지만, API 검색기는 전달받은 디컴파일 소스를 읽을 뿐 찾은 URL에 요청을 보내지 않습니다.

로컬 도구가 파일을 처리한다는 사실과 AI가 읽은 내용의 처리 범위는 따로 확인해야 합니다. 같은 정책 문서는 Claude가 읽는 소스는 Anthropic의 약관과 정책에 따라 처리된다고 밝힙니다. 민감한 앱 자료를 다룰 때는 이 경계를 이해하고 분석 범위를 정해야 합니다.

8직접 해볼 수 있는 실습 과제

실행보다 먼저, 입력·분기·출력을 설명하는 연습

다음 다섯 과제는 저장소 스크립트나 설치기를 실행하지 않아도 수행할 수 있습니다. 코드 읽기와 가짜 자료만으로 설계의 장단점을 확인합니다. 파일 경로는 저장소 루트를 기준으로 하며, 과제는 검색·읽기와 설계안 작성으로 구성합니다.

과제 1 · 입문

명령 하나가 실제로 어디까지 하는지 그리기

목표: /decompile과 전체 스킬의 범위를 구분합니다.

  1. 루트 카탈로그의 source에서 플러그인 폴더를 찾습니다.
  2. plugin.json의 commands와 skills 경로를 연결합니다.
  3. 명령 문서의 단계와 SKILL.md의 Phase 0~5를 두 열로 비교합니다.

완료 기준: 의존성 검사·디컴파일·초기 요약과, 판별·이름 복원·API 문서화를 구분한 표를 만듭니다. 어떤 단계가 명령 문서에 직접 들어 있는지 근거도 적습니다.

힌트: 명령 문서의 마지막 단계는 다음 분석을 제안합니다. 완성된 API 문서를 무조건 생성하는 지시와는 범위가 다릅니다.

과제 2 · 입문

가짜 Retrofit 코드에서 API 카드 작성하기

목표: 문자열 검색 결과를 근거가 있는 문서로 바꿉니다. 아래 코드는 학습용 가상 예제입니다.

// 실제 앱에서 추출한 코드가 아닌 학습용 예제
interface DemoApi {
    @GET("v1/profile")
    Call<Profile> profile(@Header("Authorization") String token);
}

// 클라이언트 설정의 가상 예제
new Retrofit.Builder()
    .baseUrl("https://api.example.test/");
  1. 호스트·메서드·경로·인증 관련 입력을 표로 적습니다.
  2. 이 조각만으로 알 수 없는 내용은 물음표로 남깁니다.
  3. 토큰 형식과 실제 호출자를 확인하려면 어떤 추가 코드가 필요한지 적습니다.

완료 기준: 메서드는 GET, 경로는 v1/profile로 기록하되, Authorization 인자가 있다는 이유만으로 Bearer 인증이라고 단정하지 않습니다.

과제 3 · 중급

이름 복원의 정답과 오답 후보를 나누기

목표: 복원기의 우선순위와 첫 후보 선택의 한계를 이해합니다.

// a/b/c.java에 남았다고 가정하는 가짜 메타데이터
@DebugMetadata(c = "com.example.LoginRepository$load$1")

// 다른 파일에 남았다고 가정하는 가짜 타입 목록
@Metadata(d2 = {"Lcom/example/Logger;", "Lcom/example/Profile;"})
  1. 첫 예제에서 $ 뒤를 제거한 결과를 적습니다.
  2. 두 번째 예제에서 정규식이 먼저 고르는 이름을 적습니다.
  3. 그 이름이 실제 선언 클래스와 다를 가능성을 설명합니다.

완료 기준: 첫 결과는 com.example.LoginRepository이며, 두 번째는 코드상 Logger가 먼저 선택됨을 설명합니다. 이것을 Profile의 정확한 복원이라고 보장하지 않습니다.

확장: 매핑 자료에 source_file·evidence_type·candidate를 함께 저장하는 JSON 형식을 설계해 보세요.

과제 4 · 중급

부분 성공의 흐름을 결정표로 만들기

목표: 외부 명령 종료 코드와 래퍼의 반환 의미를 구분합니다.

  1. run_jadx()에서 종료 코드가 0일 때의 분기를 찾습니다.
  2. 종료 코드가 비정상이면서 Java 파일이 12개인 경우와 0개인 경우를 비교합니다.
  3. 각 결과를 decompile_single()이 받았을 때의 다음 행동을 적습니다.
  4. both에서 첫 엔진이 완전히 실패하면 두 번째가 실행되는지 확인합니다.

완료 기준: 내부 반환 0 / 2 / 1을 구분하고, 부분 성공은 계속하지만 완전 실패는 두 번째 엔진 전에 중단함을 설명합니다.

확장: 빈 결과 폴더가 남는 정상 종료를 어떻게 표시할지 설계해 보세요. 종료 코드만으로 분석 품질까지 판정할 수 있는지도 적습니다.

과제 5 · 고급

판별기의 누락 가능성을 찾아 개선 명세 쓰기

목표: 코드의 의도와 실제 입력 자료가 일치하는지 검토합니다.

  1. short_dirs가 LISTING과 DEX_STRINGS 중 무엇을 읽는지 찾습니다.
  2. 난독화된 패키지가 DEX 안에만 있다면 현재 통계가 무엇을 놓칠지 적습니다.
  3. Compose 판별의 점 구분 패턴과 DEX 추출의 슬래시 구분 문자열을 비교합니다.
  4. 혼합 프레임워크에서 첫 일치만 반환하는 방식의 대안을 제안합니다.

완료 기준: 압축 목록과 DEX 타입 목록을 구분하고, 가짜 입력·예상 판정·현재 판정 가능성을 표로 정리합니다. 개선 코드는 원본을 바꾸지 않고 별도 설계안으로 제시합니다.

힌트: short_dirs는 현재 ZIP 항목 목록만 봅니다. Compose 패턴은 androidx\.compose지만 추출된 타입 이름은 androidx/compose/... 형태입니다. 단정적인 “정상” 대신 근거와 불확실성을 함께 표시할 방법도 생각해 보세요.

실습의 목표는 도구를 한 번 성공시키는 데서 끝나지 않고, 결과를 믿을 조건을 설명하는 것입니다. 입력·도구·출력·검증 기준을 한 장에 적으면 다른 프로젝트의 자동화도 같은 방식으로 읽을 수 있습니다.

9관련 기술 심화 학습 로드맵

6주 동안 파일 읽기에서 분석 도구 설계까지

주당 3~5시간을 가정한 학습안입니다. 처음에는 실제 대형 앱보다 작은 가짜 코드 조각을 사용하세요. 각 주의 산출물을 다음 주의 입력으로 삼으면 문법 공부가 구체적인 분석 능력으로 이어집니다.

주차학습 주제이 저장소에서 읽을 곳남길 산출물
1주ZIP·APK·DEX·JAR의 관계, 파일과 경로fingerprint.sh의 입력 분기, 디렉터리 트리포맷별 내부 구성과 분석 경로 그림
2주Bash 배열·인용·종료 코드·파이프run_jadx(), check-deps.sh명령 인자 목록과 오류 결정표
3주정규식·중복 제거·오탐과 누락run_grep(), PATHS_REGEX, URL 필터가짜 문자열 20개와 예상 분류 표
4주Python 사전·JSON·역방향 조회복원기와 조회기의 내장 Python근거 유형을 포함한 매핑 스키마
5주Android 생명주기·MVVM·DI·HTTPcall-flow-analysis.md, API 패턴 문서화면 → ViewModel → 저장소 → API 호출 지도
6주도구 어댑터·이식성·재현성·평가두 플랫폼 구현, 매니페스트, 설치기기능 동등성 표와 고정 버전 실험 계획

9-1. 각 주를 마칠 때 스스로 물어볼 것

기술 이름을 많이 외우는 것보다 한 입력이 어떤 근거를 거쳐 결론이 되는지 설명하는 능력이 먼저입니다. 더 깊이 가고 싶다면 정규식 검색을 문법 트리 분석으로 확장하거나, Kotlin 전용 메타데이터 파서와 현재의 문자열 추출 결과를 비교하는 프로젝트로 이어갈 수 있습니다.

다음 학습으로 연결
보안 분석에서 일반 소프트웨어 설계로

엔진을 바꿀 수 있는 호출 구조는 이미지 변환기에도, 부분 성공 처리는 데이터 수집기에도, 근거를 남기는 매핑은 코드 검색 도구에도 쓰입니다. 이 저장소의 학습 가치는 Android 지식과 작은 자동화 시스템의 설계를 함께 읽는 데 있습니다.

10핵심 키워드 사전

코드와 문서에 반복해서 나오는 표현을 쉬운 말로
용어쉬운 설명
APKAndroid 앱을 설치할 때 쓰는 패키지입니다. 코드와 리소스 등이 들어 있습니다.
XAPK여러 APK와 부가 파일을 ZIP으로 묶은 배포 형태입니다.
분할 APK기본 코드와 CPU 종류·언어·화면 밀도 등에 따른 자료를 나누어 배포한 APK입니다.
DEXAndroid 런타임이 사용하는 실행 코드 형식입니다.
JARJVM 클래스와 자료 등을 담는 ZIP 계열 묶음입니다.
AARAndroid 라이브러리 묶음입니다. 보통 classes.jar와 리소스 등을 포함합니다.
디컴파일실행용 코드를 읽기 쉬운 소스 형태로 다시 표현하는 과정입니다.
smaliDEX 명령을 사람이 읽을 수 있게 표현한 낮은 수준의 표기입니다.
R8 / 난독화코드를 줄이고 최적화하며 이름도 짧게 바꾸는 도구와 과정입니다.
인라이닝함수 호출 대신 함수 본문을 호출 위치에 넣는 최적화입니다. 원래 호출 형태가 사라질 수 있습니다.
FQN패키지까지 포함한 전체 이름입니다. 예: com.example.LoginRepository.
애너테이션코드에 붙이는 추가 정보입니다. @GET은 HTTP 동작을 선언하는 데 사용됩니다.
@MetadataKotlin 선언 정보를 담는 애너테이션입니다. 남아 있는 내용은 빌드와 최적화 설정에 영향을 받습니다.
@DebugMetadata코루틴을 디버깅할 때 쓰는 정보입니다. 클래스·파일·줄 관련 단서가 남을 수 있습니다.
코루틴작업을 중단하고 이어갈 수 있게 구성하는 실행 방식입니다. 컴파일 결과에는 보조 클래스가 생길 수 있습니다.
Retrofit / OkHttpHTTP 통신을 구성하는 라이브러리입니다. 전자는 인터페이스 선언, 후자는 요청 구성 흔적이 탐색 단서가 됩니다.
KtorKotlin 계열 HTTP 도구입니다. 이 저장소는 클라이언트 호출·요청 설정·토큰 흔적을 검색합니다.
Apollo / GraphQLGraphQL 요청을 다루는 클라이언트와 질의 방식입니다. URL 하나에 여러 연산이 연결될 수 있습니다.
엔드포인트API 요청의 목적지입니다. 문서화할 때는 호스트·메서드·경로를 함께 봅니다.
Bearer 토큰보유한 토큰을 인증 근거로 제시하는 방식입니다. 문자열 발견만으로 사용 가능 여부를 알 수는 없습니다.
HMAC비밀키로 메시지의 인증값을 만드는 방식입니다. 호출 흔적만으로 키가 하드코딩됐다고 단정할 수 없습니다.
DI / Koin / Hilt객체를 어디서 만들고 주입하는지 관리하는 개념과 도구입니다. 인터페이스의 실제 구현을 찾는 단서가 됩니다.
휴리스틱자주 맞는 단서를 활용하는 추정 규칙입니다. 예외가 있으므로 근거와 함께 읽어야 합니다.
오탐 / 누락대상이 아닌 것을 찾은 경우와, 찾아야 할 대상을 놓친 경우입니다.
역색인여기서는 이름 후보 하나에서 관련 난독화 파일 목록을 되찾도록 만든 조회 자료를 뜻합니다.
PATH명령어 실행 파일을 찾을 디렉터리 목록입니다. 설치돼 있어도 이 목록에 없으면 못 찾을 수 있습니다.
종료 코드명령이 끝날 때 돌려주는 숫자입니다. 의미는 도구·함수마다 정의가 다를 수 있습니다.
래퍼 / 어댑터외부 도구를 감싸 입력·옵션·출력 형태를 맞춰 주는 코드입니다.

R8는 이름 변경 외에도 코드 제거·인라이닝·클래스 병합을 수행합니다. 그래서 디컴파일 결과의 클래스 경계가 원래 소스 구조와 같다고 기대하면 안 됩니다. 관련 배경은 Android 공식 R8 설명에서 확인할 수 있습니다.

11참고 링크

소스의 근거와 외부 기술의 공식 설명을 함께 확인하기

11-1. 저장소와 핵심 소스

11-2. 관련 기술의 공식 자료

현재 상태 (2026-10-23 GitHub 기준)

항목내용
선정 위치GitHub Trending Shell Daily #4 · 2026-10-23 분석
스타 / 포크8,268 / 936 · 2026-10-23 GitHub 기준
설명 / 주 언어Claude Code로 Android 앱 역공학을 돕는 스킬 / Shell
생성일2026-02-02
최신 릴리스v1.1.0 · 2026-04-27
최근 push2026-10-12 · 저장소 갱신 시각이며 커밋 작성 시각과는 다릅니다.
최근 커밋0c7cf89 · 2026-10-11 · docs: add third-party software notices
매니페스트 버전1.5.0 · 카탈로그와 플러그인 JSON에 기재
코드 규모Bash 1,967줄 + PowerShell 1,035줄. Bash 내부 Python 147줄은 중복 집계입니다.
문서 / 전체 파일Markdown 1,686줄 / 28파일. 텍스트 전체 5,054줄, Git 내부 제외
라이선스Apache-2.0. 외부 도구는 각 프로젝트의 라이선스가 별도로 적용됩니다.
자동 검증 구성이 커밋에는 테스트 전용 디렉터리·평가 데이터·CI 워크플로가 없습니다.
쓰기 전에 알아둘 한계
분석 보조 도구의 결과를 완전한 복원이나 확정된 명세로 취급하지 마세요

이름 복원율은 README와 참고 문서의 주장입니다. 이 커밋에는 이를 재현하는 평가 자료가 없으며, 입력과 최적화 설정에 따라 메타데이터가 사라지거나 후보가 잘못 연결될 수 있습니다. 엔드포인트 검색도 동적 URL 구성·암호화된 문자열·사용하지 않는 코드 때문에 누락과 오탐이 생깁니다.

Windows 지원은 실험적이며 Bash판과 기능이 다릅니다. AAR 변환·macOS 유틸리티·Vineflower 탐색 경로처럼 추가 호환성 확인이 필요한 부분도 있습니다. 실제 앱별 성공률·처리 시간·하드웨어 최소 사양에 대한 측정값은 제시돼 있지 않습니다.

설치기는 패키지 설치·사용자 로컬 경로·셸 설정을 바꿀 수 있습니다. 정적 분석과 설치를 구분하고 변경 내용을 이해한 뒤 사용하세요. 앱을 분석할 권한과 자료의 민감도를 확인하고, 발견한 인증 문자열을 실제 서비스 요청에 사용하지 않는 학습 방식부터 시작하는 것이 좋습니다.

스크립트의 로컬 처리와 Claude가 읽는 내용의 처리는 별개입니다. 자료 반출 조건은 해당 도구와 서비스 정책을 함께 확인해야 합니다. 스타·포크는 관심 지표이며, 정확도나 보안성을 보증하지 않습니다.