What is LLVM
LLVM
It is low level virtual machine
short, in fact, is a compiler framework. llvm With the continuous development of this project, we have been unable to complete this project on behalf of, but this name has been inherited.
llvm is an open source project. The first time it is Illinois of a research project, the main person in charge is Chris Lattner, who now works in Apple. Apple is currently one of the main sponsors of the project llvm.
llvm primary role is that it can act as multilingual rear end, it can provide independent optimization function for generating a programming language and a variety of CPU code. In addition llvm now not just a programming framework, which currently contains a lot of sub-projects, such as the most famous clang.
Advantages llvm is open source, there is a good form of expression of IR language, modular made particularly good.
llvm this framework there are already a number of tools based on this framework can be used.
llvm's official website address is: llvm.org . Here you can download the latest release code, you can also find the relevant document describes the llvm
Taken: https://blog.csdn.net/snsn1984/article/details/8036032
Obfuscator-LLVM Introduction
OLLVM (Obfuscator-LLVM) is a University of Applied Sciences Northwestern Switzerland Security Labs in June 2010 launched a confusion for the LLVM source project, the main role is to increase the difficulty of reverse, to protect the security code to a certain extent. Since the late turned to commercial projects strong.protect, so the progress of the project was stalled, and in March, 2005, LLVM has been updated to version 4.0, some of the features of the new version has some limitations lead to the old version of OLLVM.
github repository latest version: https://github.com/obfuscator-llvm/obfuscator/tree/llvm-4.0
Taken: https://baijiahao.baidu.com/s?id=1572199238543099&wfr=spider&for=pc
Operating Environment
Operating environment: I use a Mac notebook, in fact, almost with Linux.
IDE: Studio Android 3.1.2
Android SDK version:
compileSdkVersion 26
buildToolsVersion '26.0.2'
NDK Version: android-ndk-r16b
I checked a lot of information online using the NDK 10, some old, NDK 16, although this is not the latest version, but with a few problems.
Built environment
- Install CMake
CMake is to install a more advanced than make cross-platform compiler, configuration tools, you can use a simple sentence to describe the installation for all platforms (compilation). And according to different platforms, different compiler generates the corresponding Makefile or project file.
1, download CMake official website: https://cmake.org/download/
Download noted in the figures cmake-3.14.0-rc3-Darwin- x86_64.dmg installation file, install it on your Mac.
2. Configure CMake environment variables
after the installation is complete, click on the icon to open the CMake, you'll be prompted to select open it.
Select the top left corner Tools, open the How to Install For Command Line Use
pop-up configuration environment prompt box, as shown below:
Use the command:PATH="/Applications/CMake.app/Contents/bin":"$PATH"
After performing the executioncmake -version
will take effect in the current command line window, open a new window does not recognize this command so also performsudo "/Applications/CMake.app/Contents/bin/cmake-gui" --install
.
This configured the camke environment.
Reference article: https://blog.csdn.net/baimafujinji/article/details/78588488
Compile obfuscator-llvm
source code
1、从https://github.com/obfuscator-llvm/obfuscator/tree/llvm-4.0下载最新代码,这个分支下有好几个版本。
我下载的是4.0版本,下载完成后解压即可,git clone会有点慢,所以我直接把压缩包下载下来了。解压后在同级目录创建build
目录。
2、下面就是编译源码的过程了,是重点:
- 进入
build
目录,cd build
- 编译源码
cmake -DCMAKE_BUILD_TYPE=Release ../obfuscator-llvm-4.0/
,后面的是目录名,网上文章一般是cmake -DCMAKE_BUILD_TYPE=Release ../obfuscator/
,所以后面你的目录是什么就执行什么命令。这个编译很快,控制台会出现很多not found,这都不影响下一步操作。 - 最后执行命令
make -j7
,这个过程会有点久,控制台会显示执行进度,大约15分钟到30分钟。
3、编译完成后会生成obfuscator-llvm
的编译源码,在build目录下,我们只需要复制bin
和lib
目录即可。
4、配置ndk的llvm
将build
下的bin
和lib
复制到ndk下的/android-ndk-r16b/toolchains/llvm/prebuilt/darwin-x86_64
目录中替换覆盖。
到这obfuscator-llvm
源码编译与配置就完事了。
混淆JNI代码
1、新建LLVMDemo带JNI的工程,如果不了解JNI开发的可以先看下文章:https://blog.csdn.net/u010982507/article/details/85345985
2、配置CMakeLists.txt
文件
cmake_minimum_required(VERSION 3.4.1)
add_library( native-lib SHARED src/main/cpp/native-lib.cpp )
find_library( log-lib log )
# 源码编译混淆配置
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mllvm -fla -mllvm -bcf -mllvm -sub")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mllvm -fla -mllvm -bcf -mllvm -sub")
target_link_libraries( native-lib ${log-lib} )
3、配置指令介绍
- release环境
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mllvm -fla -mllvm -bcf -mllvm -sub")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mllvm -fla -mllvm -bcf -mllvm -sub")
- debug环境
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -mllvm -fla -mllvm -bcf -mllvm -sub")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mllvm -fla -mllvm -bcf -mllvm -sub")
-fla
控制流扁平化的PASS参数-sub
指令替换的PASS参数-bcf
虚假控制流的PASS参数
效果对比
1、源码
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring
JNICALL
Java_com_rzr_llvm_MainActivity_stringFromJNI (
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
int a = 0;
int b = 1;
int c = a + b;
return env->NewStringUTF(hello.c_str());
}
2, use IDA view so as not to obscure file
jstring __fastcall Java_com_rzr_llvm_MainActivity_stringFromJNI(JNIEnv *env, jobject a2)
{
JNIEnv *v2; // r4
_jstring *v3; // r4
jstring result; // r0
std::allocator<char> __a; // [sp+8h] [bp-1Ch]
std::basic_string<char,std::char_traits<char>,std::allocator<char> > v6; // [sp+Ch] [bp-18h]
std::allocator<char> v7; // [sp+14h] [bp-10h]
int v8; // [sp+18h] [bp-Ch]
v2 = env;
std::string::string(&v6, "Hello from C++", &__a);
v3 = (_jstring *)((int (__fastcall *)(JNIEnv *, unsigned __int8 *))v2->functions->NewStringUTF)(
v2,
v6._M_dataplus._M_p);
std::string::_Rep::_M_dispose(
(std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Rep *const )v6._M_dataplus._M_p - 1,
&v7);
result = (jstring)(_stack_chk_guard - v8);
if ( _stack_chk_guard == v8 )
result = v3;
return result;
}
3, after using IDA view the file so confused
int __fastcall Java_com_rzr_llvm_MainActivity_stringFromJNI(int a1)
{
signed int v1; // r0
signed int v2; // r2
signed int v3; // r0
signed int v4; // r2
signed int v5; // r2
signed int v6; // r3
int v7; // r3
int v8; // r2
int *v9; // r5
int v10; // r1
int v11; // r4
int result; // r0
signed int v13; // [sp-1Ch] [bp-5Ch]
int v14; // [sp-18h] [bp-58h]
int v15; // [sp-10h] [bp-50h]
signed int v16; // [sp-4h] [bp-44h]
int *v17; // [sp+4h] [bp-3Ch]
int v18; // [sp+8h] [bp-38h]
int v19; // [sp+Ch] [bp-34h]
int *v20; // [sp+10h] [bp-30h]
int v21; // [sp+14h] [bp-2Ch]
int *v22; // [sp+18h] [bp-28h]
int v23; // [sp+1Ch] [bp-24h]
int v24; // [sp+20h] [bp-20h]
int v25; // [sp+24h] [bp-1Ch]
int v26; // [sp+28h] [bp-18h]
v18 = a1;
v17 = &v25;
v1 = 1;
v16 = 1;
v2 = 1;
if ( y >= 10 )
{
v16 = 0;
v2 = 0;
}
if ( (~((x - 1) * x) | 0xFFFFFFFE) != -1 )
{
v16 = 0;
v1 = 0;
}
v16 = v2;
v23 = -1;
if ( !(v2 & v1) && (v2 ^ v1) != 1 )
goto LABEL_13;
while ( 1 )
{
v20 = &v14;
__gnu_cxx::new_allocator<char>::new_allocator();
v13 = 1;
v3 = 1;
if ( y <= 9 )
{
v13 = 0;
v3 = 0;
}
v22 = &v15;
v24 = 1;
v21 = -v23;
v13 = 1;
v4 = 1;
if ( !((v23 | 0x3364DB48) & (((x + v23) * x ^ v23 | v23 ^ 1) ^ v23)) )
{
v13 = 0;
v4 = 0;
}
v13 = v3;
if ( v3 != v4 || ((v3 | v4) ^ 1) == 1 )
break;
LABEL_13:
__gnu_cxx::new_allocator<char>::new_allocator();
}
sub_77B4(v22, "Hello from C++", v20);
v20 = (int *)y;
v19 = x;
do
{
v5 = 1;
v6 = 1;
if ( (signed int)v20 >= 10 )
v6 = 0;
v7 = v6 ^ v24;
if ( ((v19 - v21) * v19 ^ v23 ^ 1) & (v19 - v21) * v19 )
v5 = 0;
v8 = v5 ^ v24;
v9 = v22;
}
while ( v7 == v8 && (((v7 | v8) ^ v24) & v24) != 1 );
v10 = *v22;
v11 = (*(int (**)(void))(*(_DWORD *)v18 + 668))();
sub_6D34(*v9 + v23 - 11, &v26);
result = _stack_chk_guard - *v17;
if ( _stack_chk_guard == *v17 )
result = v11;
return result;
}