花式栈溢出技巧----partial overwrite

学习资料:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/*/others/#partial-overwrite

                  https://bbs.ichunqiu.com/thread-43627-1-1.html

                  https://www.jianshu.com/p/c3624f5dd583

partial overwrite 这种技巧在很多地方都适用, 这里先以栈上的 partial overwrite 为例来介绍这种思想

我们知道, 在程序开启了 PIE 保护时 (PIE enabled) 高位的地址会发生随机化, 用来由于受到堆栈和libc地址可预测的困扰,但低位的偏移是始终固定的, 也就是说如果我们能更改低位的偏移, 就可以在一定程度上控制程序的执行流, 绕过 PIE 保护

那么就清楚了,这种绕过方法是主要争对PIE保护的,partial write(部分写入)就是一种利用了PIE技术缺陷的bypass技术

打开给的例子

花式栈溢出技巧----partial overwrite

拖进IDA找栈溢出漏洞

花式栈溢出技巧----partial overwrite

第一个read函数可以恶意溢出,第二个read函数百分之百溢出

搜字符串可以搜到我们想要的,同时文件中也包含system函数

花式栈溢出技巧----partial overwrite

可以发现先直接调用函数A3E就好,只要把rip改过去就好

在输入之前, 程序对栈空间进行了清零, 这样我们就无法通过打印栈上信息来 leak binary 或者 libc 的基址了

那咋办,这里从大佬那里看到了printf函数的小技巧

printf 使用 %s 时, 遇到 \0 结束, 覆盖 canary 低位为非 0 值, canary 就可以被 printf 打印出来了,我们把低位数据改一改就可以

研究一波怎么改

先是打断点就已经坑到我了,因为有PIE保护,后来听大佬的方法是先把程序打断点打炸,然后再vmmap,然后重打断点,重新运行才行

汇编代码可以看见buf的地址放在rsi上

花式栈溢出技巧----partial overwrite

输入a的话低位肯定是0x61是非0的

Canary保护机制的原理,是在一个函数入口处从fs段内获取一个随机值,一般存到EBP - 0x4(32位)或RBP - 0x8(64位)的位置, 如果攻击者利用栈溢出修改到了这个值,导致该值与存入的值不一致,__stack_chk_fail函数将抛出异常并退出程序

这样只要接收'a' * (0x30 - 0x8 + 1) 后的 7 位, 再加上最低位的 '\0', 我们就恢复出程序的 canary 了,为啥是七位呢,因为cannary低位是\x00,printf不就停止输出了么,那我们干脆只要七位好了

第二次read的时候我们可以观察到返回地址与 get shell 函数的地址只有低位的 16 bit 不同, 如果覆写低 16 bit 为 0x0A3E, 就有一定的几率 get shell,那我们不断循环直到成功就好了

exp

while True:
    try:
        payload='a'*(0x30-0x08+1)
        cn.recvuntil('Input your Name:')
        cn.send(payload)
        cn.recvuntil('a'*(0x30-0x08+1))
        canary = '\0' + cn.recvn(7)
        success(canary.encode('hex'))
        cn.sendafter(":\n", 'a' * (0x30 - 0x8) + canary + 'bbbbbbbb' + '\x3E\x0A')
        cn.interactive()
    except Exception as e:
        cn.close()
        print e