开始解析分析Android应用之前,我们先来了解其的整体组成。Android应用,即Android Application Package,Android应用程序包,通常都简称为APK。APK的本质是一个后缀被为apk的压缩包,其中包含了程序运行所需的可执行文件和相关资源文件,APK需要安装到Android系统上运行。Android应用标准的结构如下图所示:
Android应用程序中包含的标准文件内容如下图所示:
Android应用程序的逆向分析主要就是使用工具将.apk文件中的DEX文件、配置文件和SO动态库等文件进行逆向反编译。使用Apktool、Jadx和IDA等工具对APK文件进行反编译,分析反编译后的文件找到程序的漏洞。
Android应用程序的四大组件都需要在Manifest配置文件中声明,可通过配置文件中的组件信息快速定位到其所在的代码位置。首先通过配置文件声明的信息定位到程序应用执行入口,然后便可按着程序执行流程就行分析。配置文件中定位执行入口特征如下图所示:
通过配置文件可知该程序的程序执行的入口类为com.test.demo.MainActivity,通过该类的路径很容易定位到定位到反编译后的代码位置,如图所示:
除此之外还可以使用adb命令配合Manifest配置文件声明的组件信息进行安全测试,如组件拒绝服务漏洞等。参考命令如下所示:# 启动目标应用
adb shell am start -n com.test.demo/com.test.demo.MainActivity
# 针对空Intent导致的本地拒绝服务测试
adb shell am start -n com.test.demo/com.test.demo.TestActivity
Android应用程序除了使用Java/Kotin开发外,还可以使用C/C++开发。使用Java/Kotin开发的部分通常被称为Java层,使用C/C++开发的部分通常常被称为Native层。Java层和Native层是通过JNI进行交互,也就是说JNI接口是两者的连接点,我们在分析应用时只要定位到JNI接口能快速定位相关代码。
Java层和Native层双方都需要注册JNI函数后,双方才能正常进行交互。Java层注册JNI函数的格式可参考如下代码:package com.test.demo;
public class JniWrapper {
static {
System.loadLibrary("native-lib");
}
public static native String stringFromJNI();
}
Native层注册JNI函数的方式有静态注册和动态注册两种方式。静态注册的方式方便简便,但从攻防的角度考虑静态注册是不安全的。因其是直将Java层注册的函数以“Java_包名_类名_方法名”在Native层进行声明,可以快速通过SO动态库中暴露的JNI函数名定位到其与Java层代码的关联。静态注册具体实现如下图所示:JNIEXPORT jstring JNICALL Java_com_test_demo_JniWrapper_stringFromJNI(
JNIEnv* env,
jclass ) {
std::string hello = "Hello from JNI";
return env->NewStringUTF(hello.c_str());
}
可通过IDA逆向分析动态库库是查看导出函数,如果其是通过静态注册方式声明的JNI函数便可根据函数名定位到其在Java层的调用位置。IDA分析结果如下图所示:
如果没有安装IDA还可以使用objdump命令查看动态库中的导出函数,具体命令如下图所示:$ objdump -tT libnative-lib.so | grep Java
000088ac g DF .text 00000074 Java_com_test_demo_JniWrapper_stringFromJNI
Native层通过动态方式注册JNI函数的实现起来稍微复杂一点,我们先看一下动态注册的核心代码实现方式。只有知道其实现方式才能在逆向分析时进行快速定位。动态注册核心代码如下图所示:static JNINativeMethod method_table[] = {
{"stringFromJNI2" , "()Ljava/lang/String;", (void*)helloJni},//绑定
};
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env = nullptr;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
{
return result;
}
jclass clazz;
clazz = env->FindClass( "com/test/demo/JniWrapper");
if (clazz == nullptr)
{
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, gMethods, numMethods) < 0)
{
return JNI_FALSE;
}
return JNI_VERSION_1_4;
}
其中最核心的就是JNINativeMethod结构体,该结构体包含三个参数,这三个参数决定了Java层和Native层Jni函数的映射关系。逆向分析时可通过该结构体快速定位到Native层的JNI导出函数。JNINativeMethod结构体具体参数含义如下:typedef struct {
const char* name; //Java层中定义的 Native 方法名
const char* sign; //Java层中定义的 Native 方法签名
void* jni; //Native层中定义的JNI函数
} JNINativeMethod;
知道了JNINativeMethod结构体中参数含义就可以快速分析,首先拿到通过反编译Java层代码拿到其生命的Native函数名,然后利用IDA反编译目标SO文件。通过字符串查找功能快速定位Native函数名所在位置,如下图所示:利用IDA的交叉引用功能跳转到使用该字符串的位置,通过分析发现此处正是动态注册中初始化后的JNINativeMethod结构体。此结构中第三参数即Native层声明的JNI函数,具体如下图所示:
至此你已经初步掌握Android应用的分析方法,可以独立进行移Android应用的逆向分析。本节要通过一个iOS应用逆向案例讲解iOS应用分析的大致流程。同样开始解析分析iOS应用之前,先来了解其的整体组成。iOS标准应用是后缀IPA的文件,全称为iPhone application archive,通常简称为IPA。IPA的本质也是压缩包,其中包含了程序运行所需的可执行文件和相关资源文件,IPA需要安装到iOS系统上运行。iOS应用标准的结构如下图所示:
iOS应用在提交到AppStore时,苹果官方将对其进行加密处理,加密后的应用是无法直接进行反编译,需要进行解密处理,也就是通常所说的砸壳。砸壳需要使用越狱后的手机配合砸壳工具进行,比较常见砸壳工具有Clutch、frida-ios-dump、dumpdecrypted等,这里咱们使用Clutch工具进行砸壳,具体命令如下图所示:iPhone:~ root# Clutch -i // 查看待脱壳的目标应用
Installed apps:
1: Demo <com.test.dump>
iPhone:~ root# Clutch -d 1 // 数字1 即待砸壳应用对应的序号
脱壳结束后便可使用工具对其进行逆向分析,为了快速定位到关键函数。可使用class-dump工具将应用的的头文件导出,具体命令如下:class-dump -H Demo.app -o Headers
导出的header文件中有程序声明的函数名或者变量的名字,可通过header中的内容提高分析速度。导出的header文件内容示例如下图所示。
要想看到某个具体函数的实现逻辑可以使用反编译工具IDA或Hopper将解压IPA文件得到执行文件进行饭反编译,然后定位到目标函数即可看到其实现逻辑。此处以函数injectNSURLSessionConfiguration为例,通过反编译工具查看其实现逻辑,如下图所示:
如果自己手里关键信息只有一串字符,无法确定其在哪个函数中调用。可以通过IDA的字符串查找功能定位到字符串在代码中的位置,然后就可以通过IDA交叉引用功能跳转到其调用位置
至此你已经初步掌握iOS应用的分析方法,可以独立进行iOS应用的逆向分析。看雪ID:FIGHTING安
https://bbs.kanxue.com/user-home-452101.htm
*本文为看雪论坛优秀文章,由 FIGHTING安 原创,转载请注明来自看雪社区
文章来源: https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458537518&idx=1&sn=c72bb03f5b2c90949ab33b5d5195d3d8&chksm=b18d7ea486faf7b2f95c87b82058b2beb26c279f11a07db1c1f071f9348cd46657ce9360940b&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh