BetaMao

android环境配置

字数统计: 1.9k阅读时长: 8 min
2018/07/25 Share

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

环境配置

  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 逆向》
CATALOG
  1. 1. 环境配置
  2. 2. Android-studio
  3. 3. 开发java-helloworld
  4. 4. 开发cpp-helloworld
    1. 4.1. 静态注册
    2. 4.2. 动态注册
  5. 5. 调试
    1. 5.1. delvik-方法一
    2. 5.2. delvik-方法二
    3. 5.3. native-方法一
  6. 6. dex文件
  7. 7. 寻找关键点
    1. 7.1. 通过日志信息
    2. 7.2. 通过抓包
    3. 7.3. 特征字符串
    4. 7.4. 监控关键api
    5. 7.5. 挂钩解密函数
    6. 7.6. monitor
    7. 7.7. 插log
    8. 7.8. 动态调试
  8. 8. 工具
  9. 9. 常见问题
  10. 10. 参考