September 19, 2026
I Reverse-Engineered a “Color Prediction” Gambling App — The Results Were Suspiciously Non-Random
How APK analysis, API inspection, and statistical testing revealed what was happening behind the interface
By Muhd Shakir
7 min read
How APK analysis, API inspection, and statistical testing revealed what was happening behind the interface
You've probably seen them.
"Win ₹10,000 in 30 seconds!"
"Predict the color and double your money!"
"Join our Telegram group for guaranteed winning signals!"
These "color prediction" platforms are presented as simple games where users predict colors or numbers and receive payouts when their predictions match the result.
As someone interested in cybersecurity and reverse engineering, I wasn't particularly interested in finding a way to win.
I wanted to understand something much more fundamental:
How does the system actually work?
So I started investigating.
What began as APK analysis eventually turned into a combination of:
- Android reverse engineering
- WebView analysis
- API reconnaissance
- Network traffic inspection
- Client-side security analysis
- Historical data collection
- Statistical analysis using Python and SciPy
And the results were… interesting.
1. Starting With the APK
The first step was obtaining the Android APK and examining its structure.
I used:
apktoolapktoolto decompile and inspect the application.
My initial expectation was to find the game's core logic inside the APK.
I was expecting things like:
- Random number generation
- Game logic
- Probability calculations
- Result processing
- Local data storage
- Cryptographic functions
Instead, I found something much simpler.
The application was largely functioning as a WebView wrapper.
In other words, a significant portion of what looked like an Android application was essentially loading a web-based interface.
This changed the direction of the investigation.
If the important logic wasn't inside the APK, then the next place to look was the network.
2. Following the Network Traffic
I moved to the browser/network layer and started observing requests generated while interacting with the application.
The general architecture looked something like this:
┌─────────────────┐
│ User / App │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Frontend │
│ Web / WebView │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Backend API │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Result / Storage│
└─────────────────┘┌─────────────────┐
│ User / App │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Frontend │
│ Web / WebView │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Backend API │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Result / Storage│
└─────────────────┘The important observation was that the client wasn't independently generating the final outcome.
The client communicated with backend infrastructure, and the result was subsequently retrieved and displayed.
The basic flow looked like:
Place Bet
↓
API Request
↓
Server-Side Processing
↓
Round Result
↓
Client Retrieves Result
↓
UI Displays ResultPlace Bet
↓
API Request
↓
Server-Side Processing
↓
Round Result
↓
Client Retrieves Result
↓
UI Displays ResultThat immediately raised a question:
If the server generates the result, what mechanism determines that result?
3. Looking at the API
Once the API requests were identified, I started examining their structure.
The requests contained information associated with things such as:
- User/session information
- Game or round identifiers
- Bet information
- Timestamps
- Request parameters
- Authentication information
- Request signatures
This is where the investigation became more interesting.
The application wasn't simply sending:
"I want to place a bet.""I want to place a bet."There was additional request validation happening.
4. The MD5 Signature
The API used an MD5-based request-signing mechanism.
At first glance, this might look like a security control.
But there's an important security principle here:
A secret that must be available to the client cannot be treated as a truly secret credential.
If a web application needs a secret value in order to calculate a signature, that value has to somehow reach the client.
And if it reaches the client, someone capable of inspecting the client-side code may potentially recover it.
This doesn't automatically mean that the entire API is vulnerable.
It does, however, demonstrate an important architectural weakness:
Client-side obfuscation is not equivalent to server-side secrecy.
Sensitive credentials and signing secrets should generally remain on infrastructure controlled by the server.
5. Looking at Historical Results
At this point, I had a basic understanding of how the application communicated.
But I wanted to investigate something else:
What do the actual historical results look like?
I collected a sample of approximately 500 historical rounds from the accessible data used during the investigation.
I then extracted the numeric outcomes and calculated their frequency.
If the numbers from 0–9 were uniformly random, we would expect approximately:
500 rounds / 10 numbers = 50 occurrences per number500 rounds / 10 numbers = 50 occurrences per numberSo the expected distribution would be roughly:
0 → 50
1 → 50
2 → 50
3 → 50
4 → 50
5 → 50
6 → 50
7 → 50
8 → 50
9 → 500 → 50
1 → 50
2 → 50
3 → 50
4 → 50
5 → 50
6 → 50
7 → 50
8 → 50
9 → 50But the observed data looked very different.
6. The Distribution
The observed distribution was:
NumberExpectedObserved0505015050250035050450505500650150750085050950100
Three numbers — 2, 5 and 7 — never appeared in the sample.
Meanwhile:
6 appeared 150 times.
That's 30% of the entire sample.
And:
9 appeared 100 times.
That's 20%.
The result distribution was therefore dramatically different from what we'd expect from a uniform 0–9 process.
But I didn't want to rely on visual inspection.
I wanted a statistical test.
7. Running a Chi-Square Test
I used Python and SciPy to perform a chi-square goodness-of-fit test.
The basic code was:
from scipy.stats import chisquare
observed = [50, 50, 0, 50, 50, 0, 150, 0, 50, 100]
expected = [50] * 10
chi2, p = chisquare(observed, expected)
print(f"Chi-Square Statistic: {chi2:.2f}")
print(f"P-Value: {p:.10f}")from scipy.stats import chisquare
observed = [50, 50, 0, 50, 50, 0, 150, 0, 50, 100]
expected = [50] * 10
chi2, p = chisquare(observed, expected)
print(f"Chi-Square Statistic: {chi2:.2f}")
print(f"P-Value: {p:.10f}")The purpose of the test was simple:
Null hypothesis: the numbers follow a uniform distribution.
The test compares the observed counts against the expected counts.
The resulting p-value was below the displayed precision of the calculation.
That provides extremely strong statistical evidence that the observed sample is inconsistent with a uniform 0–9 distribution.
8. An Important Statistical Disclaimer
This is where I want to be precise.
A very small p-value does not automatically prove that the application is deliberately rigged.
The statistical test tells us:
The observed distribution is extremely unlikely under the assumption that all ten numbers are equally likely.
It does not, by itself, tell us exactly why the distribution looks this way.
Possible explanations could include:
- A non-uniform random-number generator
- An intentional weighting mechanism
- Server-side business logic
- Risk-control logic
- A bug
- Data-selection bias
- Some other result-generation mechanism
To claim deliberate manipulation, we would need additional evidence showing how the backend actually chooses the result.
That distinction matters.
As a security researcher, the goal isn't simply to find a surprising number and call it fraud.
The goal is to determine what the evidence actually proves.
9. Why This Is Interesting From a Security Perspective
This investigation demonstrates an important concept:
The interface isn't necessarily the system.
A user sees:
🎨 Color Prediction
↓
Place Bet
↓
Wait 30 sec
↓
Result🎨 Color Prediction
↓
Place Bet
↓
Wait 30 sec
↓
ResultBut underneath that interface there may be:
Frontend
↓
API
↓
Authentication
↓
Game State
↓
Result Generation
↓
Database / StorageFrontend
↓
API
↓
Authentication
↓
Game State
↓
Result Generation
↓
Database / StorageThe interesting security questions are therefore not:
"What button should I press?"
They're:
"What request does that button generate?"
"Where does that request go?"
"What does the server return?"
"How is the result generated?"
"Can the client influence any of these values?"
"Does the observed data match the claimed behavior?"
That is the mindset behind application security testing.
10. What About "Prediction Signals"?
Another interesting part of this ecosystem is the large number of social-media and messaging channels claiming to provide "guaranteed predictions."
It's important to distinguish between investigating a particular operation and understanding how prediction scams can work in general.
One possible mechanism is simple survivorship bias.
Imagine a promoter sends:
Group A → BIG
Group B → SMALLGroup A → BIG
Group B → SMALLAfter the result:
One group will potentially receive a correct prediction.
The promoter can then showcase the successful prediction as evidence that the "signal" worked.
Repeat the process over multiple rounds, and users may start believing the promoter has a reliable prediction method.
If the promoter also receives referral commissions or other financial benefits from users continuing to participate, there can be an additional incentive to keep users engaged.
This doesn't prove that every prediction channel operates this way.
But it demonstrates why screenshots of previous "winning signals" are not, by themselves, evidence that someone can consistently predict the underlying game.
11. The Mathematical Problem With Gambling
There's another important point.
Even if a game were genuinely random, the payout structure matters.
Suppose an outcome has a probability of 10%.
A mathematically fair payout would need to reflect that probability.
If the probability is:
10%10%the fair decimal return before considering other costs would be approximately:
10x10xIf a platform instead pays:
9x9xthen the expected value is already negative for the player.
For a simplified example:
Probability of winning = 10%
Payout = 9x
Expected return:
0.10 × 9 = 0.90Probability of winning = 10%
Payout = 9x
Expected return:
0.10 × 9 = 0.90A ₹100 bet would therefore have an expected return of approximately ₹90 under that simplified model.
That's a negative expected value of:
₹10₹10per ₹100 wagered.
The exact economics depend on the game's actual rules and payout structure, but the principle is universal:
Randomness does not automatically make a game fair.
The payout structure matters.
12. What I Learned From the Investigation
This small project reinforced several lessons for me.
1. Don't trust the UI
A polished interface doesn't tell you what is happening underneath.
2. Follow the network
The API often reveals more about an application's architecture than the UI does.
3. Client-side secrets aren't really secrets
If sensitive credentials have to be delivered to an untrusted client, they should be treated accordingly.
4. Data can expose system behavior
Historical data can reveal patterns that aren't obvious from interacting with the application manually.
5. Statistics can support security research
Statistical testing can turn:
"This looks weird."
into:
"This distribution is statistically inconsistent with the expected model."
6. Don't overclaim
Perhaps the most important lesson:
Evidence and interpretation are different things.
Finding an abnormal distribution is evidence.
Proving exactly how the backend generated that distribution requires further investigation.
13. Technical Methodology
The investigation followed roughly this workflow:
APK
↓
Decompilation
↓
Identify WebView / frontend
↓
Map network requests
↓
Identify API endpoints
↓
Inspect request parameters
↓
Analyze authentication/signatures
↓
Collect historical results
↓
Normalize the dataset
↓
Calculate frequency distribution
↓
Run statistical tests
↓
Interpret the resultsAPK
↓
Decompilation
↓
Identify WebView / frontend
↓
Map network requests
↓
Identify API endpoints
↓
Inspect request parameters
↓
Analyze authentication/signatures
↓
Collect historical results
↓
Normalize the dataset
↓
Calculate frequency distribution
↓
Run statistical tests
↓
Interpret the resultsTools used
Kali Linux
apktool
Python 3
Requests
SciPy
jq
Chrome DevTools
Android tooling
Statistical analysisKali Linux
apktool
Python 3
Requests
SciPy
jq
Chrome DevTools
Android tooling
Statistical analysis14. Responsible Disclosure
When conducting this type of research, it's important to avoid turning a security investigation into an attack.
I intentionally avoid publishing:
- Real authentication credentials
- API secrets
- Private user information
- Active session tokens
- Sensitive infrastructure details
- Information that could enable unauthorized access
The goal is to demonstrate the methodology and security lessons, not provide instructions for attacking a live service.
15. Final Thoughts
I started this investigation wondering whether there was a hidden pattern that could be used to predict the next result.
Instead, I ended up asking a much more interesting question:
Can the system's claimed randomness actually be supported by the evidence?
The combination of reverse engineering and statistical analysis provided some surprising results.
The APK showed me where to look.
The network traffic showed me how the components communicated.
The API analysis showed me how requests were structured.
And the statistical analysis showed that the observed distribution was dramatically different from the uniform model I tested.
But the biggest takeaway wasn't about gambling.
It was about cybersecurity.
Don't just look at what an application tells you.
Look at:
what it sends,
what it receives,
where decisions are made,
how data behaves,
and most importantly:
whether the evidence matches the claims.
That's where the real investigation begins.
⚠️ Disclaimer
This article describes an educational security research investigation. The analysis was performed using sanitized information and a test/research environment. The statistical findings describe the dataset analyzed and should not, by themselves, be interpreted as definitive proof of intentional manipulation or fraud.
No real credentials, authentication tokens, or private user information are intentionally disclosed in this article.
The techniques discussed should only be applied to systems you own, have permission to test, or are explicitly authorized to assess.
If you're interested in the technical side of the investigation, I'll be sharing additional details about the Python analysis, API architecture, and statistical methodology in future posts.
#CyberSecurity #EthicalHacking #ReverseEngineering #AndroidSecurity #API #Python #CyberSecurityResearch #WebSecurity #AppSec #InformationSecurity #DataAnalysis