2019.7.22 babypie(canary绕过)和一些调试技巧

1.2019.7.22 babypie(canary绕过)和一些调试技巧_第1张图片
2019.7.22 babypie(canary绕过)和一些调试技巧_第2张图片
以上是程序的反编译代码和保护机制。我们可以看出他开了canary保护。我们运行一下程序,发现只要输入一定数额的字符,其可以保持正常功能。
2.2019.7.22 babypie(canary绕过)和一些调试技巧_第3张图片canary总是保存在bp的上面,意是我们虽然开辟了48字节的空间,但真正能写的只有40字节。最近遇到一个pwn大佬,跟着他学到了很多gdb调试的技巧,我想把它结合这个题目记录下来。
3.
我们可以在代码中加入gdb.attach(io,’’),让程序停在某个特定的位置并吊出一个本次运行的 gdb界面。一般让他停在send之前,然后查看各个数据,因为很多程序是开了ASLR,导致地址在每次运行都会发生变化。我们在运行exp的时候,在后面加上大写的DEBUG,可以看到我们发送的东西和程序收到的东西,结合吊出来的gdb界面查的内容,我们可以检查我们发送到程序的数据是否是我们想要发送的。
4.2019.7.22 babypie(canary绕过)和一些调试技巧_第4张图片
这里的1是程序的加载地址,当程序开了PIE以后程序的加载地址始终在变化,但是在gdb中,gdb是默认将PIE关掉了的,所以每次用vmmap或piebase来查看都是不变的,此时在IDA中解析出来的是相对ELF文件头(也就是1)的相对地址。当程序关了PIE以后,
IDA解析出来的是绝对地址。且不管是开PIE还是没开,在gdb中用 p 打印出来的函数都是真实地址。只是开了以后,下次再打印会不一样。
4.
这个程序缺少调试符号,所以我们只能用gdb中的程序加载地址加上IDA中的相对偏移来下断点。我们下断点到main函数,然后进入有栈溢出的函数。

2019.7.22 babypie(canary绕过)和一些调试技巧_第5张图片
2019.7.22 babypie(canary绕过)和一些调试技巧_第6张图片
我们可以看出程序从fs段取出一个数据(canary)放在rax中,然后放到rbp-8的位置。最后函数返回的时候将rbp-8的数和前面的数进行异或,如果相等就为0,就会正常返回,否则就会报错。
5.
我们可以到gdb中来查看canary的值,每次程序运行,canary都会发生变化。
2019.7.22 babypie(canary绕过)和一些调试技巧_第7张图片
我们可以同查看此时栈中的数据来算我们应该填多少字符。
2019.7.22 babypie(canary绕过)和一些调试技巧_第8张图片
我们找到rbp的地址,发现前面有40个字节(5*8)。我们用0a覆盖00,rbp随便赋值。根据上图我们发现后门函数和返回地址只差一个最后一个字节,我们将只需将返回地址的最后一个字节变为3e,即可执行system(’/bin/sh’)。这里要注意的是我们最后要用send而不是sendline,因为用sendline会导致换行符也输到返回地址中,就像下图:
2019.7.22 babypie(canary绕过)和一些调试技巧_第9张图片
exp:
2019.7.22 babypie(canary绕过)和一些调试技巧_第10张图片

你可能感兴趣的:(pwn)