xposed 修改参数_【Android 原创】2020春节红包第三题Xposed框架Hook的应用

作者坛账号:CrazyNut

准备工具以及思路

首先不了解Xposed框架Hook的可以看看大佬的基础教程 - 《教我兄弟学Android逆向12 编写xposed模块》

本文不需要会看懂汇编代码,当你看完上面的文章,学会Xposed框架Hook的简单应用后。
就算是从未接触过的萌新跟着流程一会就能搞定,一起来动手吧!

准备工具

1.Android Studio - 以及Xposed框架环境 - 有关Xposed框架环境的搭建和编译在上述帖子都有,我就不在赘述
2.DDMS - 用于查看打印出来的日志信息,有Android Studio配套就有
3.dex2jar - 用于将Dex文件还原为jar
4.jd-gui - 用于查看jar包的java代码
5.IDA - 用于查看So文件代码
6.一款可以打开Apk的压缩软件
7.一个装有Xposed环境的安卓模拟器或者手机

思路

1.首先将APK的dex还原为jar后,可以用jd-gui查看java代码
2.后面可以发现关键代码都在So文件内[剧透] ,然后用IDA打开So文件,找到对应的关键函数
3.加以以分析Hook某关键函数后直接出结果

查看APK的java代码

Dex还原为jar

用压缩软件打开APK可以看到classes.dex文件

7e8e3c026c519d399e0aab7d7752e89a.png

将其解压并扔到dex2jar的根目录下,运行 DexToJar.bat

1a5d450103b9fcf4369cb4b121287b44.png

即可把dex文件还原为Jar

e76bab3fb6c9b5a320f53131583cf43d.png

上图红框则是我们需要的文件

用Jd-gui查看java代码

然后将其直接拖入jd-gui即可看到java代码

6d9a1f589f8cc6910312d8897d07a6ca.png

CM代码很少,很容易看到入口函数MainActivity里的代码
这段java代码里面没有任何关键的代码
有一点点安卓基础就看的出来,APK引用了一个叫libcrack_j2c的so文件,所以可以判断关键代码全在so里面

而且作者方法名都明说了是checkFlag。。 可以看到参数时一个String 肯定是传入的相关flag 返回值也是个bool值,肯定是关键函数咯当然 因为按钮只有一个  搜OnClick也是一样的,从按钮事件入手。

所以直接上IDA分析so文件找到checkFlag或者OnClick这个函数。

IDA查看so文件

定位到关键函数代码 - 方法 1.字符串大法好

直接找到
验证错误,继续加油
一步到位,香的不行
我的IDA版本暂时搜不了字符串,后面补上。。

定位到关键函数代码 - 方法 2.直接搜方法名

上面说到了 作者已经明确的告诉了checkFlag和onclick了这函数了。。明摆着就是关键函数。
所以在so文件没被混淆的情况下,可以直接用IDA打开So文件,搜索方法 checkFlag 或者 onclick

7b939bfa19d24103cd20f445e5e1e55a.png

IDA中直接拖入so载入后,在Functions Window 按ctrl+f直接搜方法名一步到位

不过这里是不推荐用这个方法的。。因为就算So文件没被混淆
正常项目代码量巨大。。根本不知道谁是谁。。。不容易直接一眼就看出来的情况下
这个方法无疑大海捞针,所以下面介绍另一种方法

定位到关键函数代码 - 方法 3.Xposed框架Hook打印堆栈

这里就需要用到Xposed框架来Hook了,还不会请先看上方基础教程

这里直接贴上一段代码 - 《利用Xposed Hook打印Java函数调用堆栈信息的几种方法》

具体思路是:既然按了验证按钮后有土司 提示长度不够,那我直接Hook Toast()这个方法 看看什么调用了他,不就可以找到点击事件了?
虽然对这题有点脱了裤子放屁。。。不过这也是一种思路吧

自己修改对应包名后变成如下

 findAndHookMethod("android.widget.Toast",    //要hook的包名+类名
                lpparam.classLoader,                                //classLoader固定"makeText",                        //要hook的方法名// 方法参数 没有就不填
                Context.class,
                CharSequence.class,int.class,new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//方法执行前执行
                        Log.i("Nut", "NutHookToast:" + param.args[1].toString());
                    }protected void afterHookedMethod(MethodHookParam param) throws Throwable {//方法执行后执行,改方法的返回值一定要在方法执行完毕后更改// 方法一:
                        Log.i("Dump Stack: ", "---------------start----------------");
                        Throwable ex = new Throwable();
                        StackTraceElement[] stackElements = ex.getStackTrace();if (stackElements != null) {for (int i = 0; i < stackElements.length; i++) {
                                Log.i("Dump Stack"+i+": ", stackElements[i].getClassName()
                                        +"----"+stackElements[i].getFileName()
                                        +"----" + stackElements[i].getLineNumber()
                                        +"----" +stackElements[i].getMethodName());
                            }
                        }
                        Log.i("Dump Stack: ", "---------------over----------------");
                    }
                }
        );

Hook后 进去 随便按一下 验证按钮 得到日志如下

cc101af637e7ebffc33f084186448a60.png

可以看出只有一个包名为 com.wuaipojie.crackme01 的方法被调用 正是onclick的按钮事件。
然后用方法2直接IDA搜方法就可以了

简单分析函数代码

按钮OnClick事件方法

这里先从按钮事件开始

搜索onclick找到函数后,汇编代码是看不懂的。。。所以直接按F5查看伪代码,一起就清晰了起来

下面是代码

int __fastcall Java_com_wuaipojie_crackme01_MainActivity_onClick__Landroid_view_View_2(int a1, int a2, int a3){int *v3; // r4int v4; // r5int v5; // r9int v6; // r0int v7; // r5int (__fastcall *v8)(int *, void *); // r2int v9; // r6int v10; // r8int v11; // r6int v12; // r8int v13; // r5int v14; // r5void *v15; // r1int v16; // r6int v17; // r5int result; // r0int v19; // [sp+Ch] [bp-6Ch]int v20; // [sp+10h] [bp-68h]int v21; // [sp+14h] [bp-64h]int v22; // [sp+18h] [bp-60h]int v23; // [sp+1Ch] [bp-5Ch]int v24; // [sp+20h] [bp-58h]int v25; // [sp+24h] [bp-54h]int v26; // [sp+28h] [bp-50h]int v27; // [sp+2Ch] [bp-4Ch]int v28; // [sp+30h] [bp-48h]int v29; // [sp+34h] [bp-44h]int v30; // [sp+38h] [bp-40h]int v31; // [sp+3Ch] [bp-3Ch]int v32; // [sp+40h] [bp-38h]int v33; // [sp+48h] [bp-30h]int v34; // [sp+50h] [bp-28h]int v35; // [sp+58h] [bp-20h]
  v3 = (int *)a1;
  v4 = a3;
  v31 = 0;
  v29 = 0;
  v30 = 0;
  v27 = 0;
  v28 = 0;
  v25 = 0;
  v26 = 0;
  v23 = 0;
  v24 = 0;
  v21 = 0;
  v22 = 0;
  v19 = 0;
  v20 = 0;
  v5 = (*(int (__fastcall **)(int, int))(*(_DWORD *)a1 + 100))(a1, a2);
  v6 = (*(int (__fastcall **)(int *, int))(*v3 + 100))(v3, v4);if ( !v5 )goto LABEL_38;
  v7 = v6;if ( sub_539C(v3, &v31, &v26, 0, "com/wuaipojie/crackme01/MainActivity", "editText", "Landroid/widget/EditText;") )goto LABEL_39;
  v9 = (*(int (__fastcall **)(int *, int, int))(*v3 + 380))(v3, v5, v26);if ( (*(int (__fastcall **)(int *))(*v3 + 912))(v3) )goto LABEL_39;if ( v7 )
    (*(void (__fastcall **)(int *, int))(*v3 + 92))(v3, v7);if ( !v9 )goto LABEL_38;if ( !v25 && sub_5288(v3, &v30, &v25, 0, (int *)"android/widget/EditText", "getText") )goto LABEL_39;
  v10 = (*(int (__fastcall **)(int *, int))(*v3 + 144))(v3, v9);                 //获取输入框中的文本 存到v10中if ( (*(int (__fastcall **)(int *))(*v3 + 912))(v3) )goto LABEL_39;
  (*(void (__fastcall **)(int *, int))(*v3 + 92))(v3, v9);if ( !v10 )goto LABEL_38;if ( !v24 && sub_5288(v3, &v29, &v24, 0, (int *)"java/lang/Object", "toString") )goto LABEL_39;
  v11 = (*(int (__fastcall **)(int *, int))(*v3 + 144))(v3, v10);               //v10 tostring一下 存到 v11if ( (*(int (__fastcall **)(int *))(*v3 + 912))(v3) )goto LABEL_39;
  (*(void (__fastcall **)(int *, int))(*v3 + 92))(v3, v10);if ( !v11 )goto LABEL_38;if ( !v23 && sub_5288(v3, &v28, &v23, 0, (int *)"java/lang/String", "trim") )goto LABEL_39;
  v12 = (*(int (__fastcall **)(int *, int))(*v3 + 144))(v3, v11);              //v11 再trim一次 存到 v12if ( (*(int (__fastcall **)(int *))(*v3 + 912))(v3) )goto LABEL_39;
  (*(void (__fastcall **)(int *, int))(*v3 + 92))(v3, v11);if ( !v12 )goto LABEL_38;if ( !v22 && sub_5288(v3, &v28, &v22, 0, (int *)"java/lang/String", "length") )goto LABEL_39;
  v13 = (*(int (__fastcall **)(int *, int))(*v3 + 204))(v3, v12);             //获取v12的长度 存到 v13 if ( (*(int (__fastcall **)(int *))(*v3 + 912))(v3) )                       //【其实上面的一堆就是获取了你输入的flag的长度】goto LABEL_39;if ( v13 == 30 )                                  //这里判断 v13 是否为 30  也就是判断flag长度是否为30   
  {//如果长度正确 则进入下面 checkflag的判断流程if ( !v21 && sub_5288(v3, &v31, &v21, 0, (int *)"com/wuaipojie/crackme01/MainActivity", "checkFlag") )goto LABEL_39;
    v32 = v12;
    v14 = (*(int (__fastcall **)(int *, int))(*v3 + 156))(v3, v5);if ( (*(int (__fastcall **)(int *))(*v3 + 912))(v3) )goto LABEL_39;
    (*(void (__fastcall **)(int *, int))(*v3 + 92))(v3, v12);
    v8 = *(int (__fastcall **)(int *, void *))(*v3 + 668);if ( !v14 )goto LABEL_40;
    v15 = &unk_22047;
  }else
  {
    (*(void (__fastcall **)(int *, int))(*v3 + 92))(v3, v12);
    v15 = &unk_2211B;
    v8 = *(int (__fastcall **)(int *, void *))(*v3 + 668);
  }while ( 1 )
  {
    v16 = v8(v3, v15);if ( v20 || !sub_5288(v3, &v27, &v20, 1, (int *)"android/widget/Toast", "makeText") )
    {
      v33 = v16;
      v32 = v5;
      v34 = 0;
      v17 = (*(int (__fastcall **)(int *, int))(*v3 + 464))(v3, v27);if ( !(*(int (__fastcall **)(int *))(*v3 + 912))(v3) )
      {if ( v16 )
          (*(void (__fastcall **)(int *, int))(*v3 + 92))(v3, v16);if ( v17 )
        {if ( v19 || !sub_5288(v3, &v27, &v19, 0, (int *)"android/widget/Toast", "show") )
          {
            (*(void (__fastcall **)(int *, int))(*v3 + 252))(v3, v17);
            (*(void (__fastcall **)(int *))(*v3 + 912))(v3);
          }
        }else
        {
LABEL_38:
          sub_4EC0(v3, "java/lang/NullPointerException", "NullPointerException");
        }
      }
    }
LABEL_39:
    result = _stack_chk_guard - v35;if ( _stack_chk_guard == v35 )break;
LABEL_40:
    v15 = &unk_220FF;
  }return result;
}

上面代码已经备注了
可以看到flag 长度要为 30 【欸! 这不是废话吗,已经提示了好不】
就会把flag传入 checkflag这个方法进行判断

所以接下来是 checkflag 这个方法

checkflag方法

和上面同样的方法 找到这个方法后F5一下 直接看伪代码

这一段代码就算是F5的伪代码 算法部分我不是很看得懂。。连蒙带猜的做的吧。。
坐等大佬们更详细的分析过程噢,这里说一下我的思路。

因为看不懂具体代码了,所以我考虑从Hook函数中所调用的方法入手

看了几遍后 发现函数最下方的 代码部分最可疑

bbbfaf56943b294b3da4bc3f84da802c.png

可以看到 一次调用了 ToString substring equals方法

之前在看到flag是30位的时候
我就一直在猜想,似乎没有什么加密是30位的啊?? 所以估计是密钥加密后进行了切割。

这三个函数应该就认证了我的猜想。

上面的一堆函数估计是对密钥进行加密toString 之后 马上用 SubString 进行切割
最后用equals方法比较。。。
所以我决定把这三个函数全部Hook打印结果
以上只是猜想,有理解错误的地方请多指正

见证奇迹的Hook

最后Hook的结果证实 对 SubString 的 Hook 确实有用 [剧透]
所以下面只上对 substring 这个方法Hook 的 函数

      findAndHookMethod("java.lang.String",    //要hook的包名+类名
                lpparam.classLoader,                                //classLoader固定"substring",                        //要hook的方法名// 方法参数 没有就不填int.class,int.class,new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//方法执行前执行
                       Log.i("Nut", "substringA 参数A:" + param.args[0]+"参数B:"+param.args[1]);
                    }protected void afterHookedMethod(MethodHookParam param) throws Throwable {//方法执行后执行,改方法的返回值一定要在方法执行完毕后更改
                       Log.i("Nut", "substringA:" + param.getResult());
                    }
                }
        );//因为substring有两种重载 所以我无脑一起hook了。。
        findAndHookMethod("java.lang.StringBuilder",    //要hook的包名+类名
                lpparam.classLoader,                                //classLoader固定"substring",                        //要hook的方法名// 方法参数 没有就不填int.class,new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//方法执行前执行
                        Log.i("Nut", "substringB 参数A:" + param.args[0]);
                    }protected void afterHookedMethod(MethodHookParam param) throws Throwable {//方法执行后执行,改方法的返回值一定要在方法执行完毕后更改
                        Log.i("Nut", "substringB:" + param.getResult());
                    }
                }
        );

随便输一个30位的flag之后  验证  当当当当 出来了

3c55d4d3707b5128e1f656afaa7432b1.png

Log如下

02-09 04:00:34.060: I/Nut(2098): Already Find Methed02-09 04:00:34.062: I/Nut(2098): substringA 参数A:1参数B:3102-09 04:00:34.062: I/Nut(2098): substringA:ed61f6308c74bcf35c71729d4db24c02-09 04:00:34.062: I/Nut(2098): NutHookToast:验证错误,继续加油

可以看到确实是32位的加密 截取了 中间的 1-31位
结果也直接就打印出来了!!最后的equals也就是做了一个字符串比较而已。

本题也就此解开! 完结 撒花~

总结

星球杯大佬说过 : Xposed用的好就是可以为所欲为!
想想自己不知道还要隔多久才能到达这种高度,不禁有些小伤感 QAQ

本题也还有很多没弄懂的地方,期待大佬们出更详细的教程!
期待大佬们第四题的详细分析噢!希望能学习一下!

谢谢大佬们阅读 , 如有错误的地方请帮忙指正,以免误人子弟!谢谢

--官方论坛

www.52pojie.cn

--推荐给朋友

公众微信号:吾爱破解论坛

或搜微信号:pojie_52

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/513316.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Let‘s Fluent:更顺滑的MyBatis

简介&#xff1a; 只需瞅一眼Google Trends上全球Java界最热门的两款SQL映射框架近一年的对比数字&#xff0c;就不难了解其实力分布&#xff1a;在此领域&#xff0c;MyBatis早已占领东亚地区开发者市场&#xff0c;并以绝对优势稳居中国最抢手Java数据库访问框架之首。 作者 …

元宇宙会成为 IPv6 的拐点吗?

‍‍作者 | 马超&#xff0c;王丽丽&#xff0c;王一凡 责编 | 张红月出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;“如无必要&#xff0c;勿增实体”的奥卡姆剃刀原则&#xff0c;从IT人士的角度来看就是“只要能运行&#xff0c;就千万不要改”&#xf…

php网站加广告位,HotNews Pro主题文章内容上面添加广告位

使用的HotNew Pro主题后&#xff0c;文章内容上面没有广告位&#xff0c;但是有时需要在那个位置添加广告&#xff0c;就使用了一款叫Smart Ads广告管理插件&#xff0c;这个插件可以在文章内容上面和下面添加广告&#xff0c;直到昨天我删掉了Smart Ads这款插件&#xff0c;因…

电脑编程教学_东莞沙田mastercam编程学习怎么收费

东莞沙田mastercam编程学习怎么收费深圳卓越培训中心UG综合班主要课程&#xff1a;1&#xff0c;软件介绍&#xff0c;界面熟悉 &#xff0c;快捷键&#xff0c;图层使用。2&#xff0c;草图使用&#xff0c;三维曲线绘制修改&#xff0c;草图线3D线互相转换。3&#xff0c;建模…

arduinowifi.send怎么获取响应_Vue3.0 响应式原理 (一)

前几天&#xff0c;回顾整理下关于vue2.0的响应式原理。温故而知新么&#xff0c;那么今天&#xff0c;整理了一下关于vue3.0的响应式原理&#xff0c;利用 JavaScript 来写的。本着尽可能的清晰易懂的原则&#xff0c;所以&#xff0c;可能会分几篇文章来发布。那现在开始上菜…

OceanBase首次阐述战略:继续坚持自研开放之路 开源300万行核心代码

简介&#xff1a; 在数据库OceanBase3.0峰会上&#xff0c;蚂蚁集团自主研发的分布式数据库OceanBase首次从技术、商业和生态三个维度对未来发展战略进行了系统性阐述。同时&#xff0c;OceanBase宣布正式开源&#xff0c;并成立OceanBase开源社区&#xff0c;社区官网同步上线…

amd核芯显卡控制面板自定义分辨率_主流显卡的一位猛将:蓝宝石Radeon RX 5500XT显卡首测...

一直以来主流级显卡总是处于一个较为尴尬的位置&#xff0c;原因是由于性能的限制&#xff0c;主流显卡经常位于不上不下的局面。上面和电竞级显卡有很大的性能差距&#xff0c;而往下又感受了日新月异的核显的压力。于是很多玩家宁可加钱购买电竞显卡也不愿意购买这些主流显卡…

阿里云研究员叔同:云原生是企业数字创新的最短路径

简介&#xff1a; 今天&#xff0c;数字化成为企业的核心竞争力&#xff0c;千行百业都在拥抱云计算&#xff0c;拥抱云原生。2020年我们认为是云原生的落地元年&#xff0c;那么2021年将是云原生加速推动企业数字创新的关键节点。 作者 | 叔同 来源 | 阿里技术公众号 今天&am…

计算 a+aa+aaa+aaaa+aaaaa+ 的和_海南A级景区,三亚市就有14个,你都去过吗

日前&#xff0c;海南省旅游资源规划开发质量评定委员会发布2020年第2号和2020年第3号公告&#xff0c;海南长影环球100奇幻乐园批准为国家4A级旅游景区&#xff0c;海南霸王岭国家森林公园和桂林洋国家热带农业公园批准为国家3A级旅游景区。具体公告如下&#xff1a;海南省旅游…

如何成为云原生时代的卓越架构师

简介&#xff1a; “软件开发需要面对本质困难和附属困难。云原生、DevOps大幅降低了附属困难&#xff0c;使得架构师可以全力聚焦于业务复杂性&#xff0c;而DDD恰是管理业务复杂性的有效方法。” 本文作者&#xff1a;张刚&#xff0c;阿里云云效资深技术专家&#xff0c;AL…

创业 4 年获近 7000 万美元融资,53 岁老程序员 all in 开源

作者 | 伍杏玲 今年 6 月&#xff0c;《人均估值 5000 万 RMB&#xff0c;53 岁程序员能做到的&#xff0c;你也能&#xff01;》一文刷爆技术人的朋友圈&#xff1a;2017 年成立的涛思数据&#xff0c;四年获近 7000 万美元融资&#xff0c;目前这个 40 人团队估值超 3 亿美元…

.net pdf转图片_PDF转图片怎么做?PDF一键转图片!

在日常工作中&#xff0c;我们经常需要把文件资料传给其他人看。但如果文档是PDF格式的话&#xff0c;很可能他人的设备因缺少相应的阅读工具而无法打开。这时&#xff0c;最好的方法就是将PDF文件转换成图片&#xff01;这样不管是在电脑还是在一些移动设备上都可以查看。接下…

为什么你应该关心领域模型?

简介&#xff1a; 领域模型是DDD的核心&#xff0c;更是业务的深入认知 作者简介&#xff1a;张刚&#xff0c;软件工程博士&#xff0c;阿里云云效资深技术专家&#xff0c;ALPD方法学核心成员。 引言 领域模型是重要的概念。但是&#xff0c;真正了解并能熟练运用它的人并不…

三包围结构的字是什么样的_一年级语文重点(字、字母、字词、词语、句子)知识点汇总!...

一年级语文重点汇总一、字母A B C D E F G H I J K L M N O P Q R S T U V W X Y Za b c d e f g h i j k l m n o p q r s t u v w x y z二、 字1、组词。(形近字和同音字)么(什么) 无(无法) 高(高兴)公(公共) 元(一元…

Java编程技巧之样板代码

简介&#xff1a; 在日常编码的过程中&#xff0c;可以总结出很多“样板代码”&#xff0c;就像”活字印刷术中的“活字”一样。当我们编写新的代码时&#xff0c;需要用到这些“活字”&#xff0c;就把“样板代码”拷贝过来&#xff0c;修改替换一下就可以了&#xff0c;写起代…

CPU 被挖矿,Redis 竟是内鬼!

作者 | 轩辕之风O来源 | 编程技术宇宙却说这一日&#xff0c;Redis正如往常一般工作&#xff0c;不久便收到了一条SAVE命令。虽说这Redis常被用来当做缓存&#xff0c;数据只存在于内存中&#xff0c;却也能通过SAVE命令将内存中的数据保存到磁盘文件中以便持久化存储。只见Red…

vos3000落地网关对接教学_跨国合作:Serverless Components 在腾讯云的落地和实践

导语 | Serverless Components 是 Serverless Framework 推出的最新解决⽅案&#xff0c;具有基础设施编排能⼒&#xff0c;开发者通过使⽤ Serverless Components&#xff0c;可以灵活构建、组合和部署 Serverless 应⽤。本文是对腾讯云云函数团队前端负责人蔡卫峰在云社区沙龙…

Hologres揭秘:深度解析高效率分布式查询引擎

简介&#xff1a; 从阿里集团诞生到云上商业化&#xff0c;随着业务的发展和技术的演进&#xff0c;Hologres也在持续不断优化核心技术竞争力&#xff0c;为了让大家更加了解Hologres&#xff0c;我们计划持续推出Hologers底层技术原理揭秘系列&#xff0c;从高性能存储引擎到高…

电脑两边黑边怎么还原_Mac电脑录制的视频有黑边?如何解决

Mac电脑录制屏幕视频时两边有黑边&#xff0c;无论是将录制格式设置为1080p还是默认分辨率&#xff0c;最终生成的视频两边都有黑边&#xff0c;遇到这种情况如何解决呢&#xff1f;原因是 mac 录制出的视频分辨率比例是 16:10 &#xff0c;比需要的 16:9 高一点。接下来给大家…

程序员有必要参加软考吗?大一可以考的编程证书还有哪些

软考的全称是&#xff1a;计算机技术与软件专业技术资格水平考试。通过考试获得证书的人员&#xff0c;表明其已具备相应等级的水平和能力&#xff0c;用人单位可根据工作需要从获得证书的人员中择优聘任相应专业技术职务。个人认为&#xff0c;程序员有没有必要参与软考最主要…