前言
在这篇文章中将学习到泄露canary、ret2scu和ret2syscall
一、程序分析
从中可以看出该程序为64位动态链接的ELF文件,开启了canary保护,需要想办法绕过。
常见的绕过canary的方法分为以下四种:
1、通过read函数泄露canary。 关键的一点就是read函数读取字符串的时候不会在末尾加上“\x00”,这就是gets函数不能用来泄露canary的原因(有些输出函数遇到‘\0’会截断)。
2、暴力破解canary。 这种方法利用起来有限制,就是一般要程序中有fork函数创造出子进程,因为子进程是父进程复制出来的,所以canary也就跟父进程相同,在子进程中覆盖canary后报错就会退回到父进程,此时canary的值是不会改变的。
3、劫持stack_chk_fail。 因为canary被覆盖的时候会调用这个函数,所以如果我们可以利用程序中的漏洞(比如格式化字符串)改got表中stack_chk_fail的地址为one_gadget的地址就能getshell。
4、利用stack_chk_fail的报错信息。 在报错信息中,会将你发生栈溢出的程序名调用输出,其位置位于argv[0],我们可以将argv[0]的地址改写为我们想要获取的内容的地址,使它随着错误提示一起输出。
这里选择泄露canary的值,可以看出canary的位置在[rbp-8h]处,接着想办法泄露出[rbp-8h]处数据。
从源码中可以看出此处可以栈溢出,且canary位置为0x50-8。
由于程序在接收到我们的输入之后会返回回来,且栈是由高地址向低地址增长的,所以如果我们可以覆盖掉canary低位的0x00就可以将canary一起打印出来。
如果我们用sendline(‘a’*(0x50-8))就可将canary低位覆盖为0x0a(空格的ascii码为0x0a)。这样就得到了canary。
之后的输入就是用来构建合适的ROP链,由于不知道libc的版本,所以我们先leak出read函数的地址,然后利用__libc_csu_init()函数来构建(__libc_csu_init()是x64下初始化libc的函数 )。
二、漏洞利用
1.用空格覆盖canary低位的0x00截断,打印出canary
2.泄露出read地址,然后得出syscall的地址
3.利用 __libc_csu_init()函数构建rop链来运行execve(’/bin/sh’,0,0)
exploit
#!/usr/bin/python3
from pwn import *
context.binary = './easypwn'
context.terminal = ['tmux','sp','-h']
# context.log_level = 'debug'
# p=process('./easypwn')
p=remote('106.75.2.53',10002)
elf=ELF('./easypwn')
p.recv