witchan 发表于 2023-2-27 17:00

【iOS逆向与安全】使用ollvm混淆你的源码

前言当你在研究别人源码的时候,是不是期望着别人代码没有进行任何的防护和混淆。这时的你,是不是应该考虑一下自己代码的安全.本篇文章将告诉你,如何使用ollvm来混淆iOS端的代码【此文为入门贴,大佬请绕道】。
一、目标编译ollvm工具,并在Xcode中来混淆你的ipa或动态库,增加别人破解你源码的难度。二、工具
[*]ollvm:下载地址:https://github.com/heroims/obfuscator
[*]Xcode:iOS开发工具
三、步骤1、基础知识LLVMLLVM(Low Level Virtual Machine)是一个开源的编译器基础架构,它包含了一组模块化、可重用的编译器和工具,支持多种编程语言和目标架构,包括x86、ARM和MIPS等。LLVM最初由美国伊利诺伊大学香槟分校(University of Illinois at Urbana–Champaign)的Chris Lattner教授开发,现在由LLVM社区进行维护和发展。LLVM的核心思想是将编译器分为前端和后端两个部分,前端负责将源代码转换为中间表示(IR),后端负责将中间表示转换为目标机器的汇编代码。这种设计使得LLVM可以支持多种编程语言,因为只需要为每种语言编写一个前端,就可以利用后端的通用性支持多种目标架构。除了编译器之外,LLVM还包括了一些工具,例如优化器、调试器、汇编器和反汇编器等,这些工具可以帮助开发者更好地分析和调试程序,提高代码的性能和可靠性。LLVM已经成为了广泛使用的编译器基础架构,许多编程语言和工具链都采用了LLVM作为后端,例如C、C++、Objective-C、Swift、Rust、Go等。LLVM还被广泛应用于计算机体系结构研究、代码安全性分析、机器学习等领域。https://witchan-1256170176.cos.ap-chengdu.myqcloud.com/620d42e96cb8ec53c539ef17_c47cbc8cca9448df840b6c203a38ab8d.jpegClangClang是基于LLVM框架的C、C++、Objective-C和Objective-C++编译器,它是一个开源项目,由LLVM社区进行开发和维护。Clang的设计目标是提供高质量的诊断、快速的编译速度、低内存占用和良好的可移植性。Clang的编译器前端使用了现代的编译器架构,包括基于词法分析器和语法分析器的语法分析,生成抽象语法树(AST)并进行类型检查和语义分析等步骤。这些步骤的优化和并行化使得Clang能够快速地进行编译,同时提供了更好的错误和警告信息,有助于开发者更快地发现和修复代码中的问题。除了作为独立的编译器之外,Clang还可以作为其他工具的库使用,例如静态分析工具、编辑器插件和代码重构工具等。Clang的模块化设计和良好的API使得它可以轻松地被集成到其他工具中,从而提供更好的编程体验。由于Clang的优秀性能和良好的设计,它已经成为了许多项目的首选编译器,例如LLVM自身、macOS和iOS的默认编译器等。同时,许多开发者和组织也在积极地开发和贡献Clang的代码,使得它在未来仍有广阔的发展空间。OLLVMOLLVM(Obfuscator-LLVM)是基于LLVM框架的混淆器,它可以对程序进行混淆以提高程序的安全性。OLLVM的设计目标是提供一种灵活的、可定制的混淆方案,使得攻击者更难理解和分析程序的行为。OLLVM通过对程序进行多种混淆操作来实现混淆效果,例如代码替换、函数内联、控制流平坦化、加密等。这些混淆操作可以改变程序的控制流图和数据流图,使得程序更难以被理解和逆向分析。同时,OLLVM还提供了一些额外的安全机制,例如加密程序的字符串、使用栈保护和位置无关代码等,以增加程序的安全性。由于OLLVM是基于LLVM框架开发的,它可以与现有的LLVM工具和编译器集成,例如Clang和LLDB等。这使得开发者可以轻松地在现有的开发环境中使用OLLVM,并且可以使用现有的工具对混淆后的程序进行调试和分析。尽管OLLVM的主要目的是提高程序的安全性,但它也可以用于其他领域,例如代码保护、代码压缩和代码优化等。由于其灵活性和可定制性,OLLVM已经被广泛应用于许多领域,例如网络安全、游戏开发和金融等。https://witchan-1256170176.cos.ap-chengdu.myqcloud.com/compiler-arch.svgIR之间的pass,就是混淆器工作的地方。相关代码位于obfuscator/llvm/lib/Transforms/Obfuscation/2、编译ollvm命令如下:witchan@witchandeMacBook-Air ~ % git clone -b llvm-13.x https://github.com/heroims/obfuscator.git
witchan@witchandeMacBook-Air ~ % $cd obfuscator
witchan@witchandeMacBook-Air ~ % mkdir build
witchan@witchandeMacBook-Air ~ % cd build
witchan@witchandeMacBook-Air ~ % cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_CREATE_XCODE_TOOLCHAIN=ON -DLLVM_ENABLE_PROJECTS="clang;libcxx;libcxxabi" -DLLVM_ENABLE_NEW_PASS_MANAGER=OFF ../llvm
witchan@witchandeMacBook-Air ~ % make -j8
witchan@witchandeMacBook-Air ~ % sudo make install-xcode-toolchain
witchan@witchandeMacBook-Air ~ % mv /usr/local/Toolchains/Library/Developer/注:make -j8这命令编译的快慢,取决于你的硬件设备挨个执行以上命令后,ollvm就编译并安装完成,效果如下:https://witchan-1256170176.cos.ap-chengdu.myqcloud.com/6gk1hq.png3、混淆命令及效果对比混淆命令简介
[*]fla:该选项使用函数级别的混淆来隐藏程序的结构。这通过随机重命名函数、添加不必要的控制流和删除调用的函数来实现。这增加了反编译和分析代码的难度。
[*]bcf:该选项使用基本块级别的混淆来隐藏代码的结构。这通过改变基本块之间的控制流、添加不必要的基本块和移除基本块之间的条件分支来实现。
[*]-sub:该选项使用字符串混淆来隐藏代码中的常量字符串。这通过将字符串分成几个小块、将其存储在数组中并在运行时重新组合来实现。这使得分析代码和查找敏感信息更加困难。
[*]split:该选项使用控制流混淆来增加程序的复杂性。这通过将函数分成几个基本块、添加随机的跳转指令和在运行时随机重组这些基本块来实现。这使得代码的流程更难以跟踪,从而增加了破解和反编译的难度。
[*]sobf:该选项使用源代码混淆技术来隐藏代码的逻辑和结构。这通过使用类似加密的方式对代码进行变换,使其难以理解和分析。这可以通过运行时解密来执行,从而隐藏代码的真实功能。
示例代码如下:- (void)testMethod {
    NSString *name = @"wit";
    int age = 18;
   
    NSArray *list = @[@1,@3,@5,@18];
    for (int i=0; i<list.count; i++) {
      int value = intValue];
      if (value == age) {
            age += 10;
            name = @"chan";
      }
    }
    NSLog(@"name = %@", name);
    NSLog(@"age = %d", age);
}未使用混淆:__int64 __fastcall -(__int64 a1, __int64 a2)
{
void *v2; // x0
__int64 v3; // ST70_8
void *v4; // x0
__int64 v5; // ST68_8
void *v6; // x0
__int64 v7; // ST60_8
void *v8; // x0
__int64 v9; // ST58_8
void *v10; // x0
void *v11; // x0
void *v12; // ST20_8
int v13; // ST2C_4
__int64 result; // x0
int i; //
void *v16; //
int v17; //
__int64 v18; //
__int64 v19; //
__int64 v20; //
__int64 v21; //
__int64 v22; //
__int64 v23; //
__int64 v24; //
__int64 v25; //

v25 = *(_QWORD *)__stack_chk_guard_ptr;
v20 = a1;
v19 = a2;
v18 = objc_retain(&stru_100008078);
v17 = 18;
v2 = objc_msgSend(off_10000D2D0, (const char *)off_10000D290, 1LL);
v3 = objc_retainAutoreleasedReturnValue(v2);
v21 = v3;
v4 = objc_msgSend(off_10000D2D0, (const char *)off_10000D290, 3LL);
v5 = objc_retainAutoreleasedReturnValue(v4);
v22 = v5;
v6 = objc_msgSend(off_10000D2D0, (const char *)off_10000D290, 5LL);
v7 = objc_retainAutoreleasedReturnValue(v6);
v23 = v7;
v8 = objc_msgSend(off_10000D2D0, (const char *)off_10000D290, 18LL);
v9 = objc_retainAutoreleasedReturnValue(v8);
v24 = v9;
v10 = objc_msgSend(off_10000D2D8, (const char *)off_10000D298, &v21, 4LL);
v16 = (void *)objc_retainAutoreleasedReturnValue(v10);
objc_release(v9);
objc_release(v7);
objc_release(v5);
objc_release(v3);
for ( i = 0; i < (unsigned __int64)objc_msgSend(v16, (const char *)off_10000D2A0); ++i )
{
    v11 = objc_msgSend(v16, (const char *)off_10000D2A8, i);
    v12 = (void *)objc_retainAutoreleasedReturnValue(v11);
    v13 = (unsigned __int64)objc_msgSend(v12, (const char *)off_10000D2B0);
    objc_release(v12);
    if ( v13 == v17 )
    {
      v17 += 10;
      objc_storeStrong(&v18);
    }
}
NSLog(&stru_1000080B8);
NSLog(&stru_1000080D8);
objc_storeStrong(&v16);
result = objc_storeStrong(&v18);
*(_QWORD *)__stack_chk_guard_ptr;
return result;
}开启ollvm混淆:https://witchan-1256170176.cos.ap-chengdu.myqcloud.com/o3yxep.pnghttps://witchan-1256170176.cos.ap-chengdu.myqcloud.com/8ykzth.pnghttps://witchan-1256170176.cos.ap-chengdu.myqcloud.com/k919ci.pnghttps://witchan-1256170176.cos.ap-chengdu.myqcloud.com/fa7ik4.pnghttps://witchan-1256170176.cos.ap-chengdu.myqcloud.com/z9bkhk.png混淆参数:-mllvm -fla -mllvm -bcf -mllvm -sub -mllvm -split -mllvm -sobf混淆后效果如下:__int64 __fastcall -(__int64 a1, __int64 a2)
{
void *v2; // x0
void *v3; // x0
__int64 v4; // ST58_8
void *v5; // x0
__int64 v6; // ST50_8
void *v7; // x0
__int64 v8; // ST48_8
void *v9; // x0
void *v10; // x0
signed int v11; // w8
BOOL v12; // w9
signed int v13; // w8
BOOL v14; // w9
signed int v15; // w8
BOOL v16; // w14
signed int v17; // w8
void *v18; // x0
void *v19; // ST20_8
int v20; // ST2C_4
BOOL v21; // w12
signed int v22; // w8
BOOL v23; // w9
signed int v24; // w8
BOOL v25; // w12
signed int v26; // w8
signed int v27; // w8
BOOL v28; // w9
signed int v29; // w8
BOOL v30; // w12
signed int v31; // w8
BOOL v32; // w14
signed int v33; // w8
BOOL v34; // w9
signed int v35; // w8
void *v37; // x0
void *v38; // ST08_8
int v39; // ST14_4
signed int v40; //
int v41; //
int v42; //
void *v43; //
int v44; //
__int64 v45; //
__int64 v46; //
__int64 v47; //
__int64 v48; //
__int64 *v49; //
const char *v50; //
void *v51; //
__int64 v52; //
unsigned __int64 v53; //
const char *v54; //
void *v55; //
void *v56; //
__int64 v57; //
bool v58; //
__int64 *v59; //
int v60; //
int v61; //
__int64 v62; //
__int64 v63; //
__int64 v64; //
__int64 v65; //
__int64 v66; //
__int64 v67; //

v67 = *(_QWORD *)__stack_chk_guard_ptr;
v47 = a1;
v46 = a2;
v45 = objc_retain(&stru_10000C078);
v44 = 18;
v2 = objc_msgSend(off_1000112D0, (const char *)off_100011290, 1LL);
v48 = objc_retainAutoreleasedReturnValue(v2);
v63 = v48;
v49 = &v64;
v50 = (const char *)off_100011290;
v51 = off_1000112D0;
v40 = -1933834049;
while ( 1 )
{
    while ( 1 )
    {
      while ( 1 )
      {
      while ( 1 )
      {
          while ( 1 )
          {
            while ( 1 )
            {
            while ( 1 )
            {
                while ( v40 == -1944675086 )
                {
                  v23 = x_24 * (x_24 - 1) % 2u == 0;
                  if ( ((unsigned __int8)v23 & (y_25 < 10) | v23 ^ (y_25 < 10)) & 1 )
                  v24 = -484710506;
                  else
                  v24 = -757913245;
                  v40 = v24;
                }
                if ( v40 != -1933834049 )
                  break;
                v3 = objc_msgSend(v51, v50, 3LL);
                v52 = objc_retainAutoreleasedReturnValue(v3);
                v40 = -1240448313;
            }
            if ( v40 != -1917278325 )
                break;
            v40 = 1916623537;
            }
            if ( v40 != -1863636706 )
            break;
            if ( v58 )
            v27 = -1295475565;
            else
            v27 = -706815919;
            v40 = v27;
          }
          if ( v40 != -1847141909 )
            break;
          v10 = objc_msgSend(v55, v54);
          if ( v53 >= (unsigned __int64)v10 )
            v11 = 1801130365;
          else
            v11 = 1380523063;
          v40 = v11;
      }
      if ( v40 != -1846767803 )
          break;
      v40 = -267481379;
      }
      if ( v40 != -1502917571 )
      break;
      v54 = (const char *)off_1000112A0;
      v55 = v43;
      v40 = -1847141909;
    }
    if ( v40 == -1361227290 )
      break;
    switch ( v40 )
    {
      case -1295475565:
      v44 += 10;
      v40 = 1987329712;
      break;
      case -1240448313:
      v4 = v52;
      *v49 = v52;
      v5 = objc_msgSend(off_1000112D0, (const char *)off_100011290, 5LL);
      v6 = objc_retainAutoreleasedReturnValue(v5);
      v65 = v6;
      v7 = objc_msgSend(off_1000112D0, (const char *)off_100011290, 18LL);
      v8 = objc_retainAutoreleasedReturnValue(v7);
      v66 = v8;
      v9 = objc_msgSend(off_1000112D8, (const char *)off_100011298, &v63, 4LL);
      v43 = (void *)objc_retainAutoreleasedReturnValue(v9);
      objc_release(v8);
      objc_release(v6);
      objc_release(v4);
      objc_release(v48);
      v42 = 0;
      v40 = -381231803;
      break;
      case -1088106110:
      v40 = -1361227290;
      break;
      case -1009849083:
      v61 = v60 + 1;
      v40 = -792637388;
      break;
      case -792637388:
      v42 = v61;
      v40 = -381231803;
      break;
      case -757913245:
      v40 = -484710506;
      break;
      case -706815919:
      v40 = 975706093;
      break;
      case -484710506:
      v58 = v41 == v44;
      v25 = x_24 * (x_24 - 1) % 2u == 0;
      if ( (!v25 ^ (y_25 >= 10) | (v25 && y_25 < 10)) & 1 )
          v26 = -1863636706;
      else
          v26 = -757913245;
      v40 = v26;
      break;
      case -381231803:
      v53 = v42;
      v40 = -1502917571;
      break;
      case -267481379:
      v56 = v43;
      v57 = v42;
      v14 = x_24 * (x_24 - 1) % 2u == 0;
      if ( ((unsigned __int8)v14 & (y_25 < 10) | v14 ^ (y_25 < 10)) & 1 )
          v15 = -1917278325;
      else
          v15 = -1846767803;
      v40 = v15;
      break;
      case 265667512:
      v60 = v42;
      v30 = x_24 * (x_24 - 1) % 2u == 0;
      if ( (!v30 ^ (y_25 >= 10) | (v30 && y_25 < 10)) & 1 )
          v31 = 1998138173;
      else
          v31 = 1042960370;
      v40 = v31;
      break;
      case 543048662:
      NSLog(&stru_10000C0B8);
      NSLog(&stru_10000C0D8);
      v34 = x_24 * (x_24 - 1) % 2u == 0;
      if ( ((unsigned __int8)v34 & (y_25 < 10) | v34 ^ (y_25 < 10)) & 1 )
          v35 = -1088106110;
      else
          v35 = 1393219629;
      v40 = v35;
      break;
      case 818848043:
      v37 = objc_msgSend(v56, (const char *)off_1000112A8, v57);
      v38 = (void *)objc_retainAutoreleasedReturnValue(v37);
      v39 = (unsigned __int64)objc_msgSend(v38, (const char *)off_1000112B0);
      objc_release(v38);
      v41 = v39;
      v40 = 1041770448;
      break;
      case 975706093:
      v28 = x_24 * (x_24 - 1) % 2u == 0;
      if ( ((unsigned __int8)v28 & (y_25 < 10) | v28 ^ (y_25 < 10)) & 1 )
          v29 = 265667512;
      else
          v29 = 1042960370;
      v40 = v29;
      break;
      case 1041770448:
      v18 = objc_msgSend(v56, (const char *)off_1000112A8, v57);
      v19 = (void *)objc_retainAutoreleasedReturnValue(v18);
      v20 = (unsigned __int64)objc_msgSend(v19, (const char *)off_1000112B0);
      objc_release(v19);
      v41 = v20;
      v21 = x_24 * (x_24 - 1) % 2u == 0;
      if ( (!v21 ^ (y_25 >= 10) | (v21 && y_25 < 10)) & 1 )
          v22 = 2069967268;
      else
          v22 = 818848043;
      v40 = v22;
      break;
      case 1042960370:
      v40 = 265667512;
      break;
      case 1146841418:
      v32 = x_24 * (x_24 - 1) % 2u == 0;
      if ( (v32 ^ (y_25 < 10) | (v32 && y_25 < 10)) & 1 )
          v33 = 543048662;
      else
          v33 = 1393219629;
      v40 = v33;
      break;
      case 1380523063:
      v12 = x_24 * (x_24 - 1) % 2u == 0;
      if ( ((unsigned __int8)v12 & (y_25 < 10) | v12 ^ (y_25 < 10)) & 1 )
          v13 = -267481379;
      else
          v13 = -1846767803;
      v40 = v13;
      break;
      case 1393219629:
      NSLog(&stru_10000C0B8);
      NSLog(&stru_10000C0D8);
      v40 = 543048662;
      break;
      case 1801130365:
      v62 = v45;
      v40 = 1146841418;
      break;
      case 1916623537:
      v16 = x_24 * (x_24 - 1) % 2u == 0;
      if ( (v16 ^ (y_25 < 10) | (v16 && y_25 < 10)) & 1 )
          v17 = 1041770448;
      else
          v17 = 818848043;
      v40 = v17;
      break;
      case 1987329712:
      v59 = &v45;
      v40 = 2123926658;
      break;
      case 1998138173:
      v40 = -1009849083;
      break;
      case 2069967268:
      v40 = -1944675086;
      break;
      case 2123926658:
      objc_storeStrong(v59);
      v40 = -706815919;
      break;
    }
}
objc_storeStrong(&v43);
return objc_storeStrong(&v45);
}
总结简单的入门文章,希望能帮助到你。

Hmily 发表于 2023-2-27 17:14

建议代码用代码框处理一下会好看很多,图片上传论坛本地,这个图床很卡。

wzzhen 发表于 2023-2-27 17:28

学习一下 感谢分享

richardvip 发表于 2023-2-27 17:39

感觉很厉害 学习一下

zscdsdf 发表于 2023-2-27 19:34

感觉很厉害 学习一下

xiaohuaisu 发表于 2023-2-27 19:57

又学习到了

79715 发表于 2023-2-27 20:15

膜拜大神。。。。。。。。。。。。。

eddemelo 发表于 2023-2-27 21:12

太强了!!

神棍丶 发表于 2023-2-27 21:21

大佬NB啊啊啊

DHYB 发表于 2023-2-27 22:23

学习理论。。。。。。。。。。。。。。。
页: [1] 2 3
查看完整版本: 【iOS逆向与安全】使用ollvm混淆你的源码