iOS 逆向 day 18 GCC LLVM Clang 代码混淆

一、LLVM

1. 什么是 LLVM
  • 官网:https://llvm.org/
  • The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
  • LLVM 项目是模块化、可重用的编译器以及工具链技术集合
2.创始人
  • Chris Lattner,亦是 Swift 之父
3. 有些文章把 LLVM 当做 Low Level Virtual Machine (低级虚拟机)的缩写简称,官方开头描述如下
  • The name "LLVM" itself is no an acronym; it is the full name of the project.
  • “LLVM” 这个名称不是首字母缩写词;它是项目的全名

二、编译器架构

1. 传统编译器架构
传统编译器架构
  • Frontend:前端;词法分析、语法分析、语义分析、生成中间代码

  • Optimizer:优化器;中间代码优化

  • Backend:后端;生成机器码

2. LLVM 架构
LLVM 架构
  • 不同的前端后端使用统一的中间代码 LLVM Intermediate Representation (LLIR)
  • 如果需要支持一种新的编程语言,那么只需要实现一个新的前端
  • 如果需要支持一种新的硬甲设备,那么只需要实现一个新的后端
  • 优化阶段是一个通用的阶段,它针对的统一的 LLVM IR,不论是支持新的编程语言,还是支持新的硬件设备,都不需要对优化阶段做修改
  • 相比之下,GCC 的前端和后端没分得太开,前后端耦合在了一起。所以 GCC 为了支持一门新的语言,或者为了支持一个新的目标平台,就变得特别困难
  • LLVM 现在被作为实现各种静态和运行时编译语言的通用基础结构(GCC 家族、Java、.NET、Python、Ruby、Scheme、Haskell 等)

三、Clang

1. 什么是 Clang?
  • LLVM 项目的一个子项目
  • 基于 LLVM 架构的 C/C++/Objective-C 编译器前端
  • 官网:http://clang.llvm.org/
2. 相比于 GCC,Clang 有如下优点
  • 编译速度快
  • 占用内存小
  • 模块化设计
  • 诊断信息可读性强
  • 设计清晰简单,容易理解,易于扩展增强
图解 Clang

四、OC 源文件编译的过程

编写如下 test.m 文件

int test(int a, int b) {
    int c = a + b + 3;
    return c;
}

1. 命令行查看编译过程:clang -ccc-print-phases test.m
carrot__lsp$ clang -ccc-print-phases test.m 
0: input, "test.m", objective-c
1: preprocessor, {0}, objective-c-cpp-output
2: compiler, {1}, ir
3: backend, {2}, assembler
4: assembler, {3}, object
5: linker, {4}, image
6: bind-arch, "x86_64", {5}, image
2. 词法分析,生成 Token:clang -fmodules -E -Xclang -dump-tokens test.m
carrot__lsp$ clang -fmodules -E -Xclang -dump-tokens test.m 
int 'int'    [StartOfLine]  Loc=<test.m:1:1>
identifier 'test'    [LeadingSpace] Loc=<test.m:1:5>
l_paren '('     Loc=<test.m:1:9>
int 'int'       Loc=<test.m:1:10>
identifier 'a'   [LeadingSpace] Loc=<test.m:1:14>
comma ','       Loc=<test.m:1:15>
int 'int'    [LeadingSpace] Loc=<test.m:1:17>
identifier 'b'   [LeadingSpace] Loc=<test.m:1:21>
r_paren ')'     Loc=<test.m:1:22>
l_brace '{'  [LeadingSpace] Loc=<test.m:1:24>
int 'int'    [StartOfLine] [LeadingSpace]   Loc=<test.m:2:5>
identifier 'c'   [LeadingSpace] Loc=<test.m:2:9>
equal '='    [LeadingSpace] Loc=<test.m:2:11>
identifier 'a'   [LeadingSpace] Loc=<test.m:2:13>
plus '+'     [LeadingSpace] Loc=<test.m:2:15>
identifier 'b'   [LeadingSpace] Loc=<test.m:2:17>
plus '+'     [LeadingSpace] Loc=<test.m:2:19>
numeric_constant '3'     [LeadingSpace] Loc=<test.m:2:21>
semi ';'        Loc=<test.m:2:22>
return 'return'  [StartOfLine] [LeadingSpace]   Loc=<test.m:3:5>
identifier 'c'   [LeadingSpace] Loc=<test.m:3:12>
semi ';'        Loc=<test.m:3:13>
r_brace '}'  [StartOfLine]  Loc=<test.m:4:1>
eof ''      Loc=<test.m:4:2>
3. 语法分析,生成语法树(AST,Abstract syntax Tree):carrot__lsp$ clang -fmodules -fsyntax-only -Xclang -ast-dump test.m
carrot__lsp$ clang -fmodules -fsyntax-only -Xclang -ast-dump test.m 
`-FunctionDecl 0x7fc0a8832ff8 <test.m:1:1, line:4:1> line:1:5 test 'int (int, int)'
  |-ParmVarDecl 0x7fc0a8832e70 <col:10, col:14> col:14 used a 'int'
  |-ParmVarDecl 0x7fc0a8832ee8 <col:17, col:21> col:21 used b 'int'
  `-CompoundStmt 0x7fc0a88332e8 <col:24, line:4:1>
    |-DeclStmt 0x7fc0a8833260 <line:2:5, col:22>
    | `-VarDecl 0x7fc0a8833110 <col:5, col:21> col:9 used c 'int' cinit
    |   `-BinaryOperator 0x7fc0a8833238 <col:13, col:21> 'int' '-'
    |     |-BinaryOperator 0x7fc0a88331f0 <col:13, col:17> 'int' '+'
    |     | |-ImplicitCastExpr 0x7fc0a88331c0 <col:13> 'int' <LValueToRValue>
    |     | | `-DeclRefExpr 0x7fc0a8833170 <col:13> 'int' lvalue ParmVar 0x7fc0a8832e70 'a' 'int'
    |     | `-ImplicitCastExpr 0x7fc0a88331d8 <col:17> 'int' <LValueToRValue>
    |     |   `-DeclRefExpr 0x7fc0a8833198 <col:17> 'int' lvalue ParmVar 0x7fc0a8832ee8 'b' 'int'
    |     `-IntegerLiteral 0x7fc0a8833218 <col:21> 'int' 3
    `-ReturnStmt 0x7fc0a88332d0 <line:3:5, col:12>
      `-ImplicitCastExpr 0x7fc0a88332b8 <col:12> 'int' <LValueToRValue>
        `-DeclRefExpr 0x7fc0a8833278 <col:12> 'int' lvalue Var 0x7fc0a8833110 'c' 'int'

五、代码混淆

iOS 程序可以通过 class-dump、Hopper、IDA 等获取类名、方法名、以及分析程序的执行逻辑,如果进行代码混淆,可以加大别人的分析难度。

1. 源码混淆,通过宏定义的方式。
  • 类名
  • 方法名
  • 协议名
2. 字符串加密
  • 很多时候,可执行文件中的字符串信息,对破解者来说,非常关键,是破解的捷径之一

  • 为了加大破解、逆向难度,可以考虑对字符串进行加密

  • 字符串的加密技术有很多种,可以根据自己的需要进行自行定制算法

  • 这里举一个简单的例子:对每个字符串进行异或(^)处理

    3. 混淆注意点
  • 不能混淆系统方法

  • 不能混淆 init 开头的等初始化方法

  • 混淆属性时需要额外注意 set 方法

  • 如果 xib、storyboard 中用到了混淆的内容,需要手动修正

  • 可以考虑吧需要混淆的符号都加上前缀,跟系统自带的符号进行区分

  • 混淆过多可能会被 App Store 拒绝上架,需要说明用途

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349