前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >反逆向分析

反逆向分析

原创
作者头像
i0gan
修改2021-06-28 10:04:32
2K0
修改2021-06-28 10:04:32
举报
文章被收录于专栏:I0ganI0gan

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编译
代码语言:javascript
复制
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ../ollvm-tll-master
make -j8
官方编译
代码语言:javascript
复制
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进行混淆

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

ida64打开F5

代码语言:javascript
复制
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:在支持动态链接的系统上,阻止连接共享库。该选项在其它系统上 无效。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 Ollvm介绍
  • 0x02 Ollvm混淆介绍
  • 0x03 Ollvm编译
    • ollvm-til编译
      • 官方编译
      • 0x4 命令介绍
        • 控制流扁平化
          • 指令替换
            • 虚假控制流程
              • 其他
              • 例子
              • 参考
              • 去除符号表
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档