Help! How to bypass delayed watchdog termination (clean exit 0 at ~40s) by Shiyue Anti-Cheat (SYCheck / libdvstat.so + FairGuard)

jennymax193

Just Crazy
Hi everyone,

I am currently reverse-engineering and analyzing the Android mobile game Evo Defense: Merge TD (published by Shiyue Games / 诗悦网络).

Target Profile:

  • Game Title: Evo Defense: Merge TD
  • Package Name: com.evodefensetd.gp
  • Game Version: 1.1.1 (VersionCode: 10101)
  • Main Activity: com.shiyuegame.fswy.GameMainActivity
  • Engine: Unity HybridCLR (Huatuo CIL runtime)
  • Architecture: ARM64 (arm64-v8a)

Security & Anti-Cheat Stack:​

Through static and runtime binary triage, I discovered the game uses a dual-layer protection mechanism:

  1. Commercial Protector (FairGuard / ZZProtect):
    • lib/arm64-v8a/libZzprotect.so (~5.44 MB, heavily obfuscated with OLLVM Control Flow Flattening).
    • Its DT_NEEDED imports libFairGuard.so.
    • It decrypts assets/bin/Data/Managed/Metadata/global-metadata.dat in memory upon Unity bootstrap (the raw metadata header magic is scrambled with 0x6D2E8F48 instead of standard 0xFAB11BAF).
  2. In-House Anti-Tamper & Risk Control SDK (Shiyue SYCheck):
    • Java layer: com.sy.check.plugin (SYRiskControl, AntiMemHack, BridgeCheatingDetector, RiskDecisionEngine).
    • Native engine: lib/arm64-v8a/libdvstat.so (~1.4 MB).
    • Strings reveal active detection for GameGuardian, Frida gadgets, memory scanners reading /proc/self/mem and /proc/self/pagemap, decoy page checksum traps, ptrace attachment, and clock drift.

The Issue (The T+40s Delayed Exit Trap):​

After patching and launching the APK on an Android 12/14 emulator (OnePlus / ASUS profiles), the game runs smoothly, renders the splash screen, and enters the main UI. However, consistently at T+40.78 seconds, the process silently dies with a clean exit:

Zygote: Process com.evodefensetd.gp (PID: xxxx) exited cleanly (0)
There is no crash dump, no SIGSEGV, and no ANR dialog.

Findings So Far:​

  1. At around T+38s, background threads (Thread-33 checking battery sysfs / /system/bin/sh via BatteryBroadcastReceiver and Thread 4947 querying Settings.Global.adb_enabled via AsyncBase) trigger risk telemetry.
  2. RiskDecisionEngine evaluates the anomaly score and calls AbstractBase.AbstractBase, which ultimately executes System.exit(0).
  3. Attempting to hook Bionic libc exit, _exit, or _Exit in native C++ using trampolines causes stability issues / crashes inside ARM-to-x86 translation layers (Houdini/NDK translator).

Questions for the Community:​

  1. For anyone who has worked on Shiyue Games titles (using com.sy.check / libdvstat.so), is the kill decision enforced purely from Dalvik (System.exit(0)), or does libdvstat.so also dispatch kernel syscalls (exit_group, kill(SIGKILL)) directly?
  2. What is the cleanest way to completely silence or stub out com.sy.check.plugin.utils.BridgeCheatingDetector and SYRiskControl without breaking the game's initialization lifecycle?
  3. Has anyone successfully dumped the decrypted global-metadata.dat from memory when libZzprotect.so / FairGuard is active on this specific game?
Thanks in advance for any insights or tips!
 
That's the cleanest post form I've ever seen lol

My personal answer (and it's imo)

You probably need to do more research on how works libc in the android system and also checking the java smali cuz it can also have watchdogs as well

Good luck for your research
 
That's the cleanest post form I've ever seen lol

My personal answer (and it's imo)

You probably need to do more research on how works libc in the android system and also checking the java smali cuz it can also have watchdogs as well

Good luck for your research
Thanks man! Have you had a chance to test out Evo Defense yet? If you've looked into this specific target, I'd love to hear your thoughts so we can pinpoint the exact approach together.
 
Back
Top Bottom