iOS加固保护新思路

发布者:Xiaofeixiang
发布于:2023-05-24 15:20

之前有写过【如何给iOS APP加固】,但是经过一段时间的思考,我找到了更具有实践性的代码,具体可以看下面。

技术简介

iOS加固保护是基于虚机源码保护技术,针对iOS平台推出的下一代加固产品。可以对iOS APP中的可执行文件进行深度混淆、加固,并使用独创的虚拟机技术对代码进行加密保护,使用任何工具都无法直接进行逆向、破解。对APP进行完整性保护,防止应用程序中的代码及资源文件被恶意篡改。

技术功能

目前iOS加固主要包含逻辑混淆、字符串加密、代码虚拟化、防调试、防篡改以及完整性保护这三大类功能。通过对下面的代码片段进行保护来展示各个功能的效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (void) test {
    if (_flag) {
        test_string(@"Hello, World!",@"你好,世界!","Hello, World!");
    } else {
         dispatch_async(dispatch_get_mian_queue(), ^{
                do_something( );
          });
    }
    int i=0;
    while (i++ < 100) {
           sleep(1);
           do_something( );
    }
}

将代码编译后拖入IDA Pro中进行分析,可以得到这样的控制流图,只有6个代码块,且跳转逻辑简单,可以很容易地判断出if-else以及while的特征:

 

将其反编译为伪代码,代码逻辑及源代码中使用的字符串均清晰可见,与源代码结构基本一致,效果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void __cdecl -[ViewController test](ViewController *self, SEL a2)
{
   signed int v2; // w19
   __int64 v3;  //x0
 
   if ( self->_flag )
      sub_100006534 ( CFSTR("Hello, World!"),CFSTR("你好,世界!"), "Hello, World!" );
   else
      dispatch_async ( &_dispatch_main_q, &off_10000C308 );
   v2 = 100;
   do
   {
       v3 = sleep( 1u );
       sub_100006584( v3 );
       --v2;
    }
    while ( v2 );
}

1 代码逻辑混淆

通过将原始代码的控制流进行切分、打乱、隐藏,或在函数中插入花指令来实现对代码的混淆,使代码逻辑复杂化但不影响原始代码逻辑。

 

对代码进行逻辑混淆保护后,该函数的控制流图会变得十分复杂,且函数中穿插了大量不会被执行到的无用代码块,以及相互间的逻辑跳转,逆向分析的难度大大增强:

 

若开启防反编译功能,则控制流图会被完全隐藏,只剩下一个代码块,且无法反编译出有效代码(如下图所示),这对于对抗逆向分析工具来说非常有效,包括但不限于(IDA Pro, Hopper Disassembler, Binary Ninja, GHIDRA等)

1
2
3
4
void __cdecl -[ViewController test](ViewController *self , SEL a2)
{
    JUMPOUT (__CS__, sub_100005A94(6LL, a2));
}

2 字符串加密

把所有静态常量字符串(支持C/C++/OC/Swift字符串)进行加密,运行时解密,防止攻击者通过字符串进行静态分析,猜测代码逻辑。

 

对代码中的字符串进行加密之后,所有的字符串都被替换为加密的引用,任何反编译手段均无法看到明文的字符串。你好,世界!,Hello, World!等字符串原本可以被轻易的反编译出来,但保护之后已经看不到了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void __cdecl -[ViewController test](ViewController *self, SEL a2)
{
   __int64 v2;  //x0
   __int64 v3;  //x0
   signed int v4; // w19
   __int64 v5;  //x0
 
   if ( self->_flag )
   {
      v2 = sub_100008288();
      v3 = sub_10000082E8(v2);
      sub_100008228(v3);
      sub_100007FB0( &stru_100010368, &stru_10001038, &unk_100011344);
   }
   else
      dispatch_async ( &_dispatch_main_q, &off_100010308 );
   }
   v4 = 100;
   do
   {
       v5 = sleep( 1u );
       sub_100008004( v5 );
       --v4;
    }
    while ( v4 );
}

3 代码虚拟化

将原始代码编译为动态的DX-VM虚拟机指令,运行在DX虚拟机之上,无法被反编译回可读的源代码,任何工具均无法直接反编译虚拟机指令。

 

采用代码虚拟化保护后,对函数进行反编译将无法看到任何与原代码相似的内容,函数体中只有对虚拟机子系统的调用:

1
2
3
4
5
6
7
8
9
10
11
void __cdecl -[ViewController test](ViewController *self, SEL a2)
{
     SEL v2;  // x19
     __int64 v3;  //  x21
 
     v2 = a2;
     v3 = sub_10000C1EC;
     (( void (* )(void))sub_10000C1D8)();
     sub_10000C1D8( v3, v2);
     sub_10000C180( v3, 17LL);
}

4 防调试

防止通过调试手段分析应用逻辑,开启防调试功能后,App进程可以有效地阻止各类调试器的调试行为:

5 防篡改,完整性保护

防止应用程序中的代码及资源文件被恶意篡改,杜绝盗版或植入广告等二次打包行为。

 

以上是根据顶象的加固产品操作指南出具的流程,如需要更详细的说明,可以自行前往用户中心~


声明:该文观点仅代表作者本人,转载请注明来自看雪