使用O-LLVM和NDK对Android应用进行混淆

@author ASCE1885的 Github 简书 微博 CSDN

原文链接

Android开发中经常需要对敏感信息进行加密,避免不了要将密钥存放在终端设备上,那么如何防止密钥被逆向出来呢?这是一个先有鸡还是先有蛋的悖论。相比较将密钥写在Java层,将其下移到NDK层是个更好的选择,本文就来介绍如何对NDK层代码进行混淆,以更好的保护我们的密钥。

混淆是一种用来隐藏程序意图的技术,具体的实现技术可能差别比较大,最有效的技术可以增加逆向工程和破解的难度,防止知识产权被窃取。已经有很多第三方的软件可以用来混淆我们的Android应用,常见的有:

这些混淆器在代码中起作用的层次是不一样的。Android编译的大致流程如下:

Java Code(.java) -> Java Bytecode(.class) -> Dalvik Bytecode(classes.dex)

有的混淆器是在编译之前直接作用于java源代码,有的作用于java字节码,有的作用于Dalvik字节码。

Android NDK使得开发者可以绕过虚拟机从而进一步提高程序性能,或者更直接的与内核和硬件交互。Google对NDK的描述是:“NDK是允许开发者使用原生C/C++语言开发app的一套工具集。这样有利于某些类型的app复用C/C++编写的已有代码库,当然大部分app不需要使用Android NDK”。

相对于Dalvik虚拟机层次的混淆而言,原生语言(C/C++)组件的代码混淆选择并不多,Obfuscator-LLVM工程是一个值得关注的例外。这个项目专注于LLVM编译器,这一点使得它可移植性很高,兼容LLVM支持的所有语言(C,C++, Objective-C, Ada and Fortran)和平台(x86, x86-64, PowerPC, PowerPC-64,ARM, Thumb, SPARC, Alpha, CellSPU, MIPS, MSP430, SystemZ,and XCore)。0vercl0k在o-llvm发布之前发表了一篇论文,解释了使用LLVM编译器的优点以及简单的代码转换。

我使用O-LLVM和NDK已经有一段时间了。在了解到TowelRoot也在使用O-LLVM时,我决定写一篇文章来介绍它。TowelRoot是一款Android一键Root工具,关于它是如何利用Linux内核bug来达到root目的的可以参见这篇文章。TowelRoot使用O-LLVM主要用来防止其他人拷贝并利用它来实现非法目的,同时防止被重打包后并出售。

下面我们就来讲解如何开始使用O-LLVM来混淆原生代码,实现类似TowelRoot的目的。

使用NDK O-LLVM二进制叠加包

我已经在OSX和Linux平台上把混淆器基于NDK打包成二进制叠加包,你也可以参照本文最后一节的步骤自己从源码进行编译。混淆器的二进制叠加包下载地址:

下载正确的二进制叠加包,将它解压到你电脑的NDK目录中。

配置O-LLVM NDK工程

现在让我们对NDK工程进行配置,使其支持O-LLVM混淆器。我们工程目录结构如下所示:

?  AndroidObfuscation-NDK git:(master) tree .
.
├── jni
│   ├── Android.mk
│   ├── Application.mk
│   └── obfuscationTest.c

工程的Application.mk内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

APP_ABI := armeabi

NDK_TOOLCHAIN_VERSION := clang3.4-obfuscator

include $(BUILD_EXECUTABLE)

混淆器的各种代码转换可以参见Obfuscator Wiki。可以通过LOCAL_CFLAGS标签把这些转换标记设置给混淆器。记住混淆器的转换标记需要以-mllvm开头,这样clang编译器可以传递它。

Android.mk的配置示例如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := obfuscated
LOCAL_SRC_FILES := obfuscationTest.c

LOCAL_LDLIBS := -static

LOCAL_CFLAGS := -mllvm -sub -mllvm -fla -mllvm -bcf

include $(BUILD_EXECUTABLE)

现在可以编译我们的工程了:

?  AndroidObfuscation-NDK git:(master) ndk-build
[armeabi] Compile thumb  : obfuscated <= obfuscationTest.c
[armeabi] Executable     : obfuscated
[armeabi] Install        : obfuscated => libs/armeabi/obfuscated

使用了上面的配置和脚本结构的例子工程可以参见AndroidObfuscation-NDK

上面我预先构建的二进制叠加包包含了由yag00贡献的试验性的字符串混淆技术。你可以通过给LOCAL_CFLAGS传递“-mllvm -xse”标记来使能字符串混淆功能。

?  AndroidObfuscation-NDK git:(master) cat jni/obfuscationTest.c
#include <stdio.h>

int main(void){
  printf("Hello, world\n");
  return 0;
}

这个例子中,在使用字符串混淆功能之前效果如下:

?  AndroidObfuscation-NDK git:(master) strings libs/armeabi/obfuscated | grep Hello
Hello, world

使用字符串混淆功能之后:

?  AndroidObfuscation-NDK git:(master) strings libs/armeabi/obfuscated | grep Hello

从源码构建适用于NDK的O-LLVM

git clone -b llvm-3.4 https://github.com/obfuscator-llvm/obfuscator.git
cd obfuscator
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE:String=Release ../obfuscator/
make -j5

构建o-llvm的完整指南参见这里,不过上面的说明应该足够了。

cp -r $NDK_PATH/toolchains/arm-linux-androideabi-clang3.4 $NDK_PATH/toolchains/arm-linux-androideabi-clang3.4-obfuscator

打开文件

$NDK_PATH/toolchains/arm-linux-androideabi-clang3.4-obfuscator/setup.mk

将文件里面的:

TARGET_CC := $(LLVM_TOOLCHAIN_PREFIX)clang$(HOST_EXEEXT)
TARGET_CXX := $(LLVM_TOOLCHAIN_PREFIX)clang++$(HOST_EXEEXT)

修改为(记得修改o-llvm为你自己电脑上面的路径)

LLVM_TOOLCHAIN_PATH := <PATH_TO_OBFUSCATOR_REPO>/build/bin/
TARGET_CC := $(LLVM_TOOLCHAIN_PATH)clang$(HOST_EXEEXT)
TARGET_CXX := $(LLVM_TOOLCHAIN_PATH)clang++$(HOST_EXEEXT)

文末摄影鉴赏

时间: 2024-10-01 03:55:20

使用O-LLVM和NDK对Android应用进行混淆的相关文章

分享 如何做到基于NDK的Android应用防破解!

 Android程序防破解是发布app时一个很需要考虑的问题,通常的做法是对代码加入混淆干扰以增加破解难度.但即便如此,混淆操作之后的java代码仍然可以被通过各种方法进行破解.在基于NDK的Android中含有相应的main.cpp来作为应用程序的入口,因而在这里进行一些防破解较验,相应的破解难度就会增大不少(相对于java代码). 在Android整个导出过程中,生成.dex阶段是整个打包发布操作的基础,包括相应的java源代码.外部库文件均会被编译链接到.dex文件中,而其中关于代码的任何

基于NDK的Android防破解

Android程序防破解是发布app时一个很需要考虑的问题,通常的做法是对代码加入混淆干扰以增加破解难度.但即便如此,混淆操作之后的java代码仍然可以被通过各种方法进行破解.在基于NDK的Android中含有相应的main.cpp来作为应用程序的入口,因而在这里进行一些防破解较验,相应的破解难度就会增大不少(相对于java代码). 在Android整个导出过程中,生成.dex阶段是整个打包发布操作的基础,包括相应的java源代码.外部库文件均会被编译链接到.dex文件中,而其中关于代码的任何改

NDK 在 Android studio如何使用(Android studio NDK)

其实这个东西入门的话.直接在官网查找demo再结合文档就能间接了解如何构建是最快捷的. 这里提供一下官网和demo的地址. 官网的NDK在Android studio的搭建:http://tools.android.com/tech-docs/new-build-system/gradle-experimental 官网的Demo:https://github.com/googlesamples/android-ndk 我比较懒:直接在Android studio中的File -->import

Android流媒体开发之路二:NDK开发Android端RTMP直播推流程序

NDK开发Android端RTMP直播推流程序 经过一番折腾,成功把RTMP直播推流代码,通过NDK交叉编译的方式,移植到了Android下,从而实现了Android端采集摄像头和麦克缝数据,然后进行h264视频编码和aac音频编码,并发送到RTMP服务器,从而实现Android摄像头直播.程序名为NdkRtmpEncoder,在这里把整个过程,和大体框架介绍一下,算是给需要的人引路. 开发思路 首先,为什么要用NDK来做,因为自己之前就已经实现过RTMP推流.RTMP播放.RTSP转码等等各种

android 反编译 混淆过程中注意事项

此文源自组内成员分享的PPT,其他成员的文档由于没有得到授权,暂不公开. 本文命令如果没有特殊注明,均为windows 7环境. 本文只涉及大概的知识点,不涉及具体的细节,需要注意. 反编译 apktool 可反编译资源文件(xml,点九图)以及代码为smali代码 使用命令:apktool d xxx.apk output_filepath dex2jar 反编译dex文件(解压apk获得的classes.dex)为jar 使用命令:dex2jar xxx.dex jd-gui 查看jar文件

Android项目:proguard混淆之常见问题及解决方法汇总

1.使用proguardgui混淆器对jar包进行混淆,出现EXCEPTION FROM SIMULATION错误: [2014-07-08 14:29:55 - Test024_HouseBox_v02_jar] Dx  EXCEPTION FROM SIMULATION: [2014-07-08 14:29:55 - Test024_HouseBox_v02_jar] Dx local variable type mismatch: attempt to set or access a va

Android项目:proguard混淆之常见开源项目混淆配置

1.Gson混淆 ## ---------------------------------- ##   ########## Gson混淆    ########## ## ---------------------------------- -keepattributes Signature  -keep class sun.misc.Unsafe { *; }  -keep class com.google.gson.examples.android.model.** { *; } 2.gr

Android开发者的混淆使用手册

综述 毫无疑问,混淆是打包过程中最重要的流程之一,在没有特殊原因的情况下,所有 app 都应该开启混淆. 首先,这里说的的混淆其实是包括了代码压缩.代码混淆以及资源压缩等的优化过程.依靠 ProGuard,混淆流程将主项目以及依赖库中未被使用的类.类成员.方法.属性移除,这有助于规避64K方法数的瓶颈:同时,将类.类成员.方法重命名为无意义的简短名称,增加了逆向工程的难度.而依靠 Gradle 的 Android 插件,我们将移除未被使用的资源,可以有效减小 apk 安装包大小. 本文由两部分构

Android日志:代码混淆,使用说明

上一篇介绍了Google官方的一些解释,这一篇主要介绍如何实战(Eclipse开发)使用Googel提供的这个工具.如对代码混淆的概念不是很了解的建议先看上一篇--Android日志:代码混淆,官方文档介绍-----来自Google最新文档 主要先简单的介绍三个主要文件,在sdk下的proguard里面:  我的SDK路径为H:\Android\android-sdk-windows\tools\proguard proguard-android.txt//系统配置好一些默认选项,考虑的比较详细