专栏首页I0gan反逆向分析
原创

反逆向分析

Ollvm

0x01 Ollvm介绍

OLLVM(Obfuscator-LLVM)是瑞士西北应用科技大学安全实验室于2010年6月份发起的一个项目,该项目旨在提供一套开源的针对LLVM的代码混淆工具,以增加逆向工程的难度, 只不过Ollvm仅更新到llvm的4.0,2017年开始就没再更新。

0x02 Ollvm混淆介绍

Ollvm混淆主要分成三种模式,这三种模式主要是流程平坦化,指令替换,以及控制流伪造。

流程平坦化 :这个模式主要通过将if-else语句替换成do-while语句,然后通过switch语句来对流程的控制,这样就能模糊基本块之间的前后关系。

指令替换 :这个模式主要通过使用更复杂的指令序列来替换一些标准的二元运算符,从而增加逆向的难度。

控制流伪造 :这个模式主要是会在一个简单的运算中外包好几层if-else的判断,从而增加逆向的难度。

对Ollvm有更深入的理解,可参阅论文《Obfuscating C++ programs via control flow flattening》

0x03 Ollvm编译

env: arch-linux

使用apt源安装g++和cmake,从github获取ollvm的源码,并进行编译。

Ollvm 6.0: https://github.com/yazhiwang/ollvm-tll.git (编译成功!)

原版src: https://github.com/obfuscator-llvm/obfuscator/tree/llvm-4.0 (编译失败!)

ollvm-til编译

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ../ollvm-tll-master
make -j8

官方编译

cd 
mkdir build
cmake  -DCMAKE_BUILD_TYPE=Release  -DLLVM_INCLUDE_TESTS=OFF  ../
make -j8

0x4 命令介绍

控制流扁平化

这个模式主要是把一些if-else语句,嵌套成do-while语句

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

-mllvm -split:激活基本块分割。在一起使用时改善展平。

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

指令替换

这个模式主要用功能上等效但更复杂的指令序列替换标准二元运算符(+ , – , & , | 和 ^)

-mllvm -sub:激活指令替换

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

虚假控制流程

这个模式主要嵌套几层判断逻辑,一个简单的运算都会在外面包几层if-else,所以这个模式加上编译速度会慢很多因为要做几层假的逻辑包裹真正有用的代码。

-mllvm -bcf:激活虚假控制流程 -mllvm -bcf_loop=3:如果激活了传递,则在函数上应用3次。默认值:1 -mllvm -bcf_prob=40:如果激活了传递,基本块将以40%的概率进行模糊处理。默认值:30

其他

-mllvm -sobf 开启字符串混淆

-mllvm -seed=0xdeadbeaf 指定随机数种子生成器 bcf可以配合下面参数使用

例子

对a.c进行混淆

#include<stdio.h>
void exec() {
    printf("OOOKKKK!");
}
int main(void) {
    int a = 0;
    a ++;
    printf("Hello World");
    if(a >= 1) {
        exec();
    }
    return 0;
}
~/tools/ollvm/bin/clang a.c -mllvm -fla  -mllvm -sobf  -mllvm -bcf  -o a

ida64打开F5

int __cdecl main(int argc, const char **argv, const char **envp)
{
  signed int v3; // eax
  __int64 *v4; // rcx
  int v5; // eax
  signed int v6; // edx
  signed int v7; // eax
  signed int v8; // eax
  signed int v9; // eax
  __int64 *v11; // rcx
  int v12; // eax
  __int64 v13; // [rsp+0h] [rbp-50h]
  int v14; // [rsp+8h] [rbp-48h]
  int v15; // [rsp+Ch] [rbp-44h]
  __int64 *v16; // [rsp+10h] [rbp-40h]
  int v17; // [rsp+18h] [rbp-38h]
  int v18; // [rsp+1Ch] [rbp-34h]
  int v19; // [rsp+20h] [rbp-30h]
  int v20; // [rsp+24h] [rbp-2Ch]
  int v21; // [rsp+28h] [rbp-28h]
  int v22; // [rsp+2Ch] [rbp-24h]
  int v23; // [rsp+30h] [rbp-20h]
  int v24; // [rsp+34h] [rbp-1Ch]
  int v25; // [rsp+38h] [rbp-18h]
  int v26; // [rsp+3Ch] [rbp-14h]
  int v27; // [rsp+40h] [rbp-10h]
  bool v28; // [rsp+45h] [rbp-Bh]
  bool v29; // [rsp+46h] [rbp-Ah]
  bool v30; // [rsp+47h] [rbp-9h]
​
  v28 = (((_BYTE)x_2 - 1) * (_BYTE)x_2 & 1) == 0;
  v29 = y_3 < 10;
  v27 = 1567572003;
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        v26 = v27;
        v25 = v27 + 1130483098;
        if ( v27 != -1130483098 )
          break;
        v9 = -1065940243;
        if ( y_3 < 10 || (((_BYTE)x_2 - 1) * (_BYTE)x_2 & 1) == 0 )
          v9 = -714366873;
        v27 = v9;
      }
      v24 = v26 + 1065940243;
      if ( v26 != -1065940243 )
        break;
      v27 = -1130483098;
    }
    v23 = v26 + 714366873;
    if ( v26 == -714366873 )
      break;
    v22 = v26 + 511865542;
    if ( v26 == -511865542 )
    {
      v8 = -1065940243;
      if ( y_3 < 10 || (((_BYTE)x_2 - 1) * (_BYTE)x_2 & 1) == 0 )
        v8 = -1130483098;
      v27 = v8;
    }
    else
    {
      v21 = v26 + 329192939;
      if ( v26 == -329192939 )
      {
        v11 = &v13 - 2;
        *((_DWORD *)&v13 - 4) = 0;
        *(_DWORD *)v11 = 0;
        *(_DWORD *)v11 = *((_DWORD *)&v13 - 4) + 1;
        v12 = printf(&byte_404030);
        v27 = 191033970;
        v14 = v12;
      }
      else
      {
        v20 = v26 - 191033970;
        if ( v26 == 191033970 )
        {
          v4 = &v13 - 2;
          *((_DWORD *)&v13 - 4) = 0;
          *(_DWORD *)v4 = 0;
          *(_DWORD *)v4 = *((_DWORD *)&v13 - 4) + 1;
          v16 = &v13 - 2;
          v5 = printf(&byte_404030);
          v6 = -329192939;
          v30 = *(_DWORD *)v16 >= 1;
          if ( y_3 < 10 || (((_BYTE)x_2 - 1) * (_BYTE)x_2 & 1) == 0 )
            v6 = 1347608926;
          v27 = v6;
          v15 = v5;
        }
        else
        {
          v19 = v26 - 1347608926;
          if ( v26 == 1347608926 )
          {
            v7 = -511865542;
            if ( v30 )
              v7 = 1700479422;
            v27 = v7;
          }
          else
          {
            v18 = v26 - 1567572003;
            if ( v26 == 1567572003 )
            {
              v3 = -329192939;
              if ( v29 || v28 )
                v3 = 191033970;
              v27 = v3;
            }
            else
            {
              v17 = v26 - 1700479422;
              if ( v26 == 1700479422 )
              {
                exec();
                v27 = -511865542;
              }
            }
          }
        }
      }
    }
  }
  return 0;
}

以上成功实现代码混淆

参考

Obfuscating C++ programs via control flow flattening

去除符号表

查看符号表

readelf -s test

采用strip工具对符号表进行去除

.symtab因为是在调试和链接时有用的,所以,可以从生产的二进制执行文件中移除。可以使用strip。strip是可以移除符号以及节的工具。

  1. 移除.symtab 符号表 以及 .strtab 符号字符串表 直接运行
    • strip --remove-section=.symtab file_in
    • strip --remove-section=.strtab file_in
  2. 想要让可执行文件没有.dynsym动态链接表,.dynstr动态链接字符表。 gcc编译时添加参数,从而使用静态编译。gcc -static 或者 gcc -nostdlib
    • gcc -nostdlib :不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。
    • gcc -static:在支持动态链接的系统上,阻止连接共享库。该选项在其它系统上 无效。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C++反汇编与逆向分析技术揭秘

    《C++反汇编与逆向分析技术揭秘》从介绍调试工具开始,到语言特性的分析,反汇编代码的重建等,再到逆向分析技术应用,内容逐步深入。软件分析技术重在方法,所以《C+...

    用户3157710
  • Switch APP逆向分析

    最近学习pwn,看到一个switch的逆向题目,于是乎在浩然表哥和the one表哥的帮助下研究了一波,学到了很多不可描述的知识。题目的下载地址:

    物联网安全小编
  • [系统安全] 一.什么是逆向分析、逆向分析基础及经典扫雷游戏逆向

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列。因此,我重新开设了这个专栏...

    Eastmount
  • Android逆向分析概述

    学习逆向的初衷是想系统学习Android下的hook技术和工具, 想系统学习Android的hook技术和工具是因为Android移动性能实战这本书. 这本书里...

    望天
  • Android逆向分析大全

    Android程序的特点相比在于使用混淆方式打包,将包名、类名、函数名改成不易看懂的字母,从而使生成的apk小很多(android studio提供了relea...

    悲伤的夏洛特@席玉铎666
  • Js逆向分析,某礼品代发网POST登陆Js逆向分析

    这里我们就获取到了相关登陆参数,固定不变的不用管,主要是两个参数,codeKey和password!

    二爷
  • JS逆向 | 分析某监测网站的 debugger 反爬措施

    这个网站的加密比较简单的,网上也有不少关于这个网站加密的分析例子,所以关于这个网站的正文加密,这里不做分析。

    咸鱼学Python
  • Android逆向之静态分析

    想必打过CTF的小伙伴多多少少都触过Android逆向,所以斗哥将给大家整一期关于Android逆向的静态分析与动态分析。本期先带来Android逆向的静态分析...

    漏斗社区
  • 小程序逆向分析 (一)

    小程序是一个以 wxapkg 为后缀的文件,在android手机的 /data/data/com.tencent.mm/MicroMsg/用户id/appbra...

    fenfei331
  • Flipagram 涂鸦特效逆向分析

    背景 Flipagram是美国一款非常火爆的短视频应用,一度登顶美国appstore榜首。前段时间又被今日头条重金收购,被当做今日头条发展海外短视频、提升国际影...

    MelonTeam
  • 一道题入门逆向分析

    将自己学习逆向破解的知识总结一下,主要是逆向的入门知识以及自己的学习感悟,包括逆向时的一些思路和补丁,注册机,保护壳等方面的一些知识,有不到之处请师傅们斧正。

    FB客服
  • Linux Security Module逆向分析实战

    本文记录了对某发行版Linux中一个安全模块(LSM)的逆向过程,该LSM对系统中待运行的程序进行安全校验,数据流穿越内核态与用户态,涉及系统内核及系统服务。此...

    FB客服
  • 逆向分析“海莲花” APT木马的花指令反混淆工具

    本文中,CheckPoint研究人员基于对“海莲花” 木马程序的分析,编写了一段绕过其混淆技术的反混淆工具-APT32GraphDeobfuscator.py,...

    FB客服
  • Android逆向之动态分析so篇

    本期,斗哥将给大家带来Android逆向的动态分析,简述Android动态分析环境配置与IDA调试so文件。

    漏斗社区
  • 第二届ZCTF逆向题分析(一)

    第二届ZCTF逆向题分析(一) From ChaMd5安全团队核心成员 Poyoten 比赛时由于第二天有事,第三题re没做,所以也就没有写WP。但是后来看了...

    ChaMd5安全团队
  • 逆向分析神器BinNavi开源了

    得益于IDA pro十分开放的架构,Gergely Erdelyi和Ero Carrera在2004年基于IDA pro发布了IDAPython,逆向工程师能够...

    FB客服
  • apktool逆向报错问题分析(一)

    比如有些apk的assets目录下有加密后的Dex文件。 看log,确实是在解析assets目录出的错。这种也好解决在原来的执行命令后面添加–only-mai...

    李小白是一只喵
  • 轻JS逆向分析“攒经验”项目之某交易所Sign加密参数逆向分析

    这篇文章是公众号《云爬虫技术研究笔记》的《JS逆向分析“攒经验”项目》的第一篇:《某交易所Sign加密参数逆向分析》

    云爬虫技术研究笔记
  • [系统安全] 二.如何学好逆向分析及吕布传游戏逆向案例

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列。因此,我重新开设了这个专栏...

    Eastmount

扫码关注云+社区

领取腾讯云代金券