一、So简介 1.Android底层是Linux,Linux本身就是使用C/C++语言,Android使用了一个Dalvik虚拟机才使得应用程序开发使用Java语言; 2.Dalvik支持JNI编程方式,第三方应用完全可以通过JNI调用自己的C/C++动态库(so文件),使用“Java+C”编程方式; 3.NDK(Native Development Kit)是“Java+C”开发的工具库,保证程序的兼容性、调试性和调用API方便性,也避免Java的不足,如安全性; 二、“Java+C”编程方式 三、使用NDK原因 1.代码保护:APK对Java代码很容易反编译、阅读和篡改,而对C/C++开发出来的so库进行反汇编难度较大; 2.方便使用现存的开源库:大部分现存的开源库(OpenCV、OPENGL等)都是用C/C++代码编写的; 3.提高程序的执行效率:将要求高性能的逻辑使用C开发,从而提高应用程序的执行效率; 4.便于移植:用C/C++写的so库可以方便移植到其它的嵌入式平台上使用; 四、NDK开发流程 在讲解so分析之前,我们先创建一个NDKDemo程序(Android Studio为例),简单通过Java调用C中的方法,返回字符串Toast显示; 1.File->Project Structure->SDK Location->Android NDK location->Download Android NDK,完成安装NDK(新版本NDK,安装在SDK目录下的ndk-bundle); 2.从传统的Android Gradle插件迁移,需要修改如下Gradle配置:
.
├── app/
│ ├── app.iml
│ ├── build.gradle
│ └── src/
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew*
├── gradlew.bat
├── local.properties
├── MyApplication.iml
└── settings.gradle
./gradle/wrapper/gradle-wrapper.properties
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
//修改gradle版本
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
./build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
//修改依赖的gradle插件
classpath "com.android.tools.build:gradle-experimental:0.7.0-alpha1"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
build.gradle
//修改使用插件
apply plugin: 'com.android.model.application'
//修改model层级
model {
android {
compileSdkVersion 23
buildToolsVersion "24.0.0"
//增加ndk配置
ndk {
moduleName "hello"
}
defaultConfig {
applicationId "com.example.pengchengxiang.securitydemo"
//修改sdk相关版本声明
minSdkVersion.apiLevel 21
targetSdkVersion.apiLevel 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
//修改proguard相关配置
proguardFiles.add(file("proguard-rules.pro"))
signingConfig = $("android.signingConfigs.myConfig")
}
}
}
//修改签名相关配置
android.signingConfigs {
create("myConfig") {
storeFile "/home/pengchengxiang/KeyStores/android.jks"
storePassword "12345678"
keyAlias "MyAndroidKey"
keyPassword "11111111"
storeType "jks"
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
} 3.迁移新的插件com.android.model.application后,你会发现Gradle构建中添加了许多相关的Task:
4.在Java类中定义native方法;
MainActivity.java:
public class MainActivity extends Activity {
//加载hello.so库
static {
System.loadLibrary("hello");
}
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.Button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//调用native方法
Toast.makeText(MainActivity.this, "add result =" + helloWorldFromJNI(100), Toast.LENGTH_SHORT).show();
}
});
}
//定义native方法
public native int helloWorldFromJNI(int count);
} 4.在Java源代码目录下,使用javah命令生成头文件;
pengchengxiang@ubuntu:~/SecurityWorkSpace/SecurityDemo/app/src/main/java$ javah -d ../jni com.example.pengchengxiang.securitydemo.MainActivity
5.在生成的jni目录下,创建hello.c文件,实现相关方法并引用生成的头文件;
Hello.c文件:
#include "com_example_pengchengxiang_securitydemo_MainActivity.h"
JNIEXPORT jint JNICALL Java_com_example_pengchengxiang_securitydemo_MainActivity_helloWorldFromJNI(JNIEnv * env, jobject obj, jint count)
{
return count + 1;
} 6.构建并运行程序;
五、so分析步骤
在分析之前,我们讲解一些两个概念,反汇编和反编译:
反编译:针对NDK开发出来的so文件进行逆向;
反混淆:逆向dex文件;
1.安装ida pro软件(该软件为收费软件);
2.将apktool反编译apk,在libs/armeabi-v7a目录中找到动态库libhello.so文件;
3.打开ida pro软件,点击Open按钮选择libhello.so文件,然后弹出一个对话框,保持自动选择,点击“OK”;
4.进入到ida pro主界面(如下图),在左边栏中列举了hello.so文件里面的函数名,如Java_com_example_pengchengxiang_securitydemo_MainActivity_helloWorldFromJNI方法,以及该函数地址00000D1C和汇编代码内容;
5.切换到Hex View(十六进制)视图,查看对应的16进制数据;
6.f5插件(如何查看伪代码?)
六、修改so逻辑
1.ids pro是伪代码的查看,so是二进制文件,不能直接对so文件进行修改和注入代码。如果希望修改so文件需要针对其代码片段的二进制进行修改。则使用UtralEdit打开libhello文件,寻找地址00000D1C(地址是连续的,在UtralEdit中找到最近的地址00000d10h),将“50 1C”修改为“90 1C”并保存
(汇编代码阅读不在本章节解读范围),将count = count + 1修改为count = count + 2;
2.将修改过的so包,替换libs/areambi-v7a目录,使用apktool重新打包,签名,重新安装,运行如下:
新技术,新未来!欢迎大家关注
“1024工场”微信服务号
,时刻关注我们的最新的技术讯息!
(甭客气!尽情的扫描或者长按!)
转载请注明原文地址: https://ju.6miu.com/read-1300125.html