热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

初识OLLVM

编译器一般编译器分为前端,中间优化和后端三部分。前端进行语法分析,中间进行优化后由后端编译成对应平台的代码(arm,x86)。现在主流的编译器有linux平台下的gcc和llvm-

编译器

一般编译器分为前端,中间优化和后端三部分。前端进行语法分析,中间进行优化后由后端编译成对应平台的代码(arm,x86)。现在主流的编译器有linux平台下的gcc 和 llvm-clang,以及windows平台下的msvc编译器。


LLVM

gcc编译器虽然强大但是有一个缺点就是因为其相当于一个完整的可执行文件,编译器的前端,中间优化和后端中间的耦合度比较高,所以要想增加一个前端用来支持一种新的语言,或者增加一个后端来生成一种新平台的机器码都需要做很大的改动很不方便。于是就有了LLVM的出现,LLVM是一个编译器框架,和传统的编译器一样也分为前端,中间优化和后端三部分。但是其利用与平台无关的中间语言IR来实现前端,中间优化和后端的分离,这样如果编译器需要新增加一种语言只需要增加一个前端语法解析器即可。例如Clang就是基于LLVM架构的能够支持C/C++/Objective-C语言的编译器前端。


LLVM编译过程

llvm编译过程大致分为 预处理-->语法分析-->生成IR代码-->IR代码优化-->生成汇编代码(x86, arm)-->Link-->生成目标文件,之后就是链接器链接各个目标文件并生成可执行文件的过程。(所以汇编的过程实际包含在编译过程中)

LLVM IR代码文件的格式为bc/llc,bc是一种bitcode的格式,而llc是一种人类可以阅读的格式。还有一种格式就是内存中的格式,LLVM在内存中会将IR分为Module,function,basicblock,Instruction四种表达形式。



  • Module就是一个c/cpp文件

  • function就是一个函数

  • basicblock就是控制流的一个基本块

  • Instruction就是一条具体的指令


LLVM中间优化过程

llvm通过将前端代码(c/cpp等)生成与平台无关的llvm IR中间代码,然后通过多个pass(就是一个一个的类,每一个类对应一种功能)来对IR代码进行优化。


OLLVM

OLLVM是一种通过利用LLVM回生产IR中间代码并通过pass优化代码的特点,通过增加自己的pass来对代码进行优化,但是这种优化不是为了让代码更简洁相反是让代码更复杂,达到混淆的目的。一般支持三种主要的混淆手段:控制流平坦化,虚假执行流和替换指令。


OLLVM之控制流平坦化

ollvm三种混淆手段中控制流平坦化混淆效果最佳。其原理是将函数分为若干个控制流基本块,这些基本块是以跳转指令(不包含调用指令)结尾的,然后利用switch结构通过判断状态变量的值来执行相应的控制流基本块,因为一个基本块可能会跳转到一个或者两个基本块中,所以还需要通过新增加一些块或代码来控制修改状态变量的值从而跳转到不同的基本块中。



  • 序言:通常是一个函数开头的部分

  • 主分发器/子分发器:通过状态变量寻找对应的真实快

  • 预处理器:可有可无,会统一跳转回主分发器中(有很多直接从真实块中跳转回主分发器中)

  • 真实块:包含函数实际的代码基本块

  • return块:函数结束代码块



去除ollvm控制流平坦化

根据ollvm控制流平坦化混淆的原理可得接混淆的步骤如下。



  • 先找到函数中所有的控制流代码块

  • 在所有的控制流代码块中找到所有的真实块

  • 确定各个真实块的执行路径,即一个执行块能跳转到哪几个块(1/2个块)

  • 对于只会跳转到一个块的真实块直接在其代码块末尾patch,跳转到对应的真实块

  • 对于会跳转到两个块的真实块,平坦化是通过在此真实块的末尾根据跳转条件更改状态变量的值来实现跳转到不同的真实块中,我们需要将其更改状态变量的跳转到不同真实块的方式更改为通过跳转指令的方式实现(bge,ble...)。我们需要根据实际的修改状态变量的指令来使用对应的跳转指令例如其通过ITT GT我们就可以修改为BGE.

  • 将控制流代码块中不是真实块的块直接nop(虚假块)

    当然在实际分析中情况很复杂,可能有很多特殊的情况需要特殊处理,大致流程一样。


利用unicron模拟执行去除控制流平坦化

测试程序是一个arm-v7a(thumb)的程序

混淆前的代码流程图

混淆后的代码流程图

参考看雪无名侠大佬的思路



  • 寻找所有的控制流代码块

    我们观察到控制流代码块都需要以跳转指令(不包括blxx等函数调用指令)结尾。记录下所有基本快后继块的引用计数。



  • 寻找真实块

    如果一个基本控制流代码块的后继块的引用数大于1,并且不等于2则其就是一个真实块。因为引用数大于1的基本块是预处理器或者主分发器(引用数为2),而指向预处理器的是真实块,而预处理器指向的主分发器的引用数也大于1(引用数为2,一个是序言,一个是预处理器),而预处理器不是真实块所以需要将预处理器过滤。

因为在过滤预处理的时候也把序言过滤了,序言其实也属于真实块,所以需要加上。

观察到return块是一个以bne开头的代码块,也属于真实块需要加上。(所以在实际寻找真实块的过程中有很多需要特殊处理的过程,具体情况具体分析)



  • 寻找各个真实块跳转的目标真实块

    从函数序言的起始地址开始模拟执行,执行的过程中只关心此真实块能够执行到的目标真实块,其他内存相关操作都不需要关心。



  • 先判断真实块中是否含有跳转指令,有跳转指令说明此真实块能够执行到两个目标真实块(两条路径),需要寻找两次路径



  • 如果没有跳转指令则只有一条路径需要寻找



  • 寻找到真实块加入到队列中,待此真实块的路径寻找完后从队列中去除新的真实块并以此块的地址作为起始地址继续模拟执行寻找它的路径。直到所有的真实块的路径都找完为止。



寻找一个真实块路径的思路是:如果模拟执行到一个地址是某个真实块的起始地址说明找到了目标真实块。

对于包含条件判断的真实块,也就是有两条路径的真实块需要人为的控制指令指令流程寻找两条路径对应的真实块。为了更好的在后续patch,我们每次都先寻找满足较小条件会执行的路径。



  • 最后就是patch程序,根据不同的条件判断指令进行修改对应的跳转指令

还原后的程序流程图

参考链接:https://bbs.pediy.com/thread-252321.htm



推荐阅读
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 【Windows】实现微信双开或多开的方法及步骤详解
    本文介绍了在Windows系统下实现微信双开或多开的方法,通过安装微信电脑版、复制微信程序启动路径、修改文本文件为bat文件等步骤,实现同时登录两个或多个微信的效果。相比于使用虚拟机的方法,本方法更简单易行,适用于任何电脑,并且不会消耗过多系统资源。详细步骤和原理解释请参考本文内容。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 通过Anaconda安装tensorflow,并安装运行spyder编译器的完整教程
    本文提供了一个完整的教程,介绍了如何通过Anaconda安装tensorflow,并安装运行spyder编译器。文章详细介绍了安装Anaconda、创建tensorflow环境、安装GPU版本tensorflow、安装和运行Spyder编译器以及安装OpenCV等步骤。该教程适用于Windows 8操作系统,并提供了相关的网址供参考。通过本教程,读者可以轻松地安装和配置tensorflow环境,以及运行spyder编译器进行开发。 ... [详细]
  • 在Windows10系统上使用VMware创建CentOS虚拟机的详细步骤教程
    本文详细介绍了在Windows10系统上使用VMware创建CentOS虚拟机的步骤,包括准备条件、安装VMware、下载CentOS ISO文件、创建虚拟机并进行自定义配置、设置虚拟机的ISO与网络、进行安装和配置等。通过本文的指导,读者可以轻松地创建自己的CentOS虚拟机并进行相应的配置和操作。 ... [详细]
  • 【技术分享】一个 ELF 蠕虫分析
    【技术分享】一个 ELF 蠕虫分析 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 如何使用PLEX播放组播、抓取信号源以及设置路由器
    本文介绍了如何使用PLEX播放组播、抓取信号源以及设置路由器。通过使用xTeve软件和M3U源,用户可以在PLEX上实现直播功能,并且可以自动匹配EPG信息和定时录制节目。同时,本文还提供了从华为itv盒子提取组播地址的方法以及如何在ASUS固件路由器上设置IPTV。在使用PLEX之前,建议先使用VLC测试是否可以正常播放UDPXY转发的iptv流。最后,本文还介绍了docker版xTeve的设置方法。 ... [详细]
  • 第四讲ApacheLAMP服务器基本配置Apache的编译安装从Apache的官方网站下载源码包:http:httpd.apache.orgdownload.cgi今 ... [详细]
  • 原文地址http://balau82.wordpress.com/2010/02/28/hello-world-for-bare-metal-arm-using-qemu/最开始时 ... [详细]
  • MySQL5.6.40在CentOS764下安装过程 ... [详细]
  • 一、设置时区方法一:使用setup工具setup选择Timezoneconfiguration选择AsiaShanghai空格键勾选上System ... [详细]
  • golang源码分析调度概述
    golang源码分析-调度过程概述本文主要概述一下golang的调度器的大概工作的流程,众所周知golang是基于用户态的协程的调度来完成多任务的执行。在Linux ... [详细]
author-avatar
路霄峰_121
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有