JNI NDK and development (5) _ using JNI code Obfuscator-LLVM confused

Disclaimer: This blog is mainly recorded some of the problems encountered by study notes and solutions, please indicate the source! https://blog.csdn.net/u010982507/article/details/87927042

What is LLVM

LLVMIt is low level virtual machineshort, 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/
    Here Insert Picture Description
    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.
    Here Insert Picture Description
    Select the top left corner Tools, open the How to Install For Command Line Use
    Here Insert Picture Description
    pop-up configuration environment prompt box, as shown below:
    Here Insert Picture Description
    Use the command: PATH="/Applications/CMake.app/Contents/bin":"$PATH"After performing the execution cmake -versionwill take effect in the current command line window, open a new window does not recognize this command so also perform sudo "/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-llvmsource code

1、从https://github.com/obfuscator-llvm/obfuscator/tree/llvm-4.0下载最新代码,这个分支下有好几个版本。
Here Insert Picture Description
我下载的是4.0版本,下载完成后解压即可,git clone会有点慢,所以我直接把压缩包下载下来了。解压后在同级目录创建build目录。
Here Insert Picture Description
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目录下,我们只需要复制binlib目录即可。
Here Insert Picture Description
4、配置ndk的llvm
build下的binlib复制到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;
}

Guess you like

Origin blog.csdn.net/u010982507/article/details/87927042