0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

OLLVM和LLVM功能介绍

我快闭嘴 来源:小道安全 作者:小道安全 2022-09-19 15:42 次阅读

基础知识

LLVM是lowlevel virtual machine的简称,它诞生于2003.10伊利诺伊大学香槟分校,创始人是ChrisLattner,它是一个完整的编译器框架,它兼容大部分主流开发语言例如:C, C++, Objective-C等等,它也兼容大部分主流的平台:x86, x86-64, PowerPC, PowerPC-64,ARM,Thumb等等。

6cfbf7ec-372d-11ed-ba43-dac502259ad0.png

(图片来源网络

LLVM会先将源码生成为与目标机器无关的LLVMIR代码,然后把LLVMIR代码先优化,再向目标机器的汇编语言而转换。LLVM编译器主要细分为前端、中层优化和后端的3部分构成。

6d154cf6-372d-11ed-ba43-dac502259ad0.png

(图片来源网络)

OLLVM就是在LLVM的基础上增加了obfuscator(混淆), Obfuscator-LLVM (OLLVM) 是2010 年 6 月由 Yverdon-les-Bains 的瑞士西北应用科技大学安全实验室针对LLVM编译组件开发的代码混淆工具,该工具完全开源,这个OLLVM主要为了增加逆向工程的难度,保证代码的安全性。

Obfuscator-LLVM (OLLVM)集成了LLVM编译器,并且兼容LLVM支持的所有语言(C,C++, Objective-C, Ada and Fortran)和平台(x86, x86-64, PowerPC,PowerPC-64,ARM,Thumb,SPARC,Alpha,CellSPU,MIPS, MSP430, SystemZ,XCore)。

OLLVM的混淆原理,就是在不改变源代码功能前提下,将C或C++代码中的控制语句if、while、for、do等转换成switch分支语句。这样实现的优势是,它可以模糊switch中case代码块之间的关系,从而增加逆向分析代码难度。

混淆的具体实现思路,首先将要实现代码平坦化的函数分成多个基本块(就是case代码块)和一个入口块,并为每个基本块设置编号,并让这些基本块都有共同的前驱模块和后继模块。前驱模块主要是进行基本块的分发,后继模块的分发通过改变switch变量来实现。

OLLVM和LLVM主要的功能的代码差异点如下图所示

6d27261a-372d-11ed-ba43-dac502259ad0.png

OLLVM功能介绍

OLLVM全面模式支持以下四种代码包含模式

1、-mllvm -fla: 控制流化扁平化

2、-mllvm -sub:指令替换

3、-mllvm -bcf: 控制流程

4、-mllvm -sobf: 字符串加密

以OLLVM保护后的功能效果都在文章的后部分进行展示。

-mllvm -fla中fla的全称:Control Flow Flattening,它也称为控制流扁平化,这个功能模式主要原理就是把一些if-else语句,嵌套成do-while语句。

它支持以下3种保护功能模式:

-mllvm -fla: 激活控制流扁平化

-mllvm -split:激活基本块分裂。一起使用时提高平整度。

-mllvm -split_num=3:如果激活通行证,则在每个基本块上应用 3 次。默认值:1

-mllvm -sub,它的全称Instructions Substitution,它又称为指令替换,这个的原理可以理解为就是不改变功能的前提下,将简单的指令替换成更复杂的指令,当有多个等效指令序列可用时候,会随机选择一个指令进行替换。这个混淆它并不会增强过多的安全性,因为它可以通过重新优化生成的代码轻松删除,如果选择使用随机生成器以不同数值作为种子,指令替换会在生成的二进制文件中带来多样性。

它支持以下的2种模式功能:

-mllvm -sub:激活指令替换

-mllvm -sub_loop=3:如果激活了传递,则在函数上应用3次。默认值:1

-mllvm -bcf,它的全称Bogus Control Flow,也称为虚假控制流。这个主要原理就是在当前基本块之前添加一个新的基本块用来修改函数调用图,这个新的基本块包含一个不透明的谓词,通过有条件地跳转到原来的基本块。原始的基本块也会被克隆并填充随机的垃圾指令。

这虚假控制流代码保护模式主要通过在不改变代码功能前提下往代码里面嵌套几层的判断逻辑,这种模式下会大大影响程序的性能,因为它在代码下混杂着真真假假的代码。

这个模式下它支持3种功能选项:

-mllvm -bcf: 激活伪造的控制流通道

-mllvm -bcf_loop=3: 如果 pass 被激活,在一个函数应用 3 次。默认值:1

-mllvm -bcf_prob=40:如果激活通行证,一个基本块将以 40% 的概率被混淆。默认值:30

-mllvm -sobf也称为字符串混淆,主要实现将代码中的字符串做加密,使得无法通过静态逆向方式直接看到字符串信息

它主要支持2种功能模式选项:

-mllvm -sobf:编译时候添加选项开启字符串加密

-mllvm -seed=0xdeadbeaf:指定随机数生成器种子流程

OLLVM编译

编译OLLVM前需要以下的工具和代码:

1、OLLVM源码(基础之源)

https://releases.llvm.org/download.html

2、cmake工具(将OLLVM转换为sln项目)

https://cmake.org/download/

3、Visual studio工具(编译OLLVM源码)

https://visualstudio.microsoft.com/zh-hans/

在window环境下编译OLLVM的源码主要需要经历2个步骤

1、通过利用cmake将OLLVM的源码转换为sln的项目

可以通过利用cmake工具或者用命令行方式转换,下面以命令行方式转换的

cmake -Thost=x64 -G "Visual Studio 16" E:ollvm9obfuscator-llvm-9.0.1obfuscator-llvm-9.0.1

上面要主要的是Visual Studio 16这个代表你环境中安装的vs版本,我安装2019版本的,所以用它。

通过执行以上命令后就会出现下图的效果

6d3f5078-372d-11ed-ba43-dac502259ad0.png

2、用Visual studio 2019 直接编译前面生成的OLLVM项目,主要编译Release版本。编译后正确情况下会生成bin和lib两个文件夹。

6d52743c-372d-11ed-ba43-dac502259ad0.png

OLLVM集成

通过前面的编译后生成的bin和lib文件夹,集成到NDK中,并通过android studio编译器进行so代码保护的应用。

将vs编译生成后的bin和lib文件夹,替换到NDK中的llvm文件夹下面toolchainsllvmprebuiltwindows-x86_64(替换之前切记做下备份,万一出问题了还能回滚)

6d5d9a88-372d-11ed-ba43-dac502259ad0.png

通过配置Android.mk文件进行设定需要对so文件采用什么方式的全局代码保护。

可能大家会觉得保护强度越强越好,代码虚拟化、字符串混淆、指令替换等等都给用下去,那样就安全了,其实不是这样的,这些强度虽然上去了但是会给项目带来非常大的负担。往往会带来负面性能影响。

个人建议:可以针对字符串做个混淆(-mllvm -sobf),外加指定核心函数进行做代码保护。这样强度也有了,对应用的性能影响方面也相对较小。

6d6ab9ac-372d-11ed-ba43-dac502259ad0.png

上图中Android.mk设置的保护方式属于全局的保护,设置后整个so就都会基于设置的保护。

通过配置Application.mk文件,进行指定ollvm的clang具体版本数据(这个具体版本数据也可以lib文件夹下clang文件夹下查看)。

6d7a73ce-372d-11ed-ba43-dac502259ad0.png

OLLVM保护效果

为了更好展示分析ollvm保护后的效果,主要通过基于__attribute((__annotate__(("sub"))))这种方式,对指定函数进行做保护,而没有进行配置全局的保护。

下图的代码功能效果仅是为了测试OLLVM的虚假指令保护后的实现效果

6d864622-372d-11ed-ba43-dac502259ad0.png

下图是基于IDA工具的原始和虚假控制流的代码保护流程图,可以看到代码的执行流程已被调整变得相对复杂化,这样就大大强化了代码的安全强度,这种逆向分析其代码至少静态分析起来就费劲了。

6da08960-372d-11ed-ba43-dac502259ad0.png

下图是通过指定函数进行设置指令替换的功能的代码展示

6db4227c-372d-11ed-ba43-dac502259ad0.png

通过下图IDA静态的代码流程图可以很清晰分析到,它实际上代码流程是没有任何变化的,所以这种保护模式下的代码保护功能时没有很明显的效果的。

6dcbd822-372d-11ed-ba43-dac502259ad0.png

下图的代码是通过调用ollvm的控制流扁平化功能进行对函数保护的代码展示

6dd66076-372d-11ed-ba43-dac502259ad0.png

通过下图IDA的代码流程图,可以看到代码控制流扁平化保护后,整个流程就变得复杂化了。这就让代码的安全性上升一个层次了,这样逆向分析还原代码功能的成本就大大提高了。

6df3938a-372d-11ed-ba43-dac502259ad0.png

小结

通过上文OLLVM的一系列的原理集成、编译、配置、集成、代码生成、效果展示,主要为了给SO代码的防破解防逆向增加点门槛,提高点安全性。这系列的代码保护对于专业搞逆向的人员来说,它们可以通过基于Trace、unicron、frida这些方式去还原和去除OLLVM的混淆保护。

对于代码的安全性思考,不过在安全攻防对抗的过程中防御一直属于被动状态的也是相对滞后的。安全防护也是随着对抗去不断去提高变强。

代码安全防护方面可以借助于OLLVM然后进行做定制魔改,现有的逆向工具更多是基于标准化进行做反汇编,那么我们可以对这些逆向工具做些防护(可以多个方案结合),然后调整成为一些非标准化的,这样会大大增加逆向分析的成本。

只要逆向分析成本超过所破解后所获取的收益,那么你的代码就相对安全了。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 代码
    +关注

    关注

    30

    文章

    4557

    浏览量

    66826
  • 编译器
    +关注

    关注

    1

    文章

    1577

    浏览量

    48635

原文标题:一种高端的APP代码保护方案

文章出处:【微信号:哆啦安全,微信公众号:哆啦安全】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    请问ubuntu 14.04 编译am57xx SDK , 发生nativesdk-ti-llvm3.6异常是为什么?

    本帖最后由 一只耳朵怪 于 2018-6-5 14:11 编辑 ubuntu 14.04 编译am57xx SDK , 发生nativesdk-ti-llvm3.6 异常, 求高手
    发表于 06-04 11:31

    LLVM编译器编译过程

    LLVM 编译器 原理解析, 插件编写
    发表于 04-28 08:15

    介绍高级时钟的PWM功能的应用

    文章目录前言前言从本文开始,介绍F429的高级时钟特性。本文主要介绍高级时钟的PWM功能的应用。关于PWM,本文重点介绍实现带有断路功能的双
    发表于 08-19 08:29

    LLVM clang 公开 -std=c++23

    合入 LLVM 17 仓库的代码对 Clang 编译器使用 -std=c++23 代替了 -std=c++2b。 随着 ISO C++ 委员会投票决定 C++23 标准已达到其技术完整状态
    发表于 05-27 11:29

    在Swift中使用LLVM的四个要点

    本文主要内容是演示如何在Swift中使用LLVM,其包含了如下四个要点: 获取最新版本的LLVM使用CMake和llvm-config编译程序编写简单的Swift程序,编译并与LLVM
    发表于 10-13 16:55 0次下载
    在Swift中使用<b class='flag-5'>LLVM</b>的四个要点

    四个不同的系统上进行LLVM/Clang 6.0 和 5.0 的编译器Benchmark测试

    参与测试的 LLVM 5.0.1 和 LLVM 6.0.0 稳定版都是来自 apt.llvm.org。测试期间,每个系统都将其 CFLAGS/CXXFLAGS 设置为 "-O3 -march
    的头像 发表于 03-29 15:25 7473次阅读

    LLVM终身程序分析与转换的编译框架的详细资料说明

    本文描述了LLVM(Low Level Virtual Machine)编译器框架,它通过在编译时、链接时、运行时和运行之间的空闲时间向编译器转换提供高级信息,支持对任意程序进行透明的、终身的程序
    发表于 06-08 08:00 0次下载
    <b class='flag-5'>LLVM</b>终身程序分析与转换的编译框架的详细资料说明

    微软与LLVM、Rust达成合作,将CFG支持添加到编译器

    微软方面宣布,该公司已与 LLVM 和 Rust 开发团队达成合作,将对 Windows Control Flow Guard(CFG)平台安全功能的支持添加到了 Clang 和 Rustc 编译器中。此前,CFG 仅适用于使用 Microsoft Visual C ++
    的头像 发表于 08-20 11:44 2714次阅读

    llvm-mctoll将二进制文件转换为LLVM IR

    ./oschina_soft/llvm-mctoll.zip
    发表于 06-22 11:35 0次下载
    <b class='flag-5'>llvm</b>-mctoll将二进制文件转换为<b class='flag-5'>LLVM</b> IR

    浅谈LLVM LibFuzzer工具和实践

    一种强大且智能的测试方式呢?答案是肯定的,它就是出自 LLVM 编译器框架的 LibFuzzer 工具。
    的头像 发表于 10-27 10:57 1453次阅读

    LLVM源码浅析-1

    作为一个优秀的开源编译器框架,llvm的代码比gcc代码的可读性更好。因此无论是学习c++,还是学习编译原理、设计模式、数据结构,都是一个很好的学习目标。
    的头像 发表于 03-02 16:06 1513次阅读
    <b class='flag-5'>LLVM</b>源码浅析-1

    LLVM国际开源软件社区发布正式支持LoongArch架构的版本

    发行版将可以直接基于上游社区版本进行构建,标志着LoongArch软件生态建设将迎来快速发展的新阶段。 LLVM介绍 LLVM是如今设计和开发编译器的最重要的框
    的头像 发表于 03-21 09:45 1350次阅读

    LLVM16的新增功能介绍

    除了对今年架构的标准支持外,我们还完成了对可扩展矩阵扩展(SME和SME2)的汇编级支持。
    的头像 发表于 05-18 10:07 1077次阅读
    <b class='flag-5'>LLVM</b>16的新增<b class='flag-5'>功能</b><b class='flag-5'>介绍</b>

    什么是LLVMLLVM的优势和特点有哪些?

    LLVM是一个开源的编译器基础设施项目,它以"Low-Level Virtual Machine"的缩写命名,尽管名称中包含了"虚拟机"一词,但LLVM不仅仅是一个虚拟机,而是一个综合的编译器工具链。
    的头像 发表于 06-11 15:54 6251次阅读

    使用LLVM-embedded-toolchain-for-Arm-17.0.1开发STM32

    LLVM-embedded-toolchain-for-Arm 是一个 ARM 公司开源的适用于 32 位ARM芯片的工具链,支持多种ARM指令集架构,包括最新的 CM85 内核。
    的头像 发表于 10-23 16:46 876次阅读
    使用<b class='flag-5'>LLVM</b>-embedded-toolchain-for-Arm-17.0.1开发STM32