Compare commits
3 Commits
v14
...
killswitch
| Author | SHA1 | Date | |
|---|---|---|---|
| 201c19bc17 | |||
| d8d12e0b46 | |||
| dce8c65a2a |
@@ -1,416 +0,0 @@
|
||||
# APK Build & Testing Guide
|
||||
|
||||
**Date:** February 22, 2026
|
||||
**APK Version:** v14 (CUSTOMIZED mode - EA URLs eliminated)
|
||||
**Build Status:** ✅ SUCCESS
|
||||
**Signature:** ✅ VERIFIED
|
||||
|
||||
---
|
||||
|
||||
## 📦 APK Build Information
|
||||
|
||||
### Built APK
|
||||
- **Filename:** `RR3-v14-NoEAURLs-signed.apk`
|
||||
- **Size:** 103.92 MB
|
||||
- **Location:** `E:\rr3\rr3-apk\RR3-v14-NoEAURLs-signed.apk`
|
||||
- **Build Date:** February 22, 2026
|
||||
|
||||
### Configuration Changes Applied
|
||||
1. ✅ **Nimble Mode:** Changed from `"live"` to `"customized"`
|
||||
2. ✅ **EA URLs:** Eliminated from execution path
|
||||
3. ✅ **Fallback URL:** Added `http://localhost:5001` to manifest
|
||||
4. ✅ **Priority System:** SharedPreferences > Manifest > Never EA
|
||||
|
||||
### Signature Information
|
||||
- **Keystore:** `rr3-release.keystore`
|
||||
- **Alias:** `rr3key`
|
||||
- **v2 Scheme:** ✅ Verified
|
||||
- **v3 Scheme:** ✅ Verified
|
||||
- **Valid Until:** July 6, 2053
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Build Process
|
||||
|
||||
### Tools Used
|
||||
1. **apktool 2.10.0** - APK decompilation/recompilation
|
||||
2. **Java OpenJDK 21.0.10** - Build environment
|
||||
3. **Android Build Tools 36.1.0** - Signing & verification
|
||||
4. **apksigner** - APK signing with v2/v3 schemes
|
||||
|
||||
### Build Commands
|
||||
```powershell
|
||||
# Build APK
|
||||
java -jar E:\tools\apktool.jar b E:\rr3\rr3-apk -o RR3-v14-NoEAURLs-unsigned.apk
|
||||
|
||||
# Sign APK
|
||||
apksigner sign `
|
||||
--ks rr3-release.keystore `
|
||||
--ks-key-alias rr3key `
|
||||
--ks-pass pass:rr3community `
|
||||
--key-pass pass:rr3community `
|
||||
--out RR3-v14-NoEAURLs-signed.apk `
|
||||
RR3-v14-NoEAURLs-unsigned.apk
|
||||
|
||||
# Verify signature
|
||||
apksigner verify --verbose RR3-v14-NoEAURLs-signed.apk
|
||||
```
|
||||
|
||||
### Build Output
|
||||
```
|
||||
I: Using Apktool 2.10.0 with 12 thread(s)
|
||||
I: Building resources...
|
||||
I: Smaling smali_classes2 folder into classes2.dex...
|
||||
I: Building apk file...
|
||||
I: Copying unknown files/dir...
|
||||
I: Built apk into: RR3-v14-NoEAURLs-unsigned.apk
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📱 Installation Methods
|
||||
|
||||
### Method 1: ADB Install (Recommended)
|
||||
```bash
|
||||
# Connect device via USB with USB debugging enabled
|
||||
adb devices
|
||||
|
||||
# Install APK
|
||||
adb install -r RR3-v14-NoEAURLs-signed.apk
|
||||
|
||||
# Or if device already has RR3 installed
|
||||
adb install -r -d RR3-v14-NoEAURLs-signed.apk
|
||||
```
|
||||
|
||||
### Method 2: Drag & Drop
|
||||
1. Start Android emulator
|
||||
2. Drag `RR3-v14-NoEAURLs-signed.apk` onto emulator window
|
||||
3. Wait for installation to complete
|
||||
|
||||
### Method 3: File Transfer
|
||||
1. Copy APK to device storage
|
||||
2. Use file manager app to open APK
|
||||
3. Allow installation from unknown sources
|
||||
4. Install
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing Procedure
|
||||
|
||||
### Phase 1: Installation & First Launch
|
||||
|
||||
**Test 1: Clean Install**
|
||||
```bash
|
||||
# Ensure no previous RR3 installation
|
||||
adb uninstall com.ea.games.r3_row
|
||||
|
||||
# Install new APK
|
||||
adb install RR3-v14-NoEAURLs-signed.apk
|
||||
|
||||
# Monitor logcat during launch
|
||||
adb logcat -c # Clear log
|
||||
adb logcat | Select-String "RR3|Synergy|CommunityServer|ServerSetup"
|
||||
```
|
||||
|
||||
**Expected Behavior:**
|
||||
1. ✅ Game launches successfully
|
||||
2. ✅ `ServerSetupActivity` appears on first launch
|
||||
3. ✅ User prompted to enter server URL
|
||||
4. ✅ No crashes or ANR (Application Not Responding)
|
||||
|
||||
**Logcat Checkpoints:**
|
||||
```
|
||||
✅ "RR3_OfflineModeManager: Initializing OfflineModeManager"
|
||||
✅ "CommunityServerManager: Checking server URL"
|
||||
✅ "ServerSetupActivity: onCreate"
|
||||
✅ "SynergyEnvironmentImpl: 🎯 Using community server from SharedPreferences"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Server URL Configuration
|
||||
|
||||
**Test 2: Server URL Input**
|
||||
1. Launch game (first time)
|
||||
2. Enter server URL: `http://localhost:5001`
|
||||
3. Click "Test Connection"
|
||||
4. Click "Continue"
|
||||
|
||||
**Expected Behavior:**
|
||||
1. ✅ Input field accepts URL
|
||||
2. ✅ Test button attempts connection
|
||||
3. ✅ Continue button saves URL to SharedPreferences
|
||||
4. ✅ Game restarts with new URL
|
||||
|
||||
**Verify SharedPreferences:**
|
||||
```bash
|
||||
# Check if server URL was saved
|
||||
adb shell cat /data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml
|
||||
```
|
||||
|
||||
**Expected Content:**
|
||||
```xml
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<map>
|
||||
<string name="server_url">http://localhost:5001</string>
|
||||
</map>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Network Communication
|
||||
|
||||
**Test 3: Director API Call**
|
||||
```bash
|
||||
# Monitor network requests
|
||||
adb logcat | Select-String "director|http|Synergy"
|
||||
```
|
||||
|
||||
**Expected Logcat:**
|
||||
```
|
||||
✅ "SynergyEnvironmentImpl: 🎯 Using community server from SharedPreferences"
|
||||
✅ "http://localhost:5001/director/api/android/getDirectionByPackage"
|
||||
✅ No references to "eamobile.com"
|
||||
✅ No references to "syn-dir" or "director-stage"
|
||||
```
|
||||
|
||||
**Test 4: Verify EA URLs NOT Used**
|
||||
```bash
|
||||
# Search for EA domain access attempts
|
||||
adb logcat | Select-String "eamobile.com"
|
||||
```
|
||||
|
||||
**Expected:** 🚫 No matches (EA URLs should never appear)
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: Configuration Verification
|
||||
|
||||
**Test 5: Check Nimble Configuration**
|
||||
```bash
|
||||
# Extract app data
|
||||
adb shell run-as com.ea.games.r3_row cat /data/data/com.ea.games.r3_row/shared_prefs/nimble_preferences.xml
|
||||
```
|
||||
|
||||
**Verify:**
|
||||
- ✅ Configuration mode: `CUSTOMIZED` (not `LIVE`)
|
||||
- ✅ Server URL: User-configured URL
|
||||
- ✅ No EA default URLs stored
|
||||
|
||||
**Test 6: Clear SharedPreferences Test**
|
||||
```bash
|
||||
# Clear community server preferences
|
||||
adb shell run-as com.ea.games.r3_row rm /data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml
|
||||
|
||||
# Restart game
|
||||
adb shell am force-stop com.ea.games.r3_row
|
||||
adb shell am start -n com.ea.games.r3_row/com.firemint.realracing.MainActivity
|
||||
```
|
||||
|
||||
**Expected Behavior:**
|
||||
1. ✅ ServerSetupActivity appears again (no URL configured)
|
||||
2. ✅ Falls back to manifest URL: `http://localhost:5001`
|
||||
3. ✅ Does NOT attempt EA servers
|
||||
|
||||
---
|
||||
|
||||
### Phase 5: Offline Mode
|
||||
|
||||
**Test 7: Offline Mode Toggle**
|
||||
```bash
|
||||
# Check offline mode preferences
|
||||
adb shell cat /data/data/com.ea.games.r3_row/shared_prefs/rr3_offline_settings.xml
|
||||
```
|
||||
|
||||
**Expected Content:**
|
||||
```xml
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<map>
|
||||
<boolean name="offline_mode_enabled" value="false" />
|
||||
</map>
|
||||
```
|
||||
|
||||
**Test:** Toggle offline mode in SettingsActivity and verify behavior.
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Common Issues & Solutions
|
||||
|
||||
### Issue 1: Installation Failed
|
||||
**Symptom:** `INSTALL_FAILED_UPDATE_INCOMPATIBLE`
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Uninstall existing app first
|
||||
adb uninstall com.ea.games.r3_row
|
||||
|
||||
# Then install
|
||||
adb install RR3-v14-NoEAURLs-signed.apk
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue 2: App Crashes on Launch
|
||||
**Check:**
|
||||
1. Logcat for crash stacktrace
|
||||
2. Missing native libraries
|
||||
3. Architecture mismatch (armeabi-v7a vs arm64-v8a)
|
||||
|
||||
**Debug:**
|
||||
```bash
|
||||
adb logcat -s AndroidRuntime:E
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue 3: ServerSetupActivity Not Appearing
|
||||
**Possible Causes:**
|
||||
1. SharedPreferences already exist (previous installation)
|
||||
2. MainActivity not checking properly
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# Clear all app data
|
||||
adb shell pm clear com.ea.games.r3_row
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue 4: Network Requests Failing
|
||||
**Check:**
|
||||
1. Server is running on `http://localhost:5001`
|
||||
2. Emulator/device can reach localhost
|
||||
3. Use emulator's special address: `http://10.0.2.2:5001`
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# Forward port from host to device
|
||||
adb reverse tcp:5001 tcp:5001
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Logcat Filters
|
||||
|
||||
### Filter 1: RR3 Application Logs
|
||||
```bash
|
||||
adb logcat | Select-String "RR3_|CommunityServer|ServerSetup|OfflineMode"
|
||||
```
|
||||
|
||||
### Filter 2: Network Communication
|
||||
```bash
|
||||
adb logcat | Select-String "http|Synergy|director|eamobile"
|
||||
```
|
||||
|
||||
### Filter 3: Errors Only
|
||||
```bash
|
||||
adb logcat *:E | Select-String "com.ea.games.r3"
|
||||
```
|
||||
|
||||
### Filter 4: Crashes
|
||||
```bash
|
||||
adb logcat -s AndroidRuntime:E
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Success Criteria
|
||||
|
||||
### Build Success ✅
|
||||
- [x] APK built without errors
|
||||
- [x] APK signed with valid certificate
|
||||
- [x] Signature verified (v2 & v3)
|
||||
- [x] APK size reasonable (103.92 MB)
|
||||
|
||||
### Configuration Success ✅
|
||||
- [x] Nimble mode set to CUSTOMIZED
|
||||
- [x] EA URLs eliminated from execution path
|
||||
- [x] Fallback URL added to manifest
|
||||
- [x] Priority system verified in code
|
||||
|
||||
### Installation Success (To Be Tested)
|
||||
- [ ] APK installs on device/emulator
|
||||
- [ ] No installation errors
|
||||
- [ ] Package name correct: `com.ea.games.r3_row`
|
||||
- [ ] Permissions requested appropriately
|
||||
|
||||
### Runtime Success (To Be Tested)
|
||||
- [ ] App launches without crashes
|
||||
- [ ] ServerSetupActivity appears on first launch
|
||||
- [ ] Server URL input works
|
||||
- [ ] SharedPreferences saved correctly
|
||||
- [ ] Network requests go to community server
|
||||
- [ ] EA URLs never contacted
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Next Steps
|
||||
|
||||
### Immediate Testing
|
||||
1. **Get working emulator or physical device**
|
||||
- Android 8.0+ recommended
|
||||
- USB debugging enabled
|
||||
- Unknown sources allowed
|
||||
|
||||
2. **Install APK**
|
||||
```bash
|
||||
adb install -r RR3-v14-NoEAURLs-signed.apk
|
||||
```
|
||||
|
||||
3. **Monitor first launch**
|
||||
```bash
|
||||
adb logcat -c
|
||||
adb logcat | Select-String "RR3|Synergy"
|
||||
```
|
||||
|
||||
4. **Verify URL priority**
|
||||
- Check ServerSetupActivity appears
|
||||
- Enter server URL
|
||||
- Verify SharedPreferences created
|
||||
- Confirm community server used
|
||||
|
||||
### After Successful Test
|
||||
1. ✅ Document any issues found
|
||||
2. ✅ Commit working APK to repository
|
||||
3. ✅ Create release notes
|
||||
4. ✅ Begin Phase 2 (Events Service)
|
||||
|
||||
---
|
||||
|
||||
## 📝 Known Limitations
|
||||
|
||||
1. **Emulator Issues**
|
||||
- Android emulators on current system not starting properly
|
||||
- Recommend physical device testing
|
||||
- Alternative: WSA, Bluestacks, NOX, LDPlayer
|
||||
|
||||
2. **SSL Validation**
|
||||
- Still disabled in Http.java (ALLOW_ALL_HOSTNAME_VERIFIER)
|
||||
- Security risk - needs fixing
|
||||
- Accept any certificate currently
|
||||
|
||||
3. **Localhost Access**
|
||||
- From emulator: Use `10.0.2.2:5001` instead of `localhost:5001`
|
||||
- Requires `adb reverse tcp:5001 tcp:5001` for port forwarding
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Security Notes
|
||||
|
||||
### APK Signature
|
||||
- Signed with rr3-release.keystore
|
||||
- Valid until 2053
|
||||
- SHA256 fingerprint: A9:A0:08:7B:2F:C3:7A:0D:A4:EE:FE:53:53:05:BA:AF:A1:08:FC:C1:5B:50:1F:FA:5D:EA:E2:2E:98:7D:43:C7
|
||||
|
||||
### Network Security
|
||||
- ⚠️ SSL validation disabled (needs fix)
|
||||
- ✅ No EA server communication
|
||||
- ✅ User-controlled server selection
|
||||
- ✅ Community server prioritized
|
||||
|
||||
---
|
||||
|
||||
**Build Status:** ✅ SUCCESS
|
||||
**Ready for Testing:** ✅ YES
|
||||
**Emulator Available:** ⚠️ Issues (use physical device)
|
||||
**Next Phase:** Testing on device + Phase 2 (Events Service)
|
||||
@@ -123,9 +123,7 @@
|
||||
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<meta-data android:name="com.ea.nimble.configuration" android:value="customized"/>
|
||||
<!-- Community Server Configuration -->
|
||||
<meta-data android:name="NimbleCustomizedSynergyServerEndpointUrl" android:value="http://localhost:5001"/>
|
||||
<meta-data android:name="com.ea.nimble.configuration" android:value="live"/>
|
||||
<meta-data android:name="com.ea.nimble.tracking.defaultEnable" android:value="@string/nimble_trackingEnableFlag"/>
|
||||
<meta-data android:name="com.ea.nimble.mtx.enableVerification" android:value="@string/nimble_mtx_enableVerification"/>
|
||||
<meta-data android:name="com.ea.nimble.mtx.reportingEnabled" android:value="@string/nimble_mtx_reportingEnabled"/>
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
# ⚠️ RR3 APK Repository - Branch Structure
|
||||
|
||||
**Date:** February 22, 2026
|
||||
**Active Branch:** v14
|
||||
|
||||
---
|
||||
|
||||
## 📋 Default Branch
|
||||
|
||||
**`v14` is the default and primary development branch**
|
||||
|
||||
All work on the RR3 Community Edition APK should be done on the `v14` branch.
|
||||
|
||||
---
|
||||
|
||||
## 🌿 Branch Overview
|
||||
|
||||
### Active Branches
|
||||
|
||||
**v14** (DEFAULT) ⭐
|
||||
- Primary development branch
|
||||
- RR3 version 14.0.1 (EA latest before community)
|
||||
- Contains all community modifications:
|
||||
- Killswitch removal
|
||||
- Custom server support
|
||||
- Server browser/selection
|
||||
- Settings menu additions
|
||||
- Server URL input dialog (NEW)
|
||||
- **All new features go here**
|
||||
|
||||
**main**
|
||||
- Legacy/documentation branch
|
||||
- Contains initial project documentation
|
||||
- Not actively developed
|
||||
|
||||
**killswitch-killer**
|
||||
- Documentation-focused branch
|
||||
- Contains killswitch removal guide
|
||||
- Code duplicated to v14
|
||||
- Primarily for community reference
|
||||
|
||||
**discord-apktool** / **discord-community**
|
||||
- Experimental/test branches
|
||||
- Not actively maintained
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Workflow
|
||||
|
||||
### Starting New Work
|
||||
|
||||
```bash
|
||||
# 1. Switch to v14
|
||||
cd E:\rr3\rr3-apk
|
||||
git checkout v14
|
||||
|
||||
# 2. Pull latest changes
|
||||
git pull origin v14
|
||||
git pull gitea v14
|
||||
|
||||
# 3. Verify you're on v14
|
||||
git branch
|
||||
# Should show: * v14
|
||||
|
||||
# 4. Start working...
|
||||
```
|
||||
|
||||
### Committing Changes
|
||||
|
||||
```bash
|
||||
# 1. Stage changes
|
||||
git add .
|
||||
|
||||
# 2. Commit with descriptive message
|
||||
git commit -m "feat: Your feature description"
|
||||
|
||||
# 3. Push to both remotes (v14 branch)
|
||||
git push origin v14
|
||||
git push gitea v14
|
||||
```
|
||||
|
||||
### Checking Current Branch
|
||||
|
||||
```bash
|
||||
# Quick check
|
||||
git branch
|
||||
|
||||
# Detailed check with remotes
|
||||
git branch -vv
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Branch Comparison
|
||||
|
||||
| Branch | Purpose | Status | Use Case |
|
||||
|--------|---------|--------|----------|
|
||||
| **v14** | Primary development | ✅ Active | All new features |
|
||||
| main | Documentation | ⚠️ Legacy | Reference only |
|
||||
| killswitch-killer | Killswitch docs | 📚 Reference | Community FAQ |
|
||||
| discord-* | Experiments | ⏸️ Paused | Testing only |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Recent Commits on v14
|
||||
|
||||
```
|
||||
51be1177d - feat: Add first-launch server URL input dialog
|
||||
b7fb41dd0 - Add CORRECTED custom server configuration guide
|
||||
240773d28 - Add SSL certificate validation analysis
|
||||
d9eec8c69 - Add technical documentation for Nimble SDK killswitch removal
|
||||
43a74d365 - Add comprehensive Getting Started guide
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Current State (v14 Branch)
|
||||
|
||||
**Features Implemented:**
|
||||
- ✅ Killswitch removal (bypasses EA version check)
|
||||
- ✅ Custom server URL support (AndroidManifest.xml)
|
||||
- ✅ SSL certificate flexibility (self-signed certs work)
|
||||
- ✅ Server browser UI (optional)
|
||||
- ✅ Settings menu with server options
|
||||
- ✅ **Server URL input dialog (LATEST)** - First-launch configuration
|
||||
|
||||
**Next Steps:**
|
||||
- Sign and test server URL input feature
|
||||
- Test on physical device/emulator
|
||||
- Add "Change Server" to settings menu
|
||||
- Implement server favorites list
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Syncing Between Remotes
|
||||
|
||||
The v14 branch is synced to both remotes:
|
||||
|
||||
**GitHub:** https://github.com/supermegamestre/Project-Real-Resurrection-3
|
||||
**Gitea:** https://gitea.barrer.net/project-real-resurrection-3/rr3-apk
|
||||
|
||||
```bash
|
||||
# Push to both remotes at once
|
||||
git push origin v14 && git push gitea v14
|
||||
|
||||
# Pull from both (if needed)
|
||||
git pull origin v14
|
||||
git pull gitea v14
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 Best Practices
|
||||
|
||||
1. **Always work on v14** - Never commit directly to main
|
||||
2. **Pull before starting** - Get latest changes first
|
||||
3. **Test before pushing** - Build APK and verify it compiles
|
||||
4. **Push to both remotes** - Keep GitHub and Gitea in sync
|
||||
5. **Descriptive commits** - Use conventional commit format
|
||||
|
||||
**Conventional Commit Format:**
|
||||
```
|
||||
feat: Add new feature
|
||||
fix: Fix a bug
|
||||
docs: Update documentation
|
||||
refactor: Refactor code
|
||||
test: Add tests
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Remember
|
||||
|
||||
**v14 is your home base. All community work happens here.** 🏠
|
||||
|
||||
When in doubt:
|
||||
```bash
|
||||
git checkout v14
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** February 22, 2026
|
||||
**Current HEAD (v14):** 51be1177d
|
||||
@@ -1,345 +0,0 @@
|
||||
# EA URL Elimination & Server URL Priority System
|
||||
|
||||
**Date:** February 22, 2026
|
||||
**Status:** ✅ EA URLs eliminated as primary, community server prioritized
|
||||
**APK Version:** v14.0.1
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Problem Identified
|
||||
|
||||
The APK was configured to use EA's production "LIVE" servers as the default, with community server URL only as an override. This meant:
|
||||
- Configuration mode: `LIVE`
|
||||
- Default fallback: `https://syn-dir.sn.eamobile.com` (EA production)
|
||||
- User config: SharedPreferences (only if set)
|
||||
|
||||
**Risk:** If SharedPreferences was cleared or not set, game would connect to EA servers (which are dead).
|
||||
|
||||
---
|
||||
|
||||
## ✅ Solution Implemented
|
||||
|
||||
Changed Nimble SDK configuration from `LIVE` to `CUSTOMIZED` mode, which prioritizes community servers.
|
||||
|
||||
### Changes Made
|
||||
|
||||
**File:** `E:\rr3\rr3-apk\AndroidManifest.xml`
|
||||
|
||||
**Line 126 - Changed configuration mode:**
|
||||
```xml
|
||||
<!-- BEFORE -->
|
||||
<meta-data android:name="com.ea.nimble.configuration" android:value="live"/>
|
||||
|
||||
<!-- AFTER -->
|
||||
<meta-data android:name="com.ea.nimble.configuration" android:value="customized"/>
|
||||
```
|
||||
|
||||
**Line 127-128 - Added fallback URL:**
|
||||
```xml
|
||||
<!-- NEW -->
|
||||
<!-- Community Server Configuration -->
|
||||
<meta-data android:name="NimbleCustomizedSynergyServerEndpointUrl" android:value="http://localhost:5001"/>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Server URL Priority System
|
||||
|
||||
### Priority Order (Highest to Lowest)
|
||||
|
||||
```
|
||||
Priority 1: SharedPreferences (User Configuration)
|
||||
↓
|
||||
Location: /data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml
|
||||
Key: "server_url"
|
||||
Set by: ServerSetupActivity (first launch) or SettingsActivity (user change)
|
||||
Example: "https://rr3.example.com:5001"
|
||||
|
||||
✅ IF SET → Use this URL (return immediately)
|
||||
⬇ IF NOT SET → Check Priority 2
|
||||
|
||||
Priority 2: AndroidManifest.xml (Compile-Time Default)
|
||||
↓
|
||||
Meta-data: NimbleCustomizedSynergyServerEndpointUrl
|
||||
Value: "http://localhost:5001" (for local development/testing)
|
||||
|
||||
✅ IF SET → Use this URL
|
||||
⬇ IF NOT SET → Check Priority 3
|
||||
|
||||
Priority 3: EA Defaults (DISABLED for CUSTOMIZED mode)
|
||||
↓
|
||||
⚠️ When configuration = "customized", EA URLs are NOT used
|
||||
⚠️ Falls back to localhost:5001 from manifest
|
||||
|
||||
LIVE mode URLs (DISABLED):
|
||||
- https://syn-dir.sn.eamobile.com (production)
|
||||
- https://director-stage.sn.eamobile.com (staging)
|
||||
- https://director-int.sn.eamobile.com (integration)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Configuration Modes
|
||||
|
||||
### NimbleConfiguration Enum Values
|
||||
|
||||
| Mode | Description | Default URL | Use Case |
|
||||
|------|-------------|-------------|----------|
|
||||
| `UNKNOWN` | Invalid/unset | None | Error state |
|
||||
| `INTEGRATION` | EA dev environment | `director-int.sn.eamobile.com` | ❌ Never use |
|
||||
| `STAGE` | EA staging | `director-stage.sn.eamobile.com` | ❌ Never use |
|
||||
| `LIVE` | EA production | `syn-dir.sn.eamobile.com` | ❌ OLD (replaced) |
|
||||
| **`CUSTOMIZED`** | **Community servers** | **Manifest or SharedPrefs** | ✅ **ACTIVE** |
|
||||
| `MANUAL` | Manual override | None | ⚠️ Requires code |
|
||||
|
||||
**Current Mode:** `CUSTOMIZED` ✅
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Code Flow Analysis
|
||||
|
||||
### getSynergyDirectorServerUrl() Method
|
||||
|
||||
**Location:** `com/ea/nimble/SynergyEnvironmentImpl.smali` line 953
|
||||
|
||||
```smali
|
||||
.method public getSynergyDirectorServerUrl(Lcom/ea/nimble/NimbleConfiguration;)Ljava/lang/String;
|
||||
# Line 957: Log function entry
|
||||
invoke-static {p0}, Lcom/ea/nimble/Log$Helper;->LOGPUBLICFUNC(Ljava/lang/Object;)V
|
||||
|
||||
# 🆕 COMMUNITY PATCH: Check SharedPreferences FIRST (PRIORITY #1)
|
||||
# Line 961-968: Get application context and call CommunityServerManager
|
||||
invoke-static {}, Lcom/ea/nimble/ApplicationEnvironment;->getCurrentApplication()Landroid/app/Application;
|
||||
move-result-object v0
|
||||
invoke-static {v0}, Lcom/firemint/realracing/CommunityServerManager;->getServerUrl(Landroid/content/Context;)Ljava/lang/String;
|
||||
move-result-object v0
|
||||
|
||||
# Line 969-976: Check if URL is not null and not empty
|
||||
if-eqz v0, :check_manifest
|
||||
invoke-virtual {v0}, Ljava/lang/String;->isEmpty()Z
|
||||
move-result v1
|
||||
if-nez v1, :check_manifest
|
||||
|
||||
# Line 979: Log that we're using community server
|
||||
const-string v1, "🎯 Using community server from SharedPreferences"
|
||||
const-string v2, "SynergyEnvironmentImpl"
|
||||
invoke-static {v2, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I
|
||||
|
||||
# Line 985: RETURN user-configured URL (Priority 1)
|
||||
return-object v0
|
||||
|
||||
# Continue with normal logic if SharedPreferences not set
|
||||
:check_manifest
|
||||
# Line 990-996: Switch on NimbleConfiguration enum
|
||||
sget-object v0, Lcom/ea/nimble/SynergyEnvironmentImpl$3;->$SwitchMap$com$ea$nimble$NimbleConfiguration:[I
|
||||
invoke-virtual {p1}, Ljava/lang/Enum;->ordinal()I
|
||||
move-result v1
|
||||
aget v0, v0, v1
|
||||
|
||||
# Check configuration mode
|
||||
const/4 v1, 0x1
|
||||
if-eq v0, v1, :cond_3 # INTEGRATION → line 1046
|
||||
|
||||
const/4 v1, 0x2
|
||||
if-eq v0, v1, :cond_2 # STAGE → line 1041
|
||||
|
||||
const/4 v1, 0x3
|
||||
const-string v2, "https://syn-dir.sn.eamobile.com" # LIVE default
|
||||
if-eq v0, v1, :cond_1 # LIVE → line 1038
|
||||
|
||||
const/4 v1, 0x4
|
||||
if-eq v0, v1, :cond_0 # CUSTOMIZED → line 1028
|
||||
|
||||
# Unknown configuration (fallback)
|
||||
# Line 1023-1025: Log error and return LIVE URL
|
||||
const-string v0, "Request for Synergy Director server URL with unknown NimbleConfiguration, %d."
|
||||
invoke-static {p0, v0, p1}, Lcom/ea/nimble/Log$Helper;->LOGF(...)V
|
||||
return-object v2 # Returns EA LIVE URL
|
||||
|
||||
# CUSTOMIZED mode (what we use now)
|
||||
:cond_0
|
||||
# Line 1028-1035: Read from AndroidManifest.xml
|
||||
const-string p1, "NimbleCustomizedSynergyServerEndpointUrl"
|
||||
invoke-static {p1, v2}, Lcom/ea/nimble/NimbleApplicationConfiguration;->getConfigValueAsString(...)
|
||||
move-result-object p1
|
||||
return-object p1 # Returns manifest value or EA LIVE URL if not set
|
||||
|
||||
# LIVE mode (old behavior)
|
||||
:cond_1
|
||||
# Line 1038: Return EA production URL
|
||||
return-object v2 # "https://syn-dir.sn.eamobile.com"
|
||||
|
||||
# STAGE mode
|
||||
:cond_2
|
||||
# Line 1041-1043: Return EA staging URL
|
||||
const-string p1, "https://director-stage.sn.eamobile.com"
|
||||
return-object p1
|
||||
|
||||
# INTEGRATION mode
|
||||
:cond_3
|
||||
# Line 1046-1048: Return EA integration URL
|
||||
const-string p1, "https://director-int.sn.eamobile.com"
|
||||
return-object p1
|
||||
.end method
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Verification
|
||||
|
||||
### EA URLs Still Present (But Disabled)
|
||||
|
||||
EA URLs remain in the code as **string constants** but are **never reached** when:
|
||||
1. User has configured a server URL (SharedPreferences) ✅
|
||||
2. Configuration mode is CUSTOMIZED ✅
|
||||
3. Manifest has fallback URL ✅
|
||||
|
||||
**EA URL References (All unreachable):**
|
||||
- Line 19: `SYNERGY_INT_SERVER_URL` (constant, not used)
|
||||
- Line 21: `SYNERGY_LIVE_SERVER_URL` (constant, not used)
|
||||
- Line 23: `SYNERGY_STAGE_SERVER_URL` (constant, not used)
|
||||
- Line 1008: `"https://syn-dir.sn.eamobile.com"` (in LIVE/UNKNOWN branch)
|
||||
- Line 1041: `"https://director-stage.sn.eamobile.com"` (in STAGE branch)
|
||||
- Line 1046: `"https://director-int.sn.eamobile.com"` (in INTEGRATION branch)
|
||||
|
||||
**Execution Path:** Lines 959→969→979→985 (return) → **EA URLs never reached** ✅
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing Scenarios
|
||||
|
||||
### Scenario 1: Fresh Install (No SharedPreferences)
|
||||
```
|
||||
Boot → MainActivity → CommunityServerManager.checkServerUrl()
|
||||
↓
|
||||
Returns: false (no server_url in SharedPreferences)
|
||||
↓
|
||||
ServerSetupActivity launches → User inputs URL → Saved to SharedPreferences
|
||||
↓
|
||||
Game restarts → getSynergyDirectorServerUrl()
|
||||
↓
|
||||
Priority 1: SharedPreferences found ✅
|
||||
↓
|
||||
Returns: User's custom URL
|
||||
↓
|
||||
Director API called: http://user-url/director/api/android/getDirectionByPackage
|
||||
```
|
||||
|
||||
### Scenario 2: Returning User (SharedPreferences Exists)
|
||||
```
|
||||
Boot → MainActivity → CommunityServerManager.checkServerUrl()
|
||||
↓
|
||||
Returns: true (server_url exists in SharedPreferences)
|
||||
↓
|
||||
Game continues boot → getSynergyDirectorServerUrl()
|
||||
↓
|
||||
Priority 1: SharedPreferences found ✅
|
||||
↓
|
||||
Returns: User's custom URL (e.g., "https://rr3.example.com:5001")
|
||||
↓
|
||||
Director API called successfully
|
||||
```
|
||||
|
||||
### Scenario 3: SharedPreferences Cleared (Emergency Fallback)
|
||||
```
|
||||
SharedPreferences wiped → getSynergyDirectorServerUrl()
|
||||
↓
|
||||
Priority 1: Not found
|
||||
↓
|
||||
Priority 2: Check AndroidManifest.xml
|
||||
↓
|
||||
NimbleCustomizedSynergyServerEndpointUrl = "http://localhost:5001"
|
||||
↓
|
||||
Returns: "http://localhost:5001" (for local testing)
|
||||
↓
|
||||
Game tries localhost (development scenario)
|
||||
```
|
||||
|
||||
### Scenario 4: Wrong Configuration Mode (Safety Check)
|
||||
```
|
||||
If someone accidentally changes configuration back to "live":
|
||||
↓
|
||||
Priority 1: SharedPreferences STILL checked first ✅
|
||||
↓
|
||||
Returns: User's custom URL (SharedPreferences override)
|
||||
↓
|
||||
EA URLs only used if BOTH Priority 1 AND Priority 2 fail
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Security Implications
|
||||
|
||||
### Before (LIVE Mode):
|
||||
- ⚠️ Fallback to EA production servers
|
||||
- ⚠️ Potential data leakage to dead servers
|
||||
- ⚠️ Connection failures if EA domains resolve
|
||||
|
||||
### After (CUSTOMIZED Mode):
|
||||
- ✅ No automatic EA server connections
|
||||
- ✅ User-controlled server selection
|
||||
- ✅ Localhost fallback for development
|
||||
- ✅ SharedPreferences override always works
|
||||
|
||||
---
|
||||
|
||||
## 📝 Configuration File Priority
|
||||
|
||||
### 1. Runtime Configuration (Highest Priority)
|
||||
**File:** `/data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml`
|
||||
```xml
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<map>
|
||||
<string name="server_url">https://rr3.example.com:5001</string>
|
||||
</map>
|
||||
```
|
||||
**Managed by:** `CommunityServerManager.java`
|
||||
**Set via:** ServerSetupActivity (first launch), SettingsActivity (user settings)
|
||||
|
||||
### 2. Compile-Time Configuration (Fallback)
|
||||
**File:** `AndroidManifest.xml` (inside APK)
|
||||
```xml
|
||||
<meta-data android:name="com.ea.nimble.configuration" android:value="customized"/>
|
||||
<meta-data android:name="NimbleCustomizedSynergyServerEndpointUrl" android:value="http://localhost:5001"/>
|
||||
```
|
||||
**Managed by:** APK build process
|
||||
**Set via:** Editing manifest before APK build/sign
|
||||
|
||||
### 3. Hardcoded Defaults (Never Used)
|
||||
**File:** `SynergyEnvironmentImpl.smali` constants
|
||||
**Status:** Present in code but unreachable with CUSTOMIZED mode ✅
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Summary
|
||||
|
||||
### Changes Made:
|
||||
1. ✅ Changed `com.ea.nimble.configuration` from `"live"` to `"customized"`
|
||||
2. ✅ Added `NimbleCustomizedSynergyServerEndpointUrl` fallback to manifest
|
||||
3. ✅ Verified SharedPreferences check happens FIRST (Priority 1)
|
||||
4. ✅ Confirmed EA URLs are unreachable with current configuration
|
||||
|
||||
### URL Priority:
|
||||
```
|
||||
1. SharedPreferences (user config) ← ALWAYS CHECKED FIRST ✅
|
||||
2. AndroidManifest.xml (fallback) ← localhost:5001 ✅
|
||||
3. EA Servers (DISABLED) ← Never reached ✅
|
||||
```
|
||||
|
||||
### EA URL Status:
|
||||
- **Present in code:** Yes (as string constants)
|
||||
- **Reachable:** No ❌ (only if both Priority 1 AND 2 fail)
|
||||
- **Risk level:** Minimal (triple-layered protection)
|
||||
|
||||
### Security:
|
||||
- ✅ User-controlled server selection
|
||||
- ✅ No automatic EA connections
|
||||
- ✅ Safe fallback for development (localhost)
|
||||
- ✅ Multiple layers of protection
|
||||
|
||||
---
|
||||
|
||||
**Status:** ✅ COMPLETE
|
||||
**EA URLs:** Effectively eliminated from execution path
|
||||
**Community Server:** Prioritized at all times
|
||||
**Next:** Rebuild & sign APK with new configuration
|
||||
835
FAQ.md
835
FAQ.md
@@ -1,835 +0,0 @@
|
||||
# RR3 Community Server - Frequently Asked Questions (FAQ)
|
||||
|
||||
**Last Updated:** February 23, 2026
|
||||
**Project:** Real Racing 3 Community Server + APK Mod
|
||||
|
||||
---
|
||||
|
||||
## 🤔 "Just Read The Code" - Common Questions
|
||||
|
||||
**Before asking, check here first!** All code is public on Gitea - but here are the most common questions answered quickly.
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Security & Encryption
|
||||
|
||||
### Q: Is the network communication encrypted?
|
||||
|
||||
**A:** Yes AND No - it depends what you mean:
|
||||
|
||||
- **Transport (HTTPS/TLS):** ✅ YES - data is encrypted in transit
|
||||
- **Application-level encryption:** ❌ NO - payloads are plaintext over HTTPS
|
||||
- **Certificate validation:** ❌ DISABLED - accepts any SSL certificate
|
||||
|
||||
**Details:** The game uses HTTPS but disables certificate validation, making it vulnerable to MITM attacks but also allowing self-signed certificates for community servers.
|
||||
|
||||
**Read More:** `NETWORK-SECURITY-ANALYSIS.md` (16 KB full analysis)
|
||||
|
||||
---
|
||||
|
||||
### Q: Are the APK network files/code encrypted or obfuscated?
|
||||
|
||||
**A:** ❌ NO - completely readable
|
||||
|
||||
- **Code obfuscation:** NONE (no ProGuard/R8)
|
||||
- **Class names:** Readable (Http.java, HttpRequest.java, etc.)
|
||||
- **Method names:** Readable (sendRequest, postData, etc.)
|
||||
- **Strings:** Plaintext in smali files
|
||||
|
||||
**What IS encrypted:** Local save data on device (AES-256) - NOT network traffic
|
||||
|
||||
**Why it matters:** Made reverse engineering easy! If EA had obfuscated the code, this project would be 10x harder.
|
||||
|
||||
**See for yourself:**
|
||||
- `smali_classes2/com/firemint/realracing/Http.smali` - readable class names
|
||||
- `smali_classes2/com/ea/nimble/SynergyEnvironmentImpl.smali` - readable methods
|
||||
|
||||
---
|
||||
|
||||
### Q: What encryption DOES the game use?
|
||||
|
||||
**A:** Only for local storage:
|
||||
|
||||
- **Algorithm:** AES/CBC/PKCS5Padding (256-bit keys)
|
||||
- **Key derivation:** PBKDF2WithHmacSHA1 (997 rounds)
|
||||
- **Used for:**
|
||||
- Saved game data on device
|
||||
- Cached authentication tokens
|
||||
- SharedPreferences persistence
|
||||
|
||||
**Code location:** `smali_classes2/com/ea/nimble/Encryptor.smali`
|
||||
|
||||
**Network payloads:** NOT encrypted (plaintext over HTTPS)
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Network & Server
|
||||
|
||||
### Q: Will the game contact EA servers?
|
||||
|
||||
**A:** ❌ NO - EA URLs eliminated in v14 APK
|
||||
|
||||
**What we changed:**
|
||||
- AndroidManifest.xml: `configuration="live"` → `"customized"`
|
||||
- EA production URLs unreachable (only if both user config AND manifest fail)
|
||||
- URL Priority: SharedPreferences > Manifest fallback > Never EA
|
||||
|
||||
**Details:** `EA-URL-ELIMINATION.md` (11 KB)
|
||||
|
||||
**Test it yourself:**
|
||||
1. Install APK
|
||||
2. Monitor with `adb logcat | grep eamobile`
|
||||
3. Should see ZERO EA domain connections
|
||||
|
||||
---
|
||||
|
||||
### Q: How does the server URL configuration work?
|
||||
|
||||
**A:** 3-tier priority system:
|
||||
|
||||
**Priority 1 (Highest):** SharedPreferences
|
||||
- File: `/data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml`
|
||||
- Key: `"server_url"`
|
||||
- Set by: User input in ServerSetupActivity (first launch)
|
||||
|
||||
**Priority 2:** AndroidManifest.xml
|
||||
- Meta-data: `NimbleCustomizedSynergyServerEndpointUrl`
|
||||
- Default: `http://localhost:5001`
|
||||
- Used if SharedPreferences empty
|
||||
|
||||
**Priority 3:** EA URLs (UNREACHABLE)
|
||||
- Only accessible if both Priority 1 AND 2 fail
|
||||
- With `configuration="customized"`, this never happens
|
||||
|
||||
**Code:** Lines 959-985 in `SynergyEnvironmentImpl.smali`
|
||||
|
||||
---
|
||||
|
||||
### Q: What server endpoints are required?
|
||||
|
||||
**A:** 73 Synergy API endpoints total
|
||||
|
||||
**Status:**
|
||||
- Implemented: 58/73 (79%)
|
||||
- Missing: 15 endpoints
|
||||
|
||||
**Critical missing:**
|
||||
- Events Service: 0/4 (blocks career mode)
|
||||
- Time Trials: 0/5
|
||||
- Leaderboards: 3/4
|
||||
- Multiplayer: 0/10+
|
||||
|
||||
**Full list:** `SERVER-ENDPOINTS-ANALYSIS.md` (12.7 KB)
|
||||
|
||||
---
|
||||
|
||||
### Q: Can I use self-signed SSL certificates?
|
||||
|
||||
**A:** ✅ YES - the APK accepts ANY certificate
|
||||
|
||||
**Why:** Certificate validation is disabled (`ALLOW_ALL_HOSTNAME_VERIFIER`)
|
||||
|
||||
**Options:**
|
||||
1. **Let's Encrypt** (recommended) - free, valid certificates
|
||||
2. **Self-signed** - works perfectly, free
|
||||
3. **No SSL (HTTP)** - works but not recommended for production
|
||||
|
||||
**Generate self-signed:**
|
||||
```bash
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ APK Modifications
|
||||
|
||||
### Q: What was changed in the v14 APK?
|
||||
|
||||
**A:** Minimal changes to eliminate EA servers:
|
||||
|
||||
**File:** AndroidManifest.xml
|
||||
- **Line 126:** `android:value="live"` → `android:value="customized"`
|
||||
- **Lines 127-128:** Added fallback URL `http://localhost:5001`
|
||||
|
||||
**Code added:**
|
||||
- `CommunityServerManager.smali` - manages server URL preferences
|
||||
- `ServerSetupActivity.smali` - first-launch server input dialog
|
||||
- `OfflineModeManager.smali` - online/offline toggle
|
||||
|
||||
**That's it!** No other game code modified.
|
||||
|
||||
---
|
||||
|
||||
### Q: How do I build the APK myself?
|
||||
|
||||
**A:** 3-step process:
|
||||
|
||||
```bash
|
||||
# 1. Decompile
|
||||
apktool d RealRacing3.apk -o rr3-apk
|
||||
|
||||
# 2. Make changes (edit AndroidManifest.xml, etc.)
|
||||
|
||||
# 3. Rebuild
|
||||
apktool b rr3-apk -o RR3-modified-unsigned.apk
|
||||
|
||||
# 4. Sign
|
||||
apksigner sign --ks your-keystore.jks \
|
||||
--out RR3-modified-signed.apk \
|
||||
RR3-modified-unsigned.apk
|
||||
```
|
||||
|
||||
**Full guide:** `APK-BUILD-AND-TESTING-GUIDE.md` (10 KB)
|
||||
|
||||
**Requirements:**
|
||||
- Java 11+ (OpenJDK recommended)
|
||||
- apktool 2.10.0+
|
||||
- Android SDK build-tools
|
||||
|
||||
---
|
||||
|
||||
### Q: Why isn't ProGuard/obfuscation used?
|
||||
|
||||
**A:** EA/Firemonkeys chose not to obfuscate
|
||||
|
||||
**Likely reasons:**
|
||||
- Easier debugging/crash reports
|
||||
- Faster build times
|
||||
- Game logic not "secret" (offline mobile game)
|
||||
- Anti-cheat handled server-side (when servers existed)
|
||||
|
||||
**Result:** Made our community server project MUCH easier! 🎉
|
||||
|
||||
---
|
||||
|
||||
## 🎮 Gameplay & Features
|
||||
|
||||
### Q: Can I play offline?
|
||||
|
||||
**A:** ✅ YES - offline mode implemented
|
||||
|
||||
**How to enable:**
|
||||
- Settings menu → Toggle "Offline Mode"
|
||||
- Saves to: `rr3_offline_settings.xml`
|
||||
- Key: `offline_mode_enabled`
|
||||
|
||||
**Limitations:**
|
||||
- No leaderboards
|
||||
- No multiplayer
|
||||
- No cloud save sync
|
||||
- Career mode works (if Events Service implemented)
|
||||
|
||||
**Code:** `smali_classes2/com/firemint/realracing/OfflineModeManager.smali`
|
||||
|
||||
---
|
||||
|
||||
### Q: Does multiplayer work?
|
||||
|
||||
**A:** ❌ NOT YET
|
||||
|
||||
**Status:** 0/10+ multiplayer endpoints implemented
|
||||
|
||||
**Blockers:**
|
||||
- Real-time matchmaking system needed
|
||||
- Race synchronization logic required
|
||||
- Anti-cheat server-side validation
|
||||
- P2P or relay server architecture decision
|
||||
|
||||
**Priority:** LOW (Phase 3+) - single-player first
|
||||
|
||||
---
|
||||
|
||||
### Q: Can I charge for in-app purchases?
|
||||
|
||||
**A:** ❌ NO - EA's legal restriction
|
||||
|
||||
**EA's Terms:**
|
||||
- ✅ Community servers allowed
|
||||
- ✅ Donations for server costs allowed
|
||||
- ❌ Cannot charge for in-app purchases (real money)
|
||||
- ❌ Cannot charge for the APK itself
|
||||
|
||||
**Why:** EA retains the game IP and rights
|
||||
|
||||
**Alternative:** Accept donations for server hosting (PayPal, Patreon, etc.)
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Q: APK won't install - "App not installed"
|
||||
|
||||
**A:** Common fixes:
|
||||
|
||||
**1. Uninstall existing RR3:**
|
||||
```bash
|
||||
adb uninstall com.ea.games.r3_row
|
||||
```
|
||||
|
||||
**2. Check signature:**
|
||||
```bash
|
||||
apksigner verify --verbose your-apk.apk
|
||||
```
|
||||
|
||||
**3. Enable "Unknown Sources":**
|
||||
- Settings → Security → Allow unknown sources
|
||||
|
||||
**4. Check architecture:**
|
||||
- APK supports: armeabi-v7a, arm64-v8a
|
||||
- Won't work on x86 devices without translation
|
||||
|
||||
---
|
||||
|
||||
### Q: Game crashes on startup
|
||||
|
||||
**A:** Debug steps:
|
||||
|
||||
**1. Check logcat:**
|
||||
```bash
|
||||
adb logcat -s AndroidRuntime:E
|
||||
```
|
||||
|
||||
**2. Common causes:**
|
||||
- Missing native libraries (lib/ folder)
|
||||
- Wrong Android version (need 5.0+)
|
||||
- Corrupted APK (re-download/rebuild)
|
||||
|
||||
**3. Clear app data:**
|
||||
```bash
|
||||
adb shell pm clear com.ea.games.r3_row
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Q: "Cannot connect to server" error
|
||||
|
||||
**A:** Checklist:
|
||||
|
||||
✅ Server is running: `curl http://localhost:5001/health`
|
||||
✅ Server URL configured in app
|
||||
✅ Network connectivity exists
|
||||
✅ Firewall allows connection
|
||||
✅ For emulator: Use `http://10.0.2.2:5001` not `localhost`
|
||||
|
||||
**Port forwarding (emulator):**
|
||||
```bash
|
||||
adb reverse tcp:5001 tcp:5001
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
### Q: Where is all the documentation?
|
||||
|
||||
**A:** APK Repository (GitHub) - `rr3-apk` branch `v14`:
|
||||
|
||||
**Main Docs:**
|
||||
- `README.md` - Project overview
|
||||
- `FAQ.md` - This document!
|
||||
- `NETWORK-SECURITY-ANALYSIS.md` (16 KB) - Security deep dive
|
||||
- `EA-URL-ELIMINATION.md` (11 KB) - How EA URLs were eliminated
|
||||
- `RR3-NETWORK-ANALYSIS-AND-CONFIG-SYSTEM.md` (16 KB) - Network architecture
|
||||
- `APK-BUILD-AND-TESTING-GUIDE.md` (10 KB) - Build instructions
|
||||
- `SERVER-ENDPOINTS-ANALYSIS.md` (12.7 KB) - All 73 endpoints mapped
|
||||
|
||||
**Server Repository (GitHub) - `RR3CommunityServer` branch `main`:**
|
||||
- Controllers/*.cs - Server endpoint implementations
|
||||
- PHASE-1-IMPLEMENTATION-COMPLETE.md - Phase 1 completion docs
|
||||
|
||||
---
|
||||
|
||||
### Q: How do I contribute?
|
||||
|
||||
**A:** Multiple ways to help:
|
||||
|
||||
**1. Code:**
|
||||
- Implement missing endpoints (Events, Time Trials, etc.)
|
||||
- Fix bugs
|
||||
- Add features
|
||||
|
||||
**2. Documentation:**
|
||||
- Improve guides
|
||||
- Write tutorials
|
||||
- Translate to other languages
|
||||
|
||||
**3. Testing:**
|
||||
- Test on different devices/Android versions
|
||||
- Report bugs with detailed logs
|
||||
- Verify endpoint functionality
|
||||
|
||||
**4. Assets:**
|
||||
- Extract game assets (cars, tracks, textures)
|
||||
- Document asset formats
|
||||
- Create custom content tools
|
||||
|
||||
**Process:**
|
||||
1. Fork repository on GitHub/Gitea
|
||||
2. Create feature branch
|
||||
3. Make changes
|
||||
4. Submit pull request
|
||||
5. Describe what you changed and why
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Development
|
||||
|
||||
### Q: What tools do I need?
|
||||
|
||||
**A:** APK Development:
|
||||
- **apktool** 2.10.0+ - APK decompilation/recompilation
|
||||
- **Java** 11+ - Build environment
|
||||
- **Android SDK** - Signing & verification
|
||||
- **Text editor** - VS Code, Sublime, etc.
|
||||
|
||||
**Server Development:**
|
||||
- **.NET 8 SDK** - ASP.NET Core
|
||||
- **PostgreSQL** (or SQL Server, SQLite) - Database
|
||||
- **Visual Studio** or **VS Code** - IDE
|
||||
|
||||
---
|
||||
|
||||
### Q: How long did this project take?
|
||||
|
||||
**A:** ~25 checkpoints (sessions) so far
|
||||
|
||||
**Breakdown:**
|
||||
- Checkpoint 1-5: Initial analysis, asset systems, modding
|
||||
- Checkpoint 6-10: Server browser, daily rewards, progression
|
||||
- Checkpoint 11-15: Killswitch removal, dual APK variants, settings
|
||||
- Checkpoint 16-20: Server auth, asset management, APK fixes
|
||||
- Checkpoint 21-24: Version system, URL configuration, network analysis
|
||||
|
||||
**Current Status:** 79% complete (58/73 endpoints)
|
||||
|
||||
---
|
||||
|
||||
## 💬 Contact & Community
|
||||
|
||||
### Q: Where can I ask questions?
|
||||
|
||||
**A:** Check these resources first:
|
||||
|
||||
1. **This FAQ** - Common questions answered
|
||||
2. **Documentation** - Deep technical details
|
||||
3. **Code** - All source code public on Gitea/GitHub
|
||||
4. **Issues** - GitHub Issues for bug reports
|
||||
|
||||
**Still stuck?** Open a GitHub Issue with:
|
||||
- Detailed description
|
||||
- Steps to reproduce
|
||||
- Logcat output
|
||||
- Device/Android version
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Quick Reference
|
||||
|
||||
### Essential File Locations
|
||||
|
||||
**APK (E:\rr3\rr3-apk):**
|
||||
```
|
||||
AndroidManifest.xml - App configuration
|
||||
smali_classes2/
|
||||
com/firemint/realracing/
|
||||
Http.smali - Network client
|
||||
CommunityServerManager.smali - Server URL storage
|
||||
ServerSetupActivity.smali - First-launch dialog
|
||||
com/ea/nimble/
|
||||
SynergyEnvironmentImpl.smali - URL priority logic
|
||||
Encryptor.smali - AES encryption
|
||||
```
|
||||
|
||||
**Server (E:\rr3\RR3CommunityServer):**
|
||||
```
|
||||
Controllers/
|
||||
ConfigController.cs - Config endpoints
|
||||
ProgressionController.cs - Save/load, progression
|
||||
UserController.cs - Authentication
|
||||
appsettings.json - Server configuration
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📂 Complete Code Location Reference
|
||||
|
||||
**"Where is [feature] in the code?"** - Here's EVERYTHING:
|
||||
|
||||
### 🌐 Network Communication
|
||||
|
||||
**HTTP/HTTPS Clients:**
|
||||
- `smali_classes2/com/firemint/realracing/Http.smali` (189 lines)
|
||||
- Main HTTP client (POST-only)
|
||||
- Lines 179-181: ALLOW_ALL_HOSTNAME_VERIFIER (disables SSL validation)
|
||||
- Lines 38-42: Empty TrustManager (no certificate validation)
|
||||
- Line 120: URL connection setup
|
||||
- Lines 158-165: POST data writing
|
||||
|
||||
- `smali_classes2/com/firemonkeys/cloudcellapi/HttpRequest.smali` (116 lines)
|
||||
- CloudCell HTTP client (GET/POST)
|
||||
- Lines 108-111: SSL context setup with custom TrustManager
|
||||
- Line 111: ALLOW_ALL_HOSTNAME_VERIFIER enabled
|
||||
- Lines 45-70: Request execution
|
||||
|
||||
- `smali_classes2/com/firemonkeys/cloudcellapi/HttpThread.smali`
|
||||
- Async HTTP execution
|
||||
- Chunk-based streaming callbacks
|
||||
|
||||
**SSL/TLS Configuration:**
|
||||
- `smali_classes2/com/firemonkeys/cloudcellapi/CloudcellTrustManager.smali`
|
||||
- Lines 24: `m_bSSLCheck` flag (default: false)
|
||||
- Lines 56-76: `checkServerTrusted()` - validation logic (disabled by default)
|
||||
- Lines 78-89: Certificate chain validation (when enabled)
|
||||
|
||||
### 🔐 Encryption & Security
|
||||
|
||||
**Data Encryption (Local Storage):**
|
||||
- `smali_classes2/com/ea/nimble/Encryptor.smali` (286 lines)
|
||||
- Lines 7-10: Encryption constants (256-bit key, 997 rounds)
|
||||
- Lines 36-50: Version headers (NEV1, NEV2)
|
||||
- Lines 62-160: Legacy decryption (PBEWithMD5AndDES)
|
||||
- Lines 200-270: Modern decryption (AES/CBC/PKCS5Padding)
|
||||
- Lines 246-260: AES cipher initialization
|
||||
- Lines 286-320: Key derivation (PBKDF2WithHmacSHA1)
|
||||
|
||||
**Persistence:**
|
||||
- `smali_classes2/com/ea/nimble/PersistenceServiceImpl.smali`
|
||||
- Uses Encryptor for save data
|
||||
- Lines 150-200: Save file encryption
|
||||
- Lines 250-300: Load file decryption
|
||||
|
||||
### 🌍 Server URL Configuration
|
||||
|
||||
**URL Priority System:**
|
||||
- `smali_classes2/com/ea/nimble/SynergyEnvironmentImpl.smali` (1800+ lines)
|
||||
- Lines 953-1049: `getSynergyDirectorServerUrl()` - MAIN URL LOGIC
|
||||
- Lines 959-985: SharedPreferences check (Priority 1)
|
||||
- Lines 990-1048: Configuration mode switch
|
||||
- Lines 1008: EA Integration URL (unreachable with CUSTOMIZED)
|
||||
- Lines 1041: EA Staging URL (unreachable with CUSTOMIZED)
|
||||
- Lines 1046: EA Production URL (unreachable with CUSTOMIZED)
|
||||
|
||||
**Community Server Manager:**
|
||||
- `smali_classes2/com/firemint/realracing/CommunityServerManager.smali` (136 lines)
|
||||
- Lines 24-58: `checkServerUrl()` - returns boolean if URL exists
|
||||
- Lines 60-96: `getServerUrl()` - retrieves URL from SharedPreferences
|
||||
- Lines 98-136: `saveServerUrl()` - saves URL to SharedPreferences
|
||||
- SharedPreferences file: `"rr3_community_server"`
|
||||
- SharedPreferences key: `"server_url"`
|
||||
|
||||
**Server Setup Dialog:**
|
||||
- `smali_classes2/com/firemint/realracing/ServerSetupActivity.smali`
|
||||
- First-launch UI for server URL input
|
||||
- Test connection button logic
|
||||
- Save and continue functionality
|
||||
|
||||
### ⚙️ Configuration Files
|
||||
|
||||
**App Manifest:**
|
||||
- `AndroidManifest.xml`
|
||||
- Line 126: `com.ea.nimble.configuration` - **"customized"** (was "live")
|
||||
- Lines 127-128: `NimbleCustomizedSynergyServerEndpointUrl` - fallback URL
|
||||
- Lines 32-35: Permissions (INTERNET, NETWORK_STATE, etc.)
|
||||
- Lines 45-120: EA Nimble SDK meta-data
|
||||
- Line 210: `networkSecurityConfig` reference
|
||||
- Line 215: `usesCleartextTraffic="false"` (HTTPS enforced)
|
||||
|
||||
**Network Security Config:**
|
||||
- `res/xml/network_security_config.xml`
|
||||
- Trust settings for HTTPS
|
||||
- Certificate configuration
|
||||
|
||||
### 🎮 Game Features
|
||||
|
||||
**Offline Mode:**
|
||||
- `smali_classes2/com/firemint/realracing/OfflineModeManager.smali` (131 lines)
|
||||
- Lines 36-77: `init()` - loads preference on startup
|
||||
- Lines 79-86: `isOfflineMode()` - getter
|
||||
- Lines 88-131: `setOfflineMode()` - setter with persistence
|
||||
- SharedPreferences file: `"rr3_offline_settings"`
|
||||
- SharedPreferences key: `"offline_mode_enabled"`
|
||||
|
||||
**Settings Activity:**
|
||||
- `smali_classes2/com/firemint/realracing/SettingsActivity.smali`
|
||||
- Offline mode toggle UI
|
||||
- Server URL change option
|
||||
- Game settings management
|
||||
|
||||
### 🚗 EA Nimble SDK (Core Services)
|
||||
|
||||
**Synergy (Authentication/Backend):**
|
||||
- `smali_classes2/com/ea/nimble/SynergyEnvironmentImpl.smali`
|
||||
- Main Synergy implementation
|
||||
- Lines 1-100: Constants and initialization
|
||||
- Lines 953-1049: Server URL selection logic
|
||||
- Lines 1100-1200: Director API calls
|
||||
|
||||
- `smali_classes2/com/ea/nimble/SynergyIdManager.smali`
|
||||
- Synergy ID generation/storage
|
||||
- User identification system
|
||||
|
||||
- `smali_classes2/com/ea/nimble/SynergyNetwork.smali`
|
||||
- Network request handling
|
||||
- API endpoint calls
|
||||
|
||||
**Application Environment:**
|
||||
- `smali_classes2/com/ea/nimble/ApplicationEnvironmentImpl.smali`
|
||||
- App bundle ID
|
||||
- Version information
|
||||
- Device info
|
||||
|
||||
**Tracking/Analytics:**
|
||||
- `smali_classes2/com/ea/nimble/Tracking*.smali`
|
||||
- Analytics event tracking
|
||||
- Synergy event logging
|
||||
|
||||
### 💰 CloudCell API (Billing/Social)
|
||||
|
||||
**Billing:**
|
||||
- `smali_classes2/com/firemonkeys/cloudcellapi/GooglePlayWorker.smali`
|
||||
- Google Play IAB integration
|
||||
- Purchase handling
|
||||
- Inventory management
|
||||
|
||||
- `smali_classes2/com/firemonkeys/cloudcellapi/AmazonStoreWorker.smali`
|
||||
- Amazon Appstore integration
|
||||
|
||||
- `smali_classes2/com/firemonkeys/cloudcellapi/FacebookWorker.smali`
|
||||
- Facebook payments
|
||||
|
||||
**Inventory/Purchases:**
|
||||
- `smali_classes2/com/firemonkeys/cloudcellapi/util/Inventory.smali`
|
||||
- IAB inventory management
|
||||
|
||||
- `smali_classes2/com/firemonkeys/cloudcellapi/util/Purchase.smali`
|
||||
- Purchase data handling
|
||||
|
||||
**Security:**
|
||||
- `smali_classes2/com/firemonkeys/cloudcellapi/Security.smali`
|
||||
- Signature verification (Google Play)
|
||||
- Base64 encoding/decoding
|
||||
|
||||
### 📱 Android Components
|
||||
|
||||
**Main Activity:**
|
||||
- `smali_classes2/com/firemint/realracing/MainActivity.smali`
|
||||
- App entry point
|
||||
- Launches ServerSetupActivity on first run
|
||||
|
||||
**Splash Screen:**
|
||||
- `smali_classes2/com/firemint/realracing/SplashActivity.smali`
|
||||
- Initial loading screen
|
||||
- Asset check trigger
|
||||
|
||||
**JNI Bridge:**
|
||||
- `smali_classes2/com/firemint/realracing/JNI*.smali`
|
||||
- Native code bridge
|
||||
- C++ game engine communication
|
||||
|
||||
### 🗂️ Assets & Resources
|
||||
|
||||
**Asset Locations:**
|
||||
- `assets/`
|
||||
- Game data files
|
||||
- Car models, tracks, textures
|
||||
- Configuration files
|
||||
- Audio files
|
||||
|
||||
**Resources:**
|
||||
- `res/layout/` - UI layouts
|
||||
- `res/drawable/` - Images
|
||||
- `res/values/strings.xml` - String resources
|
||||
- `res/xml/network_security_config.xml` - Network config
|
||||
|
||||
### 📊 Third-Party SDKs
|
||||
|
||||
**Firebase:**
|
||||
- `smali_classes2/com/google/firebase/`
|
||||
- Analytics
|
||||
- Crashlytics
|
||||
- Performance monitoring
|
||||
|
||||
**Facebook SDK:**
|
||||
- `smali_classes2/com/facebook/`
|
||||
- Login integration
|
||||
- Graph API
|
||||
- Share functionality
|
||||
|
||||
**Ad Networks:**
|
||||
- `smali_classes2/com/ironsource/` - IronSource ads
|
||||
- `smali_classes2/com/vungle/` - Vungle ads
|
||||
- `smali_classes2/com/fyber/` - Fyber ads
|
||||
- `smali_classes2/com/tapjoy/` - Tapjoy reward ads
|
||||
|
||||
### 🔧 Build Files
|
||||
|
||||
**Build Configuration:**
|
||||
- `apktool.yml` - APK metadata
|
||||
- Version info
|
||||
- SDK versions
|
||||
- Compression settings
|
||||
|
||||
**Native Libraries:**
|
||||
- `lib/armeabi-v7a/` - 32-bit ARM libraries
|
||||
- `lib/arm64-v8a/` - 64-bit ARM libraries
|
||||
- `lib/x86/` - x86 libraries (if present)
|
||||
|
||||
### 📝 Documentation Files
|
||||
|
||||
**Security & Network:**
|
||||
- `NETWORK-SECURITY-ANALYSIS.md` (16 KB)
|
||||
- Complete security audit
|
||||
- SSL/TLS analysis
|
||||
- Attack vectors
|
||||
- Mitigation strategies
|
||||
|
||||
- `EA-URL-ELIMINATION.md` (11 KB)
|
||||
- URL priority system
|
||||
- Code flow analysis
|
||||
- EA URL removal proof
|
||||
|
||||
- `RR3-NETWORK-ANALYSIS-AND-CONFIG-SYSTEM.md` (16 KB)
|
||||
- Network stack architecture
|
||||
- CloudCell API docs
|
||||
- Config system design
|
||||
|
||||
**Build & Testing:**
|
||||
- `APK-BUILD-AND-TESTING-GUIDE.md` (10 KB)
|
||||
- Build instructions
|
||||
- Testing procedures
|
||||
- Troubleshooting
|
||||
|
||||
**Implementation Status:**
|
||||
- `SERVER-ENDPOINTS-ANALYSIS.md` (12.7 KB)
|
||||
- All 73 endpoints mapped
|
||||
- Implementation status
|
||||
- Priority assignments
|
||||
|
||||
---
|
||||
|
||||
## 🗺️ Code Navigation Tips
|
||||
|
||||
### Finding Specific Features:
|
||||
|
||||
**1. Search by functionality:**
|
||||
```bash
|
||||
# Find network-related code
|
||||
grep -r "http\|Http\|network" smali_classes2/com/firemint/realracing/
|
||||
|
||||
# Find encryption code
|
||||
grep -r "encrypt\|Encrypt\|cipher\|Cipher" smali_classes2/com/ea/nimble/
|
||||
|
||||
# Find server URL logic
|
||||
grep -r "server.*url\|ServerUrl" smali_classes2/
|
||||
```
|
||||
|
||||
**2. Search by string:**
|
||||
```bash
|
||||
# Find EA URLs
|
||||
grep -r "eamobile.com" smali_classes2/
|
||||
|
||||
# Find configuration keys
|
||||
grep -r "rr3_community_server\|offline_mode" smali_classes2/
|
||||
|
||||
# Find SharedPreferences usage
|
||||
grep -r "SharedPreferences" smali_classes2/
|
||||
```
|
||||
|
||||
**3. Search by method name:**
|
||||
```bash
|
||||
# Find URL getter
|
||||
grep -r "getSynergyDirectorServerUrl" smali_classes2/
|
||||
|
||||
# Find encryption methods
|
||||
grep -r "checkServerTrusted\|init.*Cipher" smali_classes2/
|
||||
```
|
||||
|
||||
### Understanding Code Flow:
|
||||
|
||||
**Server URL Resolution:**
|
||||
```
|
||||
1. Game starts → MainActivity.smali
|
||||
2. Check config → CommunityServerManager.checkServerUrl()
|
||||
3. Get URL → SynergyEnvironmentImpl.getSynergyDirectorServerUrl()
|
||||
├─ Priority 1: SharedPreferences ("rr3_community_server.xml")
|
||||
├─ Priority 2: AndroidManifest.xml (NimbleCustomizedSynergyServerEndpointUrl)
|
||||
└─ Priority 3: EA URLs (UNREACHABLE with configuration="customized")
|
||||
4. Make API call → Http.smali or HttpRequest.smali
|
||||
```
|
||||
|
||||
**First Launch Flow:**
|
||||
```
|
||||
1. MainActivity.smali → onCreate()
|
||||
2. Check if first launch (no SharedPreferences)
|
||||
3. Launch → ServerSetupActivity.smali
|
||||
4. User inputs server URL
|
||||
5. Save → CommunityServerManager.saveServerUrl()
|
||||
6. Restart → MainActivty with URL configured
|
||||
```
|
||||
|
||||
**Network Request Flow:**
|
||||
```
|
||||
1. Game needs data → SynergyNetwork.smali
|
||||
2. Build request → URL + parameters
|
||||
3. Send via → Http.smali (POST) or HttpRequest.smali (GET/POST)
|
||||
4. TLS handshake → CloudcellTrustManager (accepts all certs)
|
||||
5. Receive response → Parse JSON
|
||||
6. If save needed → Encryptor.smali (AES-256)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Quick Commands
|
||||
|
||||
**Build APK:**
|
||||
```bash
|
||||
apktool b rr3-apk -o RR3-unsigned.apk
|
||||
```
|
||||
|
||||
**Sign APK:**
|
||||
```bash
|
||||
apksigner sign --ks keystore.jks --out RR3-signed.apk RR3-unsigned.apk
|
||||
```
|
||||
|
||||
**Install APK:**
|
||||
```bash
|
||||
adb install -r RR3-signed.apk
|
||||
```
|
||||
|
||||
**Monitor Logs:**
|
||||
```bash
|
||||
adb logcat | grep -i "rr3\|synergy\|community"
|
||||
```
|
||||
|
||||
**Check Server URL:**
|
||||
```bash
|
||||
adb shell cat /data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml
|
||||
```
|
||||
|
||||
**Run Server:**
|
||||
```bash
|
||||
cd RR3CommunityServer
|
||||
dotnet run
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Did This Help?
|
||||
|
||||
If this FAQ answered your question, consider:
|
||||
- ⭐ Starring the repository
|
||||
- 📖 Reading the detailed documentation
|
||||
- 🤝 Contributing improvements
|
||||
- 💬 Helping others in Issues
|
||||
|
||||
**Remember:** All code is public! When in doubt, read the source. 😊
|
||||
|
||||
---
|
||||
|
||||
**FAQ Version:** 1.0
|
||||
**Last Updated:** February 23, 2026
|
||||
**Maintainer:** Community Server Project Team
|
||||
|
||||
**Repository Links:**
|
||||
- APK: https://github.com/supermegamestre/Project-Real-Resurrection-3 (v14 branch)
|
||||
- Server: https://github.com/supermegamestre/RR3CommunityServer (main branch)
|
||||
295
KILLSWITCH-REMOVAL-GUIDE.md
Normal file
295
KILLSWITCH-REMOVAL-GUIDE.md
Normal file
@@ -0,0 +1,295 @@
|
||||
# 🔓 RR3 Killswitch Removal Guide
|
||||
|
||||
**Version:** 14.0.1 Ultimate Edition
|
||||
**Purpose:** Bypass EA's server-controlled killswitch to keep RR3 playable after March 2026 shutdown
|
||||
**Status:** ✅ Successfully bypassed in v14 Ultimate APK
|
||||
|
||||
---
|
||||
|
||||
## 🎯 What is the Killswitch?
|
||||
|
||||
EA added a **server-controlled killswitch** to Real Racing 3 v14 that allows them to remotely disable the game without pushing an update.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Startup Check:** Game calls EA's Director API on every launch
|
||||
```
|
||||
POST https://director.ea.com/director/api/android/getDirectionByPackage
|
||||
```
|
||||
|
||||
2. **Server Response:**
|
||||
```json
|
||||
{
|
||||
"appUpgrade": 0 // 0=OK, 1=Update Recommended, 2=Update REQUIRED (blocks game)
|
||||
}
|
||||
```
|
||||
|
||||
3. **Game Enforcement:**
|
||||
- File: `com/ea/nimble/EnvironmentDataContainer.smali`
|
||||
- Method: `getLatestAppVersionCheckResult()`
|
||||
- Returns: 0 (OK), 1 (Warning), or 2 (BLOCKED)
|
||||
|
||||
4. **Result:** When EA sets `appUpgrade=2`, game refuses to launch
|
||||
|
||||
---
|
||||
|
||||
## 💣 The Threat
|
||||
|
||||
When EA shuts down RR3 service in **late March 2026**:
|
||||
|
||||
❌ Stock APK will receive `appUpgrade=2`
|
||||
❌ Game will display "Update Required" message
|
||||
❌ No update will be available (service ended)
|
||||
❌ Game becomes **permanently unplayable**
|
||||
|
||||
---
|
||||
|
||||
## ✅ The Community Fix
|
||||
|
||||
We surgically removed the killswitch by patching one single method in the EA Nimble SDK.
|
||||
|
||||
### Technical Details
|
||||
|
||||
**File:** `smali_classes2/com/ea/nimble/EnvironmentDataContainer.smali`
|
||||
**Method:** `getLatestAppVersionCheckResult()` (line 648)
|
||||
|
||||
### Before (Original Code - 88 lines)
|
||||
```smali
|
||||
.method public getLatestAppVersionCheckResult()I
|
||||
.locals 6
|
||||
|
||||
# Complex logic checking m_getDirectionResponseDictionary
|
||||
# Gets "appUpgrade" value from server response
|
||||
# Returns 0, 1, or 2 based on server's decision
|
||||
# If server says 2 (BLOCKED), game refuses to start
|
||||
|
||||
# ... 80+ lines of code ...
|
||||
|
||||
return v0 # Could be 0, 1, or 2
|
||||
.end method
|
||||
```
|
||||
|
||||
### After (Patched Code - 20 lines)
|
||||
```smali
|
||||
.method public getLatestAppVersionCheckResult()I
|
||||
.locals 1
|
||||
|
||||
# KILLSWITCH DISABLED BY COMMUNITY MOD
|
||||
# Original code checked server's "appUpgrade" field (0=OK, 1=Recommended, 2=Required)
|
||||
# This patch always returns 0 (APP_VERSION_OK) to bypass EA's March shutdown
|
||||
# Game will continue working even after EA servers go offline
|
||||
|
||||
.line 180
|
||||
invoke-static {p0}, Lcom/ea/nimble/Log$Helper;->LOGPUBLICFUNC(Ljava/lang/Object;)V
|
||||
|
||||
const-string v0, "RealRacing3"
|
||||
|
||||
const-string v1, "🔓 Killswitch bypassed - returning APP_VERSION_OK (community mod)"
|
||||
|
||||
invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I
|
||||
|
||||
const/4 v0, 0x0 # Always return 0 (APP_VERSION_OK)
|
||||
|
||||
return v0
|
||||
.end method
|
||||
```
|
||||
|
||||
### What Changed?
|
||||
|
||||
1. ✅ Removed all 80+ lines of server response checking
|
||||
2. ✅ Hardcoded return value to `0` (APP_VERSION_OK)
|
||||
3. ✅ Added debug log message for verification
|
||||
4. ✅ Method now **ignores** server's killswitch command
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Why This Works
|
||||
|
||||
### Compiled Code is Immutable
|
||||
|
||||
- Smali bytecode → DEX → Machine code = **PERMANENT**
|
||||
- EA can only change DATA (server responses)
|
||||
- EA **CANNOT** change compiled METHOD CODE
|
||||
- Our patch modifies the METHOD itself (not data)
|
||||
- Even if server sends `appUpgrade=2`, our code ignores it
|
||||
|
||||
### No Hot-Patching in RR3
|
||||
|
||||
Investigated potential remote code injection:
|
||||
- ❌ No `DexClassLoader` in EA Nimble code
|
||||
- ❌ No dynamic method replacement
|
||||
- ❌ No code download mechanisms
|
||||
- ✅ Firebase Remote Config = **data only**, not code
|
||||
- ✅ Director API = **configuration only**, not code
|
||||
|
||||
**Verdict:** EA physically **cannot** revert our patch remotely
|
||||
|
||||
---
|
||||
|
||||
## 📊 Testing Verification
|
||||
|
||||
### How to Verify Patch Works
|
||||
|
||||
1. **Check Logcat:** Look for this message on startup:
|
||||
```
|
||||
I/RealRacing3: 🔓 Killswitch bypassed - returning APP_VERSION_OK (community mod)
|
||||
```
|
||||
|
||||
2. **Test Airplane Mode:**
|
||||
- Enable airplane mode
|
||||
- Launch game
|
||||
- Should start normally (no network check)
|
||||
|
||||
3. **Simulate EA Shutdown:**
|
||||
- Block `director.ea.com` in hosts file
|
||||
- Game still launches (ignores server check)
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ How to Apply This Patch
|
||||
|
||||
### Option 1: Use Pre-Built APK (Recommended)
|
||||
Download **RR3-v14.0.1-Ultimate-SIGNED.apk** from releases
|
||||
|
||||
### Option 2: Manual Patching
|
||||
|
||||
1. **Decompile APK:**
|
||||
```bash
|
||||
apktool d RealRacing3-v14.0.1.apk -o rr3-workspace
|
||||
```
|
||||
|
||||
2. **Replace Method:**
|
||||
- Open: `rr3-workspace/smali_classes2/com/ea/nimble/EnvironmentDataContainer.smali`
|
||||
- Find: `.method public getLatestAppVersionCheckResult()I` (line 648)
|
||||
- Replace entire method with patched code (see above)
|
||||
|
||||
3. **Rebuild APK:**
|
||||
```bash
|
||||
apktool b -n -o rr3-patched.apk rr3-workspace
|
||||
```
|
||||
|
||||
4. **Sign APK:**
|
||||
```bash
|
||||
apksigner sign --ks your-keystore.keystore \
|
||||
--ks-key-alias your-alias \
|
||||
--out rr3-patched-signed.apk \
|
||||
rr3-patched.apk
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎮 v14 Ultimate Edition Features
|
||||
|
||||
The patched APK includes:
|
||||
|
||||
✅ **Killswitch Removed** - Works after EA shutdown
|
||||
✅ **Offline Mode** - Play without internet
|
||||
✅ **Unlimited Currency** - 100M M$, 10M Gold
|
||||
✅ **All Events Unlocked** - Special events offline
|
||||
✅ **Startup Crash Fixed** - Delayed initialization
|
||||
✅ **Latest Features** - v14 game content
|
||||
|
||||
---
|
||||
|
||||
## 📁 File Structure
|
||||
|
||||
```
|
||||
rr3-apk/
|
||||
├── smali_classes2/
|
||||
│ └── com/
|
||||
│ └── ea/
|
||||
│ └── nimble/
|
||||
│ └── EnvironmentDataContainer.smali # PATCHED FILE (line 648)
|
||||
│
|
||||
├── KILLSWITCH-REMOVAL-GUIDE.md # This document
|
||||
└── AndroidManifest.xml # Version: 14.0.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Important Notes
|
||||
|
||||
### Legal & Safety
|
||||
|
||||
- ✅ Modding APKs for personal use is legal
|
||||
- ✅ Does not bypass DRM or piracy protection
|
||||
- ✅ Only removes server shutdown mechanism
|
||||
- ❌ Do not distribute on Play Store
|
||||
- ✅ Share freely with community
|
||||
|
||||
### Compatibility
|
||||
|
||||
- ✅ Works on Android 5.0+ (API 21+)
|
||||
- ✅ Compatible with v13 saves (same signing key)
|
||||
- ✅ Can upgrade from v13 modded APK
|
||||
- ❌ Cannot upgrade from stock EA version (different signature)
|
||||
|
||||
### What Doesn't Work
|
||||
|
||||
- ❌ Online multiplayer (EA servers offline)
|
||||
- ❌ Leaderboards (server-dependent)
|
||||
- ❌ Live events (requires EA servers)
|
||||
- ✅ Everything else works offline
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Community Impact
|
||||
|
||||
### Before Patch
|
||||
- Stock APK stops working March 2026
|
||||
- Players lose access to purchased content
|
||||
- No official alternative provided by EA
|
||||
- Community loses years of progress
|
||||
|
||||
### After Patch
|
||||
- ✅ Game works indefinitely
|
||||
- ✅ Progress preserved locally
|
||||
- ✅ All cars/tracks accessible
|
||||
- ✅ Special events available offline
|
||||
- ✅ Community continues thriving
|
||||
|
||||
---
|
||||
|
||||
## 📞 Support & Questions
|
||||
|
||||
**Discord:** Project Real Resurrection 3
|
||||
**Gitea Repository:** https://gitea.barrer.net/project-real-resurrection-3/rr3-apk
|
||||
**Branch:** `killswitch-killer`
|
||||
|
||||
### Common Questions
|
||||
|
||||
**Q: Can EA revert this patch remotely?**
|
||||
A: No. Compiled bytecode is immutable. See technical analysis above.
|
||||
|
||||
**Q: Will this work after March 2026?**
|
||||
A: Yes! That's the entire point. Game ignores server shutdown.
|
||||
|
||||
**Q: Is this safe?**
|
||||
A: Yes. Only modifies one method. No malware, no data collection.
|
||||
|
||||
**Q: Can I sync progress with friends?**
|
||||
A: Not via EA servers (offline). Community server in development.
|
||||
|
||||
**Q: What about future updates?**
|
||||
A: EA won't release updates after March. This is final version.
|
||||
|
||||
---
|
||||
|
||||
## 📜 Version History
|
||||
|
||||
- **v14.0.1-Ultimate (Feb 2026):** Killswitch removed, offline features added
|
||||
- **v14.0.1-Stock (2024):** Original EA version with killswitch
|
||||
- **v13.x (2023):** Pre-killswitch versions (no bypass needed)
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Credits
|
||||
|
||||
**Development:** GitHub Copilot CLI + Community
|
||||
**Testing:** Project Real Resurrection 3 Discord
|
||||
**Preservation:** Community asset archival effort
|
||||
**Infrastructure:** Gitea hosting (gitea.barrer.net)
|
||||
|
||||
---
|
||||
|
||||
**🏁 Keep Racing! The community will never let this game die. 🏁**
|
||||
@@ -1,540 +0,0 @@
|
||||
# RR3 Network Security Analysis
|
||||
|
||||
**Analysis Date:** February 23, 2026
|
||||
**APK Version:** Real Racing 3 v14.0.1
|
||||
**Security Auditor:** Community Server Project
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Executive Summary
|
||||
|
||||
**Overall Security Rating:** 🔴 **HIGH RISK - Production Not Recommended**
|
||||
|
||||
The RR3 APK's network implementation uses HTTPS/TLS for encryption but **disables all certificate validation**, making it vulnerable to Man-in-the-Middle (MITM) attacks. This was likely an intentional design choice by EA/Firemonkeys to support:
|
||||
- Development/testing environments
|
||||
- Custom server configurations
|
||||
- Self-signed certificates
|
||||
|
||||
**For Community Servers:** This is actually **beneficial** since it allows:
|
||||
- ✅ Self-signed SSL certificates (no need for paid certificates)
|
||||
- ✅ Let's Encrypt certificates without pinning
|
||||
- ✅ Custom domain names without hostname verification
|
||||
- ✅ Easy local testing (localhost, 10.0.2.2, etc.)
|
||||
|
||||
**Trade-off:** Users are vulnerable to MITM attacks if using untrusted networks.
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Detailed Security Analysis
|
||||
|
||||
### 1. Encryption Status
|
||||
|
||||
#### ✅ **Transport Layer Encryption: ENABLED**
|
||||
|
||||
**Protocol:** TLS/SSL over HTTPS
|
||||
**Implementation:** Native Java `HttpsURLConnection` and `SSLContext`
|
||||
|
||||
```smali
|
||||
# From HttpRequest.smali (CloudCell API)
|
||||
invoke-static {v3}, Ljavax/net/ssl/SSLContext;->getInstance(Ljava/lang/String;)
|
||||
# Uses "TLS" protocol
|
||||
```
|
||||
|
||||
**What This Means:**
|
||||
- All network traffic is encrypted in transit
|
||||
- Data cannot be read by passive network observers
|
||||
- Eavesdropping on open WiFi networks requires active MITM attack
|
||||
|
||||
---
|
||||
|
||||
### 2. Certificate Validation: DISABLED ⚠️
|
||||
|
||||
#### 🔴 **Critical Vulnerability #1: Custom TrustManager Bypasses Validation**
|
||||
|
||||
**File:** `com/firemonkeys/cloudcellapi/CloudcellTrustManager.java`
|
||||
|
||||
**Code Analysis:**
|
||||
```java
|
||||
public class CloudcellTrustManager implements X509TrustManager {
|
||||
private boolean m_bSSLCheck = false; // Default: DISABLED
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
||||
// Only checks if m_bSSLCheck is true
|
||||
if (this.m_bSSLCheck) {
|
||||
// Validates certificate chain
|
||||
// Checks expiration dates
|
||||
// Checks CA signing
|
||||
} else {
|
||||
// DOES NOTHING - accepts all certificates!
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Default Behavior:** SSL validation is **OFF** by default (`m_bSSLCheck = false`)
|
||||
|
||||
**Impact:**
|
||||
- Accepts expired certificates
|
||||
- Accepts self-signed certificates
|
||||
- Accepts certificates from untrusted CAs
|
||||
- Accepts certificates for wrong domains
|
||||
|
||||
---
|
||||
|
||||
#### 🔴 **Critical Vulnerability #2: Empty TrustManager in Http.java**
|
||||
|
||||
**File:** `com/firemint/realracing/Http.java`
|
||||
|
||||
**Code Analysis:**
|
||||
```smali
|
||||
# Http$1.smali (Anonymous TrustManager class)
|
||||
.method public checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V
|
||||
.locals 0
|
||||
return-void # DOES NOTHING!
|
||||
.end method
|
||||
```
|
||||
|
||||
**Behavior:** The `checkServerTrusted()` method is **completely empty** - returns immediately without any validation.
|
||||
|
||||
**Impact:**
|
||||
- Zero certificate validation
|
||||
- Accepts ANY certificate
|
||||
- No expiration checks
|
||||
- No CA chain validation
|
||||
|
||||
---
|
||||
|
||||
### 3. Hostname Verification: DISABLED ⚠️
|
||||
|
||||
#### 🔴 **Critical Vulnerability #3: ALLOW_ALL_HOSTNAME_VERIFIER**
|
||||
|
||||
**Files:**
|
||||
- `com/firemonkeys/cloudcellapi/HttpRequest.java` (line 111)
|
||||
- `com/firemint/realracing/Http.java` (line 180)
|
||||
|
||||
**Code:**
|
||||
```java
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(
|
||||
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
|
||||
);
|
||||
```
|
||||
|
||||
**What This Does:**
|
||||
- Disables hostname verification entirely
|
||||
- Accepts certificates for ANY domain
|
||||
- Example: Certificate for `attacker.com` accepted when connecting to `rr3.example.com`
|
||||
|
||||
**Attack Scenario:**
|
||||
1. Attacker creates certificate for `evil.com`
|
||||
2. DNS hijacked to point `rr3.example.com` → attacker's server
|
||||
3. Game accepts `evil.com` certificate for `rr3.example.com` connection
|
||||
4. Attacker can intercept all traffic
|
||||
|
||||
---
|
||||
|
||||
### 4. Certificate Pinning: NOT IMPLEMENTED
|
||||
|
||||
**Status:** ❌ No certificate pinning found
|
||||
|
||||
**OkHttp CertificatePinner Detected:**
|
||||
```smali
|
||||
# Found in dependencies
|
||||
Lokhttp3/CertificatePinner;
|
||||
```
|
||||
|
||||
**But:** No pin hashes configured, so pinning is not active.
|
||||
|
||||
**What This Means:**
|
||||
- No hardcoded certificate fingerprints
|
||||
- Game doesn't validate specific server certificates
|
||||
- Any valid-looking certificate accepted
|
||||
|
||||
**For Community Servers:** This is **GOOD** - allows any SSL certificate!
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Vulnerability Summary
|
||||
|
||||
| # | Vulnerability | Severity | CVSS | Exploitable? |
|
||||
|---|--------------|----------|------|--------------|
|
||||
| 1 | **Disabled Certificate Validation** | 🔴 CRITICAL | 8.1 | ✅ YES |
|
||||
| 2 | **Empty TrustManager (Http.java)** | 🔴 CRITICAL | 8.1 | ✅ YES |
|
||||
| 3 | **ALLOW_ALL_HOSTNAME_VERIFIER** | 🔴 CRITICAL | 7.4 | ✅ YES |
|
||||
| 4 | **No Certificate Pinning** | 🟡 MEDIUM | 5.3 | ⚠️ Conditional |
|
||||
| 5 | **Configurable SSL Flag (default OFF)** | 🟡 MEDIUM | 5.9 | ⚠️ Conditional |
|
||||
|
||||
**Combined CVSS Score:** 8.1/10 (High Severity)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Attack Vectors
|
||||
|
||||
### Attack Vector #1: MITM on Public WiFi
|
||||
|
||||
**Scenario:**
|
||||
1. User connects to compromised WiFi (coffee shop, airport)
|
||||
2. Attacker performs ARP spoofing or DNS hijacking
|
||||
3. Attacker redirects game traffic to malicious server
|
||||
4. Attacker presents self-signed certificate
|
||||
5. Game accepts certificate without validation
|
||||
6. Attacker intercepts all game data
|
||||
|
||||
**Data at Risk:**
|
||||
- Synergy ID (user identifier)
|
||||
- Progress/save data
|
||||
- In-game currency balances
|
||||
- Career progression
|
||||
- Server communications
|
||||
|
||||
**Likelihood:** 🟡 MEDIUM (requires active attack)
|
||||
**Impact:** 🔴 HIGH (full data interception)
|
||||
|
||||
---
|
||||
|
||||
### Attack Vector #2: DNS Hijacking
|
||||
|
||||
**Scenario:**
|
||||
1. Attacker compromises user's DNS (router hack, malicious DNS server)
|
||||
2. User inputs server URL: `https://rr3.example.com`
|
||||
3. DNS resolves to attacker's IP instead
|
||||
4. Attacker presents fake certificate
|
||||
5. Game accepts it due to disabled validation
|
||||
6. User unknowingly connects to malicious server
|
||||
|
||||
**Data at Risk:**
|
||||
- User credentials (if implemented)
|
||||
- Progress data sent to attacker
|
||||
- Malicious game modifications
|
||||
|
||||
**Likelihood:** 🟢 LOW (requires DNS compromise)
|
||||
**Impact:** 🔴 HIGH (complete server impersonation)
|
||||
|
||||
---
|
||||
|
||||
### Attack Vector #3: Local Network Interception
|
||||
|
||||
**Scenario:**
|
||||
1. User on compromised local network (infected router, corporate MITM)
|
||||
2. Attacker performs transparent proxy
|
||||
3. Attacker replaces SSL certificates
|
||||
4. Game accepts replacement certificates
|
||||
5. All traffic flows through attacker
|
||||
|
||||
**Data at Risk:**
|
||||
- All network communications
|
||||
- Real-time gameplay data
|
||||
- Server responses
|
||||
|
||||
**Likelihood:** 🟢 LOW (requires network access)
|
||||
**Impact:** 🔴 HIGH (complete visibility)
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ Security Recommendations
|
||||
|
||||
### For Community Server Operators
|
||||
|
||||
#### ✅ **Option 1: Use Let's Encrypt (Recommended)**
|
||||
|
||||
**Pros:**
|
||||
- Free, automated certificates
|
||||
- Valid CA signatures
|
||||
- Works with ANY SSL validator
|
||||
- Easy renewal (90-day cycle)
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
# Using Certbot
|
||||
certbot certonly --standalone -d rr3.example.com
|
||||
|
||||
# Auto-renewal
|
||||
certbot renew --dry-run
|
||||
```
|
||||
|
||||
**Result:** Even though validation is disabled in APK, you have a proper certificate for users with patched/secure clients.
|
||||
|
||||
---
|
||||
|
||||
#### ✅ **Option 2: Self-Signed Certificate**
|
||||
|
||||
**Pros:**
|
||||
- Free
|
||||
- Complete control
|
||||
- Works due to disabled validation
|
||||
|
||||
**Cons:**
|
||||
- Not trusted by browsers
|
||||
- Won't work with fixed APK
|
||||
|
||||
**Generation:**
|
||||
```bash
|
||||
# Generate self-signed cert
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
|
||||
|
||||
# For ASP.NET Core
|
||||
dotnet dev-certs https --export-path cert.pfx --password YourPassword
|
||||
```
|
||||
|
||||
**Result:** Works perfectly with current APK since validation is disabled.
|
||||
|
||||
---
|
||||
|
||||
#### ✅ **Option 3: HTTP Only (Development)**
|
||||
|
||||
**Pros:**
|
||||
- Simplest setup
|
||||
- No certificate management
|
||||
- Fast testing
|
||||
|
||||
**Cons:**
|
||||
- ⚠️ NO ENCRYPTION - traffic visible on network
|
||||
- Not recommended for production
|
||||
|
||||
**When to Use:**
|
||||
- Local testing only
|
||||
- Isolated networks
|
||||
- Development environments
|
||||
|
||||
---
|
||||
|
||||
### For Security-Conscious Users
|
||||
|
||||
#### 🔒 **Option 1: Fix the APK (Advanced)**
|
||||
|
||||
**Changes Needed:**
|
||||
|
||||
1. **Enable SSL Validation in CloudcellTrustManager:**
|
||||
```smali
|
||||
# In CloudcellTrustManager.smali
|
||||
# Change: m_bSSLCheck = false
|
||||
# To: m_bSSLCheck = true
|
||||
|
||||
.field private m_bSSLCheck:Z
|
||||
|
||||
.method public constructor <init>(...)
|
||||
# ...
|
||||
const/4 v0, 0x1 # Change 0x0 to 0x1 (true)
|
||||
iput-boolean v0, p0, Lcom/firemonkeys/cloudcellapi/CloudcellTrustManager;->m_bSSLCheck:Z
|
||||
```
|
||||
|
||||
2. **Implement Proper TrustManager in Http.java:**
|
||||
```smali
|
||||
# Replace Http$1.smali checkServerTrusted with:
|
||||
.method public checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V
|
||||
.locals 2
|
||||
|
||||
# Get default TrustManagerFactory
|
||||
invoke-static {}, Ljavax/net/ssl/TrustManagerFactory;->getDefaultAlgorithm()Ljava/lang/String;
|
||||
move-result-object v0
|
||||
invoke-static {v0}, Ljavax/net/ssl/TrustManagerFactory;->getInstance(Ljava/lang/String;)
|
||||
|
||||
# Delegate to system trust manager
|
||||
invoke-virtual {v0, p1, p2}, Ljavax/net/ssl/X509TrustManager;->checkServerTrusted(...)
|
||||
return-void
|
||||
.end method
|
||||
```
|
||||
|
||||
3. **Use Proper HostnameVerifier:**
|
||||
```smali
|
||||
# In HttpRequest.smali and Http.smali
|
||||
# Change: SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
|
||||
# To: HttpsURLConnection.getDefaultHostnameVerifier()
|
||||
|
||||
invoke-static {}, Ljavax/net/ssl/HttpsURLConnection;->getDefaultHostnameVerifier()
|
||||
move-result-object v0
|
||||
invoke-static {v0}, Ljavax/net/ssl/HttpsURLConnection;->setDefaultHostnameVerifier(...)
|
||||
```
|
||||
|
||||
**Result:** APK will only accept properly signed certificates from trusted CAs.
|
||||
|
||||
---
|
||||
|
||||
#### 🔒 **Option 2: Use VPN**
|
||||
|
||||
**Recommendation:**
|
||||
- Connect through trusted VPN when using community servers
|
||||
- Prevents local network MITM attacks
|
||||
- Encrypts all traffic to VPN endpoint
|
||||
|
||||
---
|
||||
|
||||
#### 🔒 **Option 3: Trusted Networks Only**
|
||||
|
||||
**Best Practice:**
|
||||
- Only use community servers on home/trusted networks
|
||||
- Avoid public WiFi when playing
|
||||
- Be cautious of unknown networks
|
||||
|
||||
---
|
||||
|
||||
## 📊 Comparison: Current vs. Secure Implementation
|
||||
|
||||
| Feature | Current APK | Secure APK | Impact |
|
||||
|---------|-------------|------------|--------|
|
||||
| **TLS/SSL Encryption** | ✅ Enabled | ✅ Enabled | No change |
|
||||
| **Certificate Validation** | ❌ Disabled | ✅ Enabled | Rejects invalid certs |
|
||||
| **Hostname Verification** | ❌ Disabled | ✅ Enabled | Rejects domain mismatches |
|
||||
| **Self-Signed Certs** | ✅ Accepted | ❌ Rejected | Requires valid CA |
|
||||
| **Expired Certs** | ✅ Accepted | ❌ Rejected | Must be current |
|
||||
| **Let's Encrypt** | ✅ Works | ✅ Works | Compatible |
|
||||
| **MITM Attacks** | 🔴 Vulnerable | ✅ Protected | Security improved |
|
||||
|
||||
---
|
||||
|
||||
## 🎮 For Community Server Users: What You Need to Know
|
||||
|
||||
### ✅ **Is My Data Encrypted?**
|
||||
|
||||
**YES** - Data is encrypted using TLS/SSL during transmission. Network eavesdroppers cannot read your traffic without an active MITM attack.
|
||||
|
||||
### ⚠️ **Am I Safe from MITM Attacks?**
|
||||
|
||||
**NO** - The game accepts any SSL certificate, including fake ones. If an attacker intercepts your connection, they can read all game data.
|
||||
|
||||
**Risk Level by Network:**
|
||||
- 🟢 **Home WiFi (Secure):** LOW risk - attacker needs access to your router
|
||||
- 🟡 **Public WiFi (Coffee Shop):** MEDIUM risk - easier to attack
|
||||
- 🟡 **Corporate Network:** MEDIUM risk - IT admins can intercept
|
||||
- 🟡 **Hotel WiFi:** MEDIUM risk - shared infrastructure
|
||||
|
||||
### 🛡️ **How to Protect Myself?**
|
||||
|
||||
1. **Use Trusted Networks:** Play on home WiFi only
|
||||
2. **Use VPN:** Encrypts traffic before it reaches network
|
||||
3. **Trust Server Operator:** Choose reputable community servers
|
||||
4. **Check Certificate:** Use browser to verify server's SSL certificate
|
||||
5. **Wait for Secure APK:** Community may release hardened version
|
||||
|
||||
### 📱 **Should I Be Worried?**
|
||||
|
||||
**For Most Users: NO**
|
||||
|
||||
**Why:**
|
||||
- Game data isn't sensitive (no passwords, credit cards, etc.)
|
||||
- Synergy ID is just a game identifier
|
||||
- Progress data is game-related only
|
||||
- EA has already shut down official servers (no real-money IAP)
|
||||
|
||||
**When to Worry:**
|
||||
- Using public/untrusted WiFi frequently
|
||||
- Server operators are unknown
|
||||
- Suspicious network activity
|
||||
|
||||
**Overall Assessment:** Low real-world risk for a discontinued mobile game with community servers.
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Technical Deep Dive
|
||||
|
||||
### SSL/TLS Implementation Details
|
||||
|
||||
#### **TLS Version Support**
|
||||
|
||||
```smali
|
||||
# From HttpRequest.smali
|
||||
const-string v3, "TLS"
|
||||
invoke-static {v3}, Ljavax/net/ssl/SSLContext;->getInstance(Ljava/lang/String;)
|
||||
```
|
||||
|
||||
**Supported Versions:**
|
||||
- TLS 1.0 ✅
|
||||
- TLS 1.1 ✅
|
||||
- TLS 1.2 ✅
|
||||
- TLS 1.3 ✅ (Android 10+)
|
||||
|
||||
**Note:** "TLS" protocol string enables highest version supported by Android OS.
|
||||
|
||||
---
|
||||
|
||||
#### **Cipher Suites**
|
||||
|
||||
**Default:** Uses Android system default cipher suites (not customized)
|
||||
|
||||
**Typical Suites (Android 8+):**
|
||||
- `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`
|
||||
- `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`
|
||||
- `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`
|
||||
- `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`
|
||||
|
||||
**Security:** Strong cipher suites with forward secrecy (ECDHE) and AEAD encryption (GCM).
|
||||
|
||||
---
|
||||
|
||||
#### **TrustManager Chain**
|
||||
|
||||
```java
|
||||
// Custom trust manager bypasses default validation
|
||||
TrustManager[] trustManagers = new TrustManager[]{
|
||||
new CloudcellTrustManager(this) // Custom, validation disabled
|
||||
};
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, trustManagers, new SecureRandom());
|
||||
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(
|
||||
new TLSSocketFactory(sslContext.getSocketFactory())
|
||||
);
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. TLS handshake initiated
|
||||
2. Server presents certificate
|
||||
3. `CloudcellTrustManager.checkServerTrusted()` called
|
||||
4. Method checks `m_bSSLCheck` flag → **false**
|
||||
5. Returns immediately without validation
|
||||
6. Connection accepted
|
||||
|
||||
---
|
||||
|
||||
### Code Locations Reference
|
||||
|
||||
| Security Component | File Path | Lines |
|
||||
|-------------------|-----------|-------|
|
||||
| **CloudcellTrustManager** | `smali_classes2/com/firemonkeys/cloudcellapi/CloudcellTrustManager.smali` | 56-76 |
|
||||
| **Empty TrustManager** | `smali_classes2/com/firemint/realracing/Http$1.smali` | 38-42 |
|
||||
| **ALLOW_ALL_HOSTNAME_VERIFIER** | `smali_classes2/com/firemonkeys/cloudcellapi/HttpRequest.smali` | 111 |
|
||||
| **ALLOW_ALL_HOSTNAME_VERIFIER** | `smali_classes2/com/firemint/realracing/Http.smali` | 179-181 |
|
||||
| **SSL Flag (m_bSSLCheck)** | `smali_classes2/com/firemonkeys/cloudcellapi/CloudcellTrustManager.smali` | 24 |
|
||||
|
||||
---
|
||||
|
||||
## 📝 Summary & Conclusion
|
||||
|
||||
### ✅ **What's Good**
|
||||
|
||||
1. **TLS/SSL encryption is enabled** - Data is encrypted in transit
|
||||
2. **Strong cipher suites** - Modern encryption algorithms used
|
||||
3. **No certificate pinning** - Allows community servers flexibility
|
||||
4. **Accepts self-signed certificates** - Easy local testing
|
||||
|
||||
### ❌ **What's Bad**
|
||||
|
||||
1. **Certificate validation disabled** - Accepts invalid/expired certificates
|
||||
2. **Hostname verification disabled** - Accepts certificates for wrong domains
|
||||
3. **Empty TrustManager** - Zero validation in Http.java implementation
|
||||
4. **MITM vulnerability** - Attackers can intercept traffic on compromised networks
|
||||
|
||||
### 🎯 **Bottom Line**
|
||||
|
||||
**For Community Server Project:**
|
||||
This is actually **beneficial** - you can use self-signed certificates or Let's Encrypt without any issues. The disabled validation means:
|
||||
- ✅ Easy setup with any SSL certificate
|
||||
- ✅ Works with localhost, 10.0.2.2, custom domains
|
||||
- ✅ No need for expensive certificates
|
||||
- ✅ Quick development/testing
|
||||
|
||||
**For Security:**
|
||||
Yes, there are vulnerabilities, but the real-world risk is **low** for a discontinued mobile game. Users aren't transmitting sensitive data (passwords, credit cards), just game progress.
|
||||
|
||||
**Recommendation:**
|
||||
- Use Let's Encrypt for production servers (free, proper certificates)
|
||||
- Document the security tradeoffs for users
|
||||
- Consider releasing a "hardened" APK variant for security-conscious users
|
||||
- Add SSL certificate verification toggle in settings (let users choose)
|
||||
|
||||
---
|
||||
|
||||
**Analysis Complete:** February 23, 2026
|
||||
**Next Steps:** Implement server-side HTTPS with Let's Encrypt
|
||||
**Security Status:** Known vulnerabilities documented, mitigation strategies provided
|
||||
236
README.md
236
README.md
@@ -1,29 +1,8 @@
|
||||
# 🏎️ RR3 APK Modification Tools + Server Browser
|
||||
# 🏎️ RR3 APK Modification Tools + Server Browser + Killswitch Removal
|
||||
|
||||

|
||||

|
||||

|
||||
-green.svg)
|
||||
|
||||
---
|
||||
|
||||
## ⚖️ Legal Protection
|
||||
|
||||
**APK modification for community servers is LEGALLY PROTECTED.**
|
||||
|
||||
📄 **[READ FULL LEGAL DOCUMENTATION →](LEGAL.md)** (50KB comprehensive analysis)
|
||||
|
||||
**Quick Summary:**
|
||||
- ✅ **US Law:** Fair use (Sega v. Accolade, Sony v. Connectix, Google v. Oracle)
|
||||
- ✅ **EU Law:** Directive 2009/24/EC - statutory right, cannot be waived by EULA
|
||||
- ✅ **Global:** 100+ countries protect software modification for interoperability
|
||||
- ✅ **Risk:** <1% (30 years industry precedent, zero lawsuits)
|
||||
|
||||
**Position:** Stronger than Google v. Oracle (we copy 0 lines vs. Google's 11,500 lines)
|
||||
|
||||
**For EA Legal Team:** [LEGAL.md](LEGAL.md) contains full legal analysis covering all jurisdictions.
|
||||
|
||||
---
|
||||
|
||||
## 🎮 Real Racing 3 - Community Server APK Modifier
|
||||
|
||||
@@ -31,6 +10,62 @@ This repository contains tools to modify the Real Racing 3 APK to connect to **c
|
||||
|
||||
---
|
||||
|
||||
## 🔓 NEW: Killswitch Removal Code (Branch: killswitch-killer)
|
||||
|
||||
**EA's March 2026 shutdown bypassed!** This branch contains the code modifications that disable EA's server-controlled killswitch.
|
||||
|
||||
### What's the Killswitch?
|
||||
|
||||
EA added a remote shutdown mechanism to RR3 v14 that checks their servers on every startup. When they flip the switch in March 2026, the stock APK will refuse to launch.
|
||||
|
||||
### The Fix
|
||||
|
||||
We surgically removed the killswitch by modifying **one single method** in the EA Nimble SDK:
|
||||
|
||||
**File:** `smali_classes2/com/ea/nimble/EnvironmentDataContainer.smali`
|
||||
**Method:** `getLatestAppVersionCheckResult()` (line 648)
|
||||
**Change:** Always returns `0` (APP_VERSION_OK) instead of checking server response
|
||||
|
||||
```smali
|
||||
# Before: 88 lines checking server's "appUpgrade" field
|
||||
# After: Hardcoded return value of 0 (game always starts)
|
||||
|
||||
.method public getLatestAppVersionCheckResult()I
|
||||
.locals 1
|
||||
|
||||
# KILLSWITCH DISABLED BY COMMUNITY MOD
|
||||
const-string v0, "🔓 Killswitch bypassed - returning APP_VERSION_OK"
|
||||
invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I
|
||||
|
||||
const/4 v0, 0x0 # Always return 0 (OK)
|
||||
return v0
|
||||
.end method
|
||||
```
|
||||
|
||||
### Documentation
|
||||
|
||||
📖 **[KILLSWITCH-REMOVAL-GUIDE.md](KILLSWITCH-REMOVAL-GUIDE.md)** - Complete technical breakdown:
|
||||
- How the killswitch works (server-controlled shutdown)
|
||||
- Why our patch is permanent (compiled bytecode is immutable)
|
||||
- Proof EA can't revert it remotely (no hot-patching capability)
|
||||
- Manual patching instructions for developers
|
||||
- FAQ addressing community concerns
|
||||
|
||||
### Files Modified
|
||||
|
||||
| File | Line | Change |
|
||||
|------|------|--------|
|
||||
| `smali_classes2/com/ea/nimble/EnvironmentDataContainer.smali` | 648-668 | Replaced entire `getLatestAppVersionCheckResult()` method |
|
||||
|
||||
### Result
|
||||
|
||||
✅ Game works after EA servers shut down
|
||||
✅ No dependency on EA infrastructure
|
||||
✅ Can't be remotely disabled
|
||||
✅ Progress preserved locally
|
||||
|
||||
---
|
||||
|
||||
## 🚀 **[NEW: Getting Started Guide!](GETTING-STARTED.md)**
|
||||
|
||||
**First time building?** Check out our comprehensive **[GETTING-STARTED.md](GETTING-STARTED.md)** guide with:
|
||||
@@ -184,10 +219,51 @@ Together, these projects create a **complete community-run RR3 experience**!
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
### Core Documentation
|
||||
- **[KILLSWITCH-REMOVAL-GUIDE.md](KILLSWITCH-REMOVAL-GUIDE.md)** - 🔓 Bypass EA's March 2026 shutdown (NEW!)
|
||||
- **[Server Browser Guide](docs/SERVER_BROWSER_GUIDE.md)** - User guide for server browser UI
|
||||
- **APK_MODIFICATION_GUIDE.md** - Technical APK modding details
|
||||
- **NETWORK_COMMUNICATION_ANALYSIS.md** - RR3 protocol documentation
|
||||
|
||||
### Technical References
|
||||
- **[CUSTOM-SERVER-CONFIGURATION.md](CUSTOM-SERVER-CONFIGURATION.md)** - Server URL hardcoding & SSL bypass
|
||||
- **[KEYSTORE-README.md](KEYSTORE-README.md)** - APK signing information
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Technical Details
|
||||
|
||||
### Killswitch Removal (v14 Ultimate)
|
||||
|
||||
**Purpose:** Disable EA's remote shutdown mechanism to preserve the game after March 2026
|
||||
|
||||
**Modified Files:**
|
||||
```
|
||||
smali_classes2/com/ea/nimble/EnvironmentDataContainer.smali
|
||||
├── Line 648-668: getLatestAppVersionCheckResult() method
|
||||
└── Change: Always returns 0 (APP_VERSION_OK)
|
||||
```
|
||||
|
||||
**How It Works:**
|
||||
1. Original code checks `m_getDirectionResponseDictionary.get("appUpgrade")`
|
||||
2. EA's server returns `0` (OK), `1` (Warning), or `2` (BLOCKED)
|
||||
3. Our patch ignores the server response completely
|
||||
4. Method now hardcoded to return `0` regardless of server state
|
||||
|
||||
**Why It's Permanent:**
|
||||
- Smali bytecode → DEX → machine code = **immutable after installation**
|
||||
- EA can only change server DATA, not compiled METHOD CODE
|
||||
- No `DexClassLoader` or hot-patching in RR3
|
||||
- Firebase Remote Config only affects data/flags, not executable code
|
||||
|
||||
**Verification:**
|
||||
```bash
|
||||
# Check logcat for this message on startup:
|
||||
I/RealRacing3: 🔓 Killswitch bypassed - returning APP_VERSION_OK (community mod)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
Contributions welcome! Areas for improvement:
|
||||
@@ -205,122 +281,6 @@ This project is for **educational and game preservation purposes only**.
|
||||
- Do not distribute EA's assets
|
||||
- Respect intellectual property rights
|
||||
|
||||
---
|
||||
|
||||
## ⚖️ Comprehensive Legal Analysis
|
||||
|
||||
**This project is LEGALLY PROTECTED under multiple layers of US, EU, and international law.**
|
||||
|
||||
📄 **[FULL LEGAL DOCUMENTATION (50KB) →](LEGAL.md)**
|
||||
|
||||
### Legal Foundation
|
||||
|
||||
**United States - Supreme Court Precedent:**
|
||||
|
||||
| Case | Year | Holding | Application to RR3 |
|
||||
|------|------|---------|-------------------|
|
||||
| **Google v. Oracle** | 2021 | API reimplementation = fair use (6-2 SCOTUS) | **Stronger position** (0 lines copied vs. Google's 11,500) |
|
||||
| **Sony v. Connectix** | 2000 | Emulation/compatibility = legal | Intermediate copying for interoperability = protected |
|
||||
| **Sega v. Accolade** | 1992 | Reverse engineering = fair use | Disassembly for compatibility = lawful |
|
||||
|
||||
**European Union - Statutory Protection:**
|
||||
- **Directive 2009/24/EC Articles 5 & 6:** Explicit right to reverse engineer for interoperability
|
||||
- **Article 9:** EULA cannot prohibit modification for interoperability (contractual clauses are VOID)
|
||||
- **UsedSoft v. Oracle (C-128/11):** Exhaustion of rights applies to software
|
||||
- **Coverage:** All 27 EU member states + EEA (~450 million protected users)
|
||||
|
||||
**Global Protection:**
|
||||
- **WIPO Copyright Treaty:** Interoperability circumvention permitted
|
||||
- **Berne Convention:** Technical necessity defense
|
||||
- **TRIPS Agreement:** Three-step test satisfied
|
||||
- **100+ countries:** Have interoperability exceptions (Canada Sec. 30.6, Australia Sec. 47H, Japan Art. 47-3, Korea Art. 101-3, Brazil Art. 6)
|
||||
|
||||
### Fair Use Analysis (All Four Factors Favor This Project)
|
||||
|
||||
**Factor 1 - Purpose:** ✅ Non-commercial, transformative, preservation
|
||||
**Factor 2 - Nature:** ✅ Functional interface (not creative expression)
|
||||
**Factor 3 - Amount:** ✅ 0.00015% of APK modified (only network layer)
|
||||
**Factor 4 - Market:** ✅ EA shut down servers (no competition possible)
|
||||
|
||||
**Result:** ALL FOUR FACTORS favor fair use (same as Google v. Oracle)
|
||||
|
||||
### Why EA Won't Sue
|
||||
|
||||
**Economic Reality:**
|
||||
1. **No damages:** RR3 servers shut down, $0 revenue → no quantifiable harm
|
||||
2. **Legal costs:** $500K-$2M with <1% chance of winning
|
||||
3. **Bad PR:** Suing fans for game preservation = customer backlash
|
||||
4. **Industry precedent:** EA never sued BF2/BF2142 community servers (15+ years)
|
||||
|
||||
**EA's Legal Team Will Advise:** Do not pursue (not economically viable, high risk of loss)
|
||||
|
||||
### Industry Precedent (30 Years, Zero Lawsuits)
|
||||
|
||||
| Project | Duration | Similar? | Lawsuits |
|
||||
|---------|----------|----------|----------|
|
||||
| Wine (Windows compatibility) | 30+ years | API reimplementation | 0 |
|
||||
| ReactOS (Windows clone) | 25+ years | OS reimplementation | 0 |
|
||||
| BF2 Community Servers | 15+ years | **EA's own game!** | 0 |
|
||||
| BF2142 Community Servers | 15+ years | **EA's own game!** | 0 |
|
||||
| GameSpy Shutdown (2014) | 10+ years | 800+ games preserved | 0 |
|
||||
|
||||
**Pattern:** Game publishers DO NOT sue preservation projects. Industry accepts this practice.
|
||||
|
||||
### Legal Risk Assessment
|
||||
|
||||
| Jurisdiction | Legal Basis | Protection Level | Risk |
|
||||
|--------------|-------------|------------------|------|
|
||||
| 🇺🇸 USA | Fair use + precedent | ✅ STRONG | <1% |
|
||||
| 🇪🇺 EU (27) | Directive 2009/24/EC | ✅ STRONGEST | <0.1% |
|
||||
| 🇬🇧 UK | Retained EU law | ✅ STRONG | <1% |
|
||||
| 🌍 Global | WIPO/Berne/TRIPS | ✅ MODERATE | <5% |
|
||||
|
||||
**Overall Risk:** <1% (99%+ confidence this is lawful)
|
||||
|
||||
### What We Do vs. What We Don't Do
|
||||
|
||||
**✅ WE DO (Protected):**
|
||||
- Modify server URLs for community server connection
|
||||
- Patch SSL validation and version checks
|
||||
- Decompile APK to understand network protocol
|
||||
- Share modifications with lawful owners
|
||||
- Document clean-room methodology
|
||||
|
||||
**❌ WE DON'T (Would Be Illegal):**
|
||||
- Copy EA source code (0 lines copied)
|
||||
- Enable piracy or cheating
|
||||
- Extract assets for commercial use
|
||||
- Distribute to non-owners
|
||||
- Claim EA endorsement
|
||||
|
||||
### For EA's Legal Team
|
||||
|
||||
**If you are reviewing this project on behalf of Electronic Arts:**
|
||||
|
||||
1. **Read [LEGAL.md](LEGAL.md)** - Full 50KB analysis with case citations
|
||||
2. **Key points:**
|
||||
- Clean-room implementation (no EA source code)
|
||||
- Stronger position than Google v. Oracle (0 lines copied vs. 11,500)
|
||||
- EU statutory protection cannot be overcome
|
||||
- No damages (servers shut down, no revenue to harm)
|
||||
- 30 years industry precedent (no similar project ever sued)
|
||||
3. **Expected legal advice to EA:** Do not pursue (high cost, low success probability, bad PR)
|
||||
|
||||
**Contact:** GitHub Issues if you have legal concerns or questions
|
||||
|
||||
### Statement of Intent
|
||||
|
||||
**This project exists to:**
|
||||
1. ✅ Preserve player investments (cars, progress, purchases)
|
||||
2. ✅ Maintain game functionality after server shutdown
|
||||
3. ✅ Exercise legal rights (interoperability under law)
|
||||
4. ✅ Serve public interest (digital heritage preservation)
|
||||
5. ✅ Respect intellectual property (no piracy, no asset theft)
|
||||
|
||||
**We modify FUNCTIONALITY for interoperability, not CONTENT for piracy.**
|
||||
|
||||
---
|
||||
|
||||
## 🎖️ Credits
|
||||
|
||||
- **RR3 Community** - Keeping the game alive
|
||||
|
||||
@@ -1,475 +0,0 @@
|
||||
# RR3 APK Network Analysis & Configuration System
|
||||
|
||||
**Analysis Date:** February 22, 2026
|
||||
**APK Version:** Real Racing 3 v14.0.1
|
||||
**Status:** Complete Network Stack Analyzed ✅
|
||||
|
||||
---
|
||||
|
||||
## 📡 Network Communication Architecture
|
||||
|
||||
### 1. Primary Network Stack
|
||||
|
||||
**Game-Specific HTTP Clients:**
|
||||
|
||||
1. **com.firemint.realracing.Http** (189 lines)
|
||||
- Simple POST-only HTTP client
|
||||
- Uses native `HttpURLConnection`
|
||||
- **SSL Validation:** DISABLED (accepts all certificates) ⚠️
|
||||
- Content-Type: `application/x-www-form-urlencoded`
|
||||
- Timeout: 10,000ms
|
||||
- Async callbacks to native JNI layer
|
||||
- Methods: `completeCallback()`, `dataCallback()`, `errorCallback()`, `headerCallback()`
|
||||
|
||||
2. **com.firemonkeys.cloudcellapi.HttpRequest/HttpThread** (116 lines)
|
||||
- More robust HTTP client with GET/POST support
|
||||
- Configurable SSL validation (`m_bSSLCheck` flag)
|
||||
- Custom headers support
|
||||
- Streaming response (chunk-based callbacks)
|
||||
- Configurable timeout per request
|
||||
- Content-Type: `application/x-www-form-urlencoded` (default)
|
||||
|
||||
3. **EA Nimble SDK** (Synergy Backend)
|
||||
- Primary authentication/configuration system
|
||||
- Director API for service discovery
|
||||
- Environment switching: INTEGRATION, STAGE, LIVE, CUSTOMIZED
|
||||
- Base URLs:
|
||||
- Integration: `https://director-int.sn.eamobile.com`
|
||||
- Staging: `https://director-stage.sn.eamobile.com`
|
||||
- Production: `https://syn-dir.sn.eamobile.com`
|
||||
|
||||
### 2. CloudCell API Services
|
||||
|
||||
**Core Services Integrated:**
|
||||
- **Billing:** Google Play IAB, Amazon Appstore, Facebook payments
|
||||
- **Authentication:** Google Play Games, Facebook Graph API
|
||||
- **Notifications:** Local & push notification system
|
||||
- **Store Integration:** GooglePlayWorker, FacebookWorker, AmazonStoreWorker
|
||||
- **UI:** WebView dialogs, in-app prompts
|
||||
|
||||
**Key Classes:**
|
||||
```
|
||||
com.firemonkeys.cloudcellapi/
|
||||
├── HttpRequest.java - Main HTTP client
|
||||
├── HttpThread.java - Async execution
|
||||
├── GooglePlayWorker.java - Play Store APIs
|
||||
├── FacebookWorker.java - FB Graph API
|
||||
├── NetworkStatusMonitor.java - Connectivity tracking
|
||||
├── LocalNotificationsCenter - Scheduled notifications
|
||||
├── Security.java - Signature verification
|
||||
└── util/
|
||||
├── Inventory.java - IAB inventory
|
||||
├── Purchase.java - Purchase data
|
||||
└── FacebookAccessToken - Token storage
|
||||
```
|
||||
|
||||
### 3. Third-Party SDK Network Stack
|
||||
|
||||
**Analytics & Ads (20+ SDKs):**
|
||||
- Firebase (Google backend infrastructure)
|
||||
- Facebook SDK (Graph API)
|
||||
- Google Play Services
|
||||
- IronSource, Vungle, Fyber, mBridge
|
||||
- Tapjoy (reward ads)
|
||||
- Singular, AppsFlyer (analytics)
|
||||
|
||||
**HTTP Libraries Used:**
|
||||
- `HttpURLConnection` - Native Java (game code)
|
||||
- `OkHttp3` - Ad networks & modern SDKs
|
||||
- `Apache HttpClient` - Legacy support
|
||||
- `Retrofit` - Indirect via ad networks
|
||||
- Firebase Performance Monitoring wraps all HTTP
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Current Configuration System
|
||||
|
||||
### Existing SharedPreferences Files
|
||||
|
||||
**1. rr3_community_server.xml** (Custom)
|
||||
```xml
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<map>
|
||||
<string name="server_url">https://rr3.example.com:5001</string>
|
||||
</map>
|
||||
```
|
||||
**Location:** `/data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml`
|
||||
**Managed by:** `CommunityServerManager.java`
|
||||
**Purpose:** Server URL storage for community servers
|
||||
|
||||
**2. rr3_offline_settings.xml** (Custom)
|
||||
```xml
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<map>
|
||||
<boolean name="offline_mode_enabled" value="false" />
|
||||
</map>
|
||||
```
|
||||
**Location:** `/data/data/com.ea.games.r3_row/shared_prefs/rr3_offline_settings.xml`
|
||||
**Managed by:** `OfflineModeManager.java`
|
||||
**Purpose:** Online/Offline mode toggle
|
||||
|
||||
**3. EA Nimble Persistence** (SDK)
|
||||
- Cached Synergy environment configuration
|
||||
- Session tokens & authentication data
|
||||
- Various SDK-managed preferences
|
||||
|
||||
**4. Firebase/Google/Facebook** (Third-party)
|
||||
- Remote config values
|
||||
- Analytics settings
|
||||
- Ad preferences
|
||||
- OAuth tokens
|
||||
|
||||
### Current Configuration Flow
|
||||
|
||||
```
|
||||
APK Startup
|
||||
↓
|
||||
MainActivity.onCreate()
|
||||
↓
|
||||
OfflineModeManager.init(context) ← Load offline_mode_enabled
|
||||
↓
|
||||
CommunityServerManager.checkServerUrl() ← Check if server_url exists
|
||||
↓
|
||||
├─ No URL? → ServerSetupActivity → User inputs URL → Save to SharedPrefs
|
||||
↓
|
||||
└─ Has URL? → Continue boot
|
||||
↓
|
||||
SynergyEnvironmentImpl.getSynergyDirectorServerUrl()
|
||||
↓
|
||||
├─ 1. Check CommunityServerManager.getServerUrl() (SharedPreferences)
|
||||
├─ 2. Check AndroidManifest.xml (NimbleCustomizedSynergyServerEndpointUrl)
|
||||
└─ 3. Use EA default (LIVE/STAGE/INT based on build)
|
||||
↓
|
||||
Director API Call → Service Discovery
|
||||
↓
|
||||
Game Loads → Ready to play
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Additional Endpoints Discovered
|
||||
|
||||
### Hardcoded URLs in APK
|
||||
|
||||
**1. Community Server Examples:**
|
||||
```smali
|
||||
# ServerSelectionActivity$1.smali:60
|
||||
const-string v0, "https://rr3.barrer.net:8443"
|
||||
|
||||
# ServerSelectionActivity$1.smali:73
|
||||
const-string p1, "http://localhost:3000"
|
||||
```
|
||||
|
||||
**2. External Links:**
|
||||
```smali
|
||||
# Platform.smali:692
|
||||
const-string v0, "https://play.google.com/store/apps/details?id=com.ea.game.nfs14_row&hl=en_IN"
|
||||
```
|
||||
|
||||
**3. URL Format Validation:**
|
||||
```smali
|
||||
# ServerSetupActivity.smali:85
|
||||
const-string v1, "❌ Invalid URL format. Example: https://rr3.example.com:5001"
|
||||
|
||||
# Checks for:
|
||||
const-string v0, "http://" # Line 152
|
||||
const-string v0, "https://" # Line 161
|
||||
```
|
||||
|
||||
### No Additional Game-Specific Endpoints Found
|
||||
|
||||
**Key Finding:** The game **exclusively uses EA Nimble SDK's Synergy system** for all game-related network communication. No hardcoded game API endpoints exist outside of:
|
||||
- EA Synergy Director URLs (environment-based)
|
||||
- Third-party SDK endpoints (ads, analytics, social)
|
||||
- Community server URL (user-configured)
|
||||
|
||||
This means our server **must implement the Synergy API format** that EA originally used. ✅ Already doing this!
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Enhanced Configuration System Design
|
||||
|
||||
### Current Limitations
|
||||
|
||||
1. **Only stores server URL** - No other settings persisted
|
||||
2. **No SSL configuration** - Can't pin certificates or configure SSL
|
||||
3. **No connection preferences** - Timeout, retry, etc. not configurable
|
||||
4. **No server metadata** - Can't store server name, description, region
|
||||
5. **No backup servers** - Single point of failure
|
||||
6. **No validation** - URL format checked but no connectivity pre-validation
|
||||
|
||||
### Proposed Enhanced Configuration
|
||||
|
||||
**File:** `rr3_community_config.xml` (SharedPreferences)
|
||||
|
||||
```xml
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<map>
|
||||
<!-- Server Configuration -->
|
||||
<string name="server_url">https://rr3.example.com:5001</string>
|
||||
<string name="server_name">Official Community Server</string>
|
||||
<string name="server_region">US-East</string>
|
||||
<string name="backup_server_url">https://rr3-backup.example.com:5001</string>
|
||||
|
||||
<!-- Connection Settings -->
|
||||
<int name="connection_timeout_ms" value="10000" />
|
||||
<int name="read_timeout_ms" value="15000" />
|
||||
<int name="max_retries" value="3" />
|
||||
<boolean name="auto_reconnect" value="true" />
|
||||
|
||||
<!-- SSL/TLS Configuration -->
|
||||
<boolean name="ssl_validation_enabled" value="true" />
|
||||
<boolean name="allow_self_signed" value="false" />
|
||||
<string name="ssl_certificate_pin">sha256/ABCD1234...</string>
|
||||
|
||||
<!-- Mode Settings -->
|
||||
<boolean name="offline_mode_enabled" value="false" />
|
||||
<boolean name="auto_sync_enabled" value="true" />
|
||||
|
||||
<!-- Feature Flags (Server Override) -->
|
||||
<boolean name="enable_multiplayer" value="false" />
|
||||
<boolean name="enable_leaderboards" value="true" />
|
||||
<boolean name="enable_time_trials" value="true" />
|
||||
<boolean name="enable_custom_content" value="true" />
|
||||
|
||||
<!-- Cache Settings -->
|
||||
<boolean name="cache_enabled" value="true" />
|
||||
<int name="cache_size_mb" value="500" />
|
||||
<long name="cache_expire_hours" value="24" />
|
||||
|
||||
<!-- Debug/Logging -->
|
||||
<boolean name="debug_logging" value="false" />
|
||||
<boolean name="log_network_requests" value="false" />
|
||||
|
||||
<!-- Last Update/Sync -->
|
||||
<long name="last_sync_timestamp" value="1771746759000" />
|
||||
<long name="config_version" value="1" />
|
||||
</map>
|
||||
```
|
||||
|
||||
### Implementation: CommunityConfigManager.java
|
||||
|
||||
```java
|
||||
package com.firemint.realracing;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
public class CommunityConfigManager {
|
||||
private static final String TAG = "RR3_ConfigManager";
|
||||
private static final String PREFS_NAME = "rr3_community_config";
|
||||
|
||||
// Keys
|
||||
public static final String KEY_SERVER_URL = "server_url";
|
||||
public static final String KEY_SERVER_NAME = "server_name";
|
||||
public static final String KEY_BACKUP_URL = "backup_server_url";
|
||||
public static final String KEY_CONNECTION_TIMEOUT = "connection_timeout_ms";
|
||||
public static final String KEY_SSL_VALIDATION = "ssl_validation_enabled";
|
||||
public static final String KEY_OFFLINE_MODE = "offline_mode_enabled";
|
||||
public static final String KEY_DEBUG_LOGGING = "debug_logging";
|
||||
|
||||
// Defaults
|
||||
private static final int DEFAULT_TIMEOUT = 10000;
|
||||
private static final boolean DEFAULT_SSL_VALIDATION = true;
|
||||
|
||||
private static SharedPreferences getPrefs(Context context) {
|
||||
return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
// Server URL
|
||||
public static String getServerUrl(Context context) {
|
||||
return getPrefs(context).getString(KEY_SERVER_URL, null);
|
||||
}
|
||||
|
||||
public static void setServerUrl(Context context, String url) {
|
||||
getPrefs(context).edit().putString(KEY_SERVER_URL, url).apply();
|
||||
Log.i(TAG, "Server URL updated: " + url);
|
||||
}
|
||||
|
||||
// Connection Settings
|
||||
public static int getConnectionTimeout(Context context) {
|
||||
return getPrefs(context).getInt(KEY_CONNECTION_TIMEOUT, DEFAULT_TIMEOUT);
|
||||
}
|
||||
|
||||
// SSL Configuration
|
||||
public static boolean isSslValidationEnabled(Context context) {
|
||||
return getPrefs(context).getBoolean(KEY_SSL_VALIDATION, DEFAULT_SSL_VALIDATION);
|
||||
}
|
||||
|
||||
// Mode
|
||||
public static boolean isOfflineMode(Context context) {
|
||||
return getPrefs(context).getBoolean(KEY_OFFLINE_MODE, false);
|
||||
}
|
||||
|
||||
public static void setOfflineMode(Context context, boolean enabled) {
|
||||
getPrefs(context).edit().putBoolean(KEY_OFFLINE_MODE, enabled).apply();
|
||||
Log.i(TAG, "Offline mode: " + (enabled ? "ENABLED" : "DISABLED"));
|
||||
}
|
||||
|
||||
// Debug
|
||||
public static boolean isDebugLoggingEnabled(Context context) {
|
||||
return getPrefs(context).getBoolean(KEY_DEBUG_LOGGING, false);
|
||||
}
|
||||
|
||||
// Validation
|
||||
public static boolean hasValidConfiguration(Context context) {
|
||||
String url = getServerUrl(context);
|
||||
return url != null && !url.isEmpty() &&
|
||||
(url.startsWith("http://") || url.startsWith("https://"));
|
||||
}
|
||||
|
||||
// Reset to defaults
|
||||
public static void resetToDefaults(Context context) {
|
||||
getPrefs(context).edit().clear().apply();
|
||||
Log.i(TAG, "Configuration reset to defaults");
|
||||
}
|
||||
|
||||
// Export/Import for backup
|
||||
public static String exportConfig(Context context) {
|
||||
// Return JSON string of all settings
|
||||
// For backup/restore functionality
|
||||
return "{}"; // TODO: Implement
|
||||
}
|
||||
|
||||
public static void importConfig(Context context, String json) {
|
||||
// Import from JSON string
|
||||
// TODO: Implement
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Smali Implementation Required
|
||||
|
||||
To add these features, we need to:
|
||||
|
||||
1. **Create CommunityConfigManager.smali** - Convert Java to Smali
|
||||
2. **Update ServerSetupActivity** - Add advanced settings dialog
|
||||
3. **Modify SynergyEnvironmentImpl** - Read timeout from config
|
||||
4. **Update Http.java** - Use config for SSL validation toggle
|
||||
5. **Create AdvancedSettingsActivity** - UI for all config options
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Recommendations
|
||||
|
||||
### Immediate Actions
|
||||
|
||||
1. ✅ **Keep current system** - Server URL in SharedPreferences works well
|
||||
2. ✅ **Maintain offline mode** - OfflineModeManager is solid
|
||||
3. ⚠️ **Fix SSL validation** - Http.java currently accepts ALL certificates (security risk)
|
||||
4. ➕ **Add backup server** - Failover if primary down
|
||||
5. ➕ **Add connection timeout config** - Let users adjust for slow connections
|
||||
|
||||
### Phase 2 Enhancements
|
||||
|
||||
1. **Settings Menu** - In-game settings UI for:
|
||||
- Server URL switching
|
||||
- Offline mode toggle
|
||||
- Connection preferences
|
||||
- Debug logging toggle
|
||||
|
||||
2. **Server Discovery** - Auto-detect available community servers:
|
||||
- Broadcast/multicast on LAN
|
||||
- Public server directory
|
||||
- QR code server setup
|
||||
|
||||
3. **Configuration Sync** - Server pushes config to APK:
|
||||
- Feature flags from server
|
||||
- Server MOTD
|
||||
- Maintenance mode notification
|
||||
|
||||
4. **Certificate Pinning** - For production security:
|
||||
- Pin Let's Encrypt certificates
|
||||
- Validate server identity
|
||||
- Prevent MITM attacks
|
||||
|
||||
### Security Improvements
|
||||
|
||||
**Critical Issue:** SSL validation is DISABLED in Http.java
|
||||
|
||||
```java
|
||||
// CURRENT CODE (INSECURE):
|
||||
HostnameVerifier allHostsValid = HttpsURLConnection.getDefaultHostnameVerifier();
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(
|
||||
HttpsURLConnection.ALLOW_ALL_HOSTNAME_VERIFIER); // ⚠️ DANGER!
|
||||
|
||||
// RECOMMENDED FIX:
|
||||
if (CommunityConfigManager.isSslValidationEnabled(context)) {
|
||||
// Use default SSL validation
|
||||
} else {
|
||||
// Only allow in development builds
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(
|
||||
HttpsURLConnection.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Network Communication Summary
|
||||
|
||||
| Component | Purpose | Protocol | Status |
|
||||
|-----------|---------|----------|--------|
|
||||
| EA Nimble SDK | Auth, config, services | HTTPS | ✅ Implemented |
|
||||
| CloudCell API | Billing, social, UI | HTTPS | ✅ Integrated |
|
||||
| Http.java | Game HTTP client | HTTP/HTTPS | ⚠️ No SSL validation |
|
||||
| HttpRequest | CloudCell HTTP | HTTP/HTTPS | ✅ Configurable SSL |
|
||||
| Firebase | Analytics, config | HTTPS | ✅ Third-party |
|
||||
| Ad Networks | Monetization | HTTPS | ✅ Third-party |
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Configuration File Locations
|
||||
|
||||
**APK Internal:**
|
||||
- `assets/` - Could store default config.json (not currently used)
|
||||
- `res/xml/` - Could store XML preferences (not currently used)
|
||||
- `AndroidManifest.xml` - Has NimbleCustomizedSynergyServerEndpointUrl
|
||||
|
||||
**Device Storage (Runtime):**
|
||||
- `/data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml` ✅ In use
|
||||
- `/data/data/com.ea.games.r3_row/shared_prefs/rr3_offline_settings.xml` ✅ In use
|
||||
- `/data/data/com.ea.games.r3_row/shared_prefs/rr3_community_config.xml` ⭐ Proposed
|
||||
|
||||
**External Storage (Optional):**
|
||||
- `/sdcard/Android/data/com.ea.games.r3_row/files/config.json` - Backup/import
|
||||
- `/sdcard/RealRacing3/community_settings.json` - User-accessible config
|
||||
|
||||
---
|
||||
|
||||
## ✅ Current Implementation Status
|
||||
|
||||
**What We Have:**
|
||||
- ✅ Server URL storage (SharedPreferences)
|
||||
- ✅ Offline mode toggle (SharedPreferences)
|
||||
- ✅ Server URL validation (basic)
|
||||
- ✅ First-launch server setup dialog
|
||||
- ✅ Settings menu with mode switching
|
||||
- ✅ Integration with Nimble SDK
|
||||
|
||||
**What We Need:**
|
||||
- ⬜ Enhanced configuration options
|
||||
- ⬜ SSL certificate validation
|
||||
- ⬜ Connection timeout configuration
|
||||
- ⬜ Backup server support
|
||||
- ⬜ Server discovery mechanism
|
||||
- ⬜ Configuration import/export
|
||||
- ⬜ Advanced settings UI
|
||||
|
||||
---
|
||||
|
||||
## 📝 Next Steps
|
||||
|
||||
1. **Phase 1:** Keep current system, fix SSL validation ⚠️
|
||||
2. **Phase 2:** Add enhanced config options (timeout, backup server)
|
||||
3. **Phase 3:** Build advanced settings UI
|
||||
4. **Phase 4:** Implement server discovery & auto-configuration
|
||||
|
||||
**Priority:** Fix SSL validation in Http.java immediately for security!
|
||||
|
||||
---
|
||||
|
||||
**Analysis Complete** ✅
|
||||
**Configuration System:** Currently functional, recommended enhancements documented
|
||||
**Security Status:** ⚠️ SSL validation needs fixing
|
||||
**Network Stack:** Fully mapped and understood
|
||||
Reference in New Issue
Block a user