- Automated PowerShell script (RR3-Community-Mod.ps1) - Complete modification guide (14,000 words) - Quick reference summary (12,000 words) - Network protocol analysis (13,000 words) - One-command APK modification - Built-in custom server support discovery Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
390 lines
12 KiB
Markdown
390 lines
12 KiB
Markdown
# Real Racing 3 - Network Communication Analysis
|
|
|
|
## Overview
|
|
Real Racing 3 uses a **custom HTTP/HTTPS-based communication system** built on top of EA's proprietary "CloudCell API" and "Nimble SDK" frameworks. The app communicates with EA's backend servers using JSON over HTTPS with custom authentication headers.
|
|
|
|
---
|
|
|
|
## 1. Core Network Architecture
|
|
|
|
### 1.1 HTTP Request System
|
|
**Location**: `com.firemonkeys.cloudcellapi.HttpRequest` and `HttpThread`
|
|
|
|
**Key Components**:
|
|
- **HttpRequest**: Main request manager with native JNI callbacks
|
|
- **HttpThread**: Worker thread that executes the actual HTTP operations
|
|
- **CloudcellTrustManager**: Custom SSL/TLS certificate validation
|
|
|
|
**Implementation Details**:
|
|
```java
|
|
// Request initialization from native code
|
|
public void init(String userAgent, String method, String url,
|
|
byte[] data, int readCapacity, long callbackPointer,
|
|
boolean failOnError, double serverTime,
|
|
boolean sslCheck, boolean addDefaultHeaders,
|
|
int timeoutSeconds)
|
|
```
|
|
|
|
**Key Features**:
|
|
- Uses `HttpURLConnection` (standard Java HTTP client)
|
|
- Wrapped with Firebase Performance monitoring (`FirebasePerfUrlConnection`)
|
|
- Custom user agent combining app version + system HTTP agent
|
|
- SSL/TLS 1.2+ with custom certificate validation
|
|
- Native callbacks for data streaming (header, data, error, complete)
|
|
- Configurable timeouts (default: 30 seconds)
|
|
- Support for HTTP methods: GET, POST, PUT, DELETE
|
|
|
|
### 1.2 SSL/TLS Configuration
|
|
**Location**: `com.firemonkeys.cloudcellapi.CloudcellTrustManager` & `TLSSocketFactory`
|
|
|
|
**Security Setup**:
|
|
```java
|
|
SSLContext sslContext = SSLContext.getInstance("TLS");
|
|
sslContext.init(null, new TrustManager[]{new CloudcellTrustManager(this)}, new SecureRandom());
|
|
HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory(sslContext.getSocketFactory()));
|
|
HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
|
```
|
|
|
|
**Certificate Validation**:
|
|
- Custom X509TrustManager implementation
|
|
- Validates certificate expiration against server-provided time
|
|
- Can be optionally disabled (m_bSSLCheck flag)
|
|
- **NOTE**: Uses `ALLOW_ALL_HOSTNAME_VERIFIER` (accepts any hostname!)
|
|
|
|
---
|
|
|
|
## 2. Server Infrastructure
|
|
|
|
### 2.1 Primary API Servers
|
|
|
|
**Synergy Director Servers** (EA's service orchestration layer):
|
|
- **Production (LIVE)**: `https://syn-dir.sn.eamobile.com`
|
|
- **Staging**: `https://director-stage.sn.eamobile.com`
|
|
- **Integration (INT)**: `https://director-int.sn.eamobile.com`
|
|
|
|
The "Director" server provides configuration that routes the client to specialized service endpoints.
|
|
|
|
### 2.2 Network Reachability Test URLs
|
|
Located in EA Nimble SDK:
|
|
- Primary: `https://ping1.tnt-ea.com`
|
|
- Backup: `https://www.google.com`
|
|
|
|
Used to detect if the device has internet connectivity before making API calls.
|
|
|
|
### 2.3 API Endpoint Structure
|
|
|
|
**Base Pattern**: `https://<director-host>/<service>/api/<platform>/<endpoint>`
|
|
|
|
**Example Endpoints**:
|
|
|
|
| Endpoint Path | Purpose |
|
|
|---------------|---------|
|
|
| `/director/api/android/getDirectionByPackage` | Get service configuration/routing |
|
|
| `/user/api/android/getDeviceID` | Retrieve unique device ID |
|
|
| `/user/api/android/validateDeviceID` | Validate existing device ID |
|
|
| `/user/api/android/getAnonUid` | Generate anonymous user ID |
|
|
| `/product/api/core/getAvailableItems` | Fetch in-game item catalog |
|
|
| `/product/api/core/getMTXGameCategories` | Get microtransaction categories |
|
|
| `/product/api/core/getDownloadItemUrl` | Get download URLs for assets |
|
|
| `/drm/api/core/getNonce` | Get DRM nonce for validation |
|
|
| `/drm/api/core/getPurchasedItems` | Retrieve purchase history |
|
|
| `/drm/api/android/verifyAndRecordPurchase` | Verify and record IAP purchases |
|
|
| `/tracking/api/core/logEvent` | Submit analytics/telemetry events |
|
|
|
|
---
|
|
|
|
## 3. Authentication & Authorization
|
|
|
|
### 3.1 HTTP Headers
|
|
|
|
**Standard Headers**:
|
|
- `User-Agent`: `<AppIdentifier> <SystemHttpAgent>`
|
|
- `Content-Type`: `application/json` or `application/x-www-form-urlencoded`
|
|
- `Content-Length`: Auto-calculated for POST/PUT requests
|
|
|
|
**EA Custom Headers** (from Nimble SDK):
|
|
- `EAM-SESSION`: Session ID (UUID generated per app session)
|
|
- `EAM-USER-ID`: Synergy user ID (persistent user identifier)
|
|
- `EA-SELL-ID`: Marketplace/seller ID (e.g., Google Play, App Store)
|
|
- `SDK-VERSION`: EA Nimble SDK version string
|
|
- `SDK-TYPE`: "Nimble" (framework identifier)
|
|
|
|
### 3.2 Device & User Identification
|
|
|
|
**Multiple ID Types Used**:
|
|
|
|
1. **EA Device ID** (`eADeviceId`)
|
|
- Generated on first launch
|
|
- Persisted in shared preferences
|
|
- Used for device-level tracking
|
|
|
|
2. **EA Hardware ID** (`eAHardwareId`)
|
|
- Derived from device hardware characteristics
|
|
- More persistent than device ID
|
|
|
|
3. **Synergy ID**
|
|
- Primary user account identifier
|
|
- Links game progress across devices
|
|
- Required for cloud save/sync
|
|
|
|
4. **Anonymous UID**
|
|
- Fallback identifier for users without accounts
|
|
- Used for analytics before login
|
|
|
|
5. **Google/Facebook OAuth Tokens**
|
|
- For social login integration
|
|
- Google Web Client ID: `1056053393768-2irtr6olub9uil5dsp16apf9p5f0ge0k.apps.googleusercontent.com`
|
|
|
|
### 3.3 Session Management
|
|
|
|
**Session Flow**:
|
|
1. App launches → Generate session UUID
|
|
2. Contact Director server → Get service configuration
|
|
3. Retrieve/validate device ID → Get or create EA Device ID
|
|
4. Initialize Synergy session → Get session token
|
|
5. Attach `EAM-SESSION` header to all subsequent requests
|
|
|
|
**Session Properties**:
|
|
- Session IDs are UUIDs (e.g., `f47ac10b-58cc-4372-a567-0e02b2c3d479`)
|
|
- Sessions expire after inactivity period (server-controlled)
|
|
- Session data cached locally and synced to server
|
|
|
|
---
|
|
|
|
## 4. Request/Response Format
|
|
|
|
### 4.1 JSON Serialization
|
|
- Request bodies: JSON with entity/DTO objects
|
|
- Response bodies: JSON parsed into native objects
|
|
- Uses Jackson/Gson for JSON serialization (standard Android libraries)
|
|
|
|
### 4.2 Protocol Buffers (for Unity Ads SDK)
|
|
**Location**: `gatewayprotocol.v1` package
|
|
|
|
**Message Types**:
|
|
- `UniversalRequest` / `UniversalResponse` - Main protocol wrapper
|
|
- `InitializationRequest` / `InitializationResponse` - SDK init handshake
|
|
- `AdRequest` / `AdResponse` - Ad serving
|
|
- `TransactionEventRequest` - Purchase tracking
|
|
- `DiagnosticEventRequest` - Telemetry/diagnostics
|
|
- `LimitedSessionToken` - Temporary auth tokens
|
|
|
|
Uses **Protocol Buffers v3** (Google protobuf library).
|
|
|
|
### 4.3 Example Request Structure
|
|
|
|
**Typical POST Request**:
|
|
```
|
|
POST /user/api/android/getDeviceID HTTP/1.1
|
|
Host: syn-dir.sn.eamobile.com
|
|
User-Agent: RealRacing3/12.5.0 Android/14
|
|
Content-Type: application/json
|
|
Content-Length: 128
|
|
EAM-SESSION: f47ac10b-58cc-4372-a567-0e02b2c3d479
|
|
EAM-USER-ID: 1234567890
|
|
EA-SELL-ID: GOOGLE_PLAY
|
|
SDK-VERSION: 5.2.1
|
|
SDK-TYPE: Nimble
|
|
|
|
{
|
|
"deviceId": "abc123...",
|
|
"hardwareId": "xyz789...",
|
|
"platform": "android",
|
|
"appVersion": "12.5.0"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Data Flow & Callbacks
|
|
|
|
### 5.1 Native Interface (JNI)
|
|
|
|
The HTTP layer bridges Java and native C++ code:
|
|
|
|
**Native Callbacks** (from `HttpRequest.java`):
|
|
```java
|
|
public native void headerCallback(long callbackPtr, int contentLength, Map<String, List<String>> headers);
|
|
public native void dataCallback(long callbackPtr, byte[] data, int length);
|
|
public native void errorCallback(long callbackPtr, int statusCode);
|
|
public native void completeCallback(long callbackPtr, int statusCode);
|
|
```
|
|
|
|
**Flow**:
|
|
1. Native C++ code calls `HttpRequest.init()` with callback pointer
|
|
2. `HttpThread` executes HTTP request in background
|
|
3. As data streams in, Java calls native callbacks with data chunks
|
|
4. Native code processes response in real-time
|
|
5. On completion, native code receives final status
|
|
|
|
### 5.2 Streaming Response Handling
|
|
|
|
**Read Strategy**:
|
|
- Configurable read buffer size (`m_readCapacity`)
|
|
- Data streamed in chunks to native callback
|
|
- Supports both success and error stream reading
|
|
- Interruptible for cancellation support
|
|
|
|
```java
|
|
byte[] buffer = new byte[readCapacity];
|
|
while (true) {
|
|
int bytesRead = inputStream.read(buffer);
|
|
if (bytesRead == -1) break;
|
|
if (isInterrupted()) return;
|
|
dataCallback(callbackPointer, buffer, bytesRead);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Network Configuration
|
|
|
|
### 6.1 Timeout Settings
|
|
- **Default Connection Timeout**: 30 seconds (30,000 ms)
|
|
- **Default Read Timeout**: 30 seconds
|
|
- **Configurable per request** via `m_TimeoutMilliseconds`
|
|
|
|
### 6.2 Connection Properties
|
|
```java
|
|
httpURLConnection.setConnectTimeout(timeoutMilliseconds);
|
|
httpURLConnection.setReadTimeout(timeoutMilliseconds);
|
|
httpURLConnection.setUseCaches(false); // No HTTP caching
|
|
httpURLConnection.setDoInput(true);
|
|
System.setProperty("http.keepAlive", "false"); // Disable keep-alive
|
|
```
|
|
|
|
**Note**: Keep-alive is disabled, so each request creates a new TCP connection.
|
|
|
|
### 6.3 Request Method Support
|
|
- GET (query parameters in URL)
|
|
- POST (JSON body)
|
|
- PUT (JSON body)
|
|
- DELETE
|
|
- Custom methods supported via `setRequestMethod()`
|
|
|
|
---
|
|
|
|
## 7. Error Handling
|
|
|
|
### 7.1 HTTP Status Code Handling
|
|
|
|
**Success Codes** (200-299):
|
|
- Data read from `inputStream`
|
|
- Parsed and passed to native callback
|
|
|
|
**Error Codes** (400-599):
|
|
- Data read from `errorStream`
|
|
- Can still contain JSON error messages
|
|
- Optional `failOnErrorStatus` flag to abort immediately
|
|
|
|
**Network Errors**:
|
|
- IOException → `errorCallback` with status code 0
|
|
- Timeout → `errorCallback` with status code 0
|
|
- SSL/Certificate errors → Custom handling in `CloudcellTrustManager`
|
|
|
|
### 7.2 SSL Certificate Expiration Check
|
|
|
|
```java
|
|
public void checkServerTrusted(X509Certificate[] certificates, String authType) {
|
|
if (sslCheckEnabled) {
|
|
Date serverDate = new Date(serverTime * 1000);
|
|
for (X509Certificate cert : certificates) {
|
|
if (cert.getNotAfter().before(serverDate)) {
|
|
setClosedBySSLCheck(true);
|
|
closeThread();
|
|
logError("SSL Certificate expired!");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Uses server-provided time to validate certificates (prevents time manipulation).
|
|
|
|
---
|
|
|
|
## 8. Additional Features
|
|
|
|
### 8.1 Network Status Monitoring
|
|
**Location**: `com.firemonkeys.cloudcellapi.NetworkStatusMonitor`
|
|
|
|
Monitors network connectivity changes (Wi-Fi ↔ Mobile Data) to handle disconnections gracefully.
|
|
|
|
### 8.2 In-App Purchase (IAP) Integration
|
|
|
|
**Google Play Billing**:
|
|
- `GooglePlayWorker` handles Play Store transactions
|
|
- Purchase verification via `/drm/api/android/verifyAndRecordPurchase`
|
|
- Receipt validation server-side
|
|
|
|
**Amazon Store**:
|
|
- `CC_AmazonStoreWorker_Class` for Amazon App Store
|
|
- Similar server-side verification flow
|
|
|
|
### 8.3 Social Platform Integration
|
|
|
|
**Google Play Games**:
|
|
- OAuth 2.0 with scope `https://www.googleapis.com/auth/games`
|
|
- Achievement unlock API: `https://www.googleapis.com/games/v1management/achievements/reset`
|
|
|
|
**Facebook**:
|
|
- Graph API for friends list, sharing, profile
|
|
- `FacebookWorker` handles login/sharing flows
|
|
|
|
---
|
|
|
|
## 9. Security Considerations
|
|
|
|
### 9.1 Vulnerabilities Observed
|
|
|
|
⚠️ **Certificate Hostname Verification Disabled**:
|
|
```java
|
|
HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
|
```
|
|
This accepts any SSL certificate hostname, making the app vulnerable to MITM attacks.
|
|
|
|
⚠️ **Optional SSL Checks**:
|
|
The `m_bSSLCheck` flag can disable certificate validation entirely.
|
|
|
|
⚠️ **Keep-Alive Disabled**:
|
|
Creates overhead but may be intentional to avoid connection state issues.
|
|
|
|
### 9.2 Security Strengths
|
|
|
|
✅ **TLS Encryption**: All API calls use HTTPS
|
|
✅ **Custom Certificate Validation**: Time-based expiration checks
|
|
✅ **Session Tokens**: Short-lived session identifiers
|
|
✅ **Server-Side Purchase Verification**: IAP receipts validated by EA servers
|
|
✅ **Firebase Performance Monitoring**: Instrumented connections for anomaly detection
|
|
|
|
---
|
|
|
|
## 10. Summary
|
|
|
|
**Communication Pattern**:
|
|
```
|
|
[App Native Code]
|
|
↕ (JNI)
|
|
[Java HttpRequest/HttpThread]
|
|
↕ (HTTPS)
|
|
[EA Synergy Director]
|
|
↕ (Service Routing)
|
|
[Specialized Service APIs]
|
|
```
|
|
|
|
**Key Takeaways**:
|
|
1. Uses standard Java `HttpURLConnection` with custom SSL handling
|
|
2. Native C++ game code interfaces via JNI callbacks for async I/O
|
|
3. EA Synergy "Director" pattern routes requests to microservices
|
|
4. Authentication via custom headers (session ID, user ID)
|
|
5. JSON for API requests, Protocol Buffers for ad SDK
|
|
6. Streaming response handling with configurable buffer sizes
|
|
7. Firebase Performance wrappers for monitoring
|
|
8. Weak SSL hostname verification (security concern)
|
|
|
|
---
|
|
|
|
**Analysis Date**: February 2026
|
|
**APK Version**: Real Racing 3 (v12.5+)
|
|
**Decompiler**: JADX 1.5.1
|