[Win Pwn] 基础栈溢出利用
window下无保护的栈溢出加载shellcode
程序
1 |
|
在windows下的防护等级有
ASLR
/DYNAMICBASE
带有剥离的重定位条目边缘情况/HIGHENTROPYVA
for 64-bit systems
Code integrity/signing:
/INTEGRITYCHECK
- 使用有效(可信、活动)证书进行 Authenticode 签名(Linux 目前不支持)
DEP
- 别称:
W^X
,NX
- 别称:
Manifest isolation
/ALLOWISOLATION
SEH
和SafeEH
SEH
=Structured Exception Handling
Control Flow Guard
和Return Flow Guard instrumentation
Stack cookie
/GS
-
ASLR:与Linux的PIE相同,指地址随机化,将在程序启动时将DLL随机的加载到内存中的未知,自Windows 10开始已经在系统中被配置为默认启动;
-
High Entropy VA:高熵64位地址空间布局随机化,开启后标识此程序的随机化取值空间为64 bit,这会导致攻击者更难去推测随机化后的地址;
-
Force Integrity:强制签名保护,开启后标识程序加载时需要验证其中的前命,如果签名不正确,程序将会被阻止运行;
-
Isolation:隔离保护,开启后表示此程序加载时将会在一个相对独立的隔离环境中被加载,从而阻止攻击者过度提升权限;
-
NX/DEP/PAE:NX保护指的是内存页不可运行。属于系统级的内存保护功能,能够将一页或多页标记为不可执行,从而防止从该内存区域运行代码,以帮助防止利用缓冲区溢出。防止代码在数据页面(例如堆、栈和内存池)中运行,在Windows中常称为DEP。
PAE指物理地址拓展,PAE是一项处理器功能,使x86处理器可以在部分windows版本上访问4 GB以上的物理内存。在基于x86的系统上运行的某些32位版本的Windows Server可以使用PAE访问最多64 GB或128 GB的物理内存,具体取决于处理器的物理地址大小。使用PAE,操作系统将从两级线性地址转换为三级地址转换。两级线性地址转换将线性地址拆分为3个独立的字段索引到内存表中,三级地址转换将其拆分为4个独立的字段:一个2位字段,两个9位字段和一个12位字段。PAE模式下的页表条目(PTE)和页目录条目(PDE)的大小从32位增加到64位。附加位允许操作系统PTE或PDE引用4 GB以上的物理内存,同时PAE将允许在基于x86的系统上运行32位windows中启用DEP等功能。
-
SEHOP
:即结构化异常处理保护(structured Exception Handling Overwrite Protection),这个保护能够防止攻击者利用结构化异常处理来进行进一步的利用。 -
CFG
:即控制流防护这项技术通过在间接跳转前插入校验代码,检查目标地址的有效性,进而可以阻止执行流跳转到预期之外的地点,最终及时有效的进行异常处理,避免引发相关的安全问题。 -
RFG:即返回地址防护,在每个函数头部将返回地址保存到
fs:[rsp](thread control stack)
,并在函数返回前将其与栈上返回地址进行比较,从而有效阻止攻击; -
SafeSEH:安全结构化异常处理(Safe Structured Exception Handlers),白名单版的安全沙箱,定义一些异常处理程序,并基于此构造安全结构化异常处理表,程序运行后,安全结构化异常处理表之外的异常处理程序将会被阻止运行;
-
GS:类似于Linux中的Canary保护,开启后,会在返回地址和BP之前压入一个额外的
Security Cookie
,系统会比较栈中的这个值和原先存放在.data
中的值做一个比较,如果两者不吻合,则说明发生了栈溢出; -
Authenticode:签名保护;
-
.NET:DLL混淆级保护
你可以查看文件头进行识别,也可以使用winchecksec进行识别
非常明显的漏洞点
漏洞分析
GCC编译gcc .\main.c -o shellcode
先试一下跳转,加上覆盖ebp的空间大小是0x1c
加载shellcode
现在想办法布置shellcode,由于没有后门函数所以需要利用SEH进行shellcode的布置。
栈中的 SEH Handle 存储的形式
基本的布置方式如下,实战的可以参考CVE-2019-9766简单栈溢出
使用x32dbg调试得到SEH链,然后得出payload
1 | payload = b"" |
使用了gadget,进行两次pop抬栈,这样就能滑行到shellcode
gadget过后的跳转
但是shellcode长度有限制,所以很寄
但是我们执行一小段shellcode,那么可以尝试自己写gadget,将shellcode写入在payload前段,然后利用SEH到自己写的gadget,最后跳转到shellcode,需要注意的是程序会把第五位归0,所以要注意。
在使用fscanf
函数读取字符串时,以下特殊字符可能会导致读取失败或产生意外的结果:
- 空格 (
0x20
) - 制表符 (
0x09
) - 换行符 (
0x0A
) - 回车符 (
0x0D
)
这块儿就只有自己根据实际情况改进shellcode了。
那么我稍微改进一下源代码
1 |
|
由于栈比较小,可以考虑自己写入gadget来帮助shellcode的跳转
1 | from ae64 import AE64 |