拟态决赛的时间在工作日,听说有一道 JerryScript 的 Pwn 题。作为苦逼打工人,周五抽空尝试做了一下。当时构造出 8 字节的越界读写后,一直尝试利用,但由于 GC 的原因一直没有成功,时间比较短,如果再多些时间应该也是可以利用成功的不过在调试过程中,了解了该引擎的一些机制,发现相比 v8 还是简单很多的。赛后与其他师傅交流,才发现原来可以通过 Patch 中的漏洞实现任意长度的越界读写。因此尝试复现了一下,诞生了这篇 writeup。题目给了几个程序运行的链接库,看了下版本是Ubuntu GLIBC 2.39-0ubuntu8.6,由于我本地位wsl2 ubuntu22版本,所以patch了一下查看jerryscript的版本信息接着本地编译一个,最后会看到build/bin目录下有一个jerry的可执行文件类型的定义位于这个文件中jerryscript/jerry-core/ecma/base/ecma-globals.hecma_object_t是类型header的开始部分,其中主要的字段有type、gc_next_cp、u1、u2其中的u1和u2分别代表properties和prototype相关,不是每一个对象都有这两个字段type_flags_refs中的Type就指的是类型,但是并不像v8那样细分为object arr、double arr……其中的refs,这个对于利用的稳定性比较重要,如果产生了越界,可以通过修改这个字段不让改对象被gc回收,从而保持布局的稳定性。然后笔者在实际利用过程中并没有这样,当时没有意识到,回头翻看源码的时候才发现。所以采用了人为构造函数进行ref,增加ref count下面是一个简单的图示接着的gc_next_cp是用于gc回收时扫描对象而设立的字段,u1与properties相关,在受限的情况下,可以采用修改和这个字段的方式进行类型混淆,u2和原型链有关,暂时也没想到这个怎么用笔者尝试过,当时由于稳定性的原因,没有构造出很好用的原语,等待后续研究……下面是ecma_extended_object_t结构体简化完毕其实是这样。ecma_object_t object和一个union u其中的object就是上方的通用类型的header,对于复杂类型会使用到ecma_extended_object_t,其中的union u会根据不同的类型选择不同的字段,以此定义不同对象的属性字段下面笔者迁移了部分v8 exploit的知识,通过ai写出了一个针对于jerryscript调试的gdb插件,提升了调试的效率这里以dataview为例子dataview的定义arraybuffer的定义实际内存中是这样的,后方的0x10是对应的byte_offset。0x64eccc323748是arraybuffer的地址注意下方的0x41414141,这里是对应的inline表示,这个并不利于后续的利用,这个是利用的后话了如何让arraybuffer分配出一个raw pointer呢?这里只需要提高arraybuffer分配的大小即可,我这里提升到了0x1000diff的内容删去了一个对于nan的检查,定位源码可以找到代码的上下文,调用函数是[A] ecma_op_to_integer,从而可以找到上层的调用上下文分别是[B] ecma_op_to_length和[C] ecma_op_to_index函数接着就是更上层的调用查找,对于ecma_op_to_length来说,更多的是倾向于被字符串和regexp的处理,如果存在漏洞,那么品相也不一定很好,所以我这里继续看了ecma_op_to_index的上层调用ecma_op_to_index的上层调用如下,这里可以看到很具有代表意义的两个对象,dataview和typearray,如果熟悉v8 exploit的话,这里两个对象的嫌疑最大 ,事实也确实如此,所以接下来继续审计dataview相关的实现typearray的代码似乎没有很明显的漏洞,因此主要审计了dataview首先我们得看一下jerryscript中的dataview对象的结构,所有对象的结果为与这个文件下jerryscript/jerry-core/ecma/base/ecma-globals.h可以看到使用了ecma_extended_object_t的header,这个是对于复杂对象的header,其中集成了ecma_object_t的内容。接着又一个buffer_p指针,这个其实指向了Arraybuffer,接着是对应的byte_offset,用户索引Arraybuffer中的偏移接着看Arraybuffer的对象结构,结构很简单,其中的buffer_p也就类似于v8中的backingstore接着可以动态的看一下,测试代码入下其中地址0x62e46178e5f0中的dword 0x10就是这里设置的byte_offset同时dataview还支持这样的语法,也就是会有一个view_offset,下发设置了view_offset为0x10,但是索引了0x20的位置,这个是不合法的,会报错审计代码路径位于jerryscript/jerry-core/ecma/operations/ecma-dataview-object.c先审计ecma_op_dataview_create这个函数,关于dataview对象的创建,代码如下这里首先会通过参数列表获取到buffer,这个就是Arraybuffer,接着会检查这个用户传入的Arraybuffer的值是否合法,也就是真实类型是否为Arraybuffer接着通过参数列表为offset赋值,同时检查是否有问题,可以看到上方[a]处调用了ecma_op_to_index,这个函数涉及到nan的处理,正常遇到nan会将nan清空为0,并返回正常的状态码ECMA_VALUE_EMPTY,但是这里没有清空,所以会正常绕过这个检查,并保留原有的nan的值接着获取Arraybuffer的长度,并赋值给buffer_byte_length。然后进入if (offset > buffer_byte_length)判断问题其实就出现在这个地方,这里的比较逻辑是将nan的值从栈上取出来,赋值给xmm0,也就是浮点数寄存器,接着调用comisd进行比较。需要注意的在 x86/x64 汇编中,comisd 指令在遇到 NaN 时,如果任一操作数是 NaN,它会设置 ZF=1, PF=1, CF=1,接下来的jbe,它的跳转条件是 CF=1 或 ZF=1,所以这里只要涉及到NaN的比较,这里都会被解释成offset <= length,结果就是绕过这个bound check调试下eflag,没有比较之前是这样比较之后是这样,成功绕过了这个检查现在可以得到一个结论,对于这个检查if (offset > buffer_byte_length)offset = NaN 时,可以直接pass同样的,这个绕过模式还可以传播为(NaN + arb_val > buffer_byte_length)→false,所以我们可以在NaN
...(已截断)
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-289314.htm
[原创] 第八届“强网”拟态防御国际精英挑战赛 - Cherry
453 浏览
3 回复
这篇教程详细讲解了使用Frida对iOS应用进行逆向分析的过程,涵盖了从侦查到漏洞利用的完整流程,适合学习iOS安全和逆向分析技术。????
这篇教程详细讲解了使用Frida对iOS应用进行逆向分析的过程,涵盖了从侦查到漏洞利用的完整流程,适合学习iOS安全和逆向分析技术。????
学习到了 支持