Skip to content

DeviceIntelligence 0.8.0

Choose a tag to compare

@iamjosephmj iamjosephmj released this 03 May 16:59
· 129 commits to main since this release

Highlights

Third ABI shipped: armeabi-v7a (32-bit ARM). The AAR now contains native binaries for arm64-v8a, x86_64, and armeabi-v7a — covering low-end Android devices common in EM markets (Samsung A-series, Tecno Spark, Infinix Hot, Itel, OPPO low-end, Vivo Y-series) that don't ship the 64-bit ABI primary or at all.

For most consumers this is a pure-additive change: existing 64-bit installs keep getting the same arm64-v8a library, plus a lib/armeabi-v7a/libdicore.so (~214 KB stripped) inside the APK that the Android loader picks when running on a 32-bit-only device.

Detector coverage on armeabi-v7a

Detector Status
integrity.apk works
integrity.bootloader works
integrity.art INCONCLUSIVE — the ArtMethod field-offset table is currently 64-bit-only. Vectors A / C / D / E / F report unavailable on this ABI. Characterising 32-bit ART struct layouts across Android versions is a research task tracked for a future minor release.
attestation.key works
runtime.environment works (including DEX-injection channels — channel a + b + unattributable_dex_at_baseline all on 32-bit, plus .text SHA-256 baseline + GOT integrity scans)
runtime.root works
runtime.emulator non-decisive — the AArch64 MRS-based probes (CNTFRQ_EL0, MIDR_EL1, etc.) have no clean ARMv7 equivalent. The graceful-degrade stub reports arch=armeabi-v7a|status=unsupported|hyp=0.
runtime.cloner works

Implementation notes

  • syscalls.cpp on __arm__ delegates to libc rather than issuing raw syscalls. The 32-bit Linux ARM ABI diverges from 64-bit in three places that are easy to get subtly wrong (lseek vs _llseek, mmap vs mmap2, fstat vs fstat64). Routing through libc is a documented trade — a libc-hooker can intercept these reads on 32-bit ARM that they cannot on 64-bit.
  • ElfParser learns ELF32. The 32-bit ELF program header has a different field order (not just smaller fields) — p_flags moves position. Each class has its own helper. The build-time .text SHA-256 baseline now lands in fingerprint.bin's dicoreTextSha256ByAbi map for all three ABIs.
  • entry_point_offset() returns kUnknownOffset on !__aarch64__ && !__x86_64__ — cascades into Vector A / E / F's "skip" path, which surfaces as integrity.art INCONCLUSIVE.

What was not changed

No wire-format changes, no schema bump, no public API additions. Every detector ID and Finding.kind is identical to 0.7.2. Backends already speaking the 0.7.x wire format keep working as-is.

Validation

  • All three ABIs build cleanly (debug + release variants).
  • Each .so confirmed as the correct architecture (ELF32 ARM / ELF64 aarch64 / ELF64 x86-64).
  • Pixel 6 Pro smoke test: sample APK installs, app launches, libdicore.so (arm64-v8a) loads, dicore G1 module bootstraps, no crashes.
  • armeabi-v7a runtime-stable on real 32-bit ARM hardware — confirmed in the Sauce Labs Android 11+ device-farm sweep alongside the 64-bit ABIs. The native lib loads, every detector except integrity.art runs to completion, JSON parses, no crashes.

Consumer (JitPack)

plugins {
    id("io.ssemaj.deviceintelligence") version "0.8.0"
}

com.github.iamjosephmj.DeviceIntelligence · tag 0.8.0

Sample APK

minimal-release.apk is attached to this release. APK now bundles lib/{arm64-v8a,armeabi-v7a,x86_64}/libdicore.so. Install on a 32-bit-only device to exercise the new path; install on a 64-bit device to verify the existing path still works (Android picks arm64-v8a on 64-bit hardware).