主播主播,你在这里直播(OLLVM学姐攻略手册)打靶场啥意思,卡了卡了 我的我的兄弟。D810这玩意在当前样本不好使,具体原因本文不深究。本文主要讲解样本的FLA分析思路,根据汇编代码提取特征并且编写脚本处理。

去除前后对比:



这里很简单直接快速过了不仔细说了。
首先第一件事情就是去找不透明谓词的表达式 尽可能把不同的组合的都找齐全
表达式1:
依旧带入值进行计算 dword_68068设为2 带入可得
化简得到 按位与 结果为0 0等于0 所以左边恒为真 接着就是逻辑或 左边为真 就得看右边了 dword_6807C不知道具体值
去看dword_6807C的交叉引用 看看有没有写入赋值的片段 如果没有 就是初始值为0
根据类型来排序 清一色的offset和read 一个write没有

那么意味着这个表达式恒为真
汇编代码1:
表达式2:
太长了懒得分析 用python直接跑出来结果就行
这个表达式也是恒为真
汇编代码2:
手工分析已经证明谓词恒真,那这一整坨(ADRP 到 CSEL 之前)算出来的东西全是死的。但不能全删,因为最后那条 CSEL W20, W9, W8, LT 是在给状态寄存器写值, 只需要把 CSEL W20, W9, W8, LT 换成 MOV W20, W9。前面那十几条计算指令一条都不用动
接下来就是找锚点,两段的开头都是:
off_61D30 是 GOT 表项,链接期就定死了,只有这个谓词会去读它 。
ADRP 和 LDR 两条指令都会对 off_61D30 产生 xref,不过滤的话同一个谓词会被处理两遍。只认 ADRP,一个谓词就只进一次。
只改 CSEL 那一条

去除后代码塌陷到300多行
随便挑选一个状态值的入口块做跟踪看看

拿这部分来看 骨干处代码是给w8赋值 然后将 w20-w8 如果结果相等就跳转到loc_6D08 结果不等就跳转到0x5CA8
先看loc_6D08 ,技巧就是只看头尾,尾巴处对w20进行赋值0x5E60B6BF,然后无条件返回主分发器。这里对w20的值进行了修改,后面肯定有一个块的值是刚好等于这个值的0x5E60B6BF 而且一定也是多后继的
直接搜索文本值,这里有两个结果0x6334就是拿着前面0x64D4C赋的值去做比较的


把这一截的汇编抠出来看看 简单说就是在前面给0x5E60B6BF赋值的部分他的后继就是0x6334,因为这里的判断是B,NE 不等于 但是这里一定是值等于的 等于才会进入下面的0x6344
如果值不一样 分发器永远不知道前者的后继是谁,无法跳转,逻辑崩盘。所以这里0x64D4C的后继就是0x6334。只不过经过了分发器的手而已,中转了一下梳理一下就是这样的。那么只需要将这个中转器去掉就解决了FLA。也就是让loc_6D08直接跳转到0x6344不经过主分发器,这样patch后主分发器的入度会少1

再回过头去看前面的左边那部分 也就是条件不等于的时候
在这里其实挺眼熟的这玩意不跟0x6334一模一样的吗?按照前面的理论 这个0x5A67B105的值一定是能够搜到的,然后下面也会有业务逻辑,业务逻辑执行完毕后一定会给w20赋值,接着又跳回主分发器。

看一下汇编 跟前面的0x6334无太大的区别(这里其实很长一坨的是不透明谓词表达式 BCF在汇编上的残留)
而且这里对W20的赋值也是通过MOV+MOVK的方式来进行赋值的。
有几个注意点 首先就是对W20的赋值方式有MOV、MOV+MOVK、CSEL
获取真实块的思路就是获取主分发器的所有前驱筛选前面提到的w20赋值方式,如果符合条件就是真实块,不符合条件就分发器的二分查找树的内部节点。
内部节点也分两个情况,一个是以B.EQ、B.NE的,在这里的被比较值w8就是其后继真实块的入口状态值
简单观察了一下当前样本的情况和上述描述都是符合的
但是这里看到两个块


先从左边的来看吧
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!