
인간과 AI 에이전트를 위한 Android 리버스 엔지니어링: 밀리초 단위의 타입 지정된 Java, xref, API 및 시크릿 정찰, APK diff, 재서명, 네이티브 뷰어 및 MCP 서버. JVM 없이 단일 Rust 실행 파일.
어떤 Android 앱이든 열어서 실제로 무엇을 하는지 확인하세요.
무엇을 수집하는지, 어떻게 당신에게서 돈을 버는지, 무엇을 노출하는지. 단 몇 초 만에, 읽기 쉬운 Java로.
AI 에이전트를 위한 뷰어, CLI 및 MCP 서버. 단일 실행 파일. Java 불필요.
각 항목은 매니페스트, 리소스, 디컴파일된 코드를 함께 읽어야만 찾을 수 있었습니다. http://를
grep해도 아무것도 찾을 수 없습니다. 증거를 보려면 발견 사항을 클릭하세요: 핵심적인 줄만 추려낸 실제 출력입니다.
Block Blast! 10.9.3 (Play 빌드), 75,938개 클래스, 3.1초 만에 스캔 완료.
누가 당신의 데이터를 받는가: AppLovin MAX, AdMob, Meta, Unity, ironSource, Pangle, Liftoff/Vungle, InMobi,
Moloco, Amazon APS, Digital Turbine/Fyber, PubMatic, Bigo. 트래커: AppsFlyer, Firebase, Facebook 및
TikTok 이벤트, ThinkingData, 스튜디오 자체의 cn.hsdata. 권한: 광고 ID 및 네 가지
Privacy Sandbox 광고 API 전부.
두 개의 엔드포인트는 어떤 SDK에서도 온 것이 아닙니다. infer는 모델 호출입니다: 이 플레이어의 광고 가치는 얼마인가?
$ apkscope search blockblast.xapk urls
q.mb("https://low-ecpm.afafb.com/infer/v1/low_ecpm_cut", appActivity, jSONObject, new c() {
return "https://ecpm.afafb.com/infer/v1/ecpm";
$ apkscope decompile blockblast.xapk me.f # the code calls it AlgorithmInterCutManager
m2.mg(jSONObject, "ActUserInfo", ClassE.ma());
m2.me(jSONObject, "AdHistInfo", jSONArray);
m2.mg(jSONObject, "UserContext", ClassE.mc(str2, appActivity, z, UUID.randomUUID().toString(), "INTER"));
m2.mg(jSONObject, "UserInfo", ClassE.md());
deviceModel, ram, disk, cpu, carrier, country, ip_country, timeZone,
install_time, cold_start_num 및 과거 광고와 해당 revenue를 채웁니다. 이 답변이 귀하의 최저가,
즉 광고주가 귀하에게 광고를 표시하기 위해 넘어야 하는 최저 입찰가를 설정합니다:
$ apkscope decompile blockblast.xapk v2.d --method Y # AlgorithmBy1004, AppLovin MAX
double d3 = d * d2; // floor = predicted eCPM x "floor_factor" (remote, default 2.0)
this.g_c.mi(d3);
String.format(Locale.locale_US, "算法接口成功更新底价 - FloorPrice: %.2f, ... // "algorithm API updated the floor price"
판정: 합법적이며, 광고 기반 게임이 작동하는 방식이다. 이제 확인할 수 있다.
Block Blast는 NetEase 패커 뒤에 게임 클래스를 숨긴다: org.cocos2dx.javascript.AppActivity는
APK에 없다. apkscope dump는 게임이 스스로 압축을 풀도록 하여 25초 만에 메모리에서 15개의 DEX를
추출했으며, 약 3,100개의 숨겨진 클래스가 있다. 스크립트는 JsCallJava를 통해 Java를 호출하며,
그 메서드들은 무엇을 요청하는지 보여준다:
$ apkscope dump com.block.juggle out/ --attach
$ apkscope decompile out/dex/classes9.dex org.cocos2dx.javascript.pay.o --method w # SPayManager.serverControl
if (jSONObject.has("isStatus")) {
boolean z = k0.ma("1", jSONObject.getString("isStatus"));
SPStore.mk().y(z);
JsCallJava.setGameAuditMode(z, "auditMode"); // → window.IPAUtils.respHearingState(1)
auditMode를 켜고, 게임은 이를 기억합니다. 게임들은 스토어가 검토하는 동안 다르게 동작하기 위해 이것을 사용합니다. Block Blast가 바꾸는 것은 암호화된 스크립트 안에 있으므로, 우리는 그 이상을 주장하지 않습니다.callNativeGetLeftBattery (배터리 %), callNativeIsInstallOtherApp (앱 X가 설치되어 있나요?), getDeviceInfoByAdb (CPU 속도, RAM, 저장 공간, 화면, 모델).trackGameEndRevenue는 각 게임이 끝날 때 수익 데이터를 저장합니다.BleBumpKit은 권한을 요청한 후 근처의 두 휴대폰을 페어링합니다.표시되지 않음: 다음 블록을 어떻게 결정하는지. 이는 암호화된 스크립트에 있습니다 (한계 참조).
파일 데이터베이스 제공자가 내보내져 있으며, 해당 <path-permission> 태그는 문자 그대로 "false"라는 이름의 권한을 지정합니다. 유일한 실제 보호 장치는 코드에 있으며, file/, dir/ 및 루트를 건너뜁니다:
$ apkscope decompile nextcloud.apk com.owncloud.android.providers.FileContentProvider
private boolean isCallerNotAllowed(Uri uri) {
switch (i) {
case 4: case 5: case 6: case 7: case 8: // shares, capabilities, uploads, ...
str = this.mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
}
return false; // file (1), dir (2), root (3): anyone
}
public Cursor query(Uri uri, ...) {
if (i != 1 && i != 2 && i != 3 && isCallerNotAllowed(uri)) {
(사례 레이블은 접었고, 주석은 추가했다.) insert, update, delete는 동일한 검사를 사용한다. 이 테이블은
path, path_decrypted, file_owner, sharees, share_by_link, metadata_gps... 를 보관한다.
판정: 설치된 모든 앱이 파일 이름, 폴더, 공유 항목을 읽을 수 있으며, 종단 간 암호화된 파일의 복호화된 이름도 포함되고, 행을 변경하거나 삭제할 수도 있다. GitHub Security Lab이 2021년에 이를 지적했다; 해당 보고서의 SQL 인젝션은 수정되었지만, 개방형 접근은 35.0.1에서도 여전히 존재한다. 기기에서 실행한 것이 아니라 코드에서 읽은 내용이다.
$ apkscope resource antennapod.apk res/xml/network_security_config.xml
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="user" />
<certificates src="system" />
$ apkscope decompile antennapod.apk de.danoeh.antennapod.net.ssl.CompositeX509TrustManager --method checkServerTrusted
X509TrustManager x509TrustManager = (X509TrustManager) iterator.next();
try {
x509TrustManager.checkServerTrusted(x509CertificateArr, str);
판정: Android 7부터 앱은 사용자 인증서를 무시하지만, 이 앱은 다시 사용자 인증서를 허용하므로, 관리 대상 기기나 인증서를 설치하는 "VPN" 앱이 이 앱의 HTTPS를 읽을 수 있습니다. 사용자 정의 TrustManager는 실제 인증서를 하나씩 시도하고 어느 것도 허용하지 않으면 예외를 던집니다. 이는 의도적인 선택이며, 모든 것을 신뢰하는 버그가 아닙니다.
scan은 Jetpack Compose의 PreviewActivity를 exported로 나열합니다. 이 액티비티는 인텐트에 지정된 이름의 클래스를 실행합니다.
$ apkscope decompile thunderbird.apk androidx.compose.ui.tooling.PreviewActivity --method onCreate
int i = getApplicationInfo().flags & 2;
if (i == 0) {
Log.md(str, "Application is not debuggable. Compose Preview not allowed.");
finish();
판정: flags & 2는 FLAG_DEBUGGABLE이며, 릴리스 빌드는 그렇지 않습니다. 모든 스캐너가 이를 지적합니다;
누군가 디버그 가능한 빌드를 배포하기 전까지는 코드만이 안전하다고 말합니다.
$ apkscope decompile keepassdx.apk com.kunzisoft.encrypt.aes.AESTransformer
cipher = Cipher.getInstance("AES/ECB/NoPadding");
key = (Key) new SecretKeySpec(bArr, "AES");
cipher.init(1, key);
while (UnsignedKt.ulongCompare(j2, j) < 0) {
판정: KeePass AES-KDF는 비밀번호 추측을 늦추기 위해 하나의 블록을 자기 자신으로 rounds번 암호화한다. 단일 블록에 대한 ECB는 명세에 따른 것이다. 어떤 플래그를 제거해야 하는지 아는 것이 작업의 절반이다.