Assembly 如何解释以下外壳代码攻击的行为?

Assembly 如何解释以下外壳代码攻击的行为?,assembly,x86,buffer-overflow,exploit,shellcode,Assembly,X86,Buffer Overflow,Exploit,Shellcode,这是利用bufferoverflow漏洞进行攻击的外壳代码。它设置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

这是利用bufferoverflow漏洞进行攻击的外壳代码。它设置
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

有人能解释清楚整个步骤吗?

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

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


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

    Pomin:实际上,代码是复杂的,因为它试图尽可能小e、 这是Gera从Core Security使用的著名的24字节外壳代码的修改版本(我希望我得到了正确的归属,我不知道如何在网上搜索该代码的最早出现)。