Simples Scanner - Linux e Windows - C

Started by Dark_Side, 08 de May , 2007, 12:37:01 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Dark_Side

Hi xD

Pois então, irei postar um simples scanner que eu havia feito por esses dias.
Basicamente, o scanner exibe informações sobre um servidor rodando o serviço HTTP, tais como o nome deste servidor, seu hostname, cookies atribuídos, versão do php, etc. Há uma funcionalidade que permite a busca por determinados arquivos e/ou diretórios dentro do servidor com base em uma lista criada dentro de um arquivo .TXT. E, finalmente, o terceiro ponto mais importante é que, fazendo-se requisições ao site http://www.milw0rm.com, o programa tenta retornar links de possíveis exploits para a exploração de ocasionais falhas que o servidor possa apresentar.

Exemplo de uso:

O programa obtém a lista de arquivos que serão analisados na etapa 2 dentro do arquivo "lista_arquivos.txt":

lista_arquivos.txt
/index.php
/forum/

Quotescan
Digite a URL do site:
>> www.darkers.com.br


Quote./scan www.darkers.com.br

Quote>> Executando etapa 1 de 3...

[-] Obtendo informacoes sobre o servidor...

  • IP:
70.84.235.218

  • HostName:
darkers.com.br

  • Servidor:
Apache/1.3.37 (Unix) mod_gzip/1.3.26.1a mod_auth_passthrough/1.808fe901766e1bebb30ff1918718f7e5c=-; path=/

  • PHP:
PHP/4.4.4

  • Cookies:
08fe901766e1bebb30ff1918718f7e5c=-; path=/

>> Terminada etapa 1.

================================================

>> Executando etapa 2 de 3...

[-] Tentando acessar arquivos definidos...

Arquivos encontrados:

http://www.darkers.com.br/index.php
http://www.darkers.com.br/forum/

>> Terminada etapa 2.

================================================

>> Executando etapa 3 de 3...

[-] Obtendo possiveis exploits em www.milw0rm.com

>>> Procurando exploits relacionados a "Apache" <<<

...

  • Apache Mod_Rewrite Off-by-one Remote Overflow Exploit (win32)
  -> http://www.milw0rm.com/exploits/download/3680

  • Ubuntu/Debian Apache 1.3.33/1.3.34 (CGI TTY) Local Root Exploit
  -> http://www.milw0rm.com/exploits/download/3384

  • Apache < 1.3.37, 2.0.59, 2.2.3 (mod_rewrite) Remote Overflow PoC
  -> http://www.milw0rm.com/exploits/download/2237

...

>>> Procurando exploits relacionados a "PHP" <<<

...

  • PHP 4.4.5 / 4.4.6 session_decode() Double Free Exploit PoC
  -> http://www.milw0rm.com/exploits/download/3586

  • PHP-Nuke Module Addressbook 1.2 Local File Inclusion Exploit
  -> http://www.milw0rm.com/exploits/download/3582

  • PHP 5.2.1 with PECL phpDOC Local Buffer Overflow Exploit
  -> http://www.milw0rm.com/exploits/download/3576

  • PHP < 4.4.5 / 5.2.1 _SESSION Deserialization Overwrite Exploit
  -> http://www.milw0rm.com/exploits/download/3572

...

>> Terminada etapa 3.

Como podemos ver nos exemplos, o programa é relativamente simples. Minha verdadeira intenção é que vocês possam tirar algo de proveito do código xD:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef WIN32
 
  #include <winsock.h>

#else

  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <netdb.h>
  #define closesocket close

#endif

//////////////////////////////////////////////////////////////////////

#define ERRO            -1
#define MAX_COOKIES     10
#define lista_arquivos  "lista_arquivos.txt"

char URL[196];

 #ifdef WIN32   
    WSADATA wsa;
 #endif
 
    int    sock;
    struct sockaddr_in addr;
    struct hostent * host;

struct s_info{
        char  * IP;
        char  * nome;
        char  servidor[64];
        char  cookies[MAX_COOKIES][256];
        char  asp_php[32];
        int   cookies_n;
       
        }info;     

     
      void erro(const char*);
      void obter_site(char*);
      int  info_servidor();
      void arquivos();
      int  verificar();
      void procura_xpl(char *);

#ifndef WIN32
  void strlwr(char * str){
   
   for(;*str != '\0'; *str++)
      if(*str >= 'A' && *str <= 'Z')
          *str  += 32;}
#endif

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

    obter_site(argv[1]);
     
    #ifdef WIN32
    if(WSAStartup(0x202,&wsa) == ERRO)
      erro("Erro ao inicializar winsock.");
    #endif
 
    if((sock = socket(AF_INET,SOCK_STREAM,0)) == ERRO)
      erro("Ocorreu um erro ao criar um socket.");
     
   
    if(!(host = gethostbyname(URL)))
      erro("Ocorreu um erro ao resolver o host.");
       
    addr.sin_family = AF_INET;
    addr.sin_port   = htons(80);
    addr.sin_addr   = *(struct in_addr*)host->h_addr;

    memset(&addr.sin_zero, 0x0, sizeof(addr.sin_zero));
   
    if(connect(sock,(struct sockaddr*)&addr,sizeof(addr)) == ERRO)
       erro("Erro ao conectar-se.");
       
    #ifdef WIN32
    system("cls");
    #else
    system("clear");
    #endif
     
    memset(&info,0x0,sizeof(info));

    puts(">> Executando etapa 1 de 3...\n");
    puts("[-] Obtendo informacoes sobre o servidor...\n");
    if(info_servidor() == ERRO)
      puts("Erro ao exibir informacoes sobre o servidor.\n");
 
    closesocket(sock);

    puts("================================================\n");
    puts(">> Executando etapa 2 de 3...\n");
    puts("[-] Tentando acessar arquivos definidos...\n");
    arquivos();

    puts("================================================\n");
    puts(">> Executando etapa 3 de 3...\n");
    puts("[-] Obtendo possiveis exploits em www.milw0rm.com\n");
   
    char * busca = NULL;     
    if(strlen(info.servidor) > 0){
    busca = strtok(info.servidor," -/\\.");
    busca ? procura_xpl(busca) : procura_xpl(info.servidor);}
   
   
    if(strlen(info.asp_php) > 0){
    busca = strtok(info.asp_php," -/\\.");
    busca ? procura_xpl(busca) : procura_xpl(info.asp_php);}

    puts("\n>> Terminada etapa 3.\n");


 #ifdef WIN32
       WSACleanup();
 #endif

 return 0;   
}

//////////////////////////////////////////////////////////////////////
void erro(const char* msg)
{
     printf("%s\n",msg);
     exit(1);
}
//////////////////////////////////////////////////////////////////////

void obter_site(char *site)
{
 
   char temp_url[256];
   
   if(!site)
     {
     printf("Digite a URL do site:\n>> ");
     fgets(temp_url,sizeof(temp_url),stdin);
     strtok(temp_url,"\r\n");
     }
   else
     strncpy(temp_url,site,sizeof(temp_url));

  strlwr(temp_url);   
  char * pt  = strstr(temp_url,"http://");
     
      if(pt != NULL)
          strncpy(URL,pt+7,sizeof(URL));
      else
          strncpy(URL,temp_url,sizeof(URL));
     
     pt = URL;
     
     for(;*pt != '\0'; *pt++)
        if(*pt == '/')
           *pt = '\0';
             

}
//////////////////////////////////////////////////////////////////////

int info_servidor()
{
     char buffer[4096];
     char * servidor, * cookies, * asp_php;

     snprintf(buffer,sizeof(buffer),"HEAD / HTTP/1.1\r\nhost: %s\r\n\r\n",URL);
     if(send(sock,buffer,strlen(buffer),0) == ERRO)
       return ERRO;
     
     memset(buffer,0x0,sizeof(buffer));
     if(recv(sock,buffer,sizeof(buffer),0) == ERRO)
        return ERRO;
   
     char * headers = strtok(buffer,"\r\n");
     if(!headers){
        puts("Erro ao obter informacoes sobre o servidor.");
        return ERRO;
                 }
   
     info.IP   = (char*)inet_ntoa(addr.sin_addr);
     info.nome = host->h_name;
   
     while(headers != NULL){
   
     servidor = strstr(headers,"Server: ");
     cookies  = strstr(headers,"Set-Cookie: ");
     asp_php  = strstr(headers,"X-Powered-By: ");

     if(servidor != NULL)
        snprintf(info.servidor,sizeof(info.servidor),"%s",servidor+8);
     
     if(asp_php != NULL)
        snprintf(info.asp_php,sizeof(info.asp_php),"%s",asp_php+14);
   
     if(cookies != NULL && info.cookies_n < MAX_COOKIES) {
        snprintf(info.cookies[info.cookies_n],sizeof(info.cookies) / MAX_COOKIES,"%s",cookies+12);
        info.cookies_n++;}
 
     headers = strtok(NULL,"\r\n");
                           }


     char * prefixo = NULL;

     printf("[+] IP:\n %s\n\n",info.IP);
     printf("[+] HostName:\n %s\n\n",info.nome);         
     printf("[+] Servidor:\n %s\n\n",info.servidor);

     if(strstr(info.asp_php,"ASP"))
        prefixo = "ASP";
     else if (strstr(info.asp_php,"PHP"))
        prefixo = "PHP";

     if(prefixo) 
        printf("[+] %s:\n %s\n\n",prefixo,info.asp_php);

     if(!info.cookies_n)
        return 0;
     
     puts("[+] Cookies:");
   
     int i = 0;
     for(;i < info.cookies_n;i++)
         printf(" %s\n",info.cookies[i]);
   
     puts("\n>> Terminada etapa 1.\n");

}
//////////////////////////////////////////////////////////////////////
void arquivos(){

  FILE * fp = fopen(lista_arquivos,"r");
  if(!fp){
     printf("Falha ao ler o arquivo "%s"\n",lista_arquivos);
     return;
         }
 
  char arq[256];
  char * arq_req;
 
  puts("Arquivos encontrados:\n");
   
  while(!feof(fp)){
       
    if(!fgets(arq,sizeof(arq),fp))
     continue;
   
    if(arq[0] == '\n')
      continue;
     
    strtok(arq,"\r\n");
    arq_req = arq;
   
    if(*arq_req == '/')
      arq_req++;

    switch(verificar(arq_req)){
   
              case 1:
                  printf("http://%s/%s\n",URL,arq_req);
              break;
             
              case -1:
                   printf("Erro ao requisitar o arquivo: "%s".\n",arq);
              break;
                              }             
                  }
 
  fclose(fp);
  puts("\n>> Terminada etapa 2.\n");
                   
}       
//////////////////////////////////////////////////////////////////////

int verificar(const char * arquivo)
 {
 
  char req[384];
  char resposta_header[16];
  int sock_local;
 
  if((sock_local = socket(AF_INET,SOCK_STREAM,0)) == ERRO)
    return ERRO;

  if(connect(sock_local,(struct sockaddr*)&addr,sizeof(addr)) == ERRO)
    return ERRO;

  snprintf(req,sizeof(req),"HEAD /%s HTTP/1.1\r\nhost: %s\r\n\r\n",arquivo,URL);

  if(send(sock_local,req,strlen(req),0) == ERRO)
    return ERRO;

  memset(resposta_header,0x0,sizeof(resposta_header));
  if(recv(sock_local,resposta_header,sizeof(resposta_header),0)==ERRO)
    return ERRO;
   
  closesocket(sock_local);
       
  if(strstr(resposta_header,"HTTP/1.1 200 OK"))
    return 1;
  else
    return 0;
}
//////////////////////////////////////////////////////////////////////

void procura_xpl(char * s1)
{
     
     if(!s1)
       return;
       
   printf(">>> Procurando exploits relacionados a "%s" <<<\n\n",s1);

   if((sock = socket(AF_INET,SOCK_STREAM,0)) == ERRO)
      erro("Ocorreu um erro ao criar um socket.");
   
   if(!(host = gethostbyname("www.milw0rm.com")))
      erro("Ocorreu um erro ao resolver o host.");
       
    addr.sin_family = AF_INET;
    addr.sin_port   = htons(80);
    addr.sin_addr   = *(struct in_addr*)host->h_addr;

    memset(&addr.sin_zero, 0x0, sizeof(addr.sin_zero));
   
    if(connect(sock,(struct sockaddr*)&addr,sizeof(addr)) == ERRO)
       erro("Erro ao conectar-se.");
   
    FILE *fp;
    if(!(fp = fopen("temp","w")))
       erro("Falha ao abrir um arquivo temporario.");
       
    char buffer[1024];
    int bytes = 1;
     
    snprintf(buffer,sizeof(buffer),"GET /search.php?dong=%s HTTP/1.1\r\nhost: %s\r\n\r\n",s1,host->h_name);
    send(sock,buffer,strlen(buffer),0);

  while(bytes > 0){
     bytes = recv(sock,buffer,sizeof(buffer),0);
     buffer[bytes] = '\0';
     fprintf(fp,buffer);
                  }
     
     if(!freopen("temp","r",fp))
       erro("Falha ao abrir um arquivo temporario.");
   
     char nome[256],download[256];
     int tam = 0;
 
  while(!feof(fp))
   
   {
     
      nome[0]     = '\0';
      download[0] = '\0';
     
      fgets(buffer,sizeof(buffer),fp);
     
      char * nome_xpl_inicial = strstr(buffer," target="_blank" class="style15">");
      char * nome_xpl = strstr(buffer," target="_blank" class="style14">");
     
      if(nome_xpl_inicial)
        nome_xpl = nome_xpl_inicial;
       
      if(!nome_xpl)
        continue;
     
      tam = (strstr(nome_xpl,"</a>")) - (nome_xpl+33);

      if(tam+33 > sizeof(nome))
        continue;

      snprintf(nome,tam,"%s",nome_xpl+33);
      nome[tam] = '\0';
           
      char * down_xpl = NULL;
     
      while(!down_xpl){
      fgets(buffer,sizeof(buffer),fp);
      down_xpl = strstr(buffer,"<a href="/exploits/download/");
                      }
     
      tam = (strchr(down_xpl+9,'"')) - (down_xpl+9);
       
      if(tam+23 > sizeof(download))
         continue;
         
      snprintf(download,tam+22,"http://www.milw0rm.com%s",down_xpl+9);
      download[tam+22] = '\0'; 
     
      if(nome[0] && download[0])
         printf("[#] %s\n  -> %s\n\n",nome,download);
       
   
   }
     
     closesocket(sock);
     fclose(fp);
     remove("temp");
}

Código no formato .C:
http://three.fsphost.com/darkside/scanweb.c

Obs:: para compilar o código no Windows, é necessário adicionar à linha de comando do linker a biblioteca do winsock: "wsock32".

Exemplo com o gcc:
gcc scanweb.c -o scanweb -lwsock32
É isso...
Bye xD

Anonymous

Cara fantastico, impressionante a explicação.... :o

Você torna a explicação muito simples.... VLw

nizep

parabens pelo programa velho
é sempre bom da uma olhada nos codes pra quem ta aprendendo
valews por compartilhar

whit3_sh4rk

[Dark_Side]
Parabéns cara..

Como foi dito, você torna as coisas simples com as explicações detalhadas, continue nos ajudando ;)

Dei uma olhada no código, apesar de não programar, eu tenho noção, e pode ser simples, mas é um pouco extenso o código, e provavelmente deu um trabalhinho para criar. Mais uma vez parabéns e Ponto positivo.

[]s

branco

eu nem comento...nao sei porque o Dark side ainda nao viro o "marsu" brasileiro...potencial pra isso tem, porém fica dando mole ai...

parabens, mas vc pode mais que isso...
Olha o trem... Quem vai ficar, quem vai partir? Quem vai chorar, quem vai sorrir?

Anonymous


OnlyOne

eu reconheço o trabalho desse cara , mas so pelo funcionamento do soft , ja da pra saber como q faz isso, mesmo q vc nao consulte o codigo fonte , ai galera , vamos estudar mais  ........
No céu toca Joy Division


insanity

hehe, legal o dark_site, programando para GNU/linux agora huahhaha

Eu estava fazendo um em Perl , que procurava falhas em aplicativos em WEB, estilo o niko ...

Bem intereçante o programa ...

Um bom começo para quem esta estudando sockets, ler manuais e horrivel hehe

nizep

ae galera ja aproveitando esse topico pra naum abrir outro

tipo no C o comando E equivale a && certo

mas uq equivale ao OU ??

Anonymous


nizep

vlw defcon

pior eh que logo depois que perguntei aki tava dando uma olhada num code do scriptbrasil e descobri ke era ||

msm assim vlws