ollvm 4.1 控制流平坦化基本概念

控制流平坦化基本概念

编译器参数:-mllvm -fla

英文全称 简称 编译参数
控制流平坦化 Control Flow Flattening fla -mllvm -fla

视频演示:https://space.bilibili.com/430241559

第1个例子 简单小程序:

c++源码

#include <cstdio>int main(int n_argc, char** argv)
{int n_num = n_argc * 2;//scanf("%2d", &n_num);if (20 == n_num){puts("20");}if(10 == n_num){puts("10");}if(2 == n_num){puts("2");}puts("error");return -1;
}

Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := wtt
LOCAL_SRC_FILES := test.cpp
include $(BUILD_EXECUTABLE)

Application.mk

注意,这里加了 -mllvm -fla参数 表示开启控制流平坦化

APP_ABI := armeabi armeabi-v7a
APP_PIE:= true
APP_CPPFLAGS := -frtti  -std=c++11 -mllvm -fla

未混淆前流程图

只用 控制流平坦化混淆后的流程图

混淆前后图解

混淆前:

混淆后:

代码本来是依照逻辑顺序执行的,控制流平坦化是把,原来的代码的基本块拆分。

把本来顺序执行的代码块用 switch case打乱分发,用分发器和一个变量,把原本代码的逻辑连接起来。

让你不知 道代码块的原本顺序。让逆向的小老弟一眼看过去不知道所以然,不知道怎么去分析。

复杂的事变简单

c++源码编译器在编译你写的源码的时候

为了提升执行速度,做了大量的把复杂事情变简单的编译优化动作

比如你写了下面这一行代码

int n = 3 + 3 - 1  + x;

编译器会直接优化成:

int n = 5 + x;

在汇编层,你是看不到 3 3 1这三个中间数字的

你只能看到 5

这个流程有个专业的术语 叫 常量折叠


编译器 把复杂的事情变简单

混淆工具 把简单的事情变复杂

第2个例子 把妹小程序

就像下面的代码,这是一个把妹小程序的c++代码

程序写了一个肥宅拿钱去和妹子约会的场景

把妹小程序c++源码

#include <cstdio>int ba_mei(int n_rmb);//逛街小程序
int main(int n_argc, char** argv)
{//带了点钱出门int n_ret = ba_mei(n_argc);return n_ret;
}//把妹函数 参数:软妹币数量
int ba_mei(int n_rmb)
{puts("和女票一起出门");puts("和女票走路去花店买花");n_rmb = n_rmb - 200;//如果手头的钱大于 800if(n_rmb >= 800){puts("和女票去迪士尼");n_rmb = n_rmb - 500;}else{puts("和女票去博物馆");n_rmb = n_rmb - 50;}puts("逛累了 和女票打的去吃饭");n_rmb = n_rmb - 30;//如果手头的钱大于 500if(n_rmb >= 500){puts("和女票去吃海底捞");n_rmb = n_rmb - 300;}else{puts("和女票去吃黄焖鸡米饭");n_rmb = n_rmb - 40;}puts("买了两瓶矿泉水");n_rmb = n_rmb - 3;//如果手头的钱大于 100if(n_rmb > 100){puts("买包华子");n_rmb = n_rmb - 70;}else{puts("买包红双喜");n_rmb = n_rmb - 10;}puts("静静的抽了一根烟");puts("和女票一起回家");return n_rmb;
}

这个程序是一个把妹小程序

看源码能清晰的看懂逻辑 看懂程序大概做了些啥事,

通过ida进行反编译 ,也是可以清晰的看到逻辑的 基本上能看懂 程序干了啥

在有分支语句的时候,判断的依据是什么

把妹小程序反编译后的代码

这里 可以看到做了一些编译优化 v4这里是花掉的钱

-250这里是 先减去200 再减去50

-700 也是 先减去200 再减去500

在看看被混淆过的程序是啥样

把妹小程序 控制流平坦化混淆后的流程图

把妹小程序混淆后 ida反编译结果

经过 ollvm 控制流平坦化混淆之后 流程变得不清晰

没混淆之前,这个程序干了点啥是很清晰的 逛街干了点啥 都很清楚

混淆之后,完全不知道程序的先后顺序,到底是先买华子,还是先吃海底捞,

去了博物馆,是不是还顺带去了趟迪士尼?

这是个举例子的程序,如果在真实算法里,也是一样的懵 你完全不知道 ,参数先后运算的顺序是咋样的

这里 ,真实块和真实块直接 不再像之前一样 直接连接

而是被打散, 执行下一个真实块的时候 要经过分发器,然后经过几次比较 才能达到下一个真实块

图解控制流平坦化

举个通俗的例子:

你约了个人 到公园见面, 公园离你比较近,你直接直走就能到公园,

但是现在

一个劫匪要跟你在公园见面,劫匪不直接告诉你去公园,他怕你被跟踪,暴露了他

劫匪也不敢跟你发短信 ,怕jc叔叔直接监控你的手机

劫匪想了一个好办法

Created with Raphaël 2.2.0-----起点-----同伙1指示路径同伙2指示路径同伙3指示路径------公园------路径3路径2路径1yesnoyesnoyesno

他给了你一个信物 假设这里是一把 大宝剑

然后他的同伙分散在各个路口

他的同伙看到这把大宝剑就知道是你过来了

他的同伙指示你应该往哪边走

本来你左拐直接到公园

这么一波操作后,你拐了七八次,走了好远一段冤枉路,才到公园、

这里,上面例子里的 信物 大宝剑,就相当于代码里的 v6变量

执行完真实块之后, v6被赋值

后续各种判断 都是基于 v6做的判断

所以,控制流平坦化就是用 switch case把整个程序流程打散

用一个变量的值 ,在多个比较语句中,走了不同的路,衔接起了被打散的真实块

这里,真实块的实际执行顺序,跟混淆之前还是一样的

混淆不会改变程序的整体逻辑,要不然被混淆之后,程序直接不能跑了,跑出错误的值,谁还用这个框架

就像之前举例说的劫匪给你的信物,每次到一个路口,劫匪的同伙都告诉你要往拿走,

最终,你走了很多弯路,到达了终点。


第3个例子 瞎写的算法

下面用一段的简单的算法源码举例子

c++源码

#include <cstdio>int main(int n_argc, char** argv)
{int n_num = n_argc * 2;//scanf("%2d", &n_num);for (int i = 0; i < 100; ++i){n_num = n_num + 3;n_num = n_num + 2;printf("%d",n_num);}if(n_num >= 1000){n_num = n_num + 200;puts("low");}else{n_num = n_num - 300;n_num = n_num / 2; puts("high");}int n_num1 = n_num + n_argc + 8;for (int i = 0; i < n_argc; ++i){n_num1 = n_num1 + n_argc;n_num1 = n_num1 + n_num * 2;printf("%d",n_num1);}int n_ret = n_num + n_num1 + n_argc;for (int i = 0; i < n_num1 - n_num; ++i){n_ret = n_num + i;printf("%d",n_ret);}if (n_ret > 65536){n_ret = n_ret - 65536;puts("sub 65536");}return n_ret;
}

上面的算法跟大佬们经常看到 rsa aes 这些不同

没啥复杂的操作 只有加减乘除 几个 if else的判断

未混淆之前的流程图

控制流平坦化 混淆之后的流程图

F5大法反编译后的代码

OLLVM把简单的流程变复杂,会拖慢程序的运行效率
所以,一般只保护一些 比较重要的代码

跟着铁头干混淆4.1 ollvm控制流平坦化基本概念相关推荐

  1. 初识ollvm控制流平坦化

    app:B站, 版本:随便搞了个最新版 目标:分析sign算法 本文第一次发布2021-10-26,时隔两个月,感觉这篇文章写的似乎并不是很清晰,于是做了一篇重制版发在了公众号里.如果感觉本文看着不清 ...

  2. 【转载】基于LLVM Pass实现控制流平坦化

    基于LLVM Pass实现控制流平坦化 文章目录 基于LLVM Pass实现控制流平坦化 0x00. 什么是LLVM和LLVM Pass 0x01. 首先写一个能跑起来的LLVM Pass 0x02. ...

  3. AST混淆实战|仿obfuscator混淆控制流平坦化(超详细版)

    之前写过一篇这样的文章 : JavaScript 代码混淆实战(六):仿obfuscator混淆控制流平坦化,但并没有写过程,在这篇文章里面说明下! 依然以文章里的代码来说明怎么进行控制流平坦化. 混 ...

  4. 利用AST对抗js混淆(三) 控制流平坦化(Control Flow Flattening)的处理

    控制流平坦化 参考:https://security.tencent.com/index.php/blog/msg/112 控制流平坦化,简单来讲就是将代码块之间的关系打断,由一个分发器来控制代码块的 ...

  5. buu-[RoarCTF2019]polyre(控制流平坦化,虚假控制流程)

    这题一开始拿到人看麻了(不会),写篇wp记录新题型 这么一大大大串的函数图,是经过OLLVM 的控制流平坦化混肴. 控制流平坦化(Control Flow Flattening)的基本思想主要是通过一 ...

  6. 某酷ckey签名生成算法系列--(三)ast代码控制流平坦化

    某酷ckey签名生成算法系列--(三)ast代码控制流平坦化 观察三个switch的值分别是Ci.mi和Ai.而这三个值又因为li的确定而确定的.也就是说已知li的值,就可以分别计算出Ci.mi和Ai ...

  7. AST还原技术专题:浅谈去控制流平坦化的思路及方法

    一. while-switch结构的控制流 这类平坦化代码很简单,常见于经过obfuscator在线工具混淆后的控制流平坦化.一般代码段不会很长,常见的 switch-case 基本都在10个分支以内 ...

  8. 中关村2019逆向 Reverse lebel:控制流平坦化 / python字节码分析

    flat 题目名字,流程图都指向了控制流平坦化 通过阅读 https://blog.csdn.net/yangbostar/article/details/6204724 了解了 顺序流/条件流/循环 ...

  9. 利用符号执行去除控制流平坦化

    1. 背景 1.1 控制流平坦化 控制流平坦化(control flow flattening)的基本思想主要是通过一个主分发器来控制程序基本块的执行流程,例如下图是正常的执行流程 经过控制流平坦化后 ...

最新文章

  1. CF 1093 E. Intersection of Permutations
  2. module 'scipy.misc' has no attribute 'imresize'
  3. sqlmap参数说明
  4. 图数据库:AgensGraph
  5. 网易前端微专业,JavaScript程序设计基础篇:数组
  6. 删除链表的倒数第n个节点 python_LeetCode 19.删除链表的倒数第N个节点(Python)
  7. 更改当前数据库的所有者
  8. 【贪心】LeetCode 55. Jump Game
  9. Android 创建服务器 NanoHttpd
  10. 车架号OCR识别算法
  11. stars-one的原创工具——星之小说下载器(JavaFx应用 )
  12. 国产操作系统银河麒麟V10桌面版新手小白常见问题
  13. 淘宝2011春季校园招聘笔试试题(回忆版)(附个人简历)
  14. 乐酷工作室孙志伟:Testin云测试有广度有深度 省钱省力值得信赖
  15. 使用UltraEdit删除重复的行
  16. Linux笔记之Docker安装,基于Debian 11(bullseye)
  17. 反编译工具ILSpy
  18. 阿里天池-全球数据智能大赛
  19. MythType添加空格
  20. OpenMV固件升级(DFU)

热门文章

  1. 记录:谷歌地图google map api实现基本测距功能
  2. 【转】EBS财务系统总账模块(GL)会计期间状态总结
  3. python小程序之七段数码读秒
  4. BAPI_BILLINGDOC_CREATEMULTIPLEdoesntcreateheadertexts_SAP刘梦_新浪博客
  5. 7个项目管理强力工具介绍
  6. mybatis plus环境搭建及代码生成器
  7. Symfony\Component\Debug\Exception\FatalErrorException: Allowed memory size of 2147483648 bytes
  8. Java 中的 int 型转为 long 型
  9. Java-双亲委派机制
  10. ecshop mysql 标题表_ECshop每个数据库表结构说明_MySQL