这是一个利用缓冲区溢出漏洞的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
任何人都可以清楚地解释整个步骤吗?
最佳答案
int
是触发软件中断的操作码。软件中断被编号(从 0 到 255)并由内核处理。在 Linux 系统上,中断 128 (0x80) 是系统调用的常规入口点。内核需要寄存器中的系统调用参数;特别是 %eax 寄存器标识了我们正在谈论的系统调用。
lea
作为“加载有效地址”但不涉及内存访问;这只是进行加法的一种迂回方式)。 setuid
.该系统调用使用一个参数(目标 UID),可以在 %ebx 中找到,在那个点它很方便地包含 0(它在第一条指令中设置)。注意:返回时,寄存器不会被修改,除了 %eax 包含系统调用的返回值,通常为 0(如果调用成功)。 setuid
返回的状态)。 execve
系统调用将用作第二个参数。 cltd
是英特尔文档所称的 AT&T 语法 cdq
.由于 %eax 在这一点上为零,这也将 %edx 设置为零。 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 字符串的内容。这当然是为了通过缓冲区溢出来攻击有缺陷的程序。
关于assembly - 我如何解释以下 shellcode 漏洞利用的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4126599/