๐ŸŽฎ White Out Survival - Cloud Android & HTPX Decryption Investigation

Last updated: June 2, 2026 | APK Version: 1.31.20 | Player: FADL2 (ID: 250893802)

๐Ÿ“‹ Executive Summary

This investigation attempted to decrypt the HTPX-encrypted global-metadata.dat and set up a cloud Android environment to run the White Out Survival XAPK for live traffic capture. Static decryption failed because HTPX uses a sophisticated position-dependent block cipher, but we discovered critical intelligence about the encryption system and identified viable cloud Android approaches for runtime decryption via Frida.

๐Ÿ” HTPX Encryption Analysis

File Structure

OffsetSizeValueDescription
0x004HTPXCustom magic (replaces AF 1B B1 FA)
0x044FC 30 94 00Original file size (9,711,868 bytes)
0x08variesEncrypted128-byte block encrypted data

Encryption Properties Discovered

Keys Extracted from libNetHTProtect.so

The HTProtect library (NetEase HTProtect, not just "N4tHTProtect") contains these potential encryption keys:

Key StringLengthContext
t76euy9fu8bv485zh17JNI interface parameter (with trailing 'h')
hccd63688a790ca6517JNIFactory identifier
e9edd62242ad7aecf17Method signature area
r316e12523620efb717Key storage area
d0f149b4da6ec47716Pure hex key
f190da6241bff18bf17Key storage area
r25d273c7ad4065c317Key storage area
u233ace17d63ca9e16Pure hex key
aebd1811194e82d916Pure hex key
437ae92817f9fc85b7e520Extended key
2be6951adc5b22410a5fd21Extended key

Also found: 16 O0-obfuscated keys (e.g., O0O00o0o0o000OOo) and obfuscated string keys (e.g., ,4$8'9-6:.6$1#?*XhHpSeA~NrZlE)

XOR Key 0x56312342 Found in libil2cpp.so

The known HTProtect string table XOR key 0x56312342 was found at offset 0x0307a6f4 in libil2cpp.so. However, it's in the encrypted dynamic symbol table region, not as a standalone constant. This key is used for decrypting the ELF symbol/string tables after the SO is loaded, not for the global-metadata.dat encryption.

HTProtect Architecture (from NetEase)

Java Interface:

Native Libraries:

Protection Layers:

  1. Section Header Table (SHT) encryption โ€” prevents IDA/Ghidra analysis
  2. Junk code / flower instructions (่ŠฑๆŒ‡ไปค) โ€” breaks decompilation
  3. Three INIT functions with custom linker implementation
  4. Modified RC4 for sub-SO decryption
  5. global-metadata.dat encryption with HTPX magic replacement
  6. Post-decryption magic zeroing (zeros out AF 1B B1 FA after runtime decryption)

โ˜๏ธ Cloud Android Services Research

Recommended Services (Ranked)

#ServiceFree TierXAPKFridaTraffic CaptureBest For
1Genymotion SaaS60 minโœ“ ADBโœ“โœ“ mitmproxyBest overall
2Appetize.io30 min/moโœ“ Native .apksโœ—โœ—App launch testing
3CorelliumTrialโœ“ ADBโœ“โœ“Best tech capability
4AWS Device Farm1000 minโœ“ ADBLimitedโœ“ tcpdumpAutomated testing
5Redroid (Docker)Free*โœ“ ADBโœ“โœ“Long-term use
6Firebase Test Lab20/day virtualโœ“โœ—LimitedQuick tests
7now.ggFreeโœ— Pre-listed onlyโœ—โœ—Playing only

* Redroid requires a VPS with Docker + kernel binder module support (~$5-10/month)

Genymotion SaaS - Step by Step

# 1. Sign up at https://cloud.geny.io (free, no credit card)
# 2. Install CLI
pip install gmsaas
gmsaas auth login --email YOUR_EMAIL

# 3. Start Android 11 instance
gmsaas instances start --name wos --shape g2.8cpu.15gb.android11
gmsaas instances adbconnect wos

# 4. Install White Out Survival (split APK)
unzip wos_latest.xapk -d wos_xapk/
adb install-multiple wos_xapk/com.gof.global.apk \
                     wos_xapk/config.arm64_v8a.apk \
                     wos_xapk/game_asset.apk

# 5. Install Frida server
FRIDA_VER=16.1.4
curl -L -o frida-server.xz \
  "https://github.com/frida/frida/releases/download/${FRIDA_VER}/frida-server-${FRIDA_VER}-android-arm64.xz"
xz -d frida-server.xz
adb push frida-server /data/local/tmp/frida-server
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "/data/local/tmp/frida-server &"

# 6. Dump decrypted metadata
frida -U -f com.gof.global -l wos_frida_metadata_dump.js --no-pause

# 7. Hook sproto protocol
frida -U -f com.gof.global -l wos_frida_sproto_hook_v2.js --no-pause

# 8. Capture traffic with mitmproxy
pip install mitmproxy
mitmproxy --listen-port 8080
adb shell settings put global http_proxy YOUR_IP:8080

Appetize.io - Quick Browser Test

# 1. Sign up at https://appetize.io (free, email only)
# 2. Upload the merged APK via API
curl -X POST https://api.appetize.io/v1/apps \
  -H "X-API-KEY: YOUR_TOKEN" \
  -F "file=@whiteout_survival_merged.apk" \
  -F "platform=android" \
  -F "timeout=300"

# 3. Access in browser using the publicKey from response
# https://appetize.io/embed/PUBLIC_KEY?device=pixel6pro&osVersion=13.0

๐Ÿ”ง Toolkit Files

FileDescriptionSize
wos_frida_metadata_dump.jsFrida script to dump decrypted global-metadata.dat from memory~8 KB
wos_frida_sproto_hook_v2.jsFrida script to hook sproto encode/decode in libtolua.so~6 KB
wos_htpx_decrypt_toolkit.pyPython script with all static decryption attempts~7 KB
wos_cloud_android_setup.shStep-by-step cloud Android setup guide~5 KB
whiteout_survival_merged.apkMerged APK (base + arm64 + assets) for cloud upload~1041 MB

๐Ÿ“Š sproto Protocol Summary

Protocol Messages Discovered: 210

CategoryCountKey Messages
NOTIFY (Serverโ†’Client)78NOTIFY_PLAYER_POWER_UPDATE, NOTIFY_PLAYER_ACTIVITY_POWER_UPDATE, NOTIFY_STOVE_INFO
REQ (Clientโ†’Server)132REQ_PLAYER, REQ_CENTER_RANK, REQ_SHOP_BUY, REQ_HERO_PROMOTE

sproto Wire Format

TCP Frame: [2B length BE][1B type][payload]

Type 0x00 REQUEST:  [4B session_id][4B proto_id][sproto_packed_data]
Type 0x01 RESPONSE: [4B session_id][sproto_packed_data]
Type 0x02 NOTIFY:   [4B proto_id][sproto_packed_data]

sproto Field Header (2 bytes, big-endian):
  High byte = field number (1-based)
  Low byte encoding:
    0x00     โ†’ next 4 bytes = int32
    0xFF     โ†’ next 8 bytes = int64
    0x01-7F  โ†’ inline value
    0x80     โ†’ length in next 2 bytes
    0x81-FE  โ†’ length = low & 0x7F

sproto Pack (zero-byte compression):
  16-byte chunks: [2B bitmap LE][non-zero bytes]
  Bitmap bit[i]=1 โ†’ byte present; bit[i]=0 โ†’ byte is zero

Known Schema Fragments

TypeFieldsNotes
power_rankid, abbr, gflag, __bg, leader, uid, language, power_rankAlliance/player ranking data
soldier_mapid, qualityBattle unit mapping
hero_mapid, star, lev, name, power/Score, abbrHero data dictionary
powerFightpve, slg_skill_id, Reset, Helper, leader_typeCombat power calculation

๐ŸŽฏ Next Steps

  1. Sign up for Genymotion SaaS (free, 60 min) at cloud.geny.io
  2. Install the XAPK via adb install-multiple
  3. Deploy Frida server on the cloud Android instance
  4. Run wos_frida_metadata_dump.js to dump decrypted global-metadata.dat from memory
  5. Run Il2CppDumper on the decrypted metadata + libil2cpp.so to extract C# class structure
  6. Extract sproto schema from the C# classes (sproto protocol definitions are compiled as C# types)
  7. Run wos_frida_sproto_hook_v2.js to capture live protocol traffic
  8. Build the complete API client with full sproto schema knowledge

๐Ÿ”‘ Previously Discovered API Secrets

SecretValueUsage
Web Sign KeyUxXkyv4g9nmvK8gPMD5 signing for web API requests
Gift Code SalttB87#kPtkxqOS2Gift code validation signing
AES-192 KeyJm93LUl9xqWd/1Ar+7QXeApCZw==Data encryption key
Test PlayerID 250893802Nickname "FADL2", State 2007, Furnace Lv31

This investigation is for authorized security research purposes only. All findings are reported to Century Game engineering.