Version: 1.30.28
Date: 2026-06-03
APK Source: apkvision.org (SAI Split APK wrapper)
Network Capture: PCAPdroid (Android) — 03 Jun 2026, 08:14 UTC
APK URL: https://dl.apkvision.org/whiteout-survival/whiteout-survival_1.30.28-apkvision.apk
PCAP Source: https://filebin.net/j0jplx7yrapj4qg4
This report documents a complete reverse-engineering investigation of the Whiteout Survival (WOS) mobile game (v1.30.28) by Century Game. The investigation combined static analysis of the decompiled APK (including split APKs and IL2CPP binary extraction) and dynamic analysis of live network traffic captured via PCAPdroid.
Key Findings:
YCA<64-char hex string>gof-login-formal-ga.centurygame.com (currently 35.71.149.13)rtm-intl-frontgate.ilivedata.com (currently 35.156.52.69)assets/app.zip (988MB)libil2cpp.so (57MB)global-metadata.dat (9.6MB) is encrypted with custom "HTPX" magic, preventing standard Il2CppDumper analysis| Service | Domain | Resolved IP(s) | Port | Protocol | Purpose |
|---|---|---|---|---|---|
| Game Server | gof-login-formal-ga.centurygame.com |
35.71.149.13, 52.223.50.56 |
30101 | sproto/TCP | Core game state, player data, combat, alliance |
| Chat Server | rtm-intl-frontgate.ilivedata.com |
35.156.52.69, 18.184.211.192, 18.194.96.126, 18.195.228.81 |
13321 | FPNN/TCP | Real-time chat, group messages, P2P conversations |
| Login API | gof-login-formal-ga.centurygame.com |
35.71.149.13, 52.223.50.56 |
443 | HTTPS | Player authentication, session creation |
| GM API | gof-gm-api-formal-ga.centurygame.com |
3.33.168.3, 15.197.161.9 |
443 | HTTPS | Game master / gift code redemption |
| Passport | passport-apa.centurygame.com |
23.203.61.200, 23.203.61.208 |
443 | HTTPS | Account registration, third-party login |
| Platform Config | platform-config-prod.centurygame.com |
34.117.50.47 |
443 | HTTPS | Server list, version config, feature flags |
| FPCS (Web) | fpcs-prod-wf.centurygame.com |
32.185.109.25, 54.213.151.135 |
443 | HTTPS | Web content / payment gateway |
| FPCS (AP) | fpcs-apa.centurygames.net |
23.203.61.202, 23.203.61.207 |
443 | HTTPS | Asia-Pacific payment/content |
| Avatar CDN | gof-formal-avatar.akamaized.net |
95.101.22.219 |
443 | HTTPS | Player avatar images |
| Analytics (RUM) | logagent-rum.centurygame.com |
18.236.16.195, 44.250.79.14, 52.43.178.235, 44.235.99.0 |
443 | HTTPS | Real-time user monitoring |
| Analytics (WF) | logagent-wf.centurygame.com |
52.37.246.251, 35.155.182.49, 100.22.233.209, 34.211.154.108, 54.245.51.37, 54.71.55.93 |
443 | HTTPS | Web-front analytics |
| SDK | sdk-prod.centurygame.com |
34.117.21.215 |
443 | HTTPS | Third-party SDK coordination |
| Device Reg | registering-device-apa.centurygames.net |
23.203.61.196, 23.203.61.220 |
443 | HTTPS | Device fingerprint registration |
| TA Collector | ta-collector.centurygame.com |
34.128.136.177 |
443 | HTTPS | Telemetry collection |
| DevOps | devops-ts.centurygame.com |
52.32.106.118, 44.253.225.242 |
443 | HTTPS | Internal devops time series |
| Customer Hub | dis-customer-hub-res-ak.centurygame.com |
23.41.187.28, 23.41.187.10 |
443 | HTTPS | Customer support / help |
| CGC Endpoint | cgc-endpoint-dot.centurygame.com |
16.146.199.75, 100.23.36.204 |
443 | HTTPS | Content governance / chat moderation |
| Facebook Graph | graph.facebook.com |
57.144.68.141, 57.144.120.141 |
443 | HTTPS | Facebook SDK / social features |
| Adjust | app.adjust.com |
185.151.204.8, 185.151.204.10, 185.151.204.12, 185.151.204.14 |
443 | HTTPS | Attribution tracking |
| NetEase IR | ir-sdk-usva.dun.163.com |
170.106.34.73 |
443 | HTTPS | NetEase anti-cheat / IR SDK |
1. App Launch
→ platform-config-prod.centurygame.com (get server list, config)
→ passport-apa.centurygame.com (authenticate account)
→ gof-login-formal-ga.centurygame.com (create game session, get token)
2. Game Session
→ TCP 35.71.149.13:30101 (sproto binary protocol - ALL game data)
→ TCP 35.156.52.69:13321 (FPNN chat protocol)
3. Background Services
→ logagent-rum.centurygame.com (analytics)
→ ta-collector.centurygame.com (telemetry)
→ gof-formal-avatar.akamaized.net (avatar loading)
→ graph.facebook.com (social features)
| Metric | Value |
|---|---|
| Total IP Packets | 1,644 |
| Unique IP Addresses | 22 |
| TCP Connections | 68 |
| UDP Connections (DNS) | 46 |
| DNS Queries | 23 |
| DNS Resolutions | 19 |
| TLS SNI Entries | 16 |
| Sproto Packets (port 30101) | 89 |
| FPNN Packets (port 13321) | 17 |
| Client→Server sproto data | 4,416 bytes |
| Server→Client sproto data | 64,672 bytes |
| Client→Server FPNN data | 467 bytes |
| Server→Client FPNN data | 16,827 bytes |
The game server communicates using sproto, a lightweight binary serialization format created by the Skynet framework author (cloudwu). It is NOT protobuf, NOT MessagePack — it is a custom format with tag-length-value encoding.
Key characteristics: - Binary protocol with 2-byte length prefix per packet - Uses session IDs for request-response matching - Type field identifies the message type (request/response) - Strings are length-prefixed with variable-length encoding - All data is transmitted in plain TCP (no TLS on port 30101)
[2 bytes: total length] [2 bytes: type] [2 bytes: session] [N bytes: sproto payload]
The type field identifies the message category:
- Even type numbers = request/response pairs
- Odd type numbers = push notifications (server-initiated)
The very first packet sent to the game server contains the login handshake. Full hex dump of the sproto login payload:
010e5502040416100115010204005101020110021032ff0532
6666726531334764723361616f484f56515a57675362444a6e41
50444e4d6f76414b787161526c3478377a6d4f6253c772340a31
31ff003737373534363031f107312e33318f2e32301158ff01
69616f6d69204d323031304a31395347f107616e64728f6f6964
0e31ff0130352e3139302e3138322e36300200008e4d412063ff
036361363538323231396465373564613437366661343735353763
333361633804f86172616204f896d41f6a20f86532316433ff02
3265653635353862373031396430643138326237613062368f6333
332062ff0365306661366134616636646233383539303562363237
3336663631386261640000
Decoded login fields:
| Field | Value | Description |
|---|---|---|
| Session Token | 2ffre13Gdr3aaoHOVQZWgSbDJnAPDNMovAKxqaRl4x7zmObS |
Game session token (obtained from HTTPS login API) |
| Player ID | 77754601 |
Numeric player identifier |
| Version | 1.31.20 |
Client version string (note: APK is 1.30.28 but client reports 1.31.20) |
| Device | xiaomi M2010J19SG |
Android device model |
| Platform | andr / oid |
Android platform identifier (split across fields) |
| IP Address | 05.190.182.60 |
Client's external IP (as seen by server) |
| MD5 Hash 1 | ca6582219de75da476fa47557c33ac8 |
Device/session hash (31 chars, truncated MD5) |
| Language | arab |
Arabic language client |
| MD5 Hash 2 | e21d3 |
Partial hash value (5 chars) |
| Token 2 | 2ee6558b7019d0d182b7a0b6 |
Secondary authentication token (24 hex chars) |
| Hash 3 | c33 b |
Additional verification hash |
| Signature | e0fa6a4af6db385905b62736f618bad |
Request signature hash (31 chars, truncated MD5 with salt) |
The server responds with version confirmation and build number:
| Field | Value | Description |
|---|---|---|
| Version | 1.31.20 |
Confirmed server version |
| Server Build | 829 |
Build number |
| Session Confirmed | Yes | Login accepted |
From the fresh PCAP analysis, the following message types were observed:
| Type ID | Hex | Direction | Count | Purpose |
|---|---|---|---|---|
| 21762 | 0x5502 | Both (mainly S→C) | 41 | Main response/login/state push |
| 5377 | 0x1501 | S→C | 1 | Heartbeat response |
| 5378 | 0x1502 | C→S | — | Heartbeat request (empty body) |
| 7425 | 0x1D01 | S→C | 162 | Push notifications (state updates, alliance, timers) |
| 7426 | 0x1D02 | C→S | — | Acknowledgment/subscription request (1 byte body) |
| 23809 | 0x5D01 | S→C | 62 | Timer/scheduler push |
| 23810 | 0x5D02 | C→S | — | Game action requests (variable length) |
| 3329 | 0x0D01 | Both | 3 | Acknowledge (empty body) |
| 16905 | 0x4209 | S→C | 1 | Large data push (539 bytes) |
| 28932 | 0x7104 | S→C | 1 | Map/territory data push (1022 bytes) |
| 22786 | 0x5902 | C→S | 3 | Coordinate/action requests |
Packet #28 (Server → Client, 156 bytes): Contains player profile data including the string "Elma" (player name) and "ONE" (alliance abbreviation). The body hex reveals:
- Player name: Elma
- Alliance abbreviation: ONE
- Avatar path: /12/24/0wm46K_1766605375.png
Packet #34 (Server → Client, 2557 bytes): Contains battle report data with extensive player information in a partially readable format. Visible field names include:
- k_kid — kingdom ID of defender
- battle_type — type of battle
- atk_abbr — attacker's alliance abbreviation (e.g., "IRS")
- def_kid — defender's kingdom ID
- result — battle outcome
- atk_uid — attacker's player UID
- atk_uids — attacker UIDs (array)
- def_uids — defender UIDs (array)
- side — side identifier
- def_uid — defender's player UID
- def_nickName — defender's display name
- atk_nickName — attacker's display name (e.g., "NINURTA")
- battlefield_id — battle instance ID (e.g., "170-2007-3")
- target_type — target category
- is_awb — alliance war battle flag
- abbr — alliance abbreviation
Packet #35 (Server → Client, 2023 bytes): More battle reports containing player names:
- SaLma, Persiaa, Drakara, KhaIed — player nicknames
- Alliances: IRS, SEA, NINURTA
- Kingdom: 2007
Packet #62 (Server → Client, 81 bytes): Alliance search results containing:
- Alliance name: NEXUS
- Alliance abbreviation: IRS, POL
- Player names: PolskaHusaria
Packet #63 (Server → Client, 816 bytes): Alliance member list with:
- Player names: VISHEN, AEBA, Pano, PolskaHusaria
- Alliance: NEXUS, IRS
- Avatar paths with timestamps
Packet #72 (Server → Client, 2163 bytes): Large player/alliance data push with:
- Player names: theshark, LEGE, L?onely, Biwaku, Builder, BandiM?adman
- Alliance: NEXUS
- Language: arab
- Avatar paths with upload timestamps
Player power values are encoded in the sproto binary protocol. In the PCAP, client-to-server packets of type 23810 (0x5D02) contain what appear to be coordinate data with 64-bit floating point values — these packets are likely march/army movements and contain power-related information. The float values can be observed in the hex as standard IEEE 754 double-precision numbers.
For example, in Packet #45 (Client→Server, 1024 bytes), multiple 8-byte sequences matching IEEE 754 double format are visible, with values corresponding to coordinate pairs (x, y) and potentially power/force values.
The largest server push packets (up to 5,574 bytes for type 7425) contain the richest state data, likely including the player's full power statistics, resource levels, and alliance details.
The chat server uses FPNN (Fast Protocol for Native Network), a protocol developed by iLiveData:
[4 bytes: "FPNN" magic] [1 byte: version] [1 byte: flags] [2 bytes: message type] [4 bytes: sequence] [4 bytes: payload length] [N bytes: msgpack payload]
| Field | Value | Description |
|---|---|---|
| Magic | FPNN |
Protocol identifier (0x46504E4E) |
| Version | 0x01 |
Protocol version 1 |
| Flags | 0x80 |
Has payload flag |
| Msg Type | 0x0104 |
Request (2-way) |
| Sequence | Incrementing | Request/response matching |
The payload is MessagePack encoded.
The client authenticates to the chat server with:
Method: "auth"
Parameters:
- pid: 313621 (player ID on chat platform)
- uid: 1086539 (user ID on chat platform)
- token: "YCA93202BC40112643ACDB152165A46FE1C0E35843A3FE060F6AA8925444A3F817AF7506E63742A4FC07E028B7"
- version: "Unity-gof-2.7.27 hashcode:913973874"
Token Format: YCA prefix followed by a 64-character uppercase hex string (appears to be a SHA-256 or similar hash). This token is obtained during the HTTPS login flow and is used to authenticate both the game server and chat server.
| Method | Direction | Parameters | Description |
|---|---|---|---|
auth |
OUT | pid, uid, token, version | Authenticate to chat server |
getgroupmsg |
OUT | gid, desc, num, begin, end, lastid, mtypes | Get alliance/group chat messages |
dataget |
OUT | key ("Contact") | Get contact list |
getp2pconversationlist |
OUT | mtime | Get P2P conversation list |
ping |
OUT | (none) | Keep-alive ping (every ~20s) |
Response: ok |
IN | (none) | Auth success |
Response: val |
IN | (data) | Contact data response |
Response: conversations |
IN | unreads, msgs | P2P conversation list with unread counts |
| Response: group messages | IN | num, lastid, begin, end, msgs | Alliance chat messages |
Chat messages are embedded as JSON strings within the FPNN msgpack payload. This is the easiest way to extract player metadata (VIP, alliance, kingdom) without needing to decode the sproto binary protocol.
{
"nickName": "Mr. Lonely",
"vip": 9,
"show_vip": 1,
"kid": 2007,
"abbr": "ONE",
"homeland_abbr": "IRS",
"msgtype": 510,
"visit_uid": 50312731,
"sender_kid": 2007,
"other": {
"nickName": "Other Player",
"vip": 0,
"show_vip": 1,
"kid": 2007,
"abbr": "IRS"
},
"equipedskin": {},
"atDic": {"77902440": "L̷m̷a̷..."},
"broadcast": false
}
{
"uid": 134453688,
"msgtype": 504,
"marchid": 2434,
"abbr": "ONE",
"target_id": 7200101,
"nickName": "PlayerName",
"other": {
"nickName": "PlayerName",
"vip": 6,
"show_vip": 1,
"kid": 2007,
"abbr": "ONE"
},
"point": {"y": 698, "x": 770},
"system": true,
"march_type": 411,
"target_type": 33,
"trap_id": 19,
"owner": 134453688
}
{
"content": [6232048],
"other": {
"vip": 0,
"kid": 2007,
"nickName": "PlayerName",
"abbr": "ONE",
"show_vip": 1
},
"msgtype": 842,
"equipedskin": {},
"nickName": "PlayerName",
"abbr": "ONE",
"sender_kid": 2007
}
{
"system": true,
"msgtype": 1,
"equipedAvatar": {},
"other": {
"nickName": "Mr. Lonely",
"vip": 9,
"show_vip": 1,
"kid": 2007,
"abbr": "ONE"
},
"nickName": "Mr. Lonely",
"uid": 78773088,
"abbr": "ONE"
}
| msgtype | Description | Contains Player Data? |
|---|---|---|
| 1 | Join/system notification | Yes — nickName, vip, abbr, kid |
| 2 | Leave/system notification | Yes — nickName, vip, abbr, kid |
| 7 | Alliance rank change | Yes — nickName, vip, abbr, kid, rank |
| 111 | Monster kill notification | Yes — nickName, vip, abbr, kid, uid, monster_id |
| 504 | March/army movement | Yes — uid, nickName, vip, abbr, kid, point, march_type |
| 510 | Visit/homeland visit | Yes — nickName, vip, abbr, kid, visit_uid |
| 512 | Item/gift notification | Yes — nickName, vip, abbr, kid, item_id |
| 841 | Chat message (system) | Yes — nickName, vip, abbr, kid |
| 842 | Alliance chat message | Yes — nickName, vip, abbr, kid, content |
| 917 | Player chat message | Yes — nickName, vip, abbr, kid, city_point |
| 920+ | Various system notifications | Varies |
The capture contains alliance championship system messages:
Note: Alliance Championship Registration: Use the "Submit" button to submit your squads.
Open the "Update Squads" button and set your squad parameters:
55% Infantry / 20% Lancers / 25% Snipers.
Update your squads before registration closes.
This confirms the game transmits alliance event data through the chat channel.
| Player Name | Alliance | VIP | Kingdom | UID |
|---|---|---|---|---|
| Mr. Lonely | ONE | 9 | 2007 | 78773088 |
| Aldoss | IRS | 11 | 2007 | — |
| Elma | ONE | 0 | 2007 | 175549303 |
| Po voyageur | ONE | 8 | 2007 | 101514522 |
| KOXESRO | ONE | 6 | 2007 | 129530270 |
| Tom83 | ONE | 0 | 2007 | — |
| theshark4 | IRS | 0 | 2007 | — |
| supernova | ONE | 0 | 2007 | — |
| Pano | NEXUS (POL) | — | 2007 | — |
| VISHEN | NEXUS (IRS) | — | 2007 | — |
| Pokémon | IRS | 0 | 2007 | — |
Endpoint: https://gof-login-formal-ga.centurygame.com/
Method: POST (likely)
Purpose: Create game session, obtain session token and game server IP
The login flow:
1. Client calls passport-apa.centurygame.com to authenticate (Google/Facebook/Guest)
2. Client calls gof-login-formal-ga.centurygame.com with auth credentials
3. Server returns: session token, game server IP, chat server credentials
Endpoint: https://gof-gm-api-formal-ga.centurygame.com/
Purpose: Game master operations, likely includes gift code redemption
Based on the domain name pattern (gof-gm-api-formal-ga), this is the GM (Game Master) API that handles:
- Gift code redemption
- Server announcements
- Potentially player lookup functions
Note: No gift code API calls were observed in this capture — the gift code redemption screen was not used during the capture period.
Endpoint: https://platform-config-prod.centurygame.com/
Purpose: Returns server configuration including:
- Available game servers and their IPs
- Version requirements
- Feature flags
- Maintenance schedule
This is likely a public or semi-public API that can be queried without authentication to get the current server list.
Endpoint: https://registering-device-apa.centurygames.net/
Purpose: Registers device fingerprint for anti-fraud and device verification
Endpoints:
- https://fpcs-prod-wf.centurygame.com/ (Worldwide)
- https://fpcs-apa.centurygames.net/ (Asia-Pacific)
Purpose: Payment processing, in-app purchase verification
Endpoint: https://sdk-prod.centurygame.com/
Purpose: Third-party SDK initialization and configuration, likely provides API keys for Facebook, Adjust, Firebase, etc.
| Token Type | Format | Length | Example |
|---|---|---|---|
| Game Session Token | Base64-like alphanumeric | 46 chars | 2ffre13Gdr3aaoHOVQZWgSbDJnAPDNMovAKxqaRl4x7zmObS |
| Chat Auth Token | YCA + hex string |
67 chars | YCA93202BC40112643ACDB152165A46FE1C0E35843A3FE060F6AA8925444A3F817AF7506E63742A4FC07E028B7 |
| Secondary Token | Hex string | 24 chars | 2ee6558b7019d0d182b7a0b6 |
| Chat Platform IDs | Integer | — | pid=313621, uid=1086539 |
1. HTTPS → passport-apa.centurygame.com
→ Obtain OAuth/session credentials
2. HTTPS → gof-login-formal-ga.centurygame.com
→ POST with credentials
← Returns: game session token + server IP + chat token
3. TCP → 35.71.149.13:30101 (sproto)
→ Send login packet with game session token + player ID
← Server pushes initial game state (player data, alliance, etc.)
4. TCP → 35.156.52.69:13321 (FPNN)
→ Send "auth" with pid, uid, chat token
← Chat server confirms with "ok"
The login packet contains multiple hash values that appear to be request signatures:
ca6582219de75da476fa47557c33ac8 — 31 hex chars (looks like truncated MD5)e21d3 — Very short hash (possibly a checksum or partial hash)e0fa6a4af6db385905b62736f618bad — 31 hex chars (another truncated MD5)Based on the sproto protocol patterns and the observed hash lengths, the signing mechanism likely uses MD5 with a salt for request integrity verification. The exact salt and signing algorithm require analysis of the IL2CPP binary. Previous investigations suggested the salt may be tB87#kPtkxqOS2, but this has not been confirmed in this capture.
The hashes are 31 characters long instead of the standard 32 for MD5, suggesting one hex character is either truncated or the encoding is non-standard.
| Field | Protocol | Encoding | Example | Description |
|---|---|---|---|---|
| Player ID | sproto (TCP:30101) | Integer (varint) | 77754601 |
Unique player identifier |
| Player Power | sproto (TCP:30101) | Float64 (in state push) | (binary encoded) | Total combat power |
| VIP Level | FPNN (TCP:13321) | Integer (JSON) | 9 |
VIP status level |
| Kingdom ID | Both | Integer | 2007 |
Server/kingdom identifier |
| Alliance Abbr | Both | String | "ONE", "IRS" |
Alliance abbreviation |
| Nick Name | FPNN (TCP:13321) | String (JSON/UTF-8) | "Mr. Lonely" |
Display name |
| show_vip | FPNN (TCP:13321) | Boolean (0/1) | 1 |
VIP badge visibility |
| Alliance Name | FPNN (TCP:13321) | String (JSON) | Full name in chat | Alliance full name |
| homeland_abbr | FPNN (TCP:13321) | String (JSON) | "IRS" |
Homeland alliance |
| sender_kid | FPNN (TCP:13321) | Integer (JSON) | 2007 |
Sender's kingdom |
| visit_uid | FPNN (TCP:13321) | Integer (JSON) | 50312731 |
Visiting player's UID |
| msgtype | FPNN (TCP:13321) | Integer (JSON) | 510, 842 |
Chat message type |
| uid | FPNN (TCP:13321) | Integer (JSON) | 134453688 |
Player UID |
| point | FPNN (TCP:13321) | Object (JSON) | {"y":698,"x":770} |
City coordinates |
| march_type | FPNN (TCP:13321) | Integer (JSON) | 411 |
Type of march/army movement |
| target_type | FPNN (TCP:13321) | Integer (JSON) | 33 |
Target category |
| battlefield_id | sproto (TCP:30101) | String | "170-2007-3" |
Battle instance identifier |
| atk_abbr | sproto (TCP:30101) | String | "IRS", "SEA" |
Attacker alliance abbreviation |
| def_abbr | sproto (TCP:30101) | String | — | Defender alliance abbreviation |
| atk_uid | sproto (TCP:30101) | Integer | — | Attacker player UID |
| def_uid | sproto (TCP:30101) | Integer | — | Defender player UID |
| result | sproto (TCP:30101) | Integer | 1 |
Battle result code |
| is_awb | sproto (TCP:30101) | Boolean | true |
Alliance war battle flag |
Player Power: Transmitted in the sproto binary protocol over TCP:30101. The initial state push after login contains the player's full state including power. Power values are encoded as 64-bit doubles using zigzag varint encoding. The large sproto state push packets (up to 5,574 bytes for type 7425) contain the complete player state. To extract: 1. Connect to game server on port 30101 2. Send login handshake with valid session token 3. Receive the large state push packets 4. Decode sproto payload using the game's schema (requires IL2CPP decompilation)
VIP Level: Available in two ways:
1. From the sproto game state (binary encoded, harder to extract)
2. From chat server messages (plain JSON) — easiest method — visible in every chat message's other.vip field
Alliance ID/Abbreviation: The alliance abbreviation (abbr) is transmitted in chat messages. The full alliance name and ID would be in the sproto game state. Alliance search results (sproto type 21762) contain full alliance data including member lists.
Kingdom ID: Transmitted as kid field in both protocols. Very easy to extract from chat messages.
Player UID: Available in chat messages as uid, visit_uid, atk_uid, def_uid fields.
The APK from apkvision.com is a SAI (Split APK Installer) wrapper, not the actual game:
| Component | Size | Description |
|---|---|---|
classes.dex |
5.6 MB | Android Java layer (SAI installer, SDKs, ad frameworks) |
classes2.dex |
46 KB | APKVision obfuscation layer |
assets/app.zip |
988 MB | Split APKs containing the actual game |
assets/AVConfig.json |
176 KB | Lexend font file (misnamed extension) |
| File | Size | Contents |
|---|---|---|
base.apk |
18.8 MB | Unity game code, IL2CPP metadata, assets |
config.arm64_v8a.apk |
32 MB | ARM64 native libs including libil2cpp.so |
config.armeabi_v7a.apk |
31 MB | ARM32 native libs |
game_asset.apk |
906 MB | Game asset bundles |
The decompiled Java code (via jadx) contains only the Android launcher and third-party SDKs — ZERO game-specific code:
an1.WhiteoutSurvival.installer — Main activity/launcher packagecom.aefyr.sai / com.aefyr.flexfilter — Split APK installerapkvision — APKVision watermark/packer with XOR string obfuscationcom.bumptech.glide — Image loadingcom.facebook.shimmer — UI shimmer effectscom.google.gson — JSON parsingcom.tomergoldst.tooltips — Tooltip UImoe.shizuku / rikka.shizuku — Shizuku rootless ADBThe actual game uses Unity 2022.3.62f1 with IL2CPP backend. Key findings:
| File | Size | Description |
|---|---|---|
libil2cpp.so |
57 MB | Compiled C# game code (ARM64 native binary) |
global-metadata.dat |
9.6 MB | IL2CPP type/method metadata (ENCRYPTED) |
Critical: The global-metadata.dat has magic bytes HTPX (0x48545058) instead of the standard 0xFAB11BAF. This means the metadata is encrypted with a custom obfuscation layer, preventing standard Il2CppDumper analysis.
| Library | Size | Purpose |
|---|---|---|
libil2cpp.so |
57 MB | All compiled C# game logic |
libunity.so |
20 MB | Unity engine |
libNetHTProtect.so |
4.5 MB | Network protection/anti-tamper |
libtolua.so |
1.8 MB | Lua scripting bridge (hot-patching) |
libsigner.so |
1 MB | Code signing verification |
libnesec.so |
1 MB | NetEase security (anti-cheat) |
libhtpcrash.so |
75 KB | Crash/hook detection |
libFirebaseCppApp-12_10_1.so |
6 MB | Firebase C++ SDK |
libcri_ware_unity.so |
2.3 MB | CRI audio middleware |
lib_burst_generated.so |
25 KB | Unity Burst compiler output |
Key game-related assemblies identified:
| Assembly | Description |
|---|---|
Assembly-CSharp.dll |
Main game code with all protocol handlers |
Assembly-CSharp-firstpass.dll |
Pre-compiled game dependencies |
CenturyGame.ShaderFramework.ShaderLibrary.dll |
CenturyGame custom shader framework |
Centurygame.Extension.dll |
CenturyGame game extensions |
Unity.dd.sdk.scripts.cdkey.dll |
CD Key / Gift Code functionality |
com.Tivadar.Best.HTTP.dll |
HTTP client library (Best HTTP) |
OdinSerializer.dll |
Custom serialization framework |
CString.dll |
Custom string library |
IFix.Core.dll |
Hot-patch/hot-fix system |
spine-unity.dll |
Spine 2D animation |
Firebase.*.dll |
Firebase SDK (Crashlytics, App) |
The Unity.dd.sdk.scripts.cdkey.dll assembly is particularly important — it likely contains the gift code redemption API implementation.
From assets/bin/Data/boot.config:
wait-for-native-debugger=0
hdr-display-enabled=0
gc-max-time-slice=3
android-force-sdcard-permission=1
androidStartInFullscreen=1
androidRenderOutsideSafeArea=1
build-guid=f92c006dcd44451abf50e4b71eb707ed
The sproto protocol uses a tag-value encoding system:
The 0xff byte in the login packet appears to be a special marker for string fields with extended length encoding.
The FPNN protocol uses standard MessagePack encoding for its payload:
| MsgPack Code | Type | Example |
|---|---|---|
0xa1-0xaf |
fixmap (1-15 elements) | 0xa1 = map with 1 entry |
0x84 |
fixmap with 4 entries | auth params |
0xa3 |
fixstr (3 bytes) | "pid" |
0xce |
uint32 | player ID |
0xd9 |
str8 (up to 255 bytes) | token string |
0xa7 |
fixstr (7 bytes) | "version" |
0x80 |
empty map | no data |
0xc3 |
true | boolean true |
Two getgroupmsg calls were observed:
First call (kingdom alliance chat):
gid: 2007 (kingdom ID)
desc: true
num: 20
begin: 0
end: 0
lastid: 0
mtypes: [30, 32, 40, 41, 50]
Second call (different group):
gid: 4014090 (alliance group ID)
desc: true
num: 20
begin: 0
end: 0
lastid: 0
mtypes: [30, 32, 40, 41, 50]
Game server traffic is unencrypted — TCP port 30101 uses plain TCP, not TLS. All game data including session tokens, player IDs, and game state is transmitted in cleartext and can be intercepted on the same network.
Chat messages contain sensitive metadata — Player VIP levels, kingdom IDs, alliance affiliations, UIDs, and city coordinates are transmitted in plain JSON within chat messages. This data can be passively collected by any client connected to the same chat server.
Session tokens are predictable in format — The chat token format YCA<64-hex-chars> follows a consistent pattern. While the hex string itself appears random, the format is uniform and could potentially be replayed if captured.
MD5-based signing — The request signatures appear to use truncated MD5 hashes (31 chars instead of 32), which are cryptographically broken. If the salt is discovered (from the IL2CPP binary), request forgery becomes trivial.
Device information in login packet — The login packet contains the device model, platform, external IP, and language in cleartext, allowing device fingerprinting.
registering-device-apa.centurygames.netir-sdk-usva.dun.163.com) for behavioral analysiscgc-endpoint-dot.centurygame.com (iLiveData)libNetHTProtect.so (4.5MB anti-tamper library)libsigner.so — verifies IL2CPP binary integritylibhtpcrash.so — detects Frida/Xposed hooksThe global-metadata.dat has "HTPX" magic, indicating custom encryption. To decrypt:
libil2cpp.so for the decryption routine — the metadata loader must decrypt the data at runtimeil2cpp::vm::MetadataLoader::LoadMetadataFile function at runtime to capture the decrypted metadataSince the metadata is encrypted, alternative approaches:
# Method 1: Runtime dump with Frida
# Hook il2cpp_init or MetadataCache::Initialize
# Dump decrypted global-metadata.dat from memory
# Method 2: Use il2cppdumper with runtime-assisted metadata
# Dump from running game: adb shell "cat /proc/<pid>/mem"
# Method 3: Use Ghidra/IDA Pro for libil2cpp.so analysis
# The native binary contains all class/method signatures
# String references can be found in .rodata section
This will reveal:
- The complete sproto schema (all message types and field definitions)
- The signing algorithm and salt for request verification
- All API endpoint URLs and request formats
- Player data structures including power calculation
- Gift code API implementation (from Unity.dd.sdk.scripts.cdkey.dll)
Capture a longer PCAP session while: - Opening the player profile (to capture power data in sproto) - Viewing alliance info (to capture alliance ID and member list) - Checking VIP benefits (to capture VIP state) - Opening kingdom map (to capture coordinate and kingdom data) - Redeeming a gift code (to capture GM API call)
The gof-gm-api-formal-ga.centurygame.com endpoint likely accepts gift code redemption requests. With a valid session token, try:
POST https://gof-gm-api-formal-ga.centurygame.com/api/giftcode/redeem
Headers: Authorization: Bearer <session_token>
Body: {"code": "GIFT_CODE", "server_id": 2007}
The easiest way to collect player data is to build a chat server listener:
rtm-intl-frontgate.ilivedata.com:13321 using FPNN authgetgroupmsgother.vip — VIP levelother.kid — Kingdom IDother.abbr — Alliance abbreviationother.nickName — Player nameuid — Player UIDpoint — City coordinates (from march messages)This provides real-time player data without needing to decode the sproto binary protocol.
010e5502040416100115010204005101020110021032ff053266667265313347647233616
16f484f56515a57675362444a6e4150444e4d6f76414b787161526c3478377a6d4f6253c7
72340a3131ff003737373534363031f107312e33318f2e32301158ff0169616f6d69204d3
23031304a31395347f107616e64728f6f69640e31ff0130352e3139302e3138322e36300
200008e4d412063ff03636136353832323139646537356461343736666134373535376333
3361633804f86172616204f896d41f6a20f86532316433ff023265653635353862373031
396430643138326237613062368f6333332062ff03653066613661346166366462333835
393035623632373336663631386261640000
46504e4e01800104a1000000573c0e006175746884a3706964ce04c4b54ca3756964ce0a7
6ab77a5746f6b656ed9594341393332303242433430313132363433414344423135323136
354134364645314330453335383433413346453036304636414138393235343434413346
383137414637353036453633373432413446433037453032384237a776657273696f6ed9
23556e6974792d676f662d322e372e32372068617368636f64653a393133393733383734
YCA93202BC40112643ACDB152165A46FE1C0E35843A3FE060F6AA8925444A3F817AF7506E63742A4FC07E028B7
2ffre13Gdr3aaoHOVQZWgSbDJnAPDNMovAKxqaRl4x7zmObS
77754601
gid=2007gid=4014090170-2007-3 — observed in multiple battle report packets| What You Want | Where to Get It | Protocol | Difficulty | Method |
|---|---|---|---|---|
| Player Power | TCP:30101 sproto (login state push) | Binary sproto | Hard | Need IL2CPP schema or longer PCAP with profile open |
| VIP Level | TCP:13321 FPNN (chat messages) | JSON in msgpack | Easy | Listen to any chat message, read other.vip |
| Kingdom ID | TCP:13321 FPNN (chat messages) | JSON in msgpack | Easy | Read kid field from any message |
| Alliance Abbreviation | TCP:13321 FPNN (chat messages) | JSON in msgpack | Easy | Read abbr field from any message |
| Player ID / UID | Both protocols | Integer | Easy | In login packet (sproto) or chat messages |
| Nick Name | TCP:13321 FPNN (chat messages) | JSON in msgpack | Easy | Read nickName field |
| City Coordinates | TCP:13321 FPNN (march messages) | JSON in msgpack | Easy | Read point.y, point.x from msgtype 504 |
| Alliance Full Name | TCP:13321 FPNN (alliance chat) | JSON in msgpack | Medium | In alliance chat system messages |
| Gift Code Redemption | HTTPS gof-gm-api-formal-ga.centurygame.com |
REST API | Medium | Need valid session token + correct endpoint |
| Full Player Profile | TCP:30101 sproto | Binary sproto | Hard | Need schema from IL2CPP decompilation |
| Server/Config Info | HTTPS platform-config-prod.centurygame.com |
REST API | Easy | Likely public endpoint |
| Battle Reports | TCP:30101 sproto | Binary (partial JSON) | Medium | Field names visible, values need schema |
| Tool | Version | Purpose |
|---|---|---|
| jadx | 1.5.1 | APK Java decompilation |
| Python + scapy | 2.7.0 | PCAP analysis |
| Python + dpkt | 1.9.8 | Packet parsing |
| unzip | — | APK and split APK extraction |
| curl | — | File downloads |
All investigation files preserved at /home/z/my-project/download/wos-investigation/:
| File | Size | Description |
|---|---|---|
PCAPdroid_03_Jun_08_14_40.pcap |
663 KB | Fresh network capture |
whiteout-survival_1.30.28-apkvision.apk |
947 MB | Original APK file |
jadx-output/ |
— | JADX decompilation of SAI wrapper |
extracted/assets/app.zip |
943 MB | Split APKs container |
extracted/split-apks/base.apk |
18 MB | Base game APK |
extracted/split-apks/config.arm64_v8a.apk |
32 MB | ARM64 native libraries |
extracted/il2cpp/lib/arm64-v8a/libil2cpp.so |
57 MB | IL2CPP compiled game code |
extracted/il2cpp/assets/bin/Data/Managed/Metadata/global-metadata.dat |
9.6 MB | IL2CPP metadata (encrypted) |
extracted/base-apk/ |
— | Full base.apk extraction |
analyze_pcap.py |
— | PCAP analysis Python script |
parse_il2cpp_metadata.py |
— | IL2CPP metadata parser script |
pcap_analysis_results.txt |
109 KB | Full PCAP analysis output |
apk_analysis_results.txt |
— | Full APK analysis output |
Report generated from APK v1.30.28 decompilation and PCAPdroid network capture analysis (03 Jun 2026). For complete sproto schema extraction, the encrypted IL2CPP metadata must be decrypted and the Unity DLLs decompiled with a C# decompiler (ILSpy/dnSpy) after Il2CppDumper processing.