20.24 如何利用objdump、grep寻找"pop ret"、"pop pop ret"序列 https://scz.617.cn/unix/201205141711.txt Q: 在编写Exploit过程中,有时需要在指定ELF文件中寻找"pop ret"、"pop pop ret"序 列,我不想在IDA中写脚本或动用反汇编引擎等等,有什么简便办法? A: Tyler Durden 2002-07-28 假设我们想在libc.so中寻找"pop ret"序列: $ objdump -d -j .text `ldd /bin/ls | cut -d' ' -f 3 | grep libc.so.` | grep -B 1 ret | grep -A 1 pop | less 真正的要点是"grep -B 1"与"grep -A 1"的组合使用,得到类似这样的输出: -- 19177: 5d pop %ebp 19178: c2 0c 00 ret $0xc -- 19384: 5d pop %ebp 19385: c2 08 00 ret $0x8 -- 195d1: 5d pop %ebp 195d2: c3 ret -- 72e25: 5f pop %edi 72e26: c3 ret -- 72f02: 5b pop %ebx 72f03: c3 ret -- 730de: 5d pop %ebp 730df: c3 ret $ ldd /bin/ls | cut -d' ' -f 3 | grep libc.so. /lib/i686/cmov/libc.so.6 $ objdump -d -j .text /lib/i686/cmov/libc.so.6 | grep -B 1 ret | grep -A 1 pop | grep -A 1 %e[^b][^p] | less 2a4fc: 5a pop %edx 2a4fd: c3 ret -- 2bf06: 5f pop %edi 2bf07: c3 ret ... 假设寻找"pop pop ret"序列: $ objdump -d -j .text /lib/i686/cmov/libc.so.6 | grep -B 2 ret | grep -A 2 pop | less 16a7c: 5e pop %esi 16a7d: 5d pop %ebp 16a7e: c3 ret -- 16d7e: 5d pop %ebp 16d7f: 8d 81 61 0b fe ff lea -0x1f49f(%ecx),%eax 16d85: c3 ret -- 16dc3: 5b pop %ebx 16dc4: 5d pop %ebp 16dc5: c3 ret ... 不能指望用这种山寨办法得到很精确的匹配,但上述结果仍有可优化的空间: $ objdump -d -j .text /lib/i686/cmov/libc.so.6 | grep -B 2 ret | grep -A 2 pop | grep -E \(pop\|ret\) | less ... 172f7: c3 ret 17335: 5b pop %ebx 17336: 5d pop %ebp 17337: c3 ret 1738e: 5f pop %edi 1738f: 5d pop %ebp 17390: c3 ret ... grep有很多精妙的用法,可以结合实际需求研究一下。 D: scz@nsfocus $ objdump -d -j .text /lib/i686/cmov/libc.so.6 | grep %esp | grep -E \(jmp\|call\) | less 63eb0: ff 54 24 40 call *0x40(%esp) 6750e: ff 54 24 20 call *0x20(%esp) 10720a: ff 54 24 34 call *0x34(%esp) 10ae2e: ff 54 24 40 call *0x40(%esp) ... 将-d换成-D试试: $ objdump -D /lib/i686/cmov/libc.so.6 | grep %esp | grep -E \(jmp\|call\) | less 63eb0: ff 54 24 40 call *0x40(%esp) 6750e: ff 54 24 20 call *0x20(%esp) 10720a: ff 54 24 34 call *0x34(%esp) ... 10d077: ff d4 call *%esp ... 11cd7f: ff 54 2c f3 call *-0xd(%esp,%ebp,1) 11cd83: ff 64 2c f3 jmp *-0xd(%esp,%ebp,1) ... 11cdbf: ff e4 jmp *%esp ... 11ce37: ff 14 6c call *(%esp,%ebp,2) ... 11ced3: ff 64 94 fc jmp *-0x4(%esp,%edx,4) ... 12a243: ff 14 84 call *(%esp,%eax,4) ... 12a453: ff 64 8c 00 jmp *0x0(%esp,%ecx,4) ... 12bf8b: ff 24 14 jmp *(%esp,%edx,1) ... 从这些五花八门的输出可以看出,如果可读即执行的话,寻找trampoline的难度将很 低,DEP很有意义。 objdump的-d、-D不能在任意位置开始反汇编。--start只能作用于-d、-r、-s,甚至 不能作用于-D。-D可以反汇编.text及其它section,但对于没有位于某个section中 的数据就无能为力了。 参看: 《linux-gate.so.1是什么东西》 $ ./get_vsyscall_page $ xxd -g 1 /tmp/vsyscall_page.so | grep "ff e4" 0000770: 02 00 00 00 e4 e1 ff ff e4 01 00 00 38 00 00 00 ............8... $ readelf -e /tmp/vsyscall_page.so ... Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al ... [11] .useless PROGBITS ffffe620 000620 00000c 04 WA 0 0 4 ... Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0xffffe000 0xffffe000 0x0062c 0x0062c R E 0x1000 DYNAMIC 0x0005a8 0xffffe5a8 0xffffe5a8 0x00078 0x00078 R 0x4 NOTE 0x000460 0xffffe460 0xffffe460 0x00018 0x00018 R 0x4 GNU_EH_FRAME 0x000478 0xffffe478 0xffffe478 0x00024 0x00024 R 0x4 $ 0xffffe000+0x0000777=0xffffe777 0xffffe777处有一条"jmp esp"指令,但这个"ff e4"没有位于任何section中,也没 有位于任何segment中。objdump是肯定反汇编不出来了,用xxd凑和着找找还可以。 $ cat /proc/self/maps | grep vdso b7faf000-b7fb0000 r-xp b7faf000 00:00 0 [vdso] 从上述输出看,整页都有E权限。 真心要找这类trampoline的话,不能依赖现成的命令行工具,前面都是山寨搞法,放 在这里仅为备忘。