almasumdev/awesome-mobile-security-agent-skills

anti-tampering

Anti-tampering on mobile — signature checks, runtime application self-protection (RASP), and realistic return on investment.

소스 보기

사용 방법

  1. 설치 명령을 복사하고 자신의 에이전트 환경에 설치하기 전에 소스 패키지를 확인하세요.
  2. 필요한 도구, 인증 정보, 지원 환경은 원본 문서에서 확인하세요.
  3. 입력과 원하는 산출물을 설명하고 출처와 결과를 대조하세요.
npx skills add https://github.com/almasumdev/awesome-mobile-security-agent-skills --skill anti-tampering

시작 전 확인

  • 설치에는 모델 구독, API 한도, 파일 접근 권한이 포함되지 않습니다.
  • 별점 수와 설치 수는 활동 지표이며 독립적인 품질·보안 검증이 아닙니다.
원본 Skill 문서

원본 저장소의 제목, 예시, 코드, 표, 링크, 이미지를 유지해 표시합니다.

Anti-Tampering on Mobile

Instructions

Anti-tampering controls are a spectrum. Pick the layers that match your actual threat model and compliance needs — not a generic checklist.

1. Tampering We Care About

ThreatExampleWho it hurts
Re-signed binaryPirated version with ads injectedRevenue, brand
Modified resourcesFree-upgrade patch for IAPRevenue
Frida instrumentationBypass a feature flag or auth checkBusiness logic integrity
Emulator / cloud deviceAutomated account fraudTrust & safety
Debugger attachedReverse engineering in progressSecrets, IP

You probably don't care about all of these. Pick two or three.

2. Signature / Bundle ID Checks

Cheap, high ROI. The app verifies at runtime that it's still signed by your key / has your bundle ID.

kotlin
fun isGenuine(ctx: Context): Boolean {
    val info = ctx.packageManager.getPackageInfo(
        ctx.packageName,
        PackageManager.GET_SIGNING_CERTIFICATES,
    )
    val expectedSha256 = "AA:BB:CC:..." // pinned at build time
    val signers = info.signingInfo?.apkContentsSigners ?: return false
    return signers.any { sha256Hex(it.toByteArray()) == expectedSha256 }
}
swift
func isGenuine() -> Bool {
    guard let bundleId = Bundle.main.bundleIdentifier else { return false }
    guard bundleId == "com.example.app" else { return false }
    // Optionally validate the embedded provisioning profile / code signature
    return hasValidCodeSignature()
}

Don't just early-return false — it tells the attacker exactly where to patch. Feed the signal into a server-side anomaly score instead.

3. Resource / Asset Integrity

For apps where specific files must not be swapped (game balance JSON, model weights, license files):

  • Ship a manifest of sha256 digests signed with a key you control.
  • At startup, recompute and compare.
  • Store only the expected digests in R8-obfuscated code, not the full JSON.

4. RASP — Where It Pays, Where It Doesn't

RASP (Runtime Application Self-Protection) libraries attempt to detect Frida, debuggers, Magisk modules, Xposed, and various hooking frameworks.

  • Worth it for: high-value financial, gambling, trading, DRM, and some compliance-driven (PSD2) apps.
  • Rarely worth it for: most SaaS, productivity, content, and social apps. RASP is noisy, adds startup cost, blocks legitimate users (niche ROMs, custom kernels), and is an arms race.
  • Never a substitute for: server-side authorization.

If you ship RASP:

  • Treat detections as signals, not kill switches. Feed them into risk scoring.
  • Test against a representative device lab before shipping — false positives on Samsung One UI / Xiaomi MIUI / Huawei EMUI are common.
  • Review the vendor's CVE history and support responsiveness.

5. Debugger Detection

Cheap to add, cheap to bypass. Still worth it as one signal.

Android:

kotlin
fun debuggerAttached(): Boolean =
    Debug.isDebuggerConnected() || Debug.waitingForDebugger() ||
    (ApplicationInfo.FLAG_DEBUGGABLE and context.applicationInfo.flags) != 0

iOS:

swift
func isBeingDebugged() -> Bool {
    var info = kinfo_proc()
    var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
    var size = MemoryLayout.stride(ofValue: info)
    sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0)
    return (info.kp_proc.p_flag & P_TRACED) != 0
}

Ship these disabled in debug builds and only in release binaries.

6. Emulator / Cloud Device Signals

Signals to combine (none are definitive):

  • Build.FINGERPRINT contains "generic" / "emulator" / "vbox".
  • /proc/cpuinfo, /dev/socket/qemud.
  • Sensor availability and realism (a perfect, unchanging accelerometer reading screams emulator).
  • iOS: simulator-only paths under /Applications/Xcode.app/.

Prefer Play Integrity (deviceRecognitionVerdict) / App Attest — they already do this with better fidelity. See api-abuse-protection.

7. Server-Side Is Where It Matters

Whatever the client detects, it reports. The server decides:

  • If a binary reports "signature invalid" and pins fail and attestation is missing, raise risk score → require step-up auth, block the transaction, or silently flag for review.
  • Never trust a single client-side boolean. Assume the client can lie about any of these signals.

8. What Not to Do

  • Do not crash the app on tamper detection. A crash is a stack trace that points to the check.
  • Do not log "tamper detected" in plain text. Use an opaque error code.
  • Do not spread checks across 200 places "to make it harder" if you never test them — they'll rot and produce false positives in production.

Checklist

  • [ ] Signature / bundle ID is checked and the result is reported, not used as a kill switch.
  • [ ] Asset integrity manifest exists for files whose content must not change.
  • [ ] RASP, if used, is justified by threat model and tested on a real device lab.
  • [ ] Debugger detection is release-only and feeds a signal, not a crash.
  • [ ] Emulator detection uses Play Integrity / App Attest as the primary source.
  • [ ] Server-side risk scoring exists to weigh these signals together.
  • [ ] No anti-tamper code relies on string literals visible in the binary.

관련 작업

같은 저장소의 Skills

더 많은 Skills

모든 Skills