BSD Sockets em linguagem C

Venho neste artigo explicar como funciona sockets em ANSi C, explicar portabilidade e exemplos reais e diferentes de artigos semelhantes. Enfim, aqui você aprenderá a usar sockets na prática.

[ Hits: 109.410 ]

Por: C00L3R_ em 06/07/2010 | Blog: http://bugsec.com.br


Na prática fazendo um FUZZER TCP



Continuando nossos estudos com sockets, vamos a um exemplo diferente de cliente e servidor. Vou mostrar um Fuzzer. Para quem não sabe fuzzing está 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.

/*
by m0nad
versão do fuzzer do Cooler_ só que melhorado
greetz 
Thanks _mlk_ , Cooler_,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 "netdb.h"
#include "unistd.h"  
#include "arpa/inet.h"
void
erro (char *msg)
{
  perror(msg);
  exit (1);
}

void *ec_malloc(unsigned int tam)
{
  void *ptr;
  ptr = malloc(tam);
  if ( ptr == NULL )
    erro("erro malloc");

  return ptr;
}

void
inicia_alvo (struct sockaddr_in *nome, unsigned int port, char *host)
{
// memset((char *) nome,0, sizeof(*nome)); // zera a estrutura
  nome->sin_family = AF_INET;
  nome->sin_port = htons (port);
  nome->sin_addr.s_addr = inet_addr(host);
}
int
inicia_socket (char *host, unsigned int porta)
{
  int sockfd, conex;
  struct sockaddr_in alvo;
  
  sockfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if ( sockfd < 0 )
    erro("[-] SOCKET");
  inicia_alvo (&alvo, porta, host);
  conex = connect (sockfd, (struct sockaddr *)&alvo, sizeof alvo);
  if ( conex < 0 )
    erro("[-] CONNECT");
  return sockfd;
}

int
main(int argc, char **argv)
{

  int sockfd, porta, bit, cont, qtd;
  char *ip, *buffer;

  if (argc < 5) {
    printf ("./fuzz_cooler <qtd chars(=> 4)>  <incremento> <porta> <ip>\n./fuzz_cooler 2000 4 6666 192.168.0.172\n");
    exit(1);
  }

  bit = atoi (argv[1]);
  qtd = atoi (argv[2]);
  porta = atoi (argv[3]);
  ip = argv[4];
  if((porta > 65535)||(porta <= 0)||(bit < 4) || qtd <=0) {
    fprintf(stderr, "ERRO veja se digitou dados validos\n");
    return 0;
  }
  buffer = (char *)ec_malloc (bit * sizeof (char));

  for (cont = 4; cont < bit; cont +=qtd) {
    memset(buffer, 'A', cont);
    buffer[cont] = 0;
    //printf ("buffer %s\n", buffer);

    sockfd = inicia_socket (ip, porta);

    send(sockfd, buffer, strlen (buffer), 0);
    printf ("[%d] letras enviadas para %s porta %d\n", cont, ip, porta);

    close(sockfd);
  }
  return 0;
}

Não tem nada de mais no fuzzer, tudo que vimos neste paper, funções e tal. Agora vamos passar um exemplo simples de uso, você tem um servidor vulnerável sabendo que ele dá crash com mais de mil caracteres de envio, então temos o ambiente:

./server 4000 <---- iniciamos server vulnerável em outro term, ele fica na escuta "listening"

No terminal do teste faça:

./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 blá blá
conexã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
...blá blá blá
[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 caracteres "A" o buffer estoura e o servidor cai.

Bom, agora explorar é com você, o tutorial aqui é apenas de sockets. ;)

Obs.: O código do servidor vulnerável está no fim deste paper.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Explanação ao TCP/IP
   3. O que é socket
   4. Funções read(), send() e exemplo cliente HTTP
   5. Funções listen(), bind(), accept() e exemplo de servidor HTTP
   6. Na prática fazendo um FUZZER TCP
   7. Servidor e cliente com fork
   8. Servidor de comandos e scanner de portas
   9. Simple socket library
   10. Explanação ao UDP e exemplo de servidor e cliente
   11. Exemplo UDP Flood
   12. Portabilidade
   13. Conclusão
Outros artigos deste autor

Usando OpenBSD como desktop

Trabalhando com arquivos no Perl

Buffer Overflow: Entendendo e explorando

Bind: Explorando e evitando falhas

Ponteiros - Saindo de Pesadelos

Leitura recomendada

Controlando UPLOAD com o CBQ

Monitorando o consumo de banda com Bwbar

O Modelo de Referência OSI

Tutorial - Aplicação em C para transferência de arquivo usando socket TCP e Thread

Alocação dinâmica de memória em C

  
Comentários
[1] Comentário enviado por VonNaturAustreVe em 06/07/2010 - 03:24h

Excelente cara vou ler tudo :)

[2] Comentário enviado por removido em 06/07/2010 - 05:29h

Hey C00L3R,
Parabéns, é um ótimo artigo. Minhas dúvidas surgiram após meus testes.
Um abraço.

[3] Comentário enviado por andrezc em 06/07/2010 - 08:12h

Cara, realmente esse é um dos melhores artigos que eu já li por aqui. Parabéns.

[4] Comentário enviado por werneral em 06/07/2010 - 11:18h

Muito bom! Obrigado!

[5] Comentário enviado por uberalles em 06/07/2010 - 11:43h

verdadeira aula, velho. parabéns!
muito bom "resumão" do Unix Network programming. Nunca consegui fazer nada decente em sockets e esta tua aula deverá me ajudar muito.

[6] Comentário enviado por stremer em 07/07/2010 - 15:28h

para quem interessar, ha algum tempo atras escrevi um script mostrando como criar um robo http e enviei ao VOL.

http://www.vivaolinux.com.br/script/Robo-HTTP-usando-socket-e-codigo-multiplataforma

Interessante para quem esta aprendendo sockets...

OTIMO ARTIGO

[7] Comentário enviado por andrezc em 07/07/2010 - 15:43h

Opa stremer, eu cheguei a ver este seu script, realmente fabuloso.

Um abraço.

[8] Comentário enviado por fernandopinheiro em 07/07/2010 - 20:23h

Parabens, muito bom!!

[9] Comentário enviado por brunosolar em 08/07/2010 - 09:48h

Parabens realmente muito bom. So queria fazer um comentario sobra a parte do UDP flood. Sim hoje em dia qualquer firewal simples pode recusar este tipo de pacote.

No entanto dependendo da quantidade de pacotes UDP enviados (leia-se DDOS) você poderá ser "derrubado" pois o firewall irá gastar muito processador para descatar todos os pacotes. A melhor solução (AINDA) para ataques DOS / DDOS é diretamente no ISP onde eles irão setar no roteador o IP do atacante para /dev/null (exemplo). claro que voce corre o risco de perder algum cliente que faça parte da rede redirecionada.

No mais excelente trabalho.

[10] Comentário enviado por shazaum em 24/09/2010 - 11:44h

opa, no fuzzer faltou uma lib...

#include <netinet/in.h>

[11] Comentário enviado por thomasawrd em 18/07/2014 - 12:41h

parabéns cara excelente artigo,me ajudou muito.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts