记录对frida、xposed hook的一点理解

本文探讨了在Android逆向工程中使用Frida和Xposed进行动态Hook的技术,以及如何通过广播实现模块间的通信。作者通过实例展示了如何在不修改原应用代码的情况下,利用Frida获取加密参数sign,并在Xposed环境中遇到的问题和解决方案,强调了进程间通信的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

记录对frida、xposed hook的一点理解


先说结论:hook就类似于在自己项目里导入了一个第三方jar,一般情况下不需要去关注app内的方法是怎么实现的,只需要确定需要传递的参数即可。使用方式和调用api类似。

由于数据抓取问题接触了安卓逆向,先后使用了frida与xposed,但之前在使用上一直存在误区,例如下面这段代码

Java.perform(function() {
		var SecurityGuardManager = Java.use("com.alibaba.wireless.security.open.SecurityGuardManager");
		var MtopUtils = Java.use("mtopsdk.common.util.MtopUtils");
		var Map = Java.use("java.util.HashMap");
		var Md5 = Java.use("mtopsdk.security.util.SecurityUtils");
		var SecurityGuardParamContext = Java.use("com.alibaba.wireless.security.open.SecurityGuardParamContext");
		/**
		省略一部分代码
		**/
		var input = hashMap.get("utdid") + "&" + hashMap.get("uid") + "&&" + hashMap.get("appKey") + "&" + hashMap.get("data") + "&" + hashMap.get("t") + "&" + hashMap.get("api") + "&" + hashMap.get("v") + "&" + hashMap.get("sid") + "&" + hashMap.get("ttid") + "&" + hashMap.get("deviceId") + "&" + hashMap.get("lat") + "&" + hashMap.get("lng") + "&" + hashMap.get("x-features");
		var inputMap = Map.$new();
		inputMap.put("INPUT", input);
		var securityGuardParamContext = SecurityGuardParamContext.$new();
		securityGuardParamContext.appKey.value = hashMap.get("appKey");
		securityGuardParamContext.requestType.value = 7;
		securityGuardParamContext.paramMap.value = inputMap;
		var sign = SecurityGuardManager.getInstance(MtopUtils.getContext()).getSecureSignatureComp().signRequest(securityGuardParamContext, "");
		console.log("sign:" + sign);
	});

这段代码是想实现主动调用frida获取加密参数sign,运行效果没有问题可以获取sign,但是代码实现属于脱裤子放屁多此一举。。。。。尤其是后来想按照这个逻辑编写xposed插件时,更是难以实现。

特此记录一下,引以为戒

记录xposed插件间通信方式


需要通过遍历ID的方式抓取某APP数据,最初的想法是为插件写个界面,在界面里设置要遍历的ID范围,通过一个按钮控制生成sign方法的启停,sign生成后发送http通过一个web服务将sign存入redis,然后服务器上的爬虫轮询redis进行数据抓取。
实际编写时遇到问题,即Activity与hook方法数据不能互通。原因是因为Activity与hook就不在一个进程内,虽然Activity与hook方法在同一个app内,所以需要将Activity与hook看作两个不同的app,数据想要互通就需要考虑跨进程通讯。
最后是通过广播实现的数据交互,当然还有其他解决方式,但对于一个android小白来说,这算是最简单的方法了。
再补充一点,同一个handleLoadPackage方法里不管你hook多少接口,只要hook的应用不同数据变不能共享,想共享数据就必须跨进程,相应的如果hook的应用相同,数据便是共享的。

下面来说下具体的实现
1.首先是在Activity的按钮点击监听事件中,发送广播

		// 首先是在Activity的按钮点击监听事件中,发送广播
        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
							 // 要广播的参数
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("startId", usernameEditText.getText().toString());
                jsonObject.put("endId", passwordEditText.getText().toString());
                jsonObject.put("status", loginButton.getText().equals("启动") ? 1 : 2);

                // 发送广播
                Intent i = new Intent("koubei_intent_send");
                i.putExtra("json", jsonObject.toJSONString());
                sendBroadcast(i, null);
                // 修改按钮文字,输出提示信息
                if(loginButton.getText().equals("启动")) {
                    updateUiWithUser("任务已启动");
                    loginButton.setText("停止");
                } else {
                    updateUiWithUser("任务已停止");
                    loginButton.setText("启动");
                }
            }
        });

2.在handleLoadPackage里需要hook两个接口,一个是Application的onCreate方法并在此处动态注册自己的广播接收者(最好通过processName名称过滤一下,不然有可能多次注册广播接收者)。
另一个就是hook sign的生成方法了。

	/**
     * 实现广播接收
     * */
    private final BroadcastReceiver myReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("koubei_intent_send")) {
                JSONObject jsonObject = JSONObject.parseObject(intent.getStringExtra("json"));
                startId = jsonObject.getInteger("startId");
                endId = jsonObject.getInteger("endId");
                status = jsonObject.getInteger("status");
                XposedBridge.log("=================>接收广播【json】:" + intent.getStringExtra("json"));
                if(status == 1) {
                    new Thread(() -> {
                    	// 具体的sign参数生成方法,这里省略了。。。
                        createSign();
                    }).start();
                }
            }
        }
    };
    
    // 实现目标接口hook
	@Override
    public void handleLoadPackage(LoadPackageParam loadPackageParam) throws Throwable {
        
        if(loadPackageParam.packageName.equals("com.taobao.mobile.dipei")) {
            /**
             * hook Application并注册广播接收者
             */
            XposedHelpers.findAndHookMethod(Application.class, "onCreate", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    application = (Application) param.thisObject;

                    // 过滤一下进程名称,不然广播接收会被多次注册,
                    if(intentFilter == null && loadPackageParam.processName.equals("com.taobao.mobile.dipei")) {
                        XposedBridge.log("=================>【" + loadPackageParam.processName + "】注册广播接收者");
                        intentFilter = new IntentFilter();
                        intentFilter.addAction("koubei_intent_send");//要接收的广播
                        application.registerReceiver(myReceiver, intentFilter);//注册接收者
                    }
                }
            });

            /**
             * hook sign参数生成接口
             */
            XposedHelpers.findAndHookMethod(
                 // 获取生成sign的method及object,将其赋值给当前类中的类变量 其他方便便可以调用到了。
            );
        }
    }
		
	// 定义具体的sign生成方法
    private void createSign() {
		// 生成sign,通过okhttp发送给web服务器进行保存,爬虫轮询抓取。
		// 这样做的好处就是不用限制网络,只要有网就能运行,不过这并不是唯一的解决方式,像内网穿透之类的也可以	
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值