android环境配置

复习累了来学学,时间有限本片仅作为笔记不多做解释~

环境配置

  1. jdk:Oracle的1.8
  2. Android studio
  3. Android SDK:第一次运行Android studio时,会自动下载必须的sdk。下载完成后将其添加到环境变量–H:\Android-Sdk\toolsH:\Android-Sdk\platform-tools,可使用adbemulator检查是否成功。若sdk manager闪退,可单独安装。
  4. Android NDK:下载后解压,在需要时选择project structure引入。
  5. 模拟器:蓝叠若不能自动脸上电脑:
    1
    2
    adb kill-server
    adb start-server #adb connect 127.0.0.1
  6. Android源码 (非必须以后会阅读部分源码)

Android-studio

1.Setting->Editor-AutoImport全部勾选可以自动在补齐的时候导入包
2.一些常用的快捷键:

开发java-helloworld

  1. 创建一个布局文件(当出现渲染错误,一般是api版本不对,选择创建时的版本就好了)
  2. 创建一个类文件(若创建类出错,打开studio64.exe.vmoptions添加-Djdk.util.zip.ensureTrailingSlash=false即可):
    1
    2
    3
    4
    5
    6
    7
    8
    public class hello extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.hello);

    }
    }
  3. AndroidManifest.xml中注册:
    1
    <activity android:name=".hello"/>
  4. 在原来的MainActivity中打开新窗体:
    1
    2
    3
    4
    5
    public void onClick(View view) {
    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
    .setAction("Action", null).show();
    startActivity(new Intent(MainActivity.this,hello.class));
    }
  5. 调试,启动bluestack后会自动连接,接着点击Android studio的运行按钮选择已经连接的模拟器就好了。
  6. 随便乱写点东西:
    1
    2
    3
    4
    5
    6
    7
    Button bt = (Button) findViewById(R.id.button);
    bt.setOnClickListener(new View.OnClickListener(){
    public void onClick(View v){
    EditText et = (EditText) findViewById(R.id.editText);
    et.setText("贝塔猫");
    }
    });

    开发cpp-helloworld

环境不一样配置差别很大,多在网上搜搜就好了,我用的Android studio2.0 ndk11

静态注册

  1. gradle.properties中添加android.useDeprecatedNdk=true
  2. project structure中添加NDK路径
  3. 添加外部工具Settings–>Tools–>ExternalTools
  4. 编写java代码:
    1
    2
    3
    4
    5
    public native static String helloWorld();
    static {
    System.loadLibrary("helloworld");
    }
    //并写调用代码
  5. gradle.build中添加:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    defaultConfig {
    ndk{
    moduleName "helloworld"
    abiFilters "armeabi","armeabi-v7a","x86"
    }
    }
    sourceSets {
    main {
    jniLibs.srcDirs =['libs']
    }
    }
  6. helloworld()上右键右键使用外部工具javah-jni生成头文件
  7. 在jni目录新建一个c文件包含头文件,并且编写代码(注意这里可以创建C文件和C++文件,区别就是有木有对象特性)
    1
    2
    3
    4
    5
    #include "com_example_wxjun_myapplication333_MainActivity.h"
    JNIEXPORT jstring JNICALL Java_com_example_wxjun_myapplication333_MainActivity_helloWorld
    (JNIEnv *env, jclass clazz){
    return (*env)->NewStringUTF(env,"helloworld");
    }
  8. 在jni目录下创建两个文件:
    1
    2
    3
    4
    5
    6
    7
    8
    //Android.mk
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := helloworld
    LOCAL_SRC_FILES := hello.c
    include $(BUILD_SHARED_LIBRARY)
    //application.mk
    APP_ABI := x86 armeabi armeabi-v7a
  9. 添加外部工具Settings–>Tools–>ExternalTools
  10. 在c文件上右键使用外部工具bdk-build来编译库文件
  11. 将编译好的库文件连同目录移动到libs目录:
  12. 编译运行apk,看到成功啦~

动态注册

和静态注册大部分内容是一样的,静态注册通过JNIEXPORT jstring JNICALL Java_com_example_wxjun_myapplication333_MainActivity_hello4这种和类对应的函数名查找函数,而动态注册则是在库被加载的向对应类注册对应方法的实现地址,灵活很多,既然和静态注册大部分地方都是一样的我就不重复了,只有在C文件里面不一样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <jni.h>
#include <stdio.h>
#include <Android/log.h>
#define TAG "result" // 这个是自定义的LOG的标识
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)

jstring hello3(JNIEnv *env, jclass clazz) { //这里是函数的实现,名字随便起
return (*env)->NewStringUTF(env, "hello3333 from dr native");
}

static int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *gMethodss,
int numMethods) { //这里稍微封装了一下
jclass clazz;
clazz = (*env)->FindClass(env,className); //先通过要注册的函数所在类名找到类,在这个类上注册函数
if (clazz == NULL) {
return JNI_FALSE;
}
if ((*env)->RegisterNatives(env,clazz, gMethodss, numMethods) < 0) { //注册
return JNI_FALSE;
}
return JNI_TRUE;
}
static const char * gClassName = "com/example/wxjun/myapplication333/MainActivity"; //测试用的类名
static JNINativeMethod gMethods[] = {
{"hello4","()Ljava/lang/String;",(void*)hello3}, //此结构体三个域分别表示类中函数名,函数签名,函数实现的地址
};
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm,void* reserved){ //调用注册函数,即在类被加载时就注册
JNIEnv *env = NULL;
//jint result = -1;
if((*vm)->GetEnv(vm,(void**)&env,JNI_VERSION_1_6)!=JNI_OK){
// LOGE("this jni version is not supported!");
return -1;
}
if(registerNativeMethods(env,gClassName,gMethods, sizeof(gMethods)/ sizeof(gMethods[0]))==JNI_FALSE){
// LOGE("unable to register native methods!");
return -1;
}
return JNI_VERSION_1_6;
}

调试

delvik-方法一

这种方法比较麻烦,需要反编译程序并修改部分文件:

  1. 反汇编代码:java -jar apktool.jar d -d beta.apk -o dir (新版的apktool已经移除了此功能,可以下载2.0.3版的)
  2. 修改AndroidManifestapplication中添加android:debuggable="true"(当系统开了调试参数后可以不用改)
  3. 在入口点类的onCreate方法添加invoke-static{},Landroid/os/Debug;->waitForDebugger()V
  4. 编译修改后的文件:java -jar apktool.jar b -d dir -o alpha.apk
  5. 对apk进行签名:java -jar signapk.jar testkey.x509.pem testkey.pk8 alpha.apk
  6. 使用Android studio导入反编译后的文件
  7. 配置远程调试,端口选择8700
  8. 打开monitor,选中要调试的文件,即开放对应端口
  9. 在Android studio中,在程序的入口点(onCreate)下好断点,接着点击调试

注1: 当回编译出错,可以尝试使用最新版工具并删除原来的框架文件
注2: 当ddms中无法显示对应程序可以换个调试器
注3: 使用这种方法可以在调试时修改值

delvik-方法二

这种方法使用比较简单,只需要以调试的方式启动程序,并且在Android studio中导入反编译后的程序即可开始调试:

  1. 反编译代码:java -jar ShakaApktool.jar d -df beta.apk -o dir。另外也可以使用Android killer等图形化工具
  2. 使用Android studio导入反编译后的文件
  3. 安装smalidea插件
  4. 在Android studio中,在程序的入口点(onCreate)下好断点
  5. 配置远程调试,端口选择8700
  6. 在控制台输入adb shell am start -D -n com.example.wxjun.myapplication/com.example.wxjun.myapplication.MainActivity

native-方法一

native层的调试和java层有很大区别的,现在记录:

  1. android_server调试服务端放在手机里:
    1
    2
    3
    4
    5
    6
    adb push H:\Tools\Reverse\IDAPro7.0\dbgsrv\android_server /data/local/tmp
    adb shell
    su
    cd /data/local/tmp
    mv android_server andsrv
    chmod +x andsrv
  2. 在adbshell中启动服务./andsrv -p12345
  3. 在powershell中转发端口adb forward tcp:23333 tcp:12345
  4. 在ida里面设置调试:
  5. 启动程序:adb shell am start -D -n com.example.wxjun.myapplication333/.MainActivity
  6. 在ida中以attach的方式调试,选择对应的进程
  7. 打开monitor选中进程打开8700端口
  8. 附着调试:jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700

dex文件

  1. 可以使用010editor配合模板打开,具体结构看说明:
  2. 源码可以使用source insight打开,存放在dalvik目录下:

寻找关键点

通过日志信息

通过抓包

特征字符串

现在很多程序都是在运行过程中动态解密字符串,此时此方法失效。

监控关键api

获取过程调用及数据,分析行为

挂钩解密函数

使用xposed等框架hook

monitor

1.ddms
2.thread
3.trace

插log

动态调试

工具

  1. jeb: 神器,对于jar文件,可以先转换为dex文件H:\android-sdk\build-tools\28.0.1\lib\dx --dex --output=1.dex 1.jar。另外jeb的使用说明,包括插件脚本开发文档都在doc目录里

常见问题

  1. Android killer显示无法解析包结构:重装Android killer
  2. Android Killer反编译dex出错:更换apktool
  3. Android Killer回编译出错:更换apktool,尝试根据错误信息删除未找到的资源引用。

参考

  1. i春秋-《零基础入门 Android 逆向》