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

原文链接:http://blog.csdn.net/asce1885/article/details/47175621


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

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

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

<code class="hljs coffeescript has-numbering">Java Code<span class="hljs-function"><span class="hljs-params">(.java)</span> -></span> Java Bytecode<span class="hljs-function"><span class="hljs-params">(.class)</span> -></span> Dalvik Bytecode(classes.dex)</code><ul class="pre-numbering" style="display: block;"><li>1</li></ul>

有的混淆器是在编译之前直接作用于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混淆器。我们工程目录结构如下所示:

<code class="hljs avrasm has-numbering">➜  AndroidObfuscation-NDK git:(master) tree .
.
├── jni
│   ├── Android<span class="hljs-preprocessor">.mk</span>
│   ├── Application<span class="hljs-preprocessor">.mk</span>
│   └── obfuscationTest<span class="hljs-preprocessor">.c</span></code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>

工程的Application.mk内容如下:

<code class="hljs ruby has-numbering"><span class="hljs-constant">LOCAL_PATH</span> <span class="hljs-symbol">:</span>= <span class="hljs-variable">$(</span>call my-dir)

<span class="hljs-keyword">include</span> <span class="hljs-variable">$(</span><span class="hljs-constant">CLEAR_VARS</span>)

<span class="hljs-constant">APP_ABI</span> <span class="hljs-symbol">:</span>= armeabi

<span class="hljs-constant">NDK_TOOLCHAIN_VERSION</span> <span class="hljs-symbol">:</span>= clang3.<span class="hljs-number">4</span>-obfuscator

<span class="hljs-keyword">include</span> <span class="hljs-variable">$(</span><span class="hljs-constant">BUILD_EXECUTABLE</span>)</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>

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

Android.mk的配置示例如下:

<code class="hljs lasso has-numbering">LOCAL_PATH <span class="hljs-subst">:=</span> $(call my<span class="hljs-attribute">-dir</span>)

include $(CLEAR_VARS)

LOCAL_MODULE    <span class="hljs-subst">:=</span> obfuscated
LOCAL_SRC_FILES <span class="hljs-subst">:=</span> obfuscationTest<span class="hljs-built_in">.</span>c

LOCAL_LDLIBS <span class="hljs-subst">:=</span> <span class="hljs-attribute">-static</span>

LOCAL_CFLAGS <span class="hljs-subst">:=</span> <span class="hljs-attribute">-mllvm</span> <span class="hljs-attribute">-sub</span> <span class="hljs-attribute">-mllvm</span> <span class="hljs-attribute">-fla</span> <span class="hljs-attribute">-mllvm</span> <span class="hljs-attribute">-bcf</span>

include $(BUILD_EXECUTABLE)</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li></ul>

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

<code class="hljs mathematica has-numbering">➜  AndroidObfuscation-NDK git:(master) ndk-build
[armeabi] <span class="hljs-keyword">Compile</span> thumb  : obfuscated <= obfuscationTest.c
[armeabi] Executable     : obfuscated
[armeabi] <span class="hljs-keyword">Install</span>        : obfuscated => libs/armeabi/obfuscated</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li></ul>

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

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

<code class="hljs cpp has-numbering">➜  AndroidObfuscation-NDK git:(master) cat jni/obfuscationTest.c
<span class="hljs-preprocessor">#include <stdio.h></span>

<span class="hljs-keyword">int</span> main(<span class="hljs-keyword">void</span>){
  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Hello, world\n"</span>);
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul>

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

<code class="hljs 1c has-numbering">➜  AndroidObfuscation-NDK git:(master) strings libs/armeabi/obfuscated <span class="hljs-string">| grep Hello</span>
Hello, world</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li></ul>

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

<code class="hljs 1c has-numbering">➜  AndroidObfuscation-NDK git:(master) strings libs/armeabi/obfuscated <span class="hljs-string">| grep Hello</span></code><ul class="pre-numbering" style="display: block;"><li>1</li></ul>

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

<code class="hljs lasso has-numbering">git clone <span class="hljs-attribute">-b</span> llvm<span class="hljs-subst">-</span><span class="hljs-number">3.4</span> https:<span class="hljs-comment">//github.com/obfuscator-llvm/obfuscator.git</span>
cd obfuscator
mkdir build
cd build
cmake <span class="hljs-attribute">-DCMAKE_BUILD_TYPE</span>:<span class="hljs-built_in">String</span><span class="hljs-subst">=</span>Release <span class="hljs-built_in">..</span>/obfuscator<span class="hljs-subst">/</span>
make <span class="hljs-attribute">-j5</span></code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>

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

<code class="hljs lasso has-numbering">cp <span class="hljs-attribute">-r</span> <span class="hljs-variable">$NDK_PATH</span>/toolchains/arm<span class="hljs-attribute">-linux</span><span class="hljs-attribute">-androideabi</span><span class="hljs-attribute">-clang3</span><span class="hljs-number">.4</span> <span class="hljs-variable">$NDK_PATH</span>/toolchains/arm<span class="hljs-attribute">-linux</span><span class="hljs-attribute">-androideabi</span><span class="hljs-attribute">-clang3</span><span class="hljs-number">.4</span><span class="hljs-attribute">-obfuscator</span></code><ul class="pre-numbering" style="display: block;"><li>1</li></ul>

打开文件

<code class="hljs lasso has-numbering"><span class="hljs-variable">$NDK_PATH</span>/toolchains/arm<span class="hljs-attribute">-linux</span><span class="hljs-attribute">-androideabi</span><span class="hljs-attribute">-clang3</span><span class="hljs-number">.4</span><span class="hljs-attribute">-obfuscator</span>/setup<span class="hljs-built_in">.</span>mk</code><ul class="pre-numbering" style="display: block;"><li>1</li></ul>

将文件里面的:

<code class="hljs makefile has-numbering"><span class="hljs-constant">TARGET_CC</span> := <span class="hljs-variable">$(LLVM_TOOLCHAIN_PREFIX)</span>clang<span class="hljs-variable">$(HOST_EXEEXT)</span>
<span class="hljs-constant">TARGET_CXX</span> := <span class="hljs-variable">$(LLVM_TOOLCHAIN_PREFIX)</span>clang++<span class="hljs-variable">$(HOST_EXEEXT)</span></code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li></ul>

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

<code class="hljs makefile has-numbering"><span class="hljs-constant">LLVM_TOOLCHAIN_PATH</span> := <PATH_TO_OBFUSCATOR_REPO>/build/bin/
<span class="hljs-constant">TARGET_CC</span> := <span class="hljs-variable">$(LLVM_TOOLCHAIN_PATH)</span>clang<span class="hljs-variable">$(HOST_EXEEXT)</span>
<span class="hljs-constant">TARGET_CXX</span> := <span class="hljs-variable">$(LLVM_TOOLCHAIN_PATH)</span>clang++<span class="hljs-variable">$(HOST_EXEEXT)</span></code>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值