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

Vin*_*d K 5 x86 assembly exploit buffer-overflow shellcode

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

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
Run Code Online (Sandbox Code Playgroud)

谁能清楚地解释整个步骤?

Tho*_*nin 11

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

  1. 将%ebx设置为0
  2. 计算%ebx + 23并将结果存储在%eax中(操作码lea为"加载有效地址",但不涉及内存访问;这只是一种添加的狡猾方式).
  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是英特尔文档所称的AT&T语法cdq.由于此时%eax为零,因此将%edx设置为零.
  12. 将%al(%eax的最低有效字节)设置为11.由于%eax为零,%eax的整个值现在为11.
  13. 系统调用.%eax(11)的值将系统调用标识为execve.execve期望三个参数,在%ebx(指向要命令执行的文件的字符串的指针),%ecx(指向字符串指针数组的指针,这是程序参数,第一个是程序名称的副本,是由调用的程序本身使用)和%edx(指向字符串的指针数组的指针,它们是环境变量; Linux允许该值为NULL,对于空环境).

因此,代码第一呼叫setuid(0),然后调用execve("//bin/sh", x, 0)其中x指向两个指针的数组,第一个是一个指针,指向"// bin/sh的",而另一个是NULL.

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