(利用stack_chk_fail函数泄露flag)
文件链接:https://pan.baidu.com/s/17pIc0RrfLRH9arMbJmJGjA
提取码:4olb

前置知识:{
在 ELF 内存映射时,bss 段会被映射两次,
所以可以使用另一处的地址来进行输出,既可以用gdb的find或grep查找,也可以用ida的字符串查找(alt+t)
}

1.搭建pwn题目环境,查看保护机制,运行ida*64远程调试文件


2.ida*64打开程序分析:


函数sub_4007E0内的gets处有溢出漏洞,不过有canary保护,不能劫持eip。
sub_4007E0函数大致功能位获取一段字符(这段字符在栈中可造成溢出),然后再获取一段字符,其中有字符为-1则结束程序,有字符为10('\n')则退出循环,有字符为32(' ')则结束函数。然后将第二次输入的那段字符复制到含有flag的data段位置处,结束循环后,有一个memset函数将data段含有flag的位置,没有被输入的字符覆盖的部分都置0。由于前置知识可以知道还有一个位置是存放flag的,并且栈溢出,肯定可以覆盖canary然后触发stack_chk_fail函数。可以计算stack_chk_fail函数中输出的函数名在栈中的位置记为leak,以及gets函数在栈中读取数据的起始位置 之间的距离。这样就可以用flag的地址栈溢出覆盖到leak,从而打印出flag

3.断点调试一下:


可以计算出gets在栈中读入数据的起始位置距离canary位置为0x108,也就是padding为0x110则可以覆盖canary,触发stack_chk_fail函数。

之后就输入1,覆盖data的数据(↓覆盖前和覆盖后):


然后就是调用memset将未覆盖的字符置0操作

再在16进制窗口查找另一个flag的地址:


跟进stack_chk_fail函数,可以在此 找到stack_chk_fail要输出的值的地址,然后计算出 偏移为0x218,也就是padding为0x218 + 要leak的地址,即可覆盖stack_chk_fail要输出的值的地址


from pwn import *

context.binary = './readme'

link = remote("192.168.93.137","6666")
flag_add = 0x400d20
payload = 'A' * 0x218 + p64(flag_add)
link.recvuntil("name? ")
link.send(payload)
link.recvuntil("flag: ")
link.send('1')
print link.recv()