首页
社区
课程
招聘
[原创]ARM64 目前主流的反混淆技术的初窥
发表于: 2025-2-14 01:53 37981

[原创]ARM64 目前主流的反混淆技术的初窥

2025-2-14 01:53
37981

本文仅限于技术讨论,不得用于非法途径,后果自负。

随着混淆技术和虚拟化的发展,我们不可能很方便的去得到我们想要的东西,既然如此,那只能比谁头更铁了,本文列举一下在逆向某一个签名字段中开发者所布下的铜墙铁壁,以及我的头铁方案,本文更多的是分析思路,而不是解决方案,所以样本自己找

在ARM64 中 寄存器跳转只剩下BR 指令了,由于ida 为了 br的准确性(cs:ip跳转),ida会识别成函数跳转,但是这却给开发者带来了天大的便利,于是乎,一个贼好用的anti 反编译器函数分析方案横空出世
alt text
让我们回到汇编

可以看到 X1的值是由sub_8D1F8 返回值加上 0x38 ,而sub_8D1F8一看地址 不对啊,为什么这么近。我们再看看sub_8D1F8的汇编
alt text
如果经常看汇编的小伙伴已经懂了

sub_8D1F8的返回值 被x30 也就是lr寄存器赋值 所以 X1 = sub_8D1F8返回地址 +0x38 = 0x8D1EC + 0x38 = 0x8d224
alt text
既然如此 直接改跳转吧,写个脚本模式匹配下

修复后
alt text

可以看到一排奇怪的东西
alt text
正常程序怎么会有呢,看看汇编

MSR NZCV, X0 x0 = 0 所以zf位为0 所以B.NE 恒成立 所以啥事没干 所以可以直接nop
简单的看下逻辑
alt text
0x8d240 在这个函数内 所以不是代码自解码 就是校验
alt text
查看sub_13C704
alt text
那就是检验咯 不管 下一个函数 sub_13DC3C
修复后发现f5 没东西
alt text
这怎么可能 切换到汇编,研究后

var_38 = x29 x29指向存放 x29 x30的栈地址 所以STR X9, [X10,#8] 等价于 x30 = x9 x0 是参数 所以回上一个函数
alt text

去看看吧 sub_8d5c8

alt text

这里简单介绍什么是控制流平坦化
源代码

经过平坦化后

可以看到一个 while switch 的结构 其中flowState 负责控制整个流程 这个就是平坦化的基本原理 可以看到8行普通的代码被膨胀到了23行 假如我再平坦化 一次呢 我们会发现随着平坦化的越来越多,肉眼阅读的能力也越来越困难
下面介绍一个我从国外看到的方案 590K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Z5k6i4S2Q4x3X3c8J5j5i4W2K6i4K6u0W2j5$3!0E0i4K6u0r3j5X3I4G2k6#2)9J5c8X3S2W2P5q4)9J5k6s2u0S2P5i4y4Q4x3X3c8E0K9h3y4J5L8$3y4G2k6r3g2Q4x3X3c8S2M7r3W2Q4x3X3c8$3M7#2)9J5k6r3!0T1k6Y4g2K6j5$3q4@1K9h3&6Y4i4K6u0V1j5$3!0E0M7r3W2D9k6i4t1`.

下面画一个简单的cfg图

如果走到某一个节点2 必须经过另外一个节点1 那么 2 被 1 支配 1 是 2的支配节点
通过bitset 可以快速计算出来

0: 0
1: 1
2:0,1
3: 0,1
4:0,1,2
5:0,1,2,3
6:0,1,3
将其反转
可得0 是所有节点的支配节点
有什么用?
仔细看平坦化的代码 可以发现 while 会被所有节点支配 所以 控制流分发快 必定被所有节点支配 由此定位到了分发块

我们来看 如果从0要走到 5 有几种 路径
0125
0135
将cfg填充内容

可以得到 0125 flowState = 1, 0124 flowState = 2 那么如果计算支配节点的所有路径 是不是可以得到所有 flowState 的状态

通过switch 可以轻松得到 状态指向的地址

将每一个状态所对应的 地址 连接

检查每一个 没有前继节点的节点 删除 反编译器自动优化

假设 0节点 flowState = 0 1 节点flowState参与 2节点中 flowState = 1 那么 flowState 1节点 将被删除 反编译器自动优化

接下来回到这个demo
将他转换成cfg
alt text

计算支配节点 为0

0:0 flowState =0

1:01 flowState=0

2:02 flowState =3

3:04 flowState =4

4:04 flowState =0

5:05 flowState =0

6: 016 flowState =1

7: 017 flowState =2

0 => 1
1 => 2
2 => 3
3 => 4
4 -> 5

alt text

alt text

这就是简单的ollvm 还原方案
下面进入正题
alt text

计算支配节点 为 0x8C1EC

dfs 算法

符号执行 angr

!!! 熟悉的switch呢 这么变成bge了
alt text
这就是非标准的ollvm了 简单概括就是控制节点下发
alt text
通过if else if else 取代了switch 结构 干扰了状态指向计算 并且带来了更多的复杂性,使其无法定位真实代码块
通过研究 发现 开发者定位真实代码块的方案为

alt text

bne 跳转 等于值跳转
于是乎 模式匹配 找出所有cmp w8,value ? reg bne loc_???的代码 拿到真实块

这里又又又有幺蛾子

alt text
alt text
发现编译器优化 flowState 更新状态的代码 被优化成1份,类似于
有点类似于

优化后

这种只能想办法给他还原回去
alt text

ida 自动优化

alt text
alt text

由于编译器优化 你永远想不到会有多少幺蛾子 ,所以混淆还原应该还有2个步骤

1.对抗编译器优化 上述

2.魔改ollvm 还原成标准ollvm if elseif else 还原为switch
对这2个感兴趣的可以看看这个 f0cK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8J5L8$3k6K6i4K6u0W2M7$3y4A6i4K6u0W2N6h3&6A6N6Y4u0Q4x3X3g2A6N6q4)9J5c8W2)9%4c8h3N6A6j5h3y4G2i4K6u0r3k6r3!0%4L8X3I4G2j5h3c8Q4x3V1k6i4j5i4c8W2M7X3#2S2M7X3E0A6L8X3N6Q4x3X3c8a6j5X3k6#2M7$3y4S2N6r3W2G2L8W2)9J5c8Y4g2F1k6X3I4S2N6s2c8W2L8W2)9J5k6i4m8V1k6R3`.`.

完结撒花表情❀❀❀ ヾ(≧▽≦*)o

.text:000000000008D1E8                 BL              sub_8D1F8
.text:000000000008D1EC                 MOV             X1, X0
.text:000000000008D1F0                 ADD             X1, X1, #0x38 ; '8'
.text:000000000008D1F4                 BR              X1
.text:000000000008D1E8                 BL              sub_8D1F8
.text:000000000008D1EC                 MOV             X1, X0
.text:000000000008D1F0                 ADD             X1, X1, #0x38 ; '8'
.text:000000000008D1F4                 BR              X1
.text:000000000008D1FC                 STP             X29, X30, [SP]
.text:000000000008D200                 LDR             X0, [SP,#8]
.text:000000000008D1FC                 STP             X29, X30, [SP]
.text:000000000008D200                 LDR             X0, [SP,#8]
def antiBR1(start,end):
    addr = start
    while addr < end :
        insn = idc.print_insn_mnem(addr)
        op0 = idc.print_operand(addr,0)
        op1 = idc.print_operand(addr,1)
        # .text:000000000008B03C                 BL              loc_8B04C
        # .text:000000000008B040                 MOV             X1, X0
        # .text:000000000008B044                 ADD             X1, X1, #0x38 ; '8'
        # .text:000000000008B048                 BR              X1
        # match 4 instructions
        if insn == "BL" and (idc.print_insn_mnem(addr + 0xc).find("BR") != -1 or idc.print_insn_mnem(addr + 0x8).find("BR") != -1):
            # find add
            addr1 =addr
            while 1:
                str = get_instruction_at_address(addr1)
                if str != None:
                    if str.find("ADD") != -1:
                        break
                addr1 = addr1 + 4
            opeValue = idc.get_operand_value(addr1,2)
            print("find add: %x" % opeValue)
            # patch addr B (addr +4 + opeValue)
            code,count =ks.asm("B "+ hex(addr + 4 + opeValue),addr)
            print(hex(addr))
            ida_bytes.patch_bytes(addr, bytes(code))
        addr = addr + 4
def antiBR1(start,end):
    addr = start
    while addr < end :
        insn = idc.print_insn_mnem(addr)
        op0 = idc.print_operand(addr,0)
        op1 = idc.print_operand(addr,1)
        # .text:000000000008B03C                 BL              loc_8B04C
        # .text:000000000008B040                 MOV             X1, X0
        # .text:000000000008B044                 ADD             X1, X1, #0x38 ; '8'
        # .text:000000000008B048                 BR              X1
        # match 4 instructions
        if insn == "BL" and (idc.print_insn_mnem(addr + 0xc).find("BR") != -1 or idc.print_insn_mnem(addr + 0x8).find("BR") != -1):
            # find add
            addr1 =addr
            while 1:
                str = get_instruction_at_address(addr1)
                if str != None:
                    if str.find("ADD") != -1:
                        break
                addr1 = addr1 + 4
            opeValue = idc.get_operand_value(addr1,2)
            print("find add: %x" % opeValue)
            # patch addr B (addr +4 + opeValue)
            code,count =ks.asm("B "+ hex(addr + 4 + opeValue),addr)
            print(hex(addr))
            ida_bytes.patch_bytes(addr, bytes(code))
        addr = addr + 4
.text:000000000008D53C loc_8D53C                               ; CODE XREF: sub_8D170:loc_8D530↑j
.text:000000000008D53C                 MRS             X1, NZCV
.text:000000000008D540                 MOV             X0, XZR
.text:000000000008D544                 CMP             X0, XZR
.text:000000000008D548                 MSR             NZCV, X0
.text:000000000008D54C                 B.NE            loc_8D558
.text:000000000008D550                 CLREX
.text:000000000008D554                 BRK             #3
.text:000000000008D558
.text:000000000008D558 loc_8D558                               ; CODE XREF: sub_8D170+3DC↑j
.text:000000000008D558                 MSR             NZCV, X1
.text:000000000008D53C loc_8D53C                               ; CODE XREF: sub_8D170:loc_8D530↑j
.text:000000000008D53C                 MRS             X1, NZCV
.text:000000000008D540                 MOV             X0, XZR
.text:000000000008D544                 CMP             X0, XZR
.text:000000000008D548                 MSR             NZCV, X0
.text:000000000008D54C                 B.NE            loc_8D558
.text:000000000008D550                 CLREX
.text:000000000008D554                 BRK             #3
.text:000000000008D558
.text:000000000008D558 loc_8D558                               ; CODE XREF: sub_8D170+3DC↑j
.text:000000000008D558                 MSR             NZCV, X1
.text:000000000013DCE4 000              MOV             X30, X17
.text:000000000013DCE8 000               SUB             SP, SP, #0x50 ; 'P'
.text:000000000013DCEC 050              STP             X29, X17, [SP,#0x50+var_10]
.text:000000000013DCF0 050              ADD             X29, SP, #0x50+var_10
.text:000000000013DCF4 050              STUR            X0, [X29,#-0x10]
.text:000000000013DCF8 050              STUR            X1, [X29,#-0x18]
.text:000000000013DCFC 050            STR             X0, [SP,#0x50+var_30]
.text:000000000013DCE4 000              MOV             X30, X17

[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!

最后于 2025-2-15 10:23 被method编辑 ,原因:
收藏
免费 240
支持
分享
最新回复 (153)
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2025-2-14 02:52
0
雪    币: 2115
活跃值: (1757)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
666
2025-2-14 11:07
0
雪    币: 1
活跃值: (86)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享,努力学习一下
2025-2-14 11:41
0
雪    币: 59
活跃值: (1552)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
6666
2025-2-14 11:50
0
雪    币: 439
活跃值: (1528)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
感谢分享
2025-2-14 12:33
0
雪    币: 2269
活跃值: (1688)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
7
不错,楼主最近还真是铁
2025-2-14 13:36
0
雪    币: 48
活跃值: (2298)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
膜拜大佬
2025-2-14 14:15
0
雪    币: 14
活跃值: (384)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2025-2-14 14:53
0
雪    币: 1827
活跃值: (2363)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
5
2025-2-14 16:17
0
雪    币: 1411
活跃值: (1017)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
6666
2025-2-14 16:27
0
雪    币: 1664
活跃值: (3317)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
6666
2025-2-14 17:21
0
雪    币: 104
活跃值: (5161)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
66666666666666666
2025-2-14 17:47
1
雪    币: 75
活跃值: (1173)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
14
66666666666666666
2025-2-14 17:53
0
雪    币: 13
活跃值: (2103)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
666666666
2025-2-14 17:59
0
雪    币: 1642
活跃值: (2032)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
666
2025-2-14 18:56
0
雪    币: 2
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
666
2025-2-14 23:10
0
雪    币: 1518
活跃值: (1405)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
真的有看沒有懂...
2025-2-15 01:23
0
雪    币: 168
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
666
2025-2-15 12:14
0
雪    币: 2013
活跃值: (1578)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
20
6666666
2025-2-15 14:07
0
雪    币: 78
活跃值: (1151)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
6666666
2025-2-15 19:17
0
雪    币: 3176
活跃值: (1224)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
666
2025-2-15 20:48
0
雪    币: 2141
活跃值: (1400)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
666
2025-2-15 21:14
0
雪    币: 19
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
24
666
2025-2-16 00:00
0
雪    币: 7385
活跃值: (4712)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
感谢分享
2025-2-16 13:08
0
游客
登录 | 注册 方可回帖
返回