Xposed框架

Xposed框架通过修改Android系统的源码,并替换Android的主程序Zygote(Init 是所有Linux程序的起点,而Zygote于Android,正如它的英文意思,是所有java程序的’孵化池’),从而能够控制Android进程的执行流程,hook java层的API。xposed的具体解析可以参考深入理解Android(三):Xposed详解

首先在app_main.cpp中,对appRuntime.cpp进行了修改,其中onVmCreated(JNIEnv* env)修改如下:

在onVmCreate中,它将调用libxposed_dalvik.so中的xposedInitLib函数,然后再调用so中设置的onVmCreated函数。这个onVmCreated函数由xposedInitLib设置。

在app_main.cpp的main方法中,进行了对xposed的环境初始化:

最后,如果xposed框架启用成功,那么zygote的入口类将由以前的com.android.internal.os.ZygoteInit变成de.robv.android.xposed.XposedBridge。

下面我们按照执行流程,把相关函数分析一遍:

AppRuntime的onVmCreated,它最终会导致libxposed_dalvik.so中的onVmCreated被调用。我们直接分析最后这个onVmCreated。

然后AppRuntime里会调用de.robv.android.xposed.XposedBridge.main函数。

所以通过调用XposedBridge.main函数,可以给APK进程的一些特定函数挂上钩子,从而能够监听该函数,进而通过beforeHookedMethod和afterHookedMethod方法可以分别实现调用函数前的操作和调用函数后的操作。


Hook用到的具体函数

下面给出我在做Android恶意程序分析时需要hook的函数的一些操作,该程序参考了halfkiss的框架。

  • 用到的Xposed的函数: 首先定义一个抽象类MethodHookCallBack继承自Xposed的XC_MethodHook类,该类有两个方法:beforeHookedMethod(MethodHookParam param)和AfterHookedMethod(MethodHookParam param)方法,这两个方法分别对应于要hook的函数调用之前所要执行的动作与该函数调用之后所要执行的动作。比如:
    public void beforeHookedMethod(MethodHookParam param)    {            Log.i("Before hook");    }

上面的例子说明在调用要hook的函数之前打印一段log为Before hook。

  • Xposed的hook的主函数hookMethod(Member hookMethod, XC_MethodHook callback),其中参数hookMethod表示要hook的函数,该函数可以通过java的反射机制获得,具体怎么获得在下面会讲到,参数callback就是前面讲到的Xposed函数的XC_MethodHook类,该类主要是表示该对要hook的函数做怎样的处理。具体的hookMethod方法如下图所示:

由hookMethod可知,一个目标函数可以挂多个钩子,这些钩子由一个集合来存储。然后我们将转到JNI层去看看hookMethodNative干了什么事情。这才是hook的核心。分析如下图所示:

所以当apk执行被hook的函数时,实际执行的是hookMethodCallBack函数,该函数就是钩子函数,我们来看看hookmethodCallBack函数具体是怎么执行的,该函数在libXposed_dalvik.cpp中。

在xposedHandleHookedMethod函数中会以此执行钩子函数,即在前面介绍的XC_MethodHook函数,然后再会执行程序的原函数。

在此,Hook需要用到的基本函数已经介绍完毕。接下来会介绍如何利用Xposed来实现hook敏感函数的操作。


hook敏感函数

  • 首先定义MethodHookCallBack类继承自XC_MethodHook,该函数实现了beforeHookedMethod和afterHookedMethod函数,主要是获得HookParam类,该类主要是存储了一些MethodHookParam的一些参数。然后调用该类中beforeHookedMethod(HookParam param)或者afterHookedMethod(HookParam param)。
    public abstract class MethodHookCallBack extends XC_MethodHook {            @Override            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {                // TODO Auto-generated method stub                super.beforeHookedMethod(param);                HookParam hookParam = HookParam.fromXposed(param);                this.beforeHookedMethod(hookParam);                if(hookParam.hasResult())                    param.setResult(hookParam.getResult());            }            @Override            protected void afterHookedMethod(MethodHookParam param) throws Throwable {                // TODO Auto-generated method stub                super.afterHookedMethod(param);                HookParam hookParam = HookParam.fromXposed(param);                this.afterHookedMethod(hookParam);                if(hookParam.hasResult())                    param.setResult(hookParam.getResult());            }            public abstract void beforeHookedMethod(HookParam param);            public abstract void afterHookedMethod(HookParam param);        }
  • 根据字符串找到要hook的函数,主要是利用java的反射函数,如果有兴趣的可以去查阅一下java的反射机制,主要是通过字符串来得到相应的类,函数或变量等,具体代码如下:
    public static Method findMethod(String className, ClassLoader classLoader, String methodName,                Class<?>... parameterTypes)        {            try {            Class clazz = classLoader.loadClass(className);            Method method = clazz.getDeclaredMethod(methodName, parameterTypes);            method.setAccessible(true);            return method;        } catch (NoSuchMethodException e) {            e.printStackTrace();        } catch (ClassNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return null;    }

我们通过该方法可以获得要hook的具体method。

  • 定义抽象类AbstractBahaviorHookCallBack继承自前面讲到的MethodHookCallBack类,该类具体实现当调用要hook的函数时,就打印该函数。具体实现如下:
    public abstract class AbstractBahaviorHookCallBack extends MethodHookCallBack {        @Override        public void beforeHookedMethod(HookParam param) {            // TODO Auto-generated method stub            /*int length = param.args.length;            Object[] m = param.args;            String args = "/";            for(int i = 0; i < length;i++)            {                args+=(String)m[i]+"/";            }*/            Logger.logD("Invoke "+ param.method.getDeclaringClass().getName()+"->"+param.method.getName());            this.descParam(param);            //this.printStackInfo();        }        @Override        public void afterHookedMethod(HookParam param) {            // TODO Auto-generated method stub            //Logger.log_behavior("End Invoke "+ param.method.toString());        }        private void printStackInfo(){            Throwable ex = new Throwable();            StackTraceElement[] stackElements = ex.getStackTrace();            if(stackElements != null){                StackTraceElement st;                for(int i=0; iif(st.getClassName().startsWith("com.android.binpang")||st.getClassName().startsWith("de.robv.android.xposed.XposedBridge"))                        continue;                    Logger.logD(st.getClassName()+":"+st.getMethodName()+":"+st.getFileName()+":"+st.getLineNumber());                }            }        }        public abstract void descParam(HookParam param);}
  • 具体要实现的hook函数
    Method sendTextMessagemethod =  FindMethod.findMethod(                    "android.telephony.SmsManager", ClassLoader.getSystemClassLoader(),                    "sendTextMessage", String.class,String.class,String.class,PendingIntent.class,PendingIntent.class);            hookhelper.hookMethod(sendTextMessagemethod, new AbstractBahaviorHookCallBack() {                @Override                public void descParam(HookParam param) {                    // TODO Auto-generated method stub                    Logger.logI("Send SMS ->");                    String dstNumber = (String)param.args[0];                    String content = (String)param.args[2];                    Logger.logI("SMS DestNumber:"+dstNumber);                    Logger.logI("SMS Content:"+content);                }            });

该示例函数是hook了android.telephony.SmeManager/sendTextMessage函数,当调用该函数的时候,会打印出来要发送的目标号码,及发送的message的内容。

  • 监听的敏感函数列表

SmsManager

  1. android.telephony.SmsManager/sendTextMessage
  2. android.telephony.SmsManager/getAllMessagesFromIcc
  3. android.telephony.SmsManager/sendDataMessage
  4. android.telephony.SmsManager/sendMultipartTextMessage

TelephonyManager

  1. android.telephony.TelephonyManager/getLine1Number
  2. android.telephony.TelephonyManager/listen

AccountManager

  1. android.accounts.AccountManager/getAccounts
  2. android.accounts.AccountManager/getAccountsByType

ActivityManager

  1. android.app.ActivityManager/killBackgroundProcesses
  2. android.app.ActivityManager/forceStopPackage

AlarmManager

  1. android.app.AlarmManager/setImpl

AudioRecord

  1. android.media.AudioRecord

Camera

  1. android.hardware.Camera/takepicture
  2. android.hardware.Camera/setPreviewCallback
  3. android.hardware.Camera/setPreviewCallbackWithBuffer
  4. android.hardware.Camera/setOneShotPreviewCallback

ConnectivityManager

  1. android.net.ConnectivityManager/setMobileDataEnabled

ContentResolver

  1. android.content.ContentResolver/qurey
  2. android.content.ContentResolver/registerContentObserver
  3. android.content.ContentResolver/insert
  4. android.content.ContentResolver/bulkInsert
  5. android.content.ContentResolver/delete
  6. android.content.ContentResolver/update
  7. android.content.ContentResolver/applyBatch

ContextImpl

  1. android.app.ContextImpl/registerReceiver

MediaRecorder

  1. android.media.MediaRecorder/start
  2. android.media.MediaRecorder/stop

Internet

  1. java.net.URL/openConnection
  2. org.apache.http.impl.client.AbstractHttpClient/execute

NotificationManager

  1. android.app.NotificationManager/notify

ApplicationPackageManager

  1. android.app.ApplicationPackageManager/installPackage
  2. android.app.ApplicationPackageManager/deletePackage
  3. android.app.ApplicationPackageManager/getInstalledPackages

Xposed编程步骤

  • 首先在xposedbridgeapi.jar包导入到项目中,这里采用了XposedBridgeApi-54.jar包
  • 再项目的assets文件夹中新建一个xposed_init文件(没有后缀),该文件表示该xposed模板的主函数类的具体路径,比如该项目为

  • 在AndroidManifest.xml文件的标签下添加xposed的一些信息,以便Xposed能够识别该模板。
    <?xml version="1.0" encoding="utf-8"?>    <manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.methodhook"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk    android:minSdkVersion="18"    android:targetSdkVersion="21" />    <application    android:allowBackup="true"    android:icon="@drawable/ic_launcher"    android:label="@string/app_name"    android:theme="@style/AppTheme" >    <activity    android:name="com.binpang.methodhook.MainActivity"    android:label="@string/app_name" >    <intent-filter>    <action android:name="android.intent.action.MAIN" />    <category android:name="android.intent.category.LAUNCHER" />    intent-filter>    activity>    <meta-data    android:name="xposedmodule"    android:value="true" />    <meta-data    android:name="xposedminversion"    android:value="40" />    <meta-data    android:name="xposeddescription"    android:value="Monitor the System's apis" />    application>    manifest>
  • 在Android手机(或模拟器,建议使用模拟器,一般的模拟器都已经root过了)中安装XposedInstaller(需要root权限), 由于Xposed替换了Android的一些程序,所以需要重启才能生效。
  • 然后启动该模板程序,使其安装到Android手机中,然后再Xposed的模板中找到它,并打钩,如图所示:

演示hook结果

通过短信软件向5554号码发送”hello,world”内容,如图所示:

结果查找logcat如图所示:


具体可以参考我的github

更多相关文章

  1. C语言函数的递归(上)
  2. Android多线程(三)HandlerThread源码原理解析
  3. Android单元测试之Robolectric
  4. Android(安卓)Studio真机测试时生成的程序出现闪退
  5. Android网络请求框架AsyncHttpClient (android-async-http)介绍
  6. # 读 Android(安卓)开发艺术探索 &8
  7. Android学习路线(二十七)键值对(SharedPreferences)存储
  8. Android系统的启动流程
  9. Android(安卓)资源加载与匹配

随机推荐

  1. MPAndroidChart介绍
  2. Android鸳鸯刀之DatePicker、TimePicker
  3. Android异步HTTP请求框架Volley的使用
  4. Android Out Of Memory(OOM) 的详细研究
  5. android 怎么进行调试程序 如何采用Andro
  6. Android(安卓)时间戳和日期之间的转化
  7. Android WebView CPU高负荷问题
  8. Android创世纪 第三天
  9. Android中通过EventBus传递消息数据
  10. Android禁止横屏竖屏切换 .