Broaden skill with unpacking, TLS triage, third-party build auditing, runtime probe
references: recon gains packer identification + unpacking workflow (payload/plaintext size mapping, dump validation, hash de-duplication, business-dex heuristic); repack-and-sign gains the de-shelled repack pipeline, why apktool over binary AXML, and the apksigner scheme-selection caveat; new tls-and-cert documents feature-scoped network failures, dual trust chains and the fix template; new third-party-builds covers auditing a cracked/modded APK before trusting it; dynamic-frida gains version pinning, remote-device path, the four-layer probe and hook-never-fires triage; environment gains UI automation pitfalls; ad-removal gains the single convergence point, dynamic-plugin SDKs and the global timestamp gate; pitfalls gains P13-P17; verification gains rung 7 and the three-signal ad check. scripts: new frida_probe.js (four-layer runtime probe), run_probe.py and tls_check.py; repack.py fixes two crash-on-default bugs and a misleading META-INF note; datastore_inject.py, PatchMethodExample.java and build_scripts.py lose hardcoded values - the example class name did not match its file and could not compile.
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
# Third-party builds — auditing a "cracked" or "modded" APK before trusting it
|
||||
|
||||
## Why this exists
|
||||
|
||||
A modded build of the exact app you are targeting is the most tempting shortcut available:
|
||||
it appears to prove the goal is achievable, and it may already contain the patch you were
|
||||
about to write. It is also the single most common source of wasted hours and of real risk,
|
||||
for two reasons.
|
||||
|
||||
1. **It is usually not editable.** Authors who redistribute mods protect them, often with
|
||||
more layers than the original app ever had. You cannot treat someone else's build as a
|
||||
patching workbench.
|
||||
2. **Its target-audience behaviour is unverified.** The binary may carry injected components,
|
||||
extra endpoints, or embedded credentials. "It runs and the ads are gone" tells you nothing
|
||||
about what else it does.
|
||||
|
||||
Treat a third-party build as an **untrusted sample to be audited**, never as a baseline.
|
||||
The useful output of an audit is a decision plus evidence — not a binary you start from.
|
||||
|
||||
## Step 1: Can you even edit it?
|
||||
|
||||
Find the app's own package prefix (the one that appears in its own class definitions, e.g.
|
||||
`com/<vendor>/<app>/`) and count how many times it appears as a **defined class** in each
|
||||
plaintext dex.
|
||||
|
||||
```
|
||||
business-prefix hits per dex:
|
||||
classes.dex 0 <- shell
|
||||
classes2.dex 0
|
||||
classes3.dex 0
|
||||
classes4.dex 0
|
||||
```
|
||||
|
||||
Zero everywhere means the business code has been **moved out of the plaintext dexes** — the
|
||||
build is protected at a level you cannot patch directly, even though it launches and works.
|
||||
Stop here and treat it as a black box.
|
||||
|
||||
Also check the reported dex count against the file count: a manifest-declared app with only
|
||||
library classes present is the same signal.
|
||||
|
||||
## Step 2: How many protection layers does it carry?
|
||||
|
||||
Mods frequently stack protection from multiple vendors, sometimes because the author
|
||||
re-protected an already-protected app. Look for independent, coexisting families:
|
||||
|
||||
| Layer kind | Typical static evidence |
|
||||
|---|---|
|
||||
| Commercial packer | shell `Application`/`appComponentFactory` in the manifest, a `lib*protect*.so`, encrypted assets, `assets/*.jar` with near-maximal entropy |
|
||||
| DEX-to-native (dex2c) | a "stub" `lib*.so` containing the tool's name, `EntryPoint`/`protect`-style symbols, and **business class names as strings** alongside a near-empty dex layer |
|
||||
| Anti-debugging / RASP | strings such as `TracerPid`, `ptrace`, `NoNewPrivs`, `CheckPtraceSelf`, `AntiFrida`, plus a self-protection log path |
|
||||
| Generic hardening marker files | small text files under `assets/` naming a protection vendor and a protection timestamp |
|
||||
|
||||
The practical consequence of an anti-debugging layer is that Frida-based dynamic work will hit
|
||||
a self-check before it hits your hook. Note it, and prefer static conclusions on such a sample.
|
||||
|
||||
## Step 3: What did the author ADD?
|
||||
|
||||
This is where the audit earns its keep. Diff against the **original build of the same version**
|
||||
(referenced as `<original>` below).
|
||||
|
||||
### New components
|
||||
|
||||
Build the set difference of `activity` / `service` / `receiver` / `provider` declarations,
|
||||
then check whether each new class name actually exists in the plaintext dexes.
|
||||
|
||||
- Class exists and is readable → you can judge its purpose.
|
||||
- Class name appears **nowhere** in plaintext but shows up inside a native library's strings →
|
||||
the logic is in the native/dex2c layer, purpose unknown. Say so.
|
||||
- Nothing registered with an implicit-launch intent-filter (`BOOT_COMPLETED`, `MAIN`) → it cannot
|
||||
be started implicitly, which limits (but does not eliminate) the risk.
|
||||
- A provider with an `authorities` value containing a package-name rewrite (a suffix/prefix that
|
||||
is not the current package) is a strong hint the build was produced by **repackaging or app
|
||||
cloning**, not by editing the original.
|
||||
|
||||
### New outbound endpoints
|
||||
|
||||
Extract every URL/domain/IP from the modded build's `lib/*.so`, `assets/*`, and dex strings,
|
||||
and subtract the original's set. Any domain that exists **only** in the modded build is the most
|
||||
important finding in the audit.
|
||||
|
||||
Rank what you find:
|
||||
- A domain that also serves install attribution or update checks is explainable.
|
||||
- A domain paired with an authorization-looking path (e.g. a `GET...`-style endpoint name
|
||||
nearby in the same string neighbourhood) is *not* explainable by de-ad work.
|
||||
|
||||
### Embedded secrets
|
||||
|
||||
Search native libraries and assets for private-key markers:
|
||||
```
|
||||
-----BEGIN ... PRIVATE KEY----- , PRIVATE KEY , PKCS#8 , RSA PRIVATE
|
||||
```
|
||||
A **private key shipped inside a client artifact** means its "authorization" or "integrity"
|
||||
path is not a security boundary — anyone can extract the key. Report it as a red flag on the
|
||||
build's trust claims, regardless of intent.
|
||||
|
||||
## Step 4: Capability picture — read both sides
|
||||
|
||||
A native library's import table is only half the story.
|
||||
|
||||
- **What it does not have** is meaningful: no `socket`/`connect`, no `execve`/`fork`/`system`,
|
||||
no `ptrace`, no installer-session strings → no direct evidence of command execution or
|
||||
silent install.
|
||||
- **What it references** can override that impression: string references to Java-layer
|
||||
`java/net/Socket`, `InetSocketAddress`, reflection entry points, or executor services mean the
|
||||
capability exists **through the Java layer**, off the native import table.
|
||||
|
||||
State findings as "capability present / no evidence of use" rather than "safe" — an import table
|
||||
is evidence of shape, not of intent.
|
||||
|
||||
## Step 5: The verdict
|
||||
|
||||
Do not hand back a binary. Hand back a decision with evidence and explicit unknowns.
|
||||
|
||||
```
|
||||
VERDICT: use / use with caution / do not use
|
||||
EVIDENCE:
|
||||
- business code plaintext? yes/no (+ counts)
|
||||
- protection layers list
|
||||
- injected components list, each with purpose known/unknown
|
||||
- endpoints present only in this build list
|
||||
- embedded credentials yes/no
|
||||
UNCONFIRMED:
|
||||
- <each item you could not establish, stated plainly>
|
||||
```
|
||||
|
||||
"Use with caution" is the honest answer whenever a build is un-analysable **and** carries new
|
||||
endpoints or unknown injected components. Do not upgrade it to "safe" because it launches
|
||||
cleanly, and do not call it malicious without evidence — both are guesses.
|
||||
|
||||
## Using the audit result
|
||||
|
||||
Two legitimate outcomes:
|
||||
|
||||
1. The audit shows the mod is an honest de-ad of the same version → you may use it to **learn the
|
||||
approach** (diff its patch points against the original), but still rebuild from the original
|
||||
yourself so the artifact you ship has a known provenance.
|
||||
2. The audit shows it is re-protected, injected, or un-analysable → discard it and do the work on
|
||||
the original. That is usually faster than reverse-engineering someone else's protection *and*
|
||||
your target's at the same time.
|
||||
Reference in New Issue
Block a user