如何解释以下shellcode漏洞的行为?

时间:2010-11-08 18:05:33

标签: assembly x86 buffer-overflow exploit shellcode

这是一个利用缓冲区溢出漏洞的shellcode。它设置setuid(0)并使用execve()生成一个shell。以下是我解释它的方式:

xor    %ebx,%ebx       ; Xoring to make ebx value 0
lea    0x17(%ebx),%eax ; adds 23 to 0 and loads effective addr to eax. for setuid()
int    $0x80           ; interrupt
push   %ebx            ; push ebx
push   $0x68732f6e     ; push address // why this address only????
push   $0x69622f2f     ; push address // same question
mov    %esp,%ebx
push   %eax
push   %ebx
mov    %esp,%ecx
cltd                   ; mov execve sys call into al
mov    $0xb,%al
int    $0x80           ; interrupt

任何人都可以清楚地解释整个步骤吗?

1 个答案:

答案 0 :(得分:11)

int是用于触发软件中断的操作码。软件中断编号(从0到255)并由内核处理。在Linux系统上,中断128(0x80)是系统调用的常规入口点。内核期望寄存器中的系统调用参数;特别是,%eax寄存器识别我们正在谈论的系统调用。

  1. 将%ebx设为0
  2. 计算%ebx + 23并将结果存储在%eax中(操作码为lea作为“加载有效地址”但不涉及内存访问;这只是一种添加的狡猾方式。)< / LI>
  3. 系统调用。 %eax包含23,表示系统调用为setuid。该系统调用使用一个参数(目标UID),可在%ebx中找到,该ebx在该点方便地包含0(它在第一条指令中设置)。注意:返回时,寄存器是未修改的,%eax除外,它包含系统调用的返回值,通常为0(如果调用成功)。
  4. 将%ebx推入堆栈(仍为0)。
  5. 在堆栈上推送$ 0x68732f6e。
  6. 在堆栈上推送$ 0x69622f2f。由于堆栈“向下”增长,并且由于x86处理器使用小端编码,因此指令4到6的效果是%esp(堆栈指针)现在指向12个字节的序列,值为2f 2f 62 69 6e 2f 73 68 00 00 00 00(十六进制)。这是“// bin / sh”字符串的编码(终止为零,之后有三个额外的零)。
  7. 将%esp移至%ebx。现在%ebx包含一个指向上面构建的“// bin / sh”字符串的指针。
  8. 在堆栈上推送%eax(此时%eax为0,它是setuid返回的状态)。
  9. 将%ebx推入堆栈(指向“// bin / sh”)。指令8和9在堆栈上构建了两个指针的数组,第一个是指向“// bin / sh”的指针,第二个指向NULL指针。该数组是execve系统调用将用作第二个参数的内容。
  10. 将%esp移至%ecx。现在%ecx指向使用指令8和9构建的数组。
  11. 将%eax签名扩展为%edx:%eax。 cltd是英特尔文档称之为cdq的AT&amp; T语法。由于此时%eax为零,因此将%edx设置为零。
  12. 将%al(%eax的最低有效字节)设置为11.由于%eax为零,%eax的整个值现在为11.
  13. 系统调用。 %eax(11)的值将系统调用标识为execveexecve需要三个参数,在%ebx中(指向要命令执行文件的字符串的指针),%ecx(指向字符串指针数组的指针,这是程序参数,第一个是副本程序名,由调用程序本身使用)和%edx(指向字符串指针数组的指针,这是环境变量; Linux允许该值为NULL,对于空环境)。
  14. 所以代码首先调用setuid(0),然后调用execve("//bin/sh", x, 0),其中x指向两个指针的数组,第一个是指向“// bin / sh”的指针,而另一个是NULL。

    这段代码非常复杂,因为它想要避免零:当组装成二进制操作码时,指令序列仅使用非零字节。例如,如果第12条指令是movl $0xb,%eax(将整个%eax设置为11),那么该操作码的二进制表示将包含三个字节的值0.缺少零使得该序列可用作零终止C字符串的内容。当然,这是为了通过缓冲区溢出来攻击有缺陷的程序。