首页
社区
课程
招聘
去花枝零.一《视频某音》
2023-6-11 14:57 25018

去花枝零.一《视频某音》

2023-6-11 14:57
25018

什么是去花指令的最高境界 莫过于去花之后替换进apk中 依然正常运行 这对汇编功底无疑是一种挑战

今天就献丑拿某流量第一的APK样本做一下IDA脚本一键去花指令分析。还有我们追求的是完美去花 而不是去花 完美去花再去动态调试会更清晰的调试出来函数路径 这个大家应该都能理解把!

献上对比图,因为没有对比就没有伤害

图片描述
图片描述

当然还有替换进去的运行图。

图片描述
图片描述

讲完效果就开干呗!

简单分析

  • 异常B指令 -寄存器间接跳转
    图片描述
    分析一下,使用了寄存器间接跳,干扰反汇编引擎让其无法正确函数尾部,也不能什么都指望IDA呗

  • 上IDA脚本,此代码为片段代码

ARM64(也被称为AArch64)是ARM架构的64位版本。ARM64的调用约定定义了函数如何传递参数和返回结果。在ARM64的调用约定中,参数是通过寄存器和堆栈传递的,具体如下:
参数传递:前八个整型或指针类型的参数通过寄存器X0至X7传递。前八个浮点型参数通过寄存器V0至V7传递。如果函数有更多的参数,那么超出的参数将通过堆栈传递。
返回值:函数的返回值通过寄存器X0(和X1,如果需要)或者V0(浮点数和SIMD类型)返回。
保留寄存器:某些寄存器在函数调用中需要被保留。这意味着如果函数修改了这些寄存器的值,那么它需要在返回前恢复它们的原始值。这些寄存器包括:X19至X28,以及栈指针SP。
调用者保存寄存器:一些寄存器在函数调用前后的值可以不同,如果调用者函数希望保留这些寄存器的值,那么它需要在调用其他函数前保存这些寄存器的值。这些寄存器包括:X0至X18,和所有的V寄存器(V0至V31)

由上文可知,函数在开头必然要分配函数所需的栈空间以及保存调用者保存寄存器,并且在函数尾部恢复保存寄存器以及栈空间,这就是下图脚本原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ins_map = {"sub": "add", "str": "ldr", "stp": "ldp"}#因为入栈出栈是对应的 所以我们只需要吧 基础的三个对应opcode替换下就可以
def find_func_end(self):
        encodings = [0xC0, 0x03, 0x5F, 0xD6# ret 的指令编码
        for i in md.disasm(ida_bytes.get_bytes(self.func_start, 12), 0): #arm64前三条指令分配栈空间保存寄存器
            if i.op_str.find('!') == -1:
                encodings = ks_disasm(self.get_inv_opcode(i)) + encodings
            else:
                s_new = i.op_str.replace("]!", "")
                s_new = s_new.replace(", #-", "],")
                dis_str = '{} {}'.format(self.ins_map.get(i.mnemonic), s_new)  # 调用约定的栈平衡指令
                encodings = ks_disasm(dis_str) + encodings
 
        opcodelist = list(ida_bytes.get_bytes(self.func_start, 0x8000))
        index = find_sublist(opcodelist, encodings)
 
        self.func_end = self.func_start + index  # 函数结尾的地址
        print("func end addr : ", hex(self.func_end))

图片描述

由图中我们也能看出这是标准的入栈出栈格式,运行后得到正确的函数尾部地址 0x32ea8
但是当我们强行把JNI_OnLoad的函数结尾地址改成0X32EA8是不行的,因为IDA还是有点倔脾气的,必须让他心服口服的认为才行!!!

不服,那就干到你服

  • 读汇编

现在找到了正确的函数尾部地址,那么经过上上图我们看到0X32804明显是个不应该在函数中出现的函数,但是他确实有完整的栈平衡格式,这个有完美起跳动作的狼人我们应该怎么处理呢?
图片描述

SP+8???经过分析这个函数返回X0竟然是LR寄存器,哦!明白了,小狼一头!

手动计算下LR的地址明显是0x327FC + 0x34 =0x32830 那么BR X1的位置就是 0x32830

看下0x32830地址的OPCDE OMG嵌套狼-

1
2
3
4
5
6
7
8
9
10
SVC             0
DCD 0x477001DE
  ****
BL              sub_32804
ADD             X6, X0, #8
BR              X6
 ****
B.NE            loc_32858
CLREX
BRK             #3

明显的花指令喽,CPU要是执行了SVC不得崩溃才怪,但是花指令花就花在它执行不到,这这这!!!
那就处理呗,反正能算出他的真实执行地址,把能NOP的都NOP呗

  • 方案1 Unicorn

图片描述

其实我是写了两个版本的,最后Unicorn arm32版本被我PASS掉了,因为都搞64了,嘻嘻嘻嘻 但是放个图纪念一下

  • 方案2 大胆干,早点散
    图片描述

经过分析所有的基础花都是基于那个获取LR的函数来的,那就通过他定位花的位置,直接nop其位置就得了。如果在函数中找到特征码存在的地方,会自动遍历其上下N个地址,直到找到花特征进行NOP

这样就可以了吗?

经过处理并且删除掉内部函数以及无用分支流我们确实得到了一个能够F5的函数,但是这对我们的要求来说远远不够,我们的要求可以替换进真机正常运行吖!

现在F5正常,但是为什么我们替换到真机里就闪退呢?

无非两个问题,第一就是花指令去除到了真实代码块,二就是检测了代码块是否被更改!


  • 动态排查

那就调试呗,首先找到崩溃位置,跟就完了
根据笔者跟了百条指令,发现崩溃点位在
图片描述
图片描述
竟然把0给了SP寄存器,并且循环清空栈空间,这不崩才怪吖!!!

  • 原理分析

其实如果安全人员想让它崩溃有更简单的办法,但是为什么用这种方法呢,大家可以看到,这一系列的操作是为了清空原本的栈空间,那么栈空间有什么不可告人的秘密呢? 如果熟悉汇编代码,画过堆栈图的大佬们应该知道,栈空间可是保存着完整的调用链条的,这也是frida之类打印调用堆栈的原理,当我们调试的时候真机崩溃了,打印出的调用堆栈确是1-2-3-4-5-6那你懵不懵呢?

放个对比图-上面的是正常的崩溃截图,frida可以准确的打印出崩溃地址!可以更清晰的供调试人员分析是因为那里崩溃,方便排查!同时,这也方便了逆向人员定位检测代码!!!
图片描述
下面的就是清空栈空间后的崩溃截图,什么都打印不出来就直接Crash掉了
图片描述


  • 向上溯源

继续排查发现,样本对代码块进行了移位亦或操作
图片描述
图片描述

因为v14指向的是本函数的代码位置,所以当我们开心的NOP掉时,必然触发了它的检测机制,这才是隐藏在最后的狼人,让我们干掉它把
图片描述

直接让他RET就好,pathch一个函数也不好玩,把整个so patch了把,RegisterNatives成功得到 !一个1000kb多的so,500kb都是业务无关代码,冤冤相报何时了,不抗了不抗了。
图片描述

杀什么杀,睡觉去了,我的逆向生涯最后一章结束了。 从此不碰逆向了!!!


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2023-7-13 11:54 被至尊小仙侠编辑 ,原因:
收藏
点赞13
打赏
分享
最新回复 (13)
雪    币: 7811
活跃值: (21271)
能力值: ( LV12,RANK:550 )
在线值:
发帖
回帖
粉丝
随风而行aa 10 2023-6-11 15:16
2
0
可以的
雪    币: 19323
活跃值: (28938)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-6-11 16:19
3
1
tql
雪    币: 6
活跃值: (345)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Acuk强 2023-6-11 18:38
4
0
有样本吗
雪    币: 228
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
exit\(0\) 2023-6-11 18:55
5
0
很是厉害 膜拜
雪    币: 2633
活跃值: (7094)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
至尊小仙侠 2023-6-11 19:09
6
0
Acuk强 有样本吗
https://bbs.kanxue.com/thread-277430.htm 最下面 样本直接发不知道有没有问题 或者直接下载这个app 找libmeta**.so 感觉应该大家都知道是啥吧 呃呃呃
雪    币: 6
活跃值: (345)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Acuk强 2023-6-11 20:16
7
0
那篇不是iOS的吗,这个是安卓吧
雪    币: 2633
活跃值: (7094)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
至尊小仙侠 2023-6-11 20:35
8
0
那个底下评论里有 自取吧 主要这东西不知道有咩有问题 不太能直接放出来感觉  
雪    币: 12837
活跃值: (8998)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
hzqst 3 2023-6-11 20:46
9
0
大哥也太狠了
雪    币: 1671
活跃值: (3987)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小黄鸭爱学习 2023-6-15 15:59
10
0
牛逼,要是能还原成源代码就好了,直接封神。
类似于将猪肉香肠还原成活猪。当然我开玩笑的
雪    币: 51
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
钱的搬运工 2023-6-30 10:24
11
0
花指令去除脚本能开源吗?
雪    币: 1
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
wx_水山 2023-6-30 14:26
12
0
小黄鸭爱学习 牛逼,要是能还原成源代码就好了,直接封神。 类似于将猪肉香肠还原成活猪。当然我开玩笑的
应该没人能做到还原源码吧?
雪    币: 2633
活跃值: (7094)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
至尊小仙侠 2023-7-4 13:14
13
0

..

最后于 2023-7-4 13:15 被至尊小仙侠编辑 ,原因:
雪    币: 2633
活跃值: (7094)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
至尊小仙侠 2023-7-4 13:15
14
0
钱的搬运工 花指令去除脚本能开源吗?

也不算开源吧  放星球里了 

最后于 2024-3-20 18:56 被至尊小仙侠编辑 ,原因:
游客
登录 | 注册 方可回帖
返回