看雪安全论坛

 

 

 

 


返回   看雪安全论坛 > 移动平台 > 『Android 安全』
  登陆   注册  

发表新主题 回复
优秀帖  
主题工具 显示模式
本站声明:看雪论坛文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者信息及本声明!
AqCxBoM
级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Oct 2015
帖子: 42 AqCxBoM 品行端正
精华: 0
现金: 78 Kx
致谢数: 21
获感谢文章数:1
获会员感谢数:6
1 旧 2017-01-05 14:39:11 icon20 【原创】安卓Hook函数的复杂参数如何给定?
AqCxBoM 当前离线

标 题: 【原创】安卓Hook函数的复杂参数如何给定?
作 者: AqCxBoM
时 间: 2017-01-05,14:39:11
链 接: http://bbs.pediy.com/showthread.php?t=215039

为什么有这文章?
前段时间用到点系统底层框架去HOOK安卓在JAVA层的流程函数,期间目标函数参数有简单类型也有复杂的数组参数,着实为HOOK时的传参头疼过一把,加上有个朋友之前也在某群问过相关的问题就组合当时网友给的提示自己来实现一次这个过程,顺便介绍下该框架插件的基本开发姿势,同时希望也可以为广大HOOK友们提供一点解决问题的根本办法。

需要些什么工具?具备些什么基本安卓开发知识?
上面说过用成熟的框架,现在在安卓上好用的扩展性框架不过两种:Xposed跟Cydia,由于本人只用过XPOSED框架所以在这篇文章中就用Xposed来给大家介绍使用,开发知识方面只要有基本的安卓经验皆可胜任,并没有什么技术含量。

怎么做?
一、HOOK 三要素:类对象、函数名、参数列表的获取。
二、构建XPOSED框架插件、编码完成测试。


这其中难点有两个,一个就是Xposed插件没开发过,网上的一些教程文章没有写得太详细,一些个小细节没有被重点提及导致一个小问题都要查找无数的资料,甚至还找不到问题所在,另一个就是网上示例都太过简单化,一般都用int\sting这种基本类型作为Demo,然而实际使用中难免会碰到一些稀奇古怪的函数参数,而没有经验的我们只能乱写一通,到最后只能不了了之,现在我想通过由浅入深的方式来记录下插件的开发过程,希望能为遇到这种情况的朋友们提供点小帮助吧。

动手:
一、HOOK JAVA层函数的三要素获取:
这其中目标类对象、函数名相信大家要拿到没有难度,问题的重点就在于函数的参数列表,在介绍插件开发步骤前,先来看看我们首要目标类及函数参数情况,截图如下:
目标类路径为:aqcxbom.xposedhooktarget;
函数名为:helloWorld
参数表:int,string
http://xianzhi.aliyun.com/forum/attachment/Mon_1701/4_31532713_4d7f7cd27dfecec.png
xposedhooktarget的onCreate方法中调用输出
http://xianzhi.aliyun.com/forum/attachment/Mon_1701/4_31532713_ad5cb355f1cd5c7.png
当前未hook前输出log前后如下:
http://xianzhi.aliyun.com/forum/attachment/thumb/Mon_1701/4_31532713_3d3d8dcd04328da.png
我们要实现的目标是分别在前后调用输出入咱自己的日志信息,如下面两箭头所指:
http://xianzhi.aliyun.com/forum/attachment/thumb/Mon_1701/4_31532713_63516b73225c614.png

二、插件开发步骤
好,明确了我们初步的目标后,现在咱来看看XPOSED框架插件开发步骤:
1. 以provided 模式导入 lib 文件 XposedBridgeApi-54.jar(不参与编译到最终文件中)且用AS开发的你千万不要将其放在libs目录中,否则你会发现你的插件安装上却一直没有运行起来的尴尬情况(大坑一)。
2. 在AndroidManifest.xml中添加框架信息。
代码:
  <application>
  <meta-data android:name="xposedmodule" android:value="true"/>
  <meta-data android:name="xposeddescription" android:value="这里填写模块说明信息"/>
  <meta-data android:name="xposedminversion" android:value="30"/> 
  </application>
xposedminversion这一项非常重要,必须与JAR内版本一致,否则模块不能运行。(大坑二)
你可以用RAR等压缩工具打开XposedBridgeApi-XX.jar包,在assets\version文件中包含了该包的版本号,这个版本号正常情况下会与jar包名内的版本保持一致。

3.编写响应类并实现类IXposedHookLoadPackage接口handleLoadPackage函数方法:
在handleLoadPackage函数的findAndHookMethod 方法我们要提供HOOK目标的信息,参数为(类全路径,当前的CLASSLOADER,HOOK的函数名,参数1类类型...参数N类类型, XC_MethodHook的回调),具体代码如下:
代码:
package aqcxbom.myxposed;
import android.util.Log;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
/**
 * Created by AqCxBoM on 2016/12/24.
 */
//实现该类方法的类在注册为Xposed插件后会被框架自动调用
public class XposedMain implements IXposedHookLoadPackage 
{
    public String TAG = "AqCxBoM" ;
    private final String mStrPackageName = "aqcxbom.xposedhooktarget"; //HOOK APP目标的包名
    private final String mStrClassPath = "aqcxbom.xposedhooktarget.MyClass"; //HOOK 目标类全路径
    private final String helloworld = "helloWorld"; //HOOK 目标函数名
    private void LOGI(String ct){ Log.d(TAG, ct); }

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        //对比此时加载的包名是否与目标包名一致
        if (loadPackageParam.packageName.equals(mStrPackageName)) {
            LOGI("found target: " + loadPackageParam.packageName); 
// findAndHookMethod方法用于查找匹配HOOK的函数方法,这里参数为HOOK的目标信息
            XposedHelpers.findAndHookMethod(mStrClassPath, //类全路径
loadPackageParam.classLoader, //ClassLoader
helloworld, //HOOK目标函数名
                    int.class, //参数1类型
                    String.class, //参数2类型(这里目标函数有多少个参数就多少个,与HOOK目标函数保持一致)
                    new XC_MethodHook() { //最后一个参数为一个回调CALLBACK
                        @Override //故名思意,这个函数会在目标函数被调用前被调用
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            super.beforeHookedMethod(param);
                            LOGI("beforeHook");
                        }
                        @Override//这个函数会在目标函数被调用后被调用
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            LOGI("afterHooke param: ");
                        }
                    });
        }
    }
}
4. 将响应类添加到框架启动文件
新建assests 文件夹,并在其中新建 xposed_init 文件,写入插件入口类的信息
代码:
aqcxbom.myxposed.XposedMain
5. 安装我们的插件设置启用,并在机器重启后插件生效,这时运行我们的Target目标,如无意外就能见到类似如下的日志输出。(注意插件的启用要到Xposed框架的模块中勾选启用)
http://xianzhi.aliyun.com/forum/attachment/thumb/Mon_1701/4_31532713_63516b73225c614.png
=============================我是墙裂的分割线================================================================
进阶篇
对于上面的函数参数为基本数据类型(INT\STRING)我们都能快速搞定,但如果函数的参数如果是数组、Map、ArrayList这种复杂类型大家是不是就瞬间懵逼了呢,下面我们就来假设有如下这个情况:

我们的目标MyClass类的fun1函数,先看一下参数原型声明:
代码:
public static boolean fun1(String[][] strAry, Map mp1, Map<String,String> mp2, Map<Integer, String> mp3,
                      ArrayList<String> al1, ArrayList<Integer> al2, ArgClass ac) 
摆在我们面前的问题是这个参数该怎么写?
这个问题让我来解决的话,我会想让安卓APP告诉我该怎么写,所以用反射调用的方式(具体的调用方式可以查看示例XposedHookTarget的ShowDeclaredMethods方法)打印出这个函数的参数列表输出如下:
代码:
([[Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/ArrayList;Ljava/util/ArrayList;Laqcxbom/xposedhooktarget/ArgClass;)
这一看很清晰嘛,总结如下:
String[][] ==> [[Ljava/lang/String;
Map数组不论何种形式 ==> Ljava/util/Map;
ArrayList 无论何种形式 ==> Ljava/util/ArrayList;
ArgClass ac 自定义类给个全路径的事==> Laqcxbom/xposedhooktarget/ArgClass;
但实际上并不是这么一回事,提示各种类找不到(Ljava/util/ArrayList; Ljava/util/Map; Laqcxbom/xposedhooktarget/ArgClass;)
那么正确的姿势该怎么呢?答案是通过上面找到的类路径,用Xposed自身提供的XposedHelpers的findClass方法加载每一个类,然后再将得到的类传递给hook函数作参数!
示例代码如下:
代码:
package aqcxbom.myxposed;
import android.util.Log;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
/**
 * Created by AqCxBoM on 2016/12/24.
 */
public class XposedMain implements IXposedHookLoadPackage
{
    public String TAG = "AqCxBoM" ;
    private final String mStrPackageName = "aqcxbom.xposedhooktarget"; //HOOK APP目标的包名
    private final String mStrClassPath = "aqcxbom.xposedhooktarget.MyClass";//HOOK 目标类全路径
    private final String mStrMethodName = "fun1"; //HOOK 目标函数名
    private void LOGI(String ct){ Log.d(TAG, ct); }
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
//判断包名是否一致
        if (loadPackageParam.packageName.equals(mStrPackageName)) {
            LOGI("found target: " + loadPackageParam.packageName);
            final Class<?> ArgClass= XposedHelpers.findClass("aqcxbom.xposedhooktarget.ArgClass", loadPackageParam.classLoader);
            final Class<?> ArrayList= XposedHelpers.findClass("java.util.ArrayList", loadPackageParam.classLoader);
            final Class<?> Map= XposedHelpers.findClass("java.util.Map", loadPackageParam.classLoader);
//包名一致时查找是否有匹配参数的类及函数
            XposedHelpers.findAndHookMethod(mStrClassPath, //类路径
loadPackageParam.classLoader, //ClassLoader
mStrMethodName, //目标函数名
                    "[[Ljava.lang.String;", //参数1
                    Map, //参数2
                    Map, //参数3
                    Map, //参数4
                    ArrayList, //参数5
                    ArrayList, //参数6
                    ArgClass, //参数7
                    new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            super.beforeHookedMethod(param); //这个函数会在被hook的函数执行前执行
                            LOGI("beforeHook");
                        }
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);//这个函数会在被hook的函数执行后执行
                            LOGI("afterHooke param: ");
                        }
                    });
        }
    }
}
编译安装,重启并运行我们的target程序得到HOOK成功的效果图
http://xianzhi.aliyun.com/forum/attachment/Mon_1701/4_31532713_2fbc66e38ffa5a1.png
至此,我想就算遇到再复杂的参数类型,朋友们都能游刃有余地解决了吧,如果答案是肯定的,那我这篇文件就算是达到目的了。

排版太菜上传pdf一份,涉及到的源代码可以在我github上找到,有需要的朋友可以自行下载:
https://github.com/FuhuiLiu/XposedHookTarget.git
https://github.com/FuhuiLiu/MyXposed.git


PS:如果有需求想让被hook函数不执行的话可以在执行前使用 setResult(NULL)函数终止其在后续执行。
其它Xposed插件使用未详尽说明处请移步Xpose官网察看,这里就不再展开细述了。

在这里非常感谢我北京一个亦师亦友的哥们提供的资料及其零日安全论坛及团队所出品的安卓零基础逆向教材,正是有他们的引领我才能顺利开启Xposed插件开发的大门,同时也感谢网上热心网友提供的真知灼见,所查资料太多,并没有详细记录为此篇小文所翻阅的网文,只能列出一二以表谢意: 
http://www.freebuf.com/articles/terminal/56453.html
http://bbs.pediy.com/showthread.php?t=202147&page=2
尤其是网友jzfcf提供的查找类对象并传参到hook函数的方法,非常的赞。
> 先知技术社区首发 https://xianzhi.aliyun.com/forum/read/611.html
> 先知技术社区独家发表本文,如需要转载,请先联系先知技术社区授权;未经授权请勿转载。
> 先知技术社区投稿邮箱:Aliyun_xianzhi@service.alibaba.com;*转载请注明来自看雪论坛@PEdiy.com
上传的附件
文件类型: pdf 安卓Hook函数的复杂参数如何给定.pdf (465.4 KB, 88 次下载)
此帖于 2017-01-11 10:36:25 被 AqCxBoM 最后编辑
回复时引用此帖 返回顶端
共 6 位会员
感谢 AqCxBoM 发表的文章:
bengou (2017-01-06), friendanx (2017-01-05), Howsk (2017-01-08), zhengsidie (2017-01-05), 醉卧美人膝 (2017-01-19), 雪衫 (2017-01-09)
KX头狼
级别:3 | 在线时长:31小时 | 升级还需:1小时级别:3 | 在线时长:31小时 | 升级还需:1小时级别:3 | 在线时长:31小时 | 升级还需:1小时

KX头狼 的头像

初级会员
初级会员

资 料:
注册日期: May 2016
帖子: 9 KX头狼 品行端正
精华: 0
现金: 56 Kx
致谢数: 1
获感谢文章数:2
获会员感谢数:9
2 旧 2017-01-05, 19:27:17 默认
KX头狼 当前离线

谢谢楼主,好方法
回复时引用此帖 返回顶端
AqCxBoM
级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Oct 2015
帖子: 42 AqCxBoM 品行端正
精华: 0
现金: 78 Kx
致谢数: 21
获感谢文章数:1
获会员感谢数:6
3 旧 2017-01-05, 19:47:08 默认
AqCxBoM 当前离线

引用:
最初由 KX头狼发布 查看帖子
谢谢楼主,好方法
能帮上忙就好
回复时引用此帖 返回顶端
zhengsidie
级别:1 | 在线时长:8小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Dec 2016
帖子: 13 zhengsidie 品行端正
精华: 0
现金: 64 Kx
致谢数: 1
获感谢文章数:0
获会员感谢数:0
4 旧 2017-01-05, 21:51:48 默认
zhengsidie 当前离线

太感谢楼主了。不过我还想问一个问题,就是如果一个app有多个包,而我们要hook的函数不在标识这个app的主包里,而是在了另一个包里,那要怎么办呢?比如主包是com.mainpack 而我们的函数在包com.otherpack里.如果我们直接hook com.otherpack会提示找不到这个包~~~求教~~~
回复时引用此帖 返回顶端
mingxuan三千
级别:28 | 在线时长:906小时 | 升级还需:51小时级别:28 | 在线时长:906小时 | 升级还需:51小时级别:28 | 在线时长:906小时 | 升级还需:51小时级别:28 | 在线时长:906小时 | 升级还需:51小时

mingxuan三千 的头像

初级会员
初级会员

资 料:
注册日期: May 2014
帖子: 140 mingxuan三千 品行端正
精华: 0
现金: 100 Kx
致谢数: 2
获感谢文章数:0
获会员感谢数:0
5 旧 2017-01-06, 09:39:21 默认
mingxuan三千 当前离线

支持原创  多出些这方面的教程
回复时引用此帖 返回顶端
AqCxBoM
级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Oct 2015
帖子: 42 AqCxBoM 品行端正
精华: 0
现金: 78 Kx
致谢数: 21
获感谢文章数:1
获会员感谢数:6
6 旧 2017-01-06, 09:43:43 默认
AqCxBoM 当前离线

引用:
最初由 zhengsidie发布 查看帖子
太感谢楼主了。不过我还想问一个问题,就是如果一个app有多个包,而我们要hook的函数不在标识这个app的主包里,而是在了另一个包里,那要怎么办呢?比如主包是com.mainpack 而我们的函数在包com.otherpack里.如果我们直接hook com.otherpack会提示找不到这个包~~...
不能很清晰地了解你所说的情况,就字面理解来说,你的APP不管多少包,只要在同一个APP的ClassLoader中加载的都能被找到,除非你自己调用动态去加载的JAR包可能会出现这个问题,如果是后面这种情况,目前我也还没有好的方法来解决,只能请万能的坛友指点一二了
回复时引用此帖 返回顶端
malokch
级别:12 | 在线时长:213小时 | 升级还需:8小时级别:12 | 在线时长:213小时 | 升级还需:8小时级别:12 | 在线时长:213小时 | 升级还需:8小时

malokch 的头像

普通会员
普通会员

资 料:
注册日期: Sep 2011
帖子: 198 malokch 品行端正
精华: 2
现金: 120 Kx
致谢数: 2
获感谢文章数:5
获会员感谢数:62
7 旧 2017-01-08, 12:23:20 默认
malokch 当前离线

xposed的参数还是好给的,但是底层hook的就难给了。曾经在底层传参数我还用了ffi来做~
回复时引用此帖 返回顶端
koflfy
级别:22 | 在线时长:593小时 | 升级还需:28小时级别:22 | 在线时长:593小时 | 升级还需:28小时级别:22 | 在线时长:593小时 | 升级还需:28小时级别:22 | 在线时长:593小时 | 升级还需:28小时

普通会员
普通会员

资 料:
注册日期: Aug 2007
帖子: 246 koflfy 品行端正
精华: 1
现金: 185 Kx
致谢数: 2
获感谢文章数:3
获会员感谢数:13
8 旧 2017-01-08, 17:52:44 默认
koflfy 当前离线

顶,mark
回复时引用此帖 返回顶端
qqsunqiang
级别:15 | 在线时长:292小时 | 升级还需:28小时级别:15 | 在线时长:292小时 | 升级还需:28小时级别:15 | 在线时长:292小时 | 升级还需:28小时级别:15 | 在线时长:292小时 | 升级还需:28小时级别:15 | 在线时长:292小时 | 升级还需:28小时级别:15 | 在线时长:292小时 | 升级还需:28小时

qqsunqiang 的头像

初级会员
初级会员

资 料:
注册日期: Dec 2013
帖子: 174 qqsunqiang 品行端正
精华: 0
现金: 80 Kx
致谢数: 1
获感谢文章数:1
获会员感谢数:2
9 旧 2017-01-08, 18:22:03 默认
qqsunqiang 当前离线

谢谢楼主的分享。
回复时引用此帖 返回顶端
fengmaple
级别:2 | 在线时长:14小时 | 升级还需:7小时级别:2 | 在线时长:14小时 | 升级还需:7小时

初级会员
初级会员

资 料:
注册日期: Apr 2016
帖子: 1 fengmaple 品行端正
精华: 0
现金: 2 Kx
致谢数: 0
获感谢文章数:0
获会员感谢数:0
10 旧 2017-01-08, 18:26:29 默认
fengmaple 当前离线

写得很不错
回复时引用此帖 返回顶端
AqCxBoM
级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Oct 2015
帖子: 42 AqCxBoM 品行端正
精华: 0
现金: 78 Kx
致谢数: 21
获感谢文章数:1
获会员感谢数:6
11 旧 2017-01-09, 00:21:01 默认
AqCxBoM 当前离线

引用:
最初由 malokch发布 查看帖子
xposed的参数还是好给的,但是底层hook的就难给了。曾经在底层传参数我还用了ffi来做~
底层传参?不明白
回复时引用此帖 返回顶端
AqCxBoM
级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Oct 2015
帖子: 42 AqCxBoM 品行端正
精华: 0
现金: 78 Kx
致谢数: 21
获感谢文章数:1
获会员感谢数:6
12 旧 2017-01-09, 00:22:54 默认
AqCxBoM 当前离线

引用:
最初由 koflfy发布 查看帖子
顶,mark
谢谢捧场!!!
回复时引用此帖 返回顶端
小豆芽
级别:13 | 在线时长:238小时 | 升级还需:14小时级别:13 | 在线时长:238小时 | 升级还需:14小时级别:13 | 在线时长:238小时 | 升级还需:14小时级别:13 | 在线时长:238小时 | 升级还需:14小时

小豆芽 的头像

初级会员
初级会员

资 料:
注册日期: Aug 2010
帖子: 170 小豆芽 品行端正
精华: 0
现金: 56 Kx
致谢数: 3
获感谢文章数:1
获会员感谢数:1
13 旧 2017-01-09, 04:09:16 默认
小豆芽 当前离线

感谢分享~!
回复时引用此帖 返回顶端
zylyy
级别:17 | 在线时长:375小时 | 升级还需:21小时级别:17 | 在线时长:375小时 | 升级还需:21小时

zylyy 的头像

初级会员
初级会员

资 料:
注册日期: Apr 2012
帖子: 187 zylyy 品行端正
精华: 0
现金: 100 Kx
致谢数: 7
获感谢文章数:0
获会员感谢数:0
14 旧 2017-01-09, 09:18:04 默认
zylyy 当前离线

真是好巧哦,最近我也在研究这东西
回复时引用此帖 返回顶端
AqCxBoM
级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时级别:3 | 在线时长:28小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Oct 2015
帖子: 42 AqCxBoM 品行端正
精华: 0
现金: 78 Kx
致谢数: 21
获感谢文章数:1
获会员感谢数:6
15 旧 2017-01-09, 14:17:42 默认
AqCxBoM 当前离线

引用:
最初由 小豆芽发布 查看帖子
感谢分享~!

回复时引用此帖 返回顶端
发表新主题 回复

添加到书签

主题工具
显示模式

发帖规则
不可以发表主题
不可以回复帖子
不可以上传附件
不可以编辑自己的帖子
论坛论坛启用 vB 代码
论坛启用 表情图标

相似的主题
主题 主题作者 论坛 回复 最后发表
【原创】rmtdebug64 yzwyq 『编程技术』 3 2016-11-24 13:02:14
【原创】CTF第6题 shmily云 『CrackMe&ReverseMe』 0 2016-11-12 19:37:44


所有时间均为北京时间, 现在的时间是 02:01:26.


  ©2000-2016 看雪学院(PEdiy.com) |关于我们 | 京ICP备10040895号-17 | 知道创宇提供带宽资源 | 微信公众帐号:ikanxue