White Out Survival — API Investigation Report

Comprehensive Reverse-Engineering & Protocol Analysis • APK v1.31.20 (build 269)

📋 Report v2.0 — Updated & Expanded 📦 com.gof.global 🔒 Unity IL2CPP + tolua 📡 209 sproto messages discovered 👤 Player 250893802 — VERIFIED

Investigation Overview

This report documents the reverse-engineering of Century Game's White Out Survival (com.gof.global, v1.31.20) network APIs, protocol schema, and security mechanisms. The investigation combines static APK analysis with live API testing to map the game's communication infrastructure.

APK Version
v1.31.20
Build 269 • com.gof.global
sproto Messages
209
Extracted from LuaJIT bytecode
Working Endpoints
5
Verified with live requests
NOTIFY Messages
77
Server-push protocol messages
Encryption Layers
4
MD5 sign, AES-192, HTPX, SSL pinning
Native Libraries
6
il2cpp, unity, NetHTProtect, tolua, nesec, signer
👤

Player Lookup Test — FID 250893802

VERIFIED
Player Avatar

FADL2

FID: 250893802 • Server: KID 2007
31
Stove Lv
30
Stove Content
FC1
Furnace Rank
$0
Total Recharge

Raw API Response

json
{
  "fid": 250893802,
  "nickname": "FADL2",
  "kid": 2007,
  "stove_lv": 31,
  "stove_lv_content": 30,
  "avatar_image": "https://gof-formal-avatar.akamaized.net/avatar/2026/04/18/nmAP54_1776551552.png",
  "total_recharge_amount": 0
}

Note: The stove_lv of 31 maps to Furnace level "30-1" (FC1 tier entry). The stove_lv_content of 30 indicates the displayed content level. See the Furnace Level Mapping section for the complete translation table.

📦

APK Technical Analysis — v1.31.20

DECOMPILED
PropertyValue
Package Namecom.gof.global
Versionv1.31.20 (version_code: 269)
EngineUnity IL2CPP
Scripting Bridgetolua (C# ↔ Lua via tolua.so)
Protocolsproto binary over WebSocket
Lua RuntimeLuaJIT (luapackage_64 bytecode)

Native Libraries

LibrarySizePurposeSecurity Role
libil2cpp.so56 MBIL2CPP compiled C# runtimeCore game logic
libunity.so20 MBUnity Engine nativeRendering & engine
libNetHTProtect.so4.4 MBHTProtect anti-tamperSSL Pinning + HTPX
libtolua.so1.8 MBLua/C bridge + sprotoProtocol encode/decode
libnesec.so1 MBNetEase Shell packerCode packing
libsigner.so961 KBAPK signature verificationIntegrity checks
🌐

Working API Endpoints

1. Giftcode Player API VERIFIED

http
POST https://wos-giftcode-api.centurygame.com/api/player

Auth: MD5 sign with secret "tB87#kPtkxqOS2"
Sign = MD5("fid={fid}&time={ts}tB87#kPtkxqOS2")

Body (form-data):
  fid: 250893802
  time: {timestamp_ms}
  sign: {md5_hash}

Returns: fid, nickname, kid, stove_lv, stove_lv_content, avatar_image, total_recharge_amount

2. Giftcode Config VERIFIED

http
POST https://wos-giftcode-api.centurygame.com/api/gift_code_config

Returns: Banner configuration for the gift code web portal

3. Platform Config VERIFIED

http
GET https://platform-config-prod.centurygame.com/config.json

No auth required
Returns: FPCS hosts, acc regions, CDN hosts, source UUID

Key data:
  - fpcs hosts (3 endpoints)
  - acc regions (default: APA, US/AU/JP/KR/TW: GA)
  - cs_cdn_host (3 CDN mirrors)
  - age_compliance host

4. GeoIP Location VERIFIED

http
GET https://fpcs-prod-apa.centurygame.com/api/location

No auth required
Returns: { country_code, ip, cmp_region }

5. Game Notices VERIFIED

http
POST https://gof-report-api-formal.centurygame.com/api/web_notice

Returns: In-game notice/announcement data

6. FPCS Config PARTIAL

http
POST https://fpcs-prod-apa.centurygame.com/api/config

Requires: game_id (20121), version, platform
Issue: Version validation currently fails (server-side mapping issue)
The server does not recognize the v1.31.20 version string,
likely requires a specific version code mapping that differs
from the APK version_code (269).
🔀

sproto Protocol Schema — Critical Finding

CRITICAL

209 protocol messages were extracted from the APK's LuaJIT bytecode (luapackage_64). The game uses the sproto serialization format (originally from the Cloudwu/skynet framework) transported over WebSocket connections with AES-192 encryption.

⚡ Key Power-Related Messages

NOTIFYNOTIFY_PLAYER_POWER_UPDATE
NOTIFYNOTIFY_PLAYER_ACTIVITY_POWER_UPDATE
NOTIFYNOTIFY_STOVE_INFO

⚔ Key Hero-Related Messages

NOTIFYNOTIFY_CLICK_SQUAD_HERO_ITEM
REQREQ_HERO_PROMOTE
REQREQ_HERO_SEARCH_
REQREQ_HERO_UPGRADE_SUCCESS
NOTIFYNOTIFY_UPDATE_EXPERT_SKILL_INFO
SETSET_DEFENSE_HERO_REFRESH

👤 Key Player-Related Messages

REQREQ_PLAYER
NOTIFYNOTIFY_PLAYER_MOOD
NOTIFYNOTIFY_PLAYER_MOOD_UPDATE
NOTIFYNOTIFY_PLAYER_OFFICE_UPDATE

♕ Key Alliance-Related Messages

NOTIFYNOTIFY_ALLIANCE_CHEST_GLORY_UPDATE
REQREQ_ALLIANCE_MEMBERS_SUCCESS
REQREQ_ALLIANCE_CHANGE_RANK_SUCCESS
ALLIANCEALLIANCE_SYNC_UPDATE

🏆 Key Rank-Related Messages

REQREQ_CENTER_RANK
REQREQ_CROSS_CAPITAL_WAR_RANK
REQREQ_ACHIEVEMENT_GET_RANK_DATA_SUCCESS

🔥 Key Furnace/Building Messages

NOTIFYNOTIFY_BUILDING_UPGRADE_FINISH_FURNACE
ACTIONCONSTRUCTION_FURNACE

Schema Fragments Recovered

sproto
-- power_rank type
.power_rank {
  id          0
  abbr        2
  gflag       3
  __bg        4
  leader      5
  uid         6
  language    8
  power_rank  9
}

-- soldier_map type
.soldier_map {
  soldier_map 7 : *battle_(id)(quality)
}

-- finish_ts field
.finish_ts 4 : integer(0)

-- vcount field
.vcount 5

-- expert_info type
.expert_info {
  -- includes effect_source field
}

-- powerFight field (found in UI context with formatnumberthousands)

sproto Library Functions (libtolua.so)

sproto_create
sproto_decode
sproto_dump
sproto_encode
sproto_name
sproto_pack
sproto_protoname
sproto_protoquery
sproto_protoresponse
sproto_prototag
sproto_release
sproto_type
sproto_unpack
luaopen_sproto_core
📥

All 77 NOTIFY Messages

COMPLETE LIST

Server-push notification messages extracted from the sproto schema. These are sent from the game server to the client without a corresponding request.

NOTIFY_ACTIVITY_9
NOTIFY_ALLIANCE_CHEST_GLORY_UPDATE
NOTIFY_ANNUAL
NOTIFY_BALLOON_LEVEL_END
NOTIFY_BRAWL_WAR_ROOM_INFO
NOTIFY_BUILD
NOTIFY_BUILDING9
NOTIFY_BUILDING_UPGRADE_FINISH
NOTIFY_BUILDING_UPGRADE_FINISH_ARENAV
NOTIFY_BUILDING_UPGRADE_FINISH_BAR
NOTIFY_BUILDING_UPGRADE_FINISH_FURNACE
NOTIFY_BUILDING_UPGRADE_FINISH_HUNTERCABIN
NOTIFY_BUILDING_UPGRADE_FINISH_INFIRMARY
NOTIFY_BUILDING_UPGRADE_FINISH_LAWSOFFICE
NOTIFY_BUILDING_UPGRADE_FINISH_WARCOLLEGE
NOTIFY_BUILDK
NOTIFY_CAPITAL_WAR_UPDATE
NOTIFY_CARD_BP_INFO
NOTIFY_CHANGE
NOTIFY_CITY_IN_TERRITORY
NOTIFY_CLICK_SQUAD_HERO_ITEM
NOTIFY_COLLECTION
NOTIFY_COLLECTION_RED_ENVELOPE_DELUXE_SETTLE
NOTIFY_CROSS_
NOTIFY_CROSS_CAPITAL
NOTIFY_DAILY_MISSIONS
NOTIFY_DEL_SURVIVOR
NOTIFY_FORMATION_UPD
NOTIFY_GAME_
NOTIFY_GLORY_INFO
NOTIFY_GOTO_NEXT_STAGE
NOTIFY_HALLOWEENW
NOTIFY_HOMELAND_WAREHOUSE_ITEM_UPDATE
NOTIFY_ICE_FIELD_HUNTER_RED_POINT_UPDATE
NOTIFY_IMMIGRANT
NOTIFY_IMMIGRANT_ACTIVL
NOTIFY_IMMIGRANT_TRANSFER_UPDATE
NOTIFY_LIMIT_TIME_SHOP_NEW_DAY
NOTIFY_MAGIC_POL
NOTIFY_MONOPOLY_NEW_RECORD
NOTIFY_OPINION
NOTIFY_PET_INFO4
NOTIFY_PITCH_POT_TICKET_UPDATE
NOTIFY_PLAYER_ACTIVITY_POWER_UPDATE
NOTIFY_PLAYER_MOOD
NOTIFY_PLAYER_MOOD_UPDATE
NOTIFY_PLAYER_OFFI
NOTIFY_PLAYER_OFFICE_UPDATE
NOTIFY_PLAYER_POWER_UPDATE
NOTIFY_POLAR
NOTIFY_POLAR_EXPEDITION_STAGE_CHANGE
NOTIFY_PUSH_MULTIPLE_CHOICE_BUY
NOTIFY_PUZZLE_ITEM_UPDATE
NOTIFY_QUEUE_INFO
NOTIFY_QUICK
NOTIFY_RELIC_ADVENTURE_INFO
NOTIFY_RETURN_NEW_JOURNEY_INFO
NOTIFY_ROOM_DISSOLVE_SPECIAL
NOTIFY_SATISFACTION_UPDATE
NOTIFY_SEVEN_SIGN_NEW_DAY
NOTIFY_SHOW_
NOTIFY_SICK_SURVIVOR
NOTIFY_SNOW_CLEAN_EXCHANGED_COUNT_UPDATE
NOTIFY_STOVE_INFO
NOTIFY_SUPREMACY_WAR_GOV_DATA
NOTIFY_THANKSGI
NOTIFY_THANKSGIV
NOTIFY_THANKSGIVING_FEAST_
NOTIFY_THANKSGIVING_FEAST_GIFT_BUY
NOTIFY_UPDAT
NOTIFY_UPDATE
NOTIFY_UPDATE1
NOTIFY_UPDATE_9
NOTIFY_UPDATE_EXPERT_SKILL_INFO
NOTIFY_WORLD_
NOTIFY_WORLD_BOSS_ACTIV
NOTIFY_WORLD_BOSS_INFO_UPDATED
🔒

Security & Cryptography

1. Web API Signature — Giftcode Endpoint

algorithm
Algorithm: MD5 hash
Formula: MD5(sorted_query_params + secret)
Secret:  "tB87#kPtkxqOS2"

Example:
  params: fid=250893802, time=1700000000000
  string: "fid=250893802&time=1700000000000tB87#kPtkxqOS2"
  sign:   MD5(above) = <32-char hex>

2. Web Signature — Platform Endpoint

algorithm
Algorithm: MD5 hash with prefix
Formula: MD5("UxXkyv4g9nmvK8gP:" + timestamp_ms)

Used for: platform-config-prod.centurygame.com requests

3. Game Protocol Encryption

crypto
Algorithm: AES-192
Key:       Jm93LUl9xqWd/1Ar+7QXeApCZw==  (Base64, 24 bytes)
Transport: WebSocket (binary frames)
Encoding:  sproto binary (pack/unpack)
Flow:      App ↔ FPCS Gateway ↔ Game Server

Packet structure:
  [AES-192 encrypted payload]
    → decrypt
    → sproto_unpack
    → decoded protocol message

4. APK Protection Layers

ProtectionLibraryMechanismStatus
NetEase Shell libnesec.so Code packing / runtime unpacking ACTIVE
HTProtect libNetHTProtect.so Metadata encryption (HTPX format, XOR-based) ACTIVE
SSL Pinning libNetHTProtect.so Certificate validation on all network calls ACTIVE
Metadata Encryption HTPX magic global-metadata.dat encrypted (0x58505448) ACTIVE
Asset Encryption Unity3D custom LZ4-compressed bundles with custom encryption ACTIVE

⚠ HTPX Format: The global-metadata.dat file begins with the HTPX magic bytes 0x58505448 ("HTPX" in ASCII) instead of the standard Unity magic 0xFAB11BAF. The decryption uses XOR-based obfuscation implemented in libNetHTProtect.so.

🔥

Furnace Level Mapping

The stove_lv field from the API uses a numeric mapping where values above 30 represent "Furnace Core" (FC) tiers. The tested player (FID 250893802) has stove_lv=31, which maps to Level 30-1 (entry into FC1).

1
Lv 1
2
Lv 2
3
Lv 3
4
Lv 4
5
Lv 5
6
Lv 6
7
Lv 7
8
Lv 8
9
Lv 9
10
Lv 10
11
Lv 11
12
Lv 12
13
Lv 13
14
Lv 14
15
Lv 15
16
Lv 16
17
Lv 17
18
Lv 18
19
Lv 19
20
Lv 20
21
Lv 21
22
Lv 22
23
Lv 23
24
Lv 24
25
Lv 25
26
Lv 26
27
Lv 27
28
Lv 28
29
Lv 29
30
Lv 30
31
30-1
32
30-2
33
30-3
34
30-4
35
FC1
36
FC1-1
37
FC1-2
38
FC1-3
39
FC1-4
40
FC2
41
FC2-1
42
FC2-2
43
FC2-3
44
FC2-4
45
FC3
46
FC3-1
47
FC3-2
48
FC3-3
49
FC3-4
50
FC4
51
FC4-1
52
FC4-2
53
FC4-3
54
FC4-4
55
FC5
56
FC5-1
57
FC5-2
58
FC5-3
59
FC5-4
60
FC6
61
FC6-1
62
FC6-2
63
FC6-3
64
FC6-4
65
FC7

API Error Codes

CodeMeaningNotes
0SuccessRequest completed successfully
40001Role not existFID does not map to a valid player
40002Already claimedGift code already used by this player
40003Gift code expiredThe gift code validity period has ended
40004Claim limit reachedMaximum redemptions for this code reached
40005Furnace level too lowPlayer's stove_lv below required threshold
40006Gift code not foundInvalid gift code string
40007Same type onceOne redemption per type per player
40008Unknown errorGeneric server error
40009Not logged inAuthentication required
40010Server busyRate-limited or server overloaded
40011Too frequentRequest rate limit exceeded
40012Account age requirementAge compliance restriction
40013Captcha too frequentCaptcha request rate limited
40014Captcha incorrectWrong captcha answer
40015Captcha expiredCaptcha session timed out
40016Network busyNetwork congestion
40018Leader Concierge onlyRestricted to alliance leaders
🌐

Platform Infrastructure

FPCS Hosts (Game Gateway)

HostRegionProtocol
https://fpcs-apa.centurygames.netAsia-Pacific (Primary)HTTPS / WSS
https://fpcs-prod-wf.centurygame.comWest (Failover)HTTPS / WSS
https://fpcs-prod-apa.centurygame.comAsia-Pacific (Alt)HTTPS / WSS

Source UUID: 98937a85-0774-439f-889f-8510fb11634a

CDN Hosts (Static Assets)

HostCDN Provider
https://dis-customer-hub-res-ak.centurygame.comAkamai
https://dis-customer-hub-res-ct.centurygame.comChina Telecom
https://dis-customer-hub-res-cf.centurygame.comCloudflare

ACC Region Mapping

RegionCountriesDefault Server
APAAsia-Pacific (default)fpcs-apa
GAUS, AU, JP, KR, TWfpcs-prod-wf
💻

Code Examples

Giftcode Player Lookup — Python

python
import hashlib
import time
import requests

def lookup_player(fid):
    """Look up a White Out Survival player by their FID."""
    ts = str(int(time.time() * 1000))
    secret = 'tB87#kPtkxqOS2'

    # Compute MD5 signature
    sign_str = f'fid={fid}&time={ts}{secret}'
    sign = hashlib.md5(sign_str.encode()).hexdigest()

    # Make the request
    resp = requests.post(
        'https://wos-giftcode-api.centurygame.com/api/player',
        data={
            'fid': str(fid),
            'time': ts,
            'sign': sign,
        },
        headers={
            'User-Agent': 'Mozilla/5.0 (Linux; Android 14) Chrome/125.0.0.0',
            'Origin': 'https://wos-giftcode.centurygame.com',
            'Referer': 'https://wos-giftcode.centurygame.com/',
        },
    )
    return resp.json()


# --- Test ---
result = lookup_player(250893802)
print(result)
# Expected output:
# {
#   "code": 0,
#   "data": {
#     "fid": 250893802,
#     "nickname": "FADL2",
#     "kid": 2007,
#     "stove_lv": 31,
#     "stove_lv_content": 30,
#     "avatar_image": "https://gof-formal-avatar.akamaized.net/...",
#     "total_recharge_amount": 0
#   }
# }

Furnace Level Decoder — Python

python
def decode_furnace_level(stove_lv):
    """Convert numeric stove_lv to human-readable furnace level."""
    if stove_lv <= 30:
        return f"Level {stove_lv}"

    fc_map = {35: "FC1", 40: "FC2", 45: "FC3", 50: "FC4", 55: "FC5", 60: "FC6", 65: "FC7"}

    # FC milestone levels
    if stove_lv in fc_map:
        return fc_map[stove_lv]

    # Find which FC tier this falls into
    milestones = sorted(fc_map.keys(), reverse=True)
    for ms in milestones:
        if stove_lv > ms:
            offset = stove_lv - ms
            tier_num = ms // 5 - 6  # FC1=1, FC2=2, etc.
            return f"FC{tier_num}-{offset}"

    # Between 30 and FC1 (31-34)
    if 31 <= stove_lv <= 34:
        return f"30-{stove_lv - 30}"

    return f"Unknown ({stove_lv})"


# Examples:
print(decode_furnace_level(31))   # "30-1"
print(decode_furnace_level(35))   # "FC1"
print(decode_furnace_level(37))   # "FC1-2"
print(decode_furnace_level(50))   # "FC4"
print(decode_furnace_level(65))   # "FC7"

Platform Config Fetch — cURL

bash
# Fetch platform config (no auth needed)
curl -s https://platform-config-prod.centurygame.com/config.json | python -m json.tool

# GeoIP lookup
curl -s https://fpcs-prod-apa.centurygame.com/api/location | python -m json.tool

# Player lookup with signature
FID=250893802
TS=$(date +%s%3N)
SIGN=$(echo -n "fid=${FID}&time=${TS}tB87#kPtkxqOS2" | md5sum | cut -d' ' -f1)

curl -s -X POST https://wos-giftcode-api.centurygame.com/api/player \
  -d "fid=${FID}&time=${TS}&sign=${SIGN}" \
  -H "Origin: https://wos-giftcode.centurygame.com" \
  -H "Referer: https://wos-giftcode.centurygame.com/" | python -m json.tool
📱

Non-Rooted Android Capture Approaches

CONSTRAINT: NO ROOT / NO PC

Option 1: HTTP Canary / Packet Capture App

Install HTTP Canary or Packet Capture from the Play Store. These create a local VPN to intercept HTTPS traffic and can capture FPCS gateway requests. However, SSL pinning will block HTTPS decryption of game traffic. Works for non-pinned connections only.

Pros: No root required, easy setup, visual UI
Cons: Cannot bypass SSL pinning, limited to non-game HTTP traffic

Option 2: Termux + mitmproxy

Install Termux from F-Droid and run mitmproxy inside it. Configure the device proxy to localhost:8080. Provides full HTTP inspection but SSL pinning still blocks game traffic. Better for analyzing web API calls.

Pros: Powerful CLI tool, scriptable, detailed output
Cons: SSL pinning blocks game protocol, complex setup

Option 3: Parallel Space + Frida-Gadget Injected APK

Use Parallel Space to run a Frida-Gadget injected version of the APK. No root required but the setup is complex: extract APK, inject frida-gadget.so into lib/arm64, repack, sign, and run in Parallel Space. Can hook SSL pinning bypasses at runtime.

Pros: Can bypass SSL pinning, full traffic access
Cons: Very complex setup, detection risk, no root still limits some hooks

Option 4: Server-Side APK Analysis ✓ (Current Approach)

Decompile the APK on a server, extract sproto schemas from Lua bytecode, reconstruct protocol from code analysis. This is the approach being used for this investigation. It works entirely offline and doesn't require interacting with the game client at all.

Pros: No device interaction needed, complete static analysis, no detection risk
Cons: No live traffic validation, schema may be incomplete without runtime testing

Option 5: Official API Access

Contact Century Game for a developer partnership and request access to player data APIs. This is the legitimate route but requires business justification and is unlikely to be granted for individual researchers.

Pros: Legal, documented, reliable, maintained
Cons: Likely requires business entity, NDA, limited scope
🚀

Investigation Roadmap

PhaseObjectiveStatusNotes
Phase 1 APK decompilation & structure analysis COMPLETE IL2CPP + LuaJIT bytecode extracted
Phase 2 Web API discovery & authentication COMPLETE 5 endpoints verified, 1 partial
Phase 3 sproto schema extraction COMPLETE 209 messages, 77 NOTIFY types identified
Phase 4 AES key & crypto mechanism recovery COMPLETE AES-192 key recovered, MD5 secrets found
Phase 5 Full sproto schema reconstruction IN PROGRESS Partial types recovered, need complete field mapping
Phase 6 Live WebSocket protocol capture BLOCKED Requires SSL pinning bypass (root or Frida)
Phase 7 Protocol message decoding & validation BLOCKED Depends on Phase 6 completion
Phase 8 Tool development & automation PLANNED sproto encoder/decoder, player data viewer

Key Findings Summary

Web API Access
WORKING
Giftcode player lookup fully functional with known auth
Game Protocol
PARTIAL
Schema extracted but live decoding blocked by SSL pinning
Crypto Keys
RECOVERED
AES-192 key + both MD5 signing secrets known
Live Traffic
BLOCKED
SSL pinning prevents capture without root/Frida