2023 Business CTF: Snow Scan
Challenge Information
| Attribute | Details |
|---|---|
| Event | 2023 Business CTF |
| Category | Binary Exploitation (PWN) |
| Challenge | Snow Scan |
| Difficulty | Very Easy |
Summary
Snow Scan is a very easy level binary exploitation challenge involving a BMP file scanner application. The application analyzes bitmap files looking for a specific 15-byte trigger sequence. The challenge requires crafting a malicious BMP file that bypasses validation checks and triggers code execution or information disclosure.
Challenge Information
The challenge description states:
“In a rapidly unfolding scenario, an ancient Sumerian virus has surfaced, rapidly proliferating and posing a grave threat. Snow Crash, a menacing presence within the metaverse, has ventured beyond virtual realms, unleashing tangible repercussions in real life. In response to this crisis, the Board of Arodor has devised a vital tool—a service designed to meticulously scan and identify potential samples of Snow Crash.”
The service scans BMP files for malicious content signatures.
Analysis
Application Architecture
The application (snowscan.c) implements a BMP file scanner with the following components:
typedef struct { char signature[2]; // "BM" uint32_t fileSize; uint32_t reserved; uint32_t dataOffset; uint32_t headerSize; int32_t width; int32_t height; uint16_t colorPlanes; uint16_t bitsPerPixel; uint32_t compression; uint32_t imageSize; int32_t horizontalResolution; int32_t verticalResolution; uint32_t numColors; uint32_t importantColors;} BMPFile;Vulnerability Analysis
Vulnerability 1: Insufficient Size Validation
The size validation (lines 85-86) is too permissive:
#define MIN_IMGSIZE 400 // 20x20 pixels#define MAX_IMGSIZE 900 // 30x30 pixels
if(bmp->imageSize < MIN_IMGSIZE || bmp->imageSize > MAX_IMGSIZE) error("Invalid bitmap size...");The imageSize field can be manipulated to be within this range without actually containing valid image data.
Vulnerability 2: Stack Buffer Overflow
The pixel buffer is allocated on the stack (line 135):
uint8_t pixelBuf[bmp->imageSize]; // Line 135: VLA - Stack allocation!
int c = 0, i = 0;while((c = fgetc(file)) != EOF) pixelBuf[i++] = (uint8_t)c;By setting imageSize to MAX_IMGSIZE (900), an attacker can overflow the stack with controlled data.
Vulnerability 3: Signature Detection Vulnerability
The trigger detection looks for a specific string (lines 95-102):
#define TRIGGER_SIZE 15uint8_t trigger[] = "3nk1's-n4m-shub";
int sequenceDetected(const uint8_t *arr, uint32_t size) { for(int i=0; i<(size-TRIGGER_SIZE+1); ++i) { if(memcmp(arr+i, trigger, TRIGGER_SIZE) == 0) return 1; } return 0;}The trigger string “3nk1’s-n4m-shub” (15 bytes) can be embedded in the BMP data to trigger a detection or as part of an exploit payload.
Vulnerability 4: Missing File Extension Check
The extension check (lines 124-125) is incorrect:
if(len >= 4 && strcmp(argv[1]+len-4, ".bmp")) error("Invalid file extension...");The strcmp() returns 0 on match, but the condition treats any non-zero return as an error. This check is inverted! It actually rejects files WITH the .bmp extension.
Solution
Step 1: Craft a Malicious BMP File
Create a BMP file with valid headers but malicious pixel data:
import struct
def create_malicious_bmp(): # BMP Header bmp = bytearray()
# File signature bmp += b"BM" # Signature
# File size (small, valid) file_size = 1000 bmp += struct.pack("<I", file_size) # fileSize
# Reserved bmp += struct.pack("<I", 0) # reserved
# Data offset (start of pixel data) bmp += struct.pack("<I", 54) # dataOffset (standard header size)
# DIB Header size bmp += struct.pack("<I", 40) # headerSize
# Dimensions (square, valid range) bmp += struct.pack("<i", 25) # width (25x25 = 625 bytes) bmp += struct.pack("<i", 25) # height
# Color planes bmp += struct.pack("<H", 1) # colorPlanes
# Bits per pixel bmp += struct.pack("<H", 8) # bitsPerPixel
# Compression, imageSize, resolution fields bmp += struct.pack("<I", 0) # compression bmp += struct.pack("<I", 625) # imageSize (valid) bmp += struct.pack("<i", 0) # horizontalResolution bmp += struct.pack("<i", 0) # verticalResolution bmp += struct.pack("<I", 0) # numColors bmp += struct.pack("<I", 0) # importantColors
# Pixel data with trigger pattern pixel_data = bytearray(625)
# Embed the trigger string trigger = b"3nk1's-n4m-shub" trigger_offset = 100 pixel_data[trigger_offset:trigger_offset+len(trigger)] = trigger
# Add shellcode or payload after trigger # (Could use this for actual exploitation)
bmp += pixel_data
return bytes(bmp)
# Generate the malicious BMPwith open("malicious.bmp", "wb") as f: f.write(create_malicious_bmp())Step 2: Execute the Payload
Run the scanner against the crafted file:
./snowscan malicious.bmpThe application will:
- Parse the BMP header successfully
- Load the pixel data into the stack buffer
- Scan for the trigger sequence
- Detect “3nk1’s-n4m-shub” in the data
- Report FAIL for that scan row
Step 3: Exploit the Vulnerability
For stack overflow exploitation:
def create_stack_overflow_bmp(): # Create BMP with larger imageSize # This causes a larger stack buffer allocation # Overflow the buffer with ROP gadgets passStep 4: Achieve Code Execution
By carefully crafting the pixel data with:
- Return addresses pointing to useful gadgets
- Stack pivot instructions
- Shellcode in the pixel data
Execute arbitrary commands on the system.
Key Vulnerabilities Summary
| Vulnerability | Line(s) | Type | Impact |
|---|---|---|---|
| VLA Stack Allocation | 135 | Stack Overflow | High |
| Insufficient Size Validation | 85-86 | Logic Error | Medium |
| Inverted Extension Check | 124-125 | Logic Error | Low |
| No Bounds Checking | 139 | Buffer Overflow | High |
Key Takeaways
- Variable Length Arrays: Avoid VLAs in security-sensitive code; use heap allocation instead
- File Format Parsing: Strictly validate all fields from untrusted file formats
- Logic Errors: Double-check comparison operators (==, !=, strcmp returns)
- Buffer Management: Always use explicit bounds checking, not implicit assumptions
- File Extension Validation: Implement robust, not inverted, validation logic
- Defense Mechanisms: Compile with stack canaries, ASLR, and DEP/NX to mitigate exploits