Files
2026-10-31 23:35:41 +01:00

3.8 KiB

Android protection removal

One pipeline removes AnoSDK (overseas) or Mobile ACE/TSS (CN); the variants differ only in the constants in protection/profile.rs, and --variant auto picks one from the libraries present. It restores four protected ARM64 libraries, neutralizes the SDK startup and native API calls, drops the protection libraries, and signs a new APK.

Variant profiles

Field AnoSDK Mobile ACE/TSS
Regions SEA, GLB, JP, KR, TW CN
Decoder library libanort.so libtprt.so
Guard library libanogs.so libtersafe2.so
Key record XOR 0xDF 0x49
Decoder symbol g_acf_array g_tprt_pfn_array
Application class com.ano.gshell.AnoApplication com.ace.gshell.AceApplication
SDK class com.gamesafe.ano.AnoSdk com.tencent.tp.TssSdk
Native APIs 6 AnoSDK* 5 tp2_*

Identification (protection/mod.rs)

Checks ChannelConfig (ChannelName/BundleIdentifier) against the variant's regions, confirms both protection libraries are ARM64 ELFs, and rejects APKs that also contain the other variant's libraries. ARM64 is the only supported ABI.

Restore (protection/loader.rs)

  • permutation follows the decoder symbol through its routine and GOT reference to the eight-page permutation (a digit string permuting 0..8).
  • Each 48-byte protected-section descriptor is matched to an ELF section by name, RVA, file offset and size. The Base64 key record at descriptor table +0x1A4 is XORed with the variant byte: magic 0x20240829, key id 1 drives restoration, and the mode at +0x184 (1 or 2) selects page treatment. Each restored section must match its recorded CRC-32.
    • Large sections: AES-128-CBC over 0x4000 bytes in 0x800-byte chunks from 0x2000 - (RVA & 0xFFF) (key: the value's repeated lowercase hex; IV 0x02..0x11, reset per chunk). Mode 1 XORs and shuffles 0x4000 fragments across eight 0x10000 strides; mode 2 XORs the remainder.
    • Small sections: whole-section XOR.
  • BBMG311DIS12IMP gives the protected import count (+16), .rela.plt RVA (+24), entry count (+28) and excluded GOT slots (+32/+36); selected import r_info values are rotated back into order. BBMG311ENC12IAI gives the constructor array RVA (+16) and count (+20). The wrapper DT_INIT, the decoder library's DT_NEEDED entry and the APS2/RELA wrapper relocations are cleared, and the fread/fwrite/fclose GOT imports are restored. The removed DT_INIT RVA is passed to the API helper.

Neutralize (protection/native.rs)

In restored libil2cpp.so, finds the SDK API names and the guard library name in .rodata, traces ADRP/ADD references to them, and redirects each resolver BL to a 16-byte helper written over the removed DT_INIT initializer. The helper returns a pointer to a function that returns zero; other P/Invoke resolutions are untouched. Aborts if the initializer is still active, an API is missing, or the call graph is ambiguous.

DEX edits (protection/dex.rs)

Three methods are edited after each call is validated:

Method Edit
Application.<clinit> NOP both native library loads (20 bytes)
Application.attachBaseContext Replace the invoke + move-result after the superclass call with return/NOPs (8 bytes)
SDK class <clinit> NOP the guard library load (const-string 10 bytes, or const-string/jumbo 12 bytes); keep the return

All 8 attachBaseContext bytes are rewritten because leftover operand words after the return would still fail DEX verification. Checksums are recomputed.

Output

The decoder and guard libraries are dropped; the restored libraries and edited DEX files are repacked and signed by android::sign. Any mismatched marker, CRC, method or resolver layout aborts the patch.