首页
社区
课程
招聘
[原创]ollvm的混淆反混淆和定制修改
发表于: 2017-5-19 10:46 46384

[原创]ollvm的混淆反混淆和定制修改

2017-5-19 10:46
46384

                                        ollvm的混淆反混淆和定制修改

   最近各大杀毒公司陆续都出了混淆,网上关于ollvm的资料比较少,于是就有了这篇文章,这篇文章介绍,androidnative代码,也就是solinuxc/c++代码均可使用的混淆工具ollvm的编译,混淆,反混淆,和反反混淆。

第一篇.ollvm的编译环境搭建------混淆

教你搭建编译和使用ollvm3.4 3.5 3.6的环境,非常详细

第二篇.ollvm的还原---反混淆

根据网上的一些文章,对ollvm混淆后的代码进行还原,写下我详细的心得和代码注释和环境搭建(目前只能还原linux x86,对于arm有兴趣的可以进一步研究)

第三篇.ollvm的定制---反反混淆

由于公司原因,这里介绍修改后的结果

====================第一篇ollvm的编译环境搭建------混淆======================

一、androidNDK搭建ollvm环境和使用

注意这里有编译环境和编译后的版本,ubuntu64位的系统依然可以使用ndk32,但是只能编译clang64,所以你不需要ndk64就不需要编译64位的ollvm64

1.编译ollvm 32  

版本有三个我们选择obfuscator-llvm-3.4解压得到文件夹obfuscator-llvm-3.4

ollvm的下载地址https://github.com/obfuscator-llvm/obfuscator/tree/llvm-3.4

ndk选择android-ndk-r10b-linux-x86.tar.bz2

环境选择ubuntu14.0.4 x32 or x64

(0)安装ndk

ndk解压到/opt/android/ndk/

解压后的目录

/opt/android/ndk/android-ndk-r10e

$ sudo gedit /etc/profile,在文件末尾加入如下内容:
#set NDK env
export NDK_HOME=/opt/android/ndk/android-ndk-r10b

export PATH=$NDK_HOME:$PATH

$ source /etc/profile   使之生效

(1)编译ollvm的工具

apt-get install cmake

sudo apt-get install g++

正式编译ollvm

cd obfuscator-llvm-3.4

mkdir build

cd build

cmake -DCMAKE_BUILD_TYPE:String=Release ../

make –j4   (不要复制哦,手动输入命令)(注意这里一定要加j4,如果只是make –j他默认只会用一个cpu然后会卡到蛋疼的)

注意:分配内存和cpu多点不然卡死,我这里是8G内存+(2处理器数量每个处理器2个核心)

编译完后得到二进制程序都在build/binbuild/lib

(2)下面来配置32位的ndk

[1]打开ndktoolchains目录新建目录obfuscator-llvm-3.4

并将llvm-3.3目录下的prebuilt目录和文件 config.mksetup.mksetup-common.mk拷贝到obfuscator-llvm-3.4目录中

然后替换obfuscator-llvm-3.4/prebuilt/linux-x86下的binlib为我们编译好的binlib

然后将下面文件复制一份,改名称如下,比如arm-linux-androideabi-clang3.4复制一行改名为arm-linux-androideabi-obfuscator3.4

arm-linux-androideabi-clang3.4-> arm-linux-androideabi-obfuscator3.4

mipsel-linux-android-clang3.4-> mipsel-linux-android-obfuscator3.4

x86-clang3.4-> x86-obfuscator3.4

 

分别修改以上三个文件的 setup.mk 中的 LLVM_NAME ,即将其指定到开始建立的obfuscator-llvm-3.4目录,也就是把

LLVM_NAME := llvm-$(LLVM_VERSION)改成LLVM_NAME := obfuscator-llvm-$(LLVM_VERSION)

 

如果是配置64位的ndk配置,还要额外修改$NDK_PATH/build/core/setup-toolchain.mk文件,在NDK_64BIT_TOOLCHAIN_LIST := 加入 obfuscator 对应的NDK_TOOLCHAIN_VERSION

NDK_64BIT_TOOLCHAIN_LIST := obfuscator3.4 clang3.6 clang3.5 clang3.4 4.9

 

2.使用

Application.mk中指定编译器名字:

NDK_TOOLCHAIN_VERSION := obfuscator3.4

Android.mk中设置混淆参数:

LOCAL_CFLAGS += -mllvm -sub -mllvm -bcf -mllvm –fla

正常编译ndk就行了

例子

Application.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

APP_ABI := armeabi

NDK_TOOLCHAIN_VERSION := obfuscator

include $(BUILD_EXECUTABLE)

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello

LOCAL_SRC_FILES := hello.c

LOCAL_CFLAGS += -mllvm -sub -mllvm -bcf -mllvm –fla  混淆参数

LOCAL_ARM_MODE := arm

include $(BUILD_EXECUTABLE)

hello.c

#include <stdio.h>

int main(int argc, char **args){    

    int a=1;

         int b=0;

         if(a>b){

                   printf("snow:%d\n", a);

         }

         else{

                   printf("test:%d\n", b);

         }

         return 0;

}

3.更多使用

bcf可以配合下面参数使用

-mllvm -perBCF=20: 对所有函数都混淆的概率是20%,默认100%

-mllvm -boguscf-loop=3: 对函数做3次混淆,默认1

-mllvm -boguscf-prob=40: 代码块被混淆的概率是40%,默认30%

给某个函数单独加入混淆;注意注意经过我测试只有ollvm3.5ollvm3.6可以使用单独函数加混淆

int main(int argc, char **args)__attribute((__annotate__(("bcf"))));

 

linux可执行文件搭建ollvm环境和使用

环境跟前面那个一样,在编译完毕ollvm之后有目录obfuscator-llvm-3.4/build/bin/此目录下面有一个clang,指向clang-3.4我们编译linux可执行的程序可以用

obfuscator-llvm-3.4/build/bin/clang  xx.c –o xx –mllvm –fla 就是控制流平展了

 

 

 

=========================第二篇.ollvm的还原---反混淆===================

一、网上的Decllvm的分析

F8LEFT写的一个工具,这个工具出现在吾爱破解2016的安全挑战赛第七题的解答里面

此工具给的demoAliLLVM.py针对阿里第二届安全挑战赛crackme3

下面只是说这个工具的使用和原理

1.入口360LLVM.py文件

if __name__ == "__main__":

    print("============360LLVMStart=================")

    ins = C360LLVM()

    reg = ArmReg()

    dbgEng = DbgEngine(reg, ins)

    fd = open("F:/trace.log", "w+")

    dbgEng.start_run(GetRegValue("PC"), 1000, fd)

    fd.close()

    del dbgEng

    del reg

    del ins

    print("============360LLVMEnd=================")         

大致原理这是一个ida的脚本,运行需要动态调试程序才行,根据程序运行的时候把寄存器的参数打印下来并且写到txt文件里面,方便分析,这个用处不是太大,只是利用ida打印程序流程,但是可以通吃NDKlinux的混淆,顺便感谢一下他的脚本里面包含很多ida api的使用哦!

 

二、又找的的另外一篇利用符号执行

参考文章https://security.tencent.com/index.php/blog/msg/1122  利用符号执行去除控制流平坦化

 

这篇文章的办法可以完美的恢复控制流平坦化但是只是linux6432位可执行文件x86格式的混淆后完美还原,对于androidso和可执行文件不行,arm格式的指令找不到规则不像x86那样找到规则,需要我们自己分析规则

注意作者给的deflat.py依赖的barf只能运行于linux64位,所以就算在linux32位上混淆了,我们也要拿到linux64位上运行deflat.py脚本哦!!!

 

我的电脑是ubuntu14.04 x64

1.搭建环境和运行

[1]安装python

ubuntu自带了Python 2.7.6

[2]安装pip和??

apt-get install python-pip

sudo apt-get install python-dev libffi-dev build-essential

 

[3]安装barf

下载barf解压cd到目录运行

python setup.py install

 

[4]安装angr

sudo pip install angr 报错,再次安装sudo apt-get install python-dev libffi-dev build-essential

 

[5]运行

python deflat.py check_passwd_flat 0x400530

 

 

注意在ubuntu14.0.4 x32环境运行出错

ImportError: ERROR: fail to load the dynamic library

因为deflat.py会去调用BARFBARF这货只能在linux x64位运行坑爹啊,但是我们可以在x32上编译了,拿到x64上面跑,

这里我们自己编译和混淆在ubuntu14.04_x32位下面在ubuntu14.0.4_64里面还原混淆

[1]编译

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int check_password(char *passwd)

{

    int i, sum = 0;

    for (i = 0; ; i++)

    {

        if (!passwd[i])

        {

            break;

        }

        sum += passwd[i];

    }

    if (i == 4)

    {

        if (sum == 0x1a1 && passwd[3] > 'c' && passwd[3] < 'e' && passwd[0] == 'b')

        {

            if ((passwd[3] ^ 0xd) == passwd[1])

            {

                return 1;

            }  

            puts("Orz...");

        }

    }

    else

    {

        puts("len error");

    }

    return 0;

}

 

int main(int argc, char **argv)

{

    if (argc != 2)

    {

        puts("error");

        return 1;

    }

    if (check_password(argv[1]))

    {

        puts("Congratulation!");

    }

    else

    {

        puts("error");

    }

    return 0;

}

gcc check_passwd.c -o check_passwd

[2]混淆控制流平坦

root/桌面/software/my _compile_ollvm/obfuscator-llvm-3.4/build/bin/clang-3.4  check_passwd.c -o check_passwd_32_flat -mllvm -fla

[3]拿到x64位上还原混淆

python deflat.py check_passwd_32_flat 0x80488B0  //main函数

 

[4]全混淆

python deflat.py check_passwd_32_flat_sub_bcf 0x8048420

 

依然可以还原-fla

2. deflat.py脚本分析心得和我的注释

ida函数中可以看见很多块,一块一块的

 



                                            

#第一步:找出6大块,可以用静态分析得到

序言                            保留

主分发器                   去掉

预处理器                   去掉

retn                        保留

真实块                       保留

无用块                       去掉

 

[1]序言和主分发器,函数开始就是序言,序言下面紧接着就是主分发器


[2]预处理器

ida查找办法谁调用了主分发器,谁就是预处理器(在主分发器按x,看见的就是预处理器)

[3]真实块,


ida查找办法所有调用预处理器的块都是预处理器(在预处理器按x查看到的都是真实块)

[4]retn  


ida查找办法,没有后继的块就是,也就是下线没有分支的

[5]无用块

其余均是无用块

#第二步:找出真实块和序言和retn之间的调用关系,必须动态运行

#难点一:使用symbolic_execution找出真实块和序言的调用关系,必须使用他的引擎运行或者动态运行

如下的关系

         #执行到这里已经获得了原函数的调用关系,下面是恢复之后的关系,真实块7->retn返回块

         #0x8048a82: ['0x8048a95']  真实块6 : retn返回块

         #0x8048a65: ['0x8048a82']  真实块5 : 真实块6

         #0x8048a48: ['0x8048a82']  真实块4 : 真实块6

         #0x80488b0: ['0x80489d4']  序言    : 真实块1

         #0x80489d4: ['0x8048a1b', '0x80489f7']  真实块1 :真实块3,真实块2

         #0x8048a95: []                                                                 retn返回块

         #0x80489f7: ['0x8048a95']                                真实块2 : retn返回块

         #0x8048a1b: ['0x8048a65', '0x8048a48']  真实块3 :真实块5,真实块4

下面是修复后他们的调用图

 


#第三步:nop掉无用块和主分发器和预处理器,可以静态分析得到

#第四步:修复真实块序言部分的跳转指令,修复办法,

#情况一:有一个childs,也就是一个后继的块,找到块的最后一条指令,将其抹掉后改成新的jmpjmp到自己的childs

#情况二:有多个childs

下面是我的代码注释

#coding: UTF-8

from barf.barf import BARF

import angr

import simuvex

import pyvex

import claripy

import struct

import sys

 

def get_retn_predispatcher(cfg):

    global main_dispatcher

    for block in cfg.basic_blocks:

        if len(block.branches) == 0 and block.direct_branch == None:

            retn = block.start_address


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 2
支持
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  CCkicker   +1.00 2017/05/22
最新回复 (34)
雪    币: 6575
活跃值: (4531)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
2
好详细,辛苦了
2017-5-19 11:01
0
雪    币: 1037
活跃值: (1780)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
大坟,留个qq号,线下多交流交流呗
2017-5-19 13:21
0
雪    币: 111
活跃值: (219)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
MARK,谢谢分享~
2017-5-19 15:27
0
雪    币: 1039
活跃值: (355)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
mark.
2017-5-19 15:34
0
雪    币: 783
活跃值: (1121)
能力值: ( LV5,RANK:78 )
在线值:
发帖
回帖
粉丝
6
很强.
2017-5-19 15:45
0
雪    币: 7012
活跃值: (4222)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7

厉害了我的哥,  感谢分享

我的知识百科->match目录这个在哪??????????

2017-5-19 18:57
0
雪    币: 191
活跃值: (195)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
8
MaYil 厉害了我的哥,&nbsp; 感谢分享 我的知识百科-&gt;match目录这个在哪??????????
第七题的解答网上有详细内容的
2017-5-19 22:10
0
雪    币: 3712
活跃值: (1401)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
9
2017-5-20 11:17
0
雪    币: 184
活跃值: (96)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
厉害了,最近正在学习安卓
2017-5-20 16:29
0
雪    币: 347
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
好贴~  非常感谢分享
2017-5-20 18:18
0
雪    币: 4687
活跃值: (253)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
mark,留着慢慢学习看
2017-5-23 10:47
0
雪    币: 208
活跃值: (479)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
13
很强很厉害
2017-5-23 14:26
0
雪    币: 11
活跃值: (80)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
mark。。。
2017-6-1 09:56
0
雪    币: 1895
活跃值: (1657)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
15
mark。学习。
2017-6-2 10:30
0
雪    币: 1392
活跃值: (5177)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
16
mark  llvm混淆
2017-6-2 10:34
0
雪    币: 2314
活跃值: (2205)
能力值: (RANK:400 )
在线值:
发帖
回帖
粉丝
17
写的不错~~ 
感谢LZ。
2017-6-2 10:43
0
雪    币: 76
活跃值: (114)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
群号:57354586  建立了一个关于LLVM反思考的群,喜欢探讨贡献的朋友请进。
2017-6-2 15:03
0
雪    币: 72
活跃值: (324)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
19

厉害了~~请教一个问题哈

我使用ollvm3.5只用控制流平坦化-mllvm -fla同是x86平台,用ndk+ollvm混淆出来的流程图不如直接用ollvm的clang编译出来的那样“漂亮”。
clang直接编译的有层次分明的主分发器、预分发器

而用ndk+ollvm编译的没有这些明显的特征,显得比较混乱,请问这是为什么啊?

2017-6-2 16:18
0
雪    币: 11
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20

ida查找办法所有调用预处理器的块都是预处理器
---
上面的描述是不是错的,应该是:ida查找办法所有调用预处理器的块都是真实块

2017-7-10 23:48
0
雪    币: 153
活跃值: (181)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
21
freebuf那篇的附件你有吗?楼主
2017-7-13 00:26
0
雪    币: 29
活跃值: (97)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
niubility  哈哈哈
2017-7-17 12:19
0
雪    币: 63
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
好详细  好人一生平安
2017-7-17 13:09
0
雪    币: 102
活跃值: (2050)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
24
很详细,牛逼,mark了。
2018-8-18 17:37
0
雪    币: 249
活跃值: (346)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
好人一生平安,牛人无处不在
2018-9-29 20:18
0
游客
登录 | 注册 方可回帖
返回
//