xyz 新文章解释了 PS Vita 首个公开的内核漏洞的原理

  • B
    BoomerCE
    几个小时之前刚刚发布的文章,非常值得一读

    https://blog.xyz.is/2016/vita-netps-ioctl.html
  • k
    kz.lj
    好歹daoni
  • f
    fantasyzxc
    完美破解了吗 到底 3.60表示流口水
  • e
    eulereld
    破的聽說也不是全部遊戲?那期待一下接下來的進展也無可厚非吧,畢竟PSP 破解後能玩的花樣多太多,珠玉在前
  • l
    londo_bell
    看完了,关键在于修改内核SOCKET结构中的函数指针,可见HEAP在FREE之后进一步清零是多么重要
  • l
    londo_bell
    不过第二个线程要准确地覆盖第一个线程创建的内核SOCKET结构,并修改相应位置的指针,Yifan Lu他们应该尝试了很多次
  • k
    kabunsan
    能模拟3DS么,有就把吃灰的PSV翻出来 -_-||

    —— 来自 HUAWEI GRA-UL10, Android 6.0
  • n
    nihse
    本来想着如果能拿来玩模拟器倒也不错,
    但我买了猴戏机···
  • c
    cfeng123
    仔细看了下文章
    大概的原理就是利用了VITA的KM_SLEEP标志(当可供申请的内存不足时,会卡住当前线程等内存释放到可申请为止)

    然后在 NetBSD里有个BUG,在调用ioctl接口前的判断内存空间是否足够时,判断的是是否有5个0x800 (2048字节)的区块,但申请时,使用的标志位来申请内存最多可以申请0X1FFF(8191字节)。

    所以原理就是,
    B线程 先把内存占用到足够多 (有5个0X800,但没有一个完整的0X1FFF的区块)
    A线程 先申请一个socket,然后传入参数flag申请足够大的内存(大于目前的内存空余量,小于等于8191) 于是因为heapmem = malloc(memsz, 0, 8) 内存不足,于是SLEEP了
    B线程 释放掉A线程申请的socket,然后往对应的那块内存写入破解用的数据 再释放掉足够的内存,让A线程可以申请内存
    A线程 申请到内存,开始调用后续代码,使用原先socket的那块内存空间的函数指针(已经被B线程篡改,指向了破解的函数) crack!
  • c
    cfeng123
    不,并不是进一步清零的问题,其实问题出在了判断和申请不一致(判断是5块0x800,申请是1块1-0X1FFF)
    然后杯具的socket没有引用计数再加上vita那个申请不到内存就休眠等到能申请的时候的设定(一般的程序基本上都是alloc失败就返回NULL了)

    3个问题只要有一个没有,就不会触发这个问题
  • l
    lvcha
    都是码农,差距怎么就那么大呢。。他说的我看都看不懂
  • c
    cfeng123
    3.61已经修复了这个漏洞了
  • B
    BoomerCE
    3.61 就已经封上了
  • l
    londo_bell
    倘若FREE后有清零,这步就不成立了
  • c
    cfeng123
    哦,我没注意他们是如何往A线程的socket那块空间释放后重新写数据的。要往这块空间写数据,似乎也要调用有核心权限的函数,那free时没memset就的确是有很大问题了
  • 亚瑟姆·明日野
    能模拟个NDS就不错了还3DS
  • 雨鱼
    目前只能说henkaku不支援3.61而已,并不能说已经封上了
  • d
    deadbeef
    跟清0没有任何关系 任何一个系统都没有要求内存被释放后还需要清0的
    而该BUG之所以只在VITA上发生 核心问题是

    VITA的SOCKET结构 没有引用计数 没有引用计数 没有引用计数

    正是因为没有引用计数 才导致出现了UAF漏洞
    如果能确保UAF漏洞不出现 内存释放后是不会被使用的 清0与否根本无关紧要
  • l
    londo_bell
    见22楼引用,调侃一下罢了,这么激动
  • d
    deadbeef
    倒不是激动 只是觉得有点误导人
    没有任何代码会在FREE之前清0内存的 更不可能在FREE之后

    这里的问题很简单 就算真的在FREE前清了0
    破解者依旧可以人为造成一个UAF漏洞的发生
    结果就是一个全0的SOCKET结构 导致内核发生不可预知的崩溃
    虽然这个崩溃无法被破解者利用了 但是依旧是一个内核态的崩溃

    所以问题的核心在于UAF漏洞的产生
    而不在于FREE后清不清0

    我主要想澄清这一点
    并不希望有人看了这调侃后 真的养成了FREE前都清0一下的习惯 这是完全没必要的
    更重要的是 在通常的内存管理机制中 使用FREE是不需要知道该块的大小的 而清0则需要
    如果执意要这样 会影响到算法的设计 甚至可能因为使用的静态大小并不是实际的动态结构大小 而引入新的漏洞