xposed 修改参数_【Android 原创】2020春节红包第三题Xposed框架Hook的应用
作者論壇賬號:CrazyNut
準(zhǔn)備工具以及思路
首先不了解Xposed框架Hook的可以看看大佬的基礎(chǔ)教程 -?《教我兄弟學(xué)Android逆向12 編寫xposed模塊》
本文不需要會看懂匯編代碼,當(dāng)你看完上面的文章,學(xué)會Xposed框架Hook的簡單應(yīng)用后。
就算是從未接觸過的萌新跟著流程一會就能搞定,一起來動手吧!
準(zhǔn)備工具
1.Android Studio - 以及Xposed框架環(huán)境 - 有關(guān)Xposed框架環(huán)境的搭建和編譯在上述帖子都有,我就不在贅述
2.DDMS - 用于查看打印出來的日志信息,有Android Studio配套就有
3.dex2jar?- 用于將Dex文件還原為jar
4.jd-gui?- 用于查看jar包的java代碼
5.IDA?- 用于查看So文件代碼
6.一款可以打開Apk的壓縮軟件
7.一個(gè)裝有Xposed環(huán)境的安卓模擬器或者手機(jī)
思路
1.首先將APK的dex還原為jar后,可以用jd-gui查看java代碼
2.后面可以發(fā)現(xiàn)關(guān)鍵代碼都在So文件內(nèi)[劇透] ,然后用IDA打開So文件,找到對應(yīng)的關(guān)鍵函數(shù)
3.加以以分析Hook某關(guān)鍵函數(shù)后直接出結(jié)果
查看APK的java代碼
Dex還原為jar
用壓縮軟件打開APK可以看到classes.dex文件
將其解壓并扔到dex2jar的根目錄下,運(yùn)行 DexToJar.bat
即可把dex文件還原為Jar
上圖紅框則是我們需要的文件
用Jd-gui查看java代碼
然后將其直接拖入jd-gui即可看到j(luò)ava代碼
CM代碼很少,很容易看到入口函數(shù)MainActivity里的代碼
這段java代碼里面沒有任何關(guān)鍵的代碼
有一點(diǎn)點(diǎn)安卓基礎(chǔ)就看的出來,APK引用了一個(gè)叫l(wèi)ibcrack_j2c的so文件,所以可以判斷關(guān)鍵代碼全在so里面
所以直接上IDA分析so文件找到checkFlag或者OnClick這個(gè)函數(shù)。
IDA查看so文件
定位到關(guān)鍵函數(shù)代碼 - 方法 1.字符串大法好
直接找到
驗(yàn)證錯(cuò)誤,繼續(xù)加油
一步到位,香的不行
我的IDA版本暫時(shí)搜不了字符串,后面補(bǔ)上。。
定位到關(guān)鍵函數(shù)代碼 - 方法 2.直接搜方法名
上面說到了 作者已經(jīng)明確的告訴了checkFlag和onclick了這函數(shù)了。。明擺著就是關(guān)鍵函數(shù)。
所以在so文件沒被混淆的情況下,可以直接用IDA打開So文件,搜索方法 checkFlag 或者 onclick
IDA中直接拖入so載入后,在Functions Window 按ctrl+f直接搜方法名一步到位
不過這里是不推薦用這個(gè)方法的。。因?yàn)榫退鉙o文件沒被混淆
正常項(xiàng)目代碼量巨大。。根本不知道誰是誰。。。不容易直接一眼就看出來的情況下
這個(gè)方法無疑大海撈針,所以下面介紹另一種方法
定位到關(guān)鍵函數(shù)代碼 - 方法 3.Xposed框架Hook打印堆棧
這里就需要用到Xposed框架來Hook了,還不會請先看上方基礎(chǔ)教程
這里直接貼上一段代碼 -?《利用Xposed Hook打印Java函數(shù)調(diào)用堆棧信息的幾種方法》
具體思路是:既然按了驗(yàn)證按鈕后有土司 提示長度不夠,那我直接Hook Toast()這個(gè)方法 看看什么調(diào)用了他,不就可以找到點(diǎn)擊事件了?雖然對這題有點(diǎn)脫了褲子放屁。。。不過這也是一種思路吧
自己修改對應(yīng)包名后變成如下
findAndHookMethod("android.widget.Toast",? ? //要hook的包名+類名? ?? ?? ?? ?? ? lpparam.classLoader,? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//classLoader固定"makeText",? ?? ?? ?? ?? ?? ?? ?? ?//要hook的方法名// 方法參數(shù) 沒有就不填
? ?? ?? ?? ?? ? Context.class,
? ?? ?? ?? ?? ? CharSequence.class,int.class,new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//方法執(zhí)行前執(zhí)行
? ?? ?? ?? ?? ?? ?? ?? ?Log.i("Nut", "NutHookToast:" + param.args[1].toString());
? ?? ?? ?? ?? ?? ???}protected void afterHookedMethod(MethodHookParam param) throws Throwable {//方法執(zhí)行后執(zhí)行,改方法的返回值一定要在方法執(zhí)行完畢后更改// 方法一:
? ?? ?? ?? ?? ?? ?? ?? ?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后 進(jìn)去 隨便按一下 驗(yàn)證按鈕 得到日志如下
可以看出只有一個(gè)包名為 com.wuaipojie.crackme01 的方法被調(diào)用 正是onclick的按鈕事件。
然后用方法2直接IDA搜方法就可以了
簡單分析函數(shù)代碼
按鈕OnClick事件方法
這里先從按鈕事件開始
搜索onclick找到函數(shù)后,匯編代碼是看不懂的。。。所以直接按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) )? ?? ?? ?? ?? ?? ?? ???//【其實(shí)上面的一堆就是獲取了你輸入的flag的長度】goto LABEL_39;if ( v13 == 30 )? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //這里判斷 v13 是否為 30??也就是判斷flag長度是否為30? ?
??{//如果長度正確 則進(jìn)入下面 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;
}
上面代碼已經(jīng)備注了
可以看到flag 長度要為 30 【欸! 這不是廢話嗎,已經(jīng)提示了好不】
就會把flag傳入 checkflag這個(gè)方法進(jìn)行判斷
所以接下來是 checkflag 這個(gè)方法
checkflag方法
和上面同樣的方法 找到這個(gè)方法后F5一下 直接看偽代碼
這一段代碼就算是F5的偽代碼 算法部分我不是很看得懂。。連蒙帶猜的做的吧。。
坐等大佬們更詳細(xì)的分析過程噢,這里說一下我的思路。
因?yàn)榭床欢唧w代碼了,所以我考慮從Hook函數(shù)中所調(diào)用的方法入手
看了幾遍后 發(fā)現(xiàn)函數(shù)最下方的 代碼部分最可疑
可以看到 一次調(diào)用了 ToString substring equals方法
之前在看到flag是30位的時(shí)候我就一直在猜想,似乎沒有什么加密是30位的啊?? 所以估計(jì)是密鑰加密后進(jìn)行了切割。
這三個(gè)函數(shù)應(yīng)該就認(rèn)證了我的猜想。
上面的一堆函數(shù)估計(jì)是對密鑰進(jìn)行加密toString 之后 馬上用 SubString 進(jìn)行切割最后用equals方法比較。。。
所以我決定把這三個(gè)函數(shù)全部Hook打印結(jié)果
以上只是猜想,有理解錯(cuò)誤的地方請多指正
見證奇跡的Hook
最后Hook的結(jié)果證實(shí) 對 SubString 的 Hook 確實(shí)有用 [劇透]
所以下面只上對 substring 這個(gè)方法Hook 的 函數(shù)
? ?? ?? ?? ?? ? lpparam.classLoader,? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//classLoader固定"substring",? ?? ?? ?? ?? ?? ?? ?? ?//要hook的方法名// 方法參數(shù) 沒有就不填int.class,int.class,new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//方法執(zhí)行前執(zhí)行
? ?? ?? ?? ?? ?? ?? ???Log.i("Nut", "substringA 參數(shù)A:" + param.args[0]+"參數(shù)B:"+param.args[1]);
? ?? ?? ?? ?? ?? ???}protected void afterHookedMethod(MethodHookParam param) throws Throwable {//方法執(zhí)行后執(zhí)行,改方法的返回值一定要在方法執(zhí)行完畢后更改
? ?? ?? ?? ?? ?? ?? ???Log.i("Nut", "substringA:" + param.getResult());
? ?? ?? ?? ?? ?? ???}
? ?? ?? ?? ?? ? }
? ?? ???);//因?yàn)閟ubstring有兩種重載 所以我無腦一起hook了。。
? ?? ???findAndHookMethod("java.lang.StringBuilder",? ? //要hook的包名+類名
? ?? ?? ?? ?? ? lpparam.classLoader,? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//classLoader固定"substring",? ?? ?? ?? ?? ?? ?? ?? ?//要hook的方法名// 方法參數(shù) 沒有就不填int.class,new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//方法執(zhí)行前執(zhí)行
? ?? ?? ?? ?? ?? ?? ?? ?Log.i("Nut", "substringB 參數(shù)A:" + param.args[0]);
? ?? ?? ?? ?? ?? ???}protected void afterHookedMethod(MethodHookParam param) throws Throwable {//方法執(zhí)行后執(zhí)行,改方法的返回值一定要在方法執(zhí)行完畢后更改
? ?? ?? ?? ?? ?? ?? ?? ?Log.i("Nut", "substringB:" + param.getResult());
? ?? ?? ?? ?? ?? ???}
? ?? ?? ?? ?? ? }
? ?? ???);
隨便輸一個(gè)30位的flag之后??驗(yàn)證??當(dāng)當(dāng)當(dāng)當(dāng) 出來了
Log如下
02-09 04:00:34.060: I/Nut(2098): Already Find Methed02-09 04:00:34.062: I/Nut(2098): substringA 參數(shù)A:1參數(shù)B:3102-09 04:00:34.062: I/Nut(2098): substringA:ed61f6308c74bcf35c71729d4db24c02-09 04:00:34.062: I/Nut(2098): NutHookToast:驗(yàn)證錯(cuò)誤,繼續(xù)加油可以看到確實(shí)是32位的加密 截取了 中間的 1-31位
結(jié)果也直接就打印出來了!!最后的equals也就是做了一個(gè)字符串比較而已。
本題也就此解開! 完結(jié) 撒花~
總結(jié)
星球杯大佬說過 : Xposed用的好就是可以為所欲為!
想想自己不知道還要隔多久才能到達(dá)這種高度,不禁有些小傷感 QAQ
本題也還有很多沒弄懂的地方,期待大佬們出更詳細(xì)的教程!
期待大佬們第四題的詳細(xì)分析噢!希望能學(xué)習(xí)一下!
謝謝大佬們閱讀 , 如有錯(cuò)誤的地方請幫忙指正,以免誤人子弟!謝謝
--官方論壇
www.52pojie.cn
--推薦給朋友
公眾微信號:吾愛破解論壇
或搜微信號:pojie_52
總結(jié)
以上是生活随笔為你收集整理的xposed 修改参数_【Android 原创】2020春节红包第三题Xposed框架Hook的应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 发债企业是什么意思
- 下一篇: 公积金第二次提取规则