2023 Business CTF: PAC Breaker
Challenge Information
| Attribute | Details |
|---|---|
| Event | 2023 Business CTF |
| Category | Binary Exploitation (PWN) |
| Challenge | PAC Breaker |
| Difficulty | Hard |
Summary
PAC Breaker is a hard-level binary exploitation challenge where you must infiltrate and disable the Board of Arodor’s Persistent Access Control (PAC) surveillance system. The challenge involves exploiting a target tracking application that manages surveillance targets. Vulnerabilities include file operation bypass techniques and heap corruption through improper buffer management.
Challenge Information
The challenge description states:
“Welcome to Operation PACbreaker, where your skills as a highly trained operative from the United Nations of Zenium are crucial. Your mission is of utmost importance: infiltrate the oppressive surveillance system maintained by the Board of Arodor and bypass their formidable Persistent Access Control (PAC) mechanisms.”
The application is the “Board of Arodor Tracking Server [BETA VERSION - v1.0]” - a target management system for tracking surveillance subjects.
Analysis
Application Architecture
The application (source.c) implements a target tracking database with the following functionality:
struct Target { char target_name[MAX_NAME_LEN]; // 30 bytes char residence_address[MAX_ADDRESS_LEN]; // 50 bytes char contact_number[MAX_CON_LEN]; // 15 bytes};The application supports:
- Initiate Surveillance: Load targets from a file
- Target Acquisition: Add new targets manually
- Exploit: Search/list targets
- Transmit Data: Save all targets to file
- Extract Data: Save specific target to file
- Eliminate Targets: Remove a target from the list
Vulnerability Analysis
Vulnerability 1: File Restriction Bypass
The check_filename() function (lines 76-82) attempts to restrict file operations:
void check_filename(char *file_name){ if (strstr(file_name, "/") || strstr(file_name, "flag") || strstr(file_name, ".")){ printf("That doesn't seem like a target identification code to work with\n"); _exit(0); } return;}Bypass Technique: This validation is case-sensitive and can be bypassed using:
- Alternative path representations
- Uppercase variations (if the filesystem is case-insensitive)
- Encoding techniques
Vulnerability 2: Buffer Overflow in print_target
The print_target() function (lines 37-44) uses write() with fixed sizes:
void print_target(struct Target *p) { printf("Target Name: "); write(1, p->target_name, MAX_NAME_LEN); // Writes 30 bytes printf("Residence Address: "); write(1, p->residence_address, MAX_ADDRESS_LEN); // Writes 50 bytes printf("Contact Number: "); write(1, p->contact_number, MAX_CON_LEN); // Writes 15 bytes}This prints uninitialized or adjacent memory if the strings are not null-terminated.
Vulnerability 3: Heap Corruption in remove_targets
The remove_targets() function (lines 146-159) has a critical vulnerability:
void remove_targets(struct Target *targets, size_t *num_targets){ int choice = 0; printf("Target to remove: "); scanf("%d", &choice);
if (choice > -1 && choice >= *num_targets){ // Line 151: Logic error! printf("Selection is out of Range.\n"); return; }
// Line 156: Incorrect memmove calculation memmove((void*)&targets[choice], (void*)&targets[choice+1], sizeof(struct Target)**num_targets-choice); *num_targets = *num_targets - 1;}Critical Issues:
-
Logic Error (Line 151): The condition
choice > -1 && choice >= *num_targetsallows choice = -1 to bypass the check (signed integer issue) -
memmove Calculation Error (Line 156): The expression is parsed as
sizeof(struct Target) * (*num_targets - choice)when it should besizeof(struct Target) * (*num_targets - choice). However, the operator precedence error causes:sizeof(struct Target) ** num_targets(dereference then multiply)- Then subtract
choice
This results in copying far more memory than intended, causing heap corruption.
Vulnerability 4: Information Disclosure
The save_target_to_file() function writes fixed-size fields:
write(fp, targets[choice].target_name, MAX_NAME_LEN);write(fp, targets[choice].residence_address, MAX_ADDRESS_LEN);write(fp, targets[choice].contact_number, MAX_CON_LEN);This leaks uninitialized memory if fields aren’t properly null-terminated.
Solution
Step 1: Exploit File Restriction Bypass
Create a filename that passes the validation check:
// Valid names (no "/" "flag" or ".")// Examples: "targetdata", "surveillance", "suspects"Step 2: Trigger Heap Corruption
Use the remove_targets function with a negative or edge-case input:
Menu Option: 6 (Eliminate Targets)Target to remove: -1 // Triggers the signed integer bypassThis causes the memmove to corrupt heap metadata.
Step 3: Leverage Memory Corruption
The corrupted heap state can be leveraged to:
- Overwrite function pointers in global structures
- Corrupt allocation metadata
- Achieve arbitrary writes to memory
- Execute shellcode
Step 4: Achieve Code Execution
Through careful heap manipulation:
# Interaction with the application# 1. Add multiple targets to populate heap# 2. Trigger the memmove overflow with negative index# 3. Overwrite adjacent memory structures# 4. Force code execution through corrupted pointersStep 5: Read the Flag
Once code execution is achieved:
cat /flag.txtKey Vulnerabilities Summary
| Vulnerability | Line | Type | Impact |
|---|---|---|---|
| Weak File Validation | 77 | Logic Error | Medium - Bypass |
| Signed Integer Bypass | 151 | Integer Overflow | High - OOB Access |
| memmove Overflow | 156 | Heap Corruption | Critical - RCE |
| Information Disclosure | 39-43 | Memory Leak | Medium |
Key Takeaways
- Input Validation: File restriction checks must be comprehensive and consider encoding variations
- Integer Arithmetic: Be careful with signed/unsigned integer mixing and operator precedence
- Memory Operations: Use safe versions of functions like
memmovewith explicit bounds checking - Fixed-Size Arrays: Avoid fixed-size buffers; use dynamic allocation with explicit length tracking
- Null Termination: Ensure strings are properly null-terminated before printing or copying
- Defense Mechanisms: Implement heap canaries, bounds checking, and ASLR to mitigate heap exploits