Android原理
Android架构
- linux kernel
- 与linux的异同
- adb
# 基础操作 adb devices //列出设备id adb shell //进入shell adb install xxx.apk //安装apk adb shell pm list packages // package manager,列出包名 adb shell pm path com.tence01.mm //找到相应包名apk路径 adb uninstall com.xxx.xxx //指明设备卸载apk adb pull /data/app/com.xxx.xxx.apk /apks/x.apk //取出apk adb logcat -s xxx // 指明标签为xxx的log输出 # 调试有关 adb shell ps // 查看进程 adb forward tcp:8080 tcp:8000 //端口转发 adb shell am start -D -n PackAgename.ActivityName //activity manager,以调试方式启动应用 -D:指明调试 -n:指明启动参数的是包名+活动名 # 运行dex adb shell // 进入shell,并cd到相应目录 delvikvm -classpath helloworld.dex HelloWorld
- 系统运行库
- 程序库——Android包含一些C/C++库
- android运行库——dalvik
- dvm与jvm的异同
- .dex将一堆.class封装,并减少冗余
- dvm基于寄存器可用(0-65535)
- jvm基于栈操作,四个常用寄存器
- dvm与jvm的异同
- 应用程序框架
- android SDK提供的
- 视图
- 内容提供器
- 资源管理器
- 通知管理器
- 活动管理器
- android SDK提供的
- 应用
- app——java与androidsdk的开发
安卓应用也可以加载Jar,可以作为功能模块
- app——java与androidsdk的开发
编译java在android上运行
1. javac -source 1.6 -target 1.6 HelloWorld.java
# -source 指定用哪个版本的编译器对java源码进行编译.
# -target 指定生成的class文件将保证和哪个版本的虚拟机进行兼容。
2. dx --dex --debug --verbose-dump --output=helloworld.dex HelloWorld.class
# dx工具在 sdk/build-tools/版本号/ 目录中
3. push进安卓手机,adb shell 进入相应目录
4. dalvikvm -classpath helloworld.dex HelloWorld
二进制文件结构
dex文件结构
利用工具:010 Editor(win,mac,linux)进行分析。在菜单栏的templates中选择dex模板,可以自动分析dex文件结构,并可以在results窗口中查看分析结果。
apk文件结构
APK和Jar包一样,本质是Zip包
APK=DEX+资源+Manifest(+签名)
assets/
资源文件夹,资源可任意存放,通过文件名来引用资源,文件不会被编译。res/
资源文件夹,资源需放在相应的子目录中,子目录只能有一层,且必须是预定义的。资源要通过R文件来引用,目录中的资源子目录除了raw外,其他资源目录中的资源文件都会被编译。META-INF/
工程属性文件夹,存放签名,工程信息以及资源校验hash。lib/
动态链接库so存放文件夹,分析so文件方法如下:- Readelf解析ELF文件
- 链接视图 - IDA
- 执行视图 - linker
AndroidManifest.xml
工程基础配置属性文件。classes.dex
Dalvik字节码,DVM的可执行执行文件。程序的主体二进制文件。很多class集合成一个dex。
反编译
问题
如何将apk解析成代码
——反编译工具
字节码长什么样子
.method public onClick(View)V
.registers 4
00000000 iget-object v0, p0, b->a:MainActivity
00000004 iget-object v0, v0, MainActivity->c:EditText
00000008 invoke-virtual EditText->getText()Editable, v0
0000000E move-result-object v0
00000010 invoke-virtual Object->toString()String, v0
00000016 move-result-object v0
00000018 invoke-static a->a(String)V, v0
0000001E sget-object v0, MainActivity->b:WebView
00000022 const-string v1, "javascript:o0O0oo0o0o0o0oO()"
00000026 invoke-virtual WebView->loadUrl(String)V, v0, v1
0000002C return-void
.end method
语法
赋值操作
const
move-result
new-instance
方法调用
Invoke {参数},类->方法
数据类型
简写为字母,对照关系如右
怎么修改字节码
——修改smali文件,保存,反编译打包,重新签名
工具
apktool
https://ibotpeaches.github.io/Apktool/
反编译dex为smali,以及反编译被编译过得资源文件。
$ apktool d xxx.apk foldername
打包修改过的文件,形成新的apk
$ apktool b foldername XXX.apk
dex2jar
https://sourceforge.net/projects/dex2jar/
反编译dex为java
$ dex2jar.bat classes.dex
JEB
https://www.52pojie.cn/forum.php?mod=viewthread&tid=556950
网上找到2.2.7破解版,需要配置jdk为1.8.0_31以下版本,否则会闪退。JEB集成了上述工具的功能,并且反编译结果较好。
Androidkiller(windows
)
链接:http://pan.baidu.com/s/1c1Ogeg4 密码:1nr6
参考:https://www.52pojie.cn/thread-650395-1-1.html
可以修改smali文件,改好后重新打包成新的apk并签名。还可以单独对apk进行签名。
调试与注入
调试的本质也是一种代码注入。等待debug源码。
IDA调试方法
http://blog.csdn.net/deathmemory/article/details/51489818
动态调试SO之在.init_array段下断点
http://blog.csdn.net/zihao2012/article/details/44226377
注入方法
xposed
Xposed框架是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,通过替换/system/bin/app_process程序控制zygote进程,使得app_process在启动过程中会加载XposedBridge.jar这个jar包,从而完成对Zygote进程及其创建的Dalvik虚拟机的劫持。
官网地址: http://repo.xposed.info/
源码地址: https://github.com/rovo89
Xposed安装
Android 6.0.x https://pan.baidu.com/s/1qY7oW36 密码:r3mh
- 设备需要root
- recovery 刷入
xposed-v78-sdk23-arm.zip
- 安装
xposed.apk
Xposed使用
打开Xposed Installer
- 框架——安装、检查框架运行状态
- 模块——列出当前可用模块以及状态
- 下载——框架商店
- 日志——Xposed中日志记录
注意:每次启用或者关闭模块均需要重启设备
Xposed模块开发
Xposed模块的安装包实际上就是一个有着特殊的AndroidManifest.xml和添加了XposedBridgeApi.jar包的apk文件,所以同样可以用Android Studio 来开发。同时我们在开发时需获取的目标(被劫持的)apk的信息有:
- 包名
- 类名
- 函数名
- 函数参数
LoginDemo
package com.example.xuanxuan.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private Button bt1;
private EditText name1;
private EditText password1;
private final String ACCOUNT="xuanxuan";
private final String PASSWORD="123456";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt1 = (Button) findViewById(R.id.id_button);
name1 = (EditText)findViewById(R.id.id_name);
password1 = (EditText)findViewById(R.id.id_password);
bt1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String username = name1.getText().toString();
String password = password1.getText().toString();
if(isOK(username,password)){
Toast.makeText(MainActivity.this,"login success",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this,"login failed",Toast.LENGTH_SHORT).show();
}
}
});
}
private boolean isOK (String argc,String argv){
return argc.equals(ACCOUNT)&&argv.equals(PASSWORD);
}
}
HookDemo
- 新建一个不需要Activity的空白工程。
- 在空工程的java文件夹中新建一个类,该类就是一个模块类,这里命名为“Module”。
- 配置AndroidManifest.xml,其中的meta-data内容要照搬。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.xuanxuan.hackdemo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<meta-data
android:name="xposedmodule"
android:value="true"/>
<meta-data
android:name="xposeddescription"
android:value="Hook Test!"/>
<meta-data
android:name="xposedminversion"
android:value="54"/>
</application>
</manifest>
- 在main文件夹下创建一个assets文件夹,并在里面创建一个名为“xposed_init”的普通文件,在里面添加一句字符串,即包名+模块类名,如
com.example.xuanxuan.hackdemo.Module
- 新建一个名为
lib
的文件夹,注意不是libs
。然后放入XposedBridgeApi.jar包,并在该jar包上右键Add as Library。并且在project structure中设置这个jar包为非complie模式,否则会在运行时冲突。
XposedBridgeApi.jar下载地址:
https://forum.xda-developers.com/xposed/xposed-api-changelog-developer-news-t2714067
- 编写模块类Module.java
package com.example.xuanxuan.hackdemo;
import android.util.Log;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
/**
* Created by xuanxuan on 2018/1/15.
*/
public class Module implements IXposedHookLoadPackage{
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if(loadPackageParam.packageName.equals("com.example.xuanxuan.myapplication")){ //包名
XposedHelpers.findAndHookMethod(
"com.example.xuanxuan.myapplication.MainActivity", //类名
loadPackageParam.classLoader,
"isOK", //函数名
String.class,
String.class, //函数参数
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("账号:"+(String)param.args[0]+" 密码:"+(String)param.args[1]);
Log.d("zz","账号:"+(String)param.args[0]+" 密码:"+(String)param.args[1]);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Log.d("zz", param.getResult().toString());
}
});
}
}
}
说明:
-
Module继承了IXposedHookLoadPackage接口,当系统加载应用包的时候回调 handleLoadPackage;
-
XposedHelpers的静态方法findAndHookMethod就是hook函数的的方法,其参数对应为:
- 类名,必须要有包名前缀,即“packageName+className”
- loadPackageParam.classLoader,有壳的例外:http://www.mamicode.com/info-detail-1705499.html
- 方法名
- 参数类型(根据所hook方法的参数的类型,即有多少个写多少个,加上.class)
- XC_MethodHook回调接口
如果代码被混淆过,即使你明知道代码中要hook的类名和方法名,但都不一定能用,必须以smali中的名字为准,比如:isOk()混淆之后在smali中的函数名为a,那么hook的时候就必须写a,而不是isOK,第一个参数类名同理!
- 参数里有一个监听类XC_MethodHook,该类在hook前后回调,通过回调方法的MethodHookParam可以拦截到函数参数。
- 打包 Build->Generate Signed APK生成一个APK,并安装在手机,重启。即可在Xposed日志中查看到被记录的登录信息。
Xposed模块编写的那些事
http://www.freebuf.com/articles/terminal/114910.html
frida
https://www.jianshu.com/p/ca8381d3e094
混淆
java:proguard、dexguard、ZKM
c/c++:o-llvm
加壳
加固原理:反编译器毕竟不是运行时的虚拟机
第一代
加密隐藏真实dex,运行时动态加载
脱壳方法:通过各种办法得到在加载dex时的地址和长度
- http://blog.csdn.net/deathmemory/article/details/51489818
- hook:xposed(延时启动)+frida(hook libart.so中的加载函数)
第二代
内存里不再有完整DEX结构
脱壳方法:dexhunter
第三代
编译为未知语言解释执行
脱壳方法:
参考
android基本架构
https://www.cnblogs.com/lijunamneg/archive/2013/01/18/2866953.html
Android Dex文件结构解析
http://blog.csdn.net/feglass/article/details/51761902
Android 6.0.x 系统安装xposed框架
http://blog.csdn.net/u011303443/article/details/51031170
XPosed入门与登陆劫持演示
https://www.csdn.net/article/2015-08-14/2825462
Android逆向分析之Xposed的hook技术
http://blog.csdn.net/qq_18870023/article/details/51753587
IDA Pro Android 静态分析
https://www.52pojie.cn/thread-672885-1-1.html
IDA 调试 Android 方法及简单的脱壳实现
http://blog.csdn.net/deathmemory/article/details/51489818