Files
HolodoriCalc/docs/research/android-master-open-2026-09-29.md
T
dal4segno 07b98db520
Publish GitHub Pages output / publish (push) Successful in 44s
data: switch to recovered game DB and refresh cards and charts
2026-09-29 22:48:08 +09:00

44 lines
4.1 KiB
Markdown

# Android 마스터 DB 열기 경로 조사
후속 결과: 같은 날 메모리에서 379개 파일별 키를 복구하고 전체 DB의 복호화와 SQLite 검증에 성공했다. 아래 미확인 항목은 이 최초 정적 조사 시점 기준이며, 후속 검증은 [복구 기록](android-master-recovery-2026-09-29.md)을 참고한다.
2026-09-29, LDPlayer 14 / Android 14 / 게임 1.2.0에서 확인했다.
앱 파일과 프로세스는 수정하지 않았다. 테스트 계정 인증 정보 사용은 허용받았지만 이번 조사에서는 사용하지 않았다.
## 실행 상태에서 확인한 사실
- PID 4380의 파일 디스크립터에 외부 앱 저장소 `files/EB0A191797624DD3A48FA681D3061212/`의 후보 파일들이 열려 있었다.
- 같은 프로세스가 앱의 ARM64 `libsqlcipher.so`를 로드하고 있었다.
- 이 폴더에는 379개 파일이 있었다. 두 표본의 첫 32바이트에 일반 SQLite 헤더는 없었다.
- 시스템 SQLite도 함께 로드되어 있으므로, 라이브러리 존재만으로 모든 파일을 SQLCipher DB라고 판정하지 않았다.
## 현재 Android 바이너리에서 확인한 호출 경로
복사한 `libil2cpp.so`와 복호화한 IL2CPP 메타데이터를 연결하고 ARM64 명령을 확인했다. 아래 주소는 이 바이너리의 RVA이며 실행 시 절대 주소가 아니다.
1. `MasterManagerBase<object>.CreateCryptKey` (`0xB6283A0`)는 파일 정보 인터페이스의 슬롯 3을 호출한다. 메타데이터에서 이 슬롯은 `IMasterFileInfo.get_CryptoKey`다. 앞뒤 인자를 포함한 세 문자열 연결 결과를 UTF-8 바이트로 변환한다. 앞뒤 문자열의 실제 값은 이번 기록에서 확정하지 않았다.
2. `MasterDBConnectionPool.GetConnection` (`0xDC45458`)은 기존 연결을 찾고, 없으면 파일 경로와 키 바이트를 `CreateConnection`으로 넘긴다.
3. `CreateConnection` (`0xDC45678`)은 URI를 만들고 `SQLite3Manager.Open`에 플래그 `0x41`을 전달한다.
4. 키를 받는 `SQLite3Manager.Open` (`0xDC45A18`)은 내부 Open (`0xDC48138`)을 호출한 뒤 `sqlite3_key` (`0xDC48020`)에 연결과 키 바이트, 길이를 전달한다.
5. 내부 Open은 플래그가 있는 경우 `sqlite3_open_v2`를 호출한다. `0x41`은 SQLite의 READONLY(1)와 URI(0x40) 조합이다.
6. `CreateConnection`은 이어서 준비된 PRAGMA 목록을 `PreparedStatement.ExecuteNoQuery`로 실행한다.
메타데이터에는 `query_only = ON`, `journal_mode = OFF`, `locking_mode = EXCLUSIVE`, `automatic_index = 0`, `cache_size = 10`, `synchronous = 0` PRAGMA 문자열이 있다. 기본 `GetConnectionOpenPragmas`는 6개 항목 배열을 만든다. 이 문자열 각각의 배열 슬롯 연결은 아직 검증하지 않았다.
따라서 마스터 연결 코드는 SQLCipher에 키를 적용해 DB를 직접 읽는 구조로 확인된다. 별도의 평문 DB를 먼저 만드는 경로는 위 함수들에서 발견되지 않았다. 다른 경로의 존재를 배제한 것은 아니다.
## 미확인 사항
- 현재 각 파일에 대응하는 CryptoKey 값과 앞뒤 문자열의 실제 값.
- 실제 실행에서의 키와 암호화 옵션, 후보 파일 전체의 테이블 구성.
- 복사본을 독립적으로 열고 조회하는 검증은 아직 하지 않았다. 실제 마스터 복호화 성공을 의미하지 않는다.
## 재현 자료
원본 바이너리, 메타데이터, 분석 스크립트는 무시되는 `data/inspection/android-master-2026-09-29/`에 보관했다. `disasm.py`와 `open-path-assembly.txt`에 호출 근거가 있다. 덤퍼의 출력은 기존 도구 디렉터리 `data/inspection/master-direct-2026-09-26/dumper-bin/`에 생성되었으며 Android 1.2.0 분석 결과다.
- libil2cpp.so SHA-256: `f3c02abd02f8d0c5263e2181e712bf495fa83c80568df8c29414a61809c4fffe`
- libsqlcipher.so SHA-256: `91060e3d9360d4ac0858633f24ed97a62b66b6cdf18c00f8ef8a1e39e72fd76f`
공식 HolodoriDB main은 앞선 동일 조사 세션에서 fetch했고 3개 언어 모두 9월 26일 수집 기준과 같은 커밋이었다. 계산기 데이터 수집·반영은 실행하지 않았다.