# 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.` | 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 `` | 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.