首先,我们没有ASLR和堆栈cookie,并假定我们无法在此系统上创建自己的文件

所以我试图在此代码中执行shellcode,这就是我到目前为止,已经做过了:

我设法覆盖了缓冲区并将foo函数的返回地址设置为关键函数,但是我的问题是如何在此处运行特定的shellcode? execv将运行bin / sh,但我无法用shellcode替换第一个参数,它将无法正常工作,我不确定是否甚至可以使用execv运行shellcode,以及何时将shellcode传递给sh它不起作用。

我也知道返回libc漏洞,但仍然不知道如何使用system()执行shellcode?甚至可以将shellcode传递给它吗?或者也许我可以使用另一个函数只是将shellcode传递给它?

如果我创建了自己的shellcode文件并替换了sh路径,我想我们可以运行自己的shellcode,但是我们无权创建文件,我们只需要使用此代码即可。

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

int bar(char *arg, char *out)
    {
      strcpy(out, arg);
      return 0;
    }

    int foo(char *arg)
    {
      char buffer1[100]="Test program.\n";
      char buffer2[100];
      bar(arg, buffer2);
      printf("%s",buffer1);
      return 0;
    }

    void critical()
    {
      char *msg[]={"/bin/sh",NULL};
      execv(msg[0],msg);
    }

    int main(int argc, char *argv[])
    {
      if (argc != 2)
      {
        fprintf(stderr, "prog_vuln2: argc != 2\n");
        exit(EXIT_FAILURE);
      }
      foo(argv[1]);
      return 0;
    }


#1 楼

当您拥有不可执行的堆栈时,首先想到的是面向返回的程序,顾名思义,该程序使用return来执行所需的代码。
使用ROP时,您将希望使用程序的可执行文件和dll(或Linux中的.so文件),并尽可能减少对系统dll的依赖,因为它们会随操作系统版本的变化而变化。
想法是,您会找到一系列指令。每个人都叫gadget。小工具可以通过以下操作来设置寄存器值:q4312079从堆栈中查询一个值,pop一个值或添加/减去一个寄存器,然后mov(这意味着您通常可以在函数末尾找到它们),从而使它们返回堆栈上的下一个值(预期返回地址将在其中)创建一个ret
一个简单的示例是,当您想使用ROP Chain执行命令时。
您可以(在64位上) OS)跳转到弹出返回,其中堆栈上的第一个值是您的缓冲区地址,第二个值是system的地址,从而导致系统使用缓冲区作为正确寄存器中的参数来调用系统(对于Linux,rdi,ecx对于Windows)。
在32位操作系统上,溢出稍微简单一些。您需要做的是将返回地址覆盖到system,并将其后的4个字节覆盖为缓冲区的地址。这将以缓冲区作为第一个参数执行system

#2 楼

您是正确的,您不能将您的shellcode传递给execv(),但这不是这个主意。您需要的是将返回地址从调用更改为foo()以指向critical(),以便execv()接收路径“ / bin / sh”作为参数。通常,您的shellcode将是critical()本身的内容,并且返回地址将指向保存critical()函数的缓冲区。