99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁精彩閱讀原生安卓開發(fā)app的框架frida常用關(guān)鍵代碼定位
原生安卓開發(fā)app的框架frida常用關(guān)鍵代碼定位
2022-07-04
收藏

作者:Python進(jìn)階者

來源:Python爬蟲與數(shù)據(jù)挖掘

前言

有時候可能會對APP進(jìn)行字符串加密等操作,這樣的話你的變量名等一些都被混淆了,看代碼就可能無從下手

不管沒關(guān)系,像系統(tǒng)級別的東西,Toast了等函數(shù),是不能混淆的,所以可以根據(jù)蛛絲馬跡,終究找到破解的點

frida常用命令

frida -U 連接USB設(shè)備
    -F 附加到最前面的app
    -l 注入的js
 -o 輸出到文件
 -f 重新啟動
 --no-pause 立馬執(zhí)行,中間不停頓

打印堆棧

打印堆棧的本質(zhì)就是拋異常,他的結(jié)果是從下往上看的!

代碼

function printStacks() { console.log(
        Java.use("android.util.Log")
        .getStackTraceString(
            Java.use("java.lang.Throwable").$new()
        )
    );
}

執(zhí)行結(jié)果

原生安卓開發(fā)app的框架frida常用關(guān)鍵代碼定位

常用hook函數(shù)代碼

hook HashMap的put方法

hashMap,,那就很常用了,懂的都懂,但是一定要做好篩選,要不然app容易崩潰!

var hashMap = Java.use("java.util.HashMap");
hashMap.put.implementation = function (a, b) { //a=="username"和a.equals("username")一般都可以 //如果不行換一下即可 if (a=="username") { console.log("hashMap.put: ", a, b);
        printStacks();
 } return this.put(a, b);
}

hook ArrayList的add方法

Array似乎也很常用

var arrayList = Java.use("java.util.ArrayList");
arrayList.add.overload('java.lang.Object').implementation = function (a) { if (a == "username=18903916120") { console.log("arrayList.add: ", a);
        printStacks();  
    } //console.log("arrayList.add: ", a); return this.add(a);
}
arrayList.add.overload('int', 'java.lang.Object').implementation = function (a, b) { console.log("arrayList.add: ", a, b); return this.add(a, b);
}

hook TextUtils的isEmpty方法

這個方法通常是安卓判斷輸入框是否為空必經(jīng)的方法!

var textUtils = Java.use("android.text.TextUtils");
textUtils.isEmpty.implementation = function (a) { if (a == "TURJNk1EQTZNREE2TURBNk1EQTZNREE9") { console.log("textUtils.isEmpty: ", a);
        printStacks();

    } //console.log("textUtils.isEmpty: ", a); return this.isEmpty(a);
}

hook String的trim方法

這個方法似乎也挺多,去掉開頭和結(jié)尾的空格,防止臟數(shù)據(jù)

var str = Java.use("java.lang.String");
str.trim.implementation = function () { console.log("str.trim: ", this);
    printStacks(); return this.trim();
}

hook log的w方法

var log = Java.use("android.util.Log");
    log.w.overload('java.lang.String', 'java.lang.String').implementation = function (tag, message) { console.log("log.w: ", tag, message);
        printStacks(); return this.w(tag, message);
    }

hook EditText的getText方法

這個應(yīng)該就多了,但是這個一般在加密的上層,可以考慮使用。

var editText = Java.use("android.widget.EditText");
editText.getText.overload().implementation = function () { var result = this.getText();
    result = Java.cast(result, Java.use("java.lang.CharSequence")); console.log("editText.getText: ", result.toString());
    printStacks(); return result;
}

hook Collections的sort方法

排序方法,頻率還湊合

var collections = Java.use("java.util.Collections");
collections.sort.overload('java.util.List').implementation = function (a) {
    var result = Java.cast(a, Java.use("java.util.ArrayList"));
    console.log("collections.sort List: ", result.toString());
    printStacks(); return this.sort(a);
}
collections.sort.overload('java.util.List', 'java.util.Comparator').implementation = function (a, b) {
    var result = Java.cast(a, Java.use("java.util.ArrayList"));
    console.log("collections.sort List Comparator: ", result.toString());
    printStacks(); return this.sort(a, b);
}
// .overload('java.lang.String', 'double')
// .overload('java.lang.String', 'int')
// .overload('java.lang.String', 'long')
// .overload('java.lang.String', 'boolean')

hook jSONObject的put方法

一般在轉(zhuǎn)成json時用的聽過的,可以考慮

var jSONObject = Java.use("org.json.JSONObject");
jSONObject.put.overload('java.lang.String', 'java.lang.Object').implementation = function (a, b) { //var result = Java.cast(a, Java.use("java.util.ArrayList")); console.log("jSONObject.put: ", a, b);
    printStacks(); return this.put(a, b);
}
jSONObject.getString.implementation = function (a) { //var result = Java.cast(a, Java.use("java.util.ArrayList")); console.log("jSONObject.getString: ", a); var result = this.getString(a); console.log("jSONObject.getString result: ", result);
    printStacks(); return result;
}

hook Toast的show方法

這個就很多了,基本上每個app都有,但是hook這個位置又偏加密下層,因為肯定是處理完才彈窗

但是可以考慮不輸入賬號密碼直接提交,這樣位置大概在加密的上層,可以順著往下走

var toast = Java.use("android.widget.Toast");
toast.show.implementation = function () { console.log("toast.show: ");
    printStacks(); return this.show();
}

hook Base64的encodeToString方法

base64就很多了吧,除了消息摘要算法其他最后的形式都是base64格式,很有必要。

var base64 = Java.use("android.util.Base64");
base64.encodeToString.overload('[B', 'int').implementation = function (a, b) { console.log("base64.encodeToString: ", JSON.stringify(a)); var result = this.encodeToString(a, b); console.log("base64.encodeToString result: ", result)
    printStacks(); return result;
}

hook String的getBytes方法

var str = Java.use("java.lang.String");
str.getBytes.overload().implementation = function () { var result = this.getBytes(); var newStr = str.$new(result); console.log("str.getBytes result: ", newStr);
    printStacks(); return result;
}
str.getBytes.overload('java.lang.String').implementation = function (a) { var result = this.getBytes(a); var newStr = str.$new(result, a); console.log("str.getBytes result: ", newStr);
    printStacks(); return result;
}

findViewById找控件方法

這種方式hook代碼,需要frida幫助我們啟動app。

所以本次啟動的命令為

frida -U -f com.dodonew.online -l g_關(guān)鍵代碼快速定位.js -o 1.txt --no-pause 

因為可能一開始就綁定了很多控件,所以一開始就要開始hook。

如何找控件id

控件id可以通過<SDK目錄>toolsbin下的uiautomatorviewer.bat來進(jìn)行查看

原生安卓開發(fā)app的框架frida常用關(guān)鍵代碼定位

查看登錄按鈕id

原生安卓開發(fā)app的框架frida常用關(guān)鍵代碼定位

所以這個登錄按鈕的id就是btn_login

代碼

// 找id var btn_login_id = Java.use("com.dodonew.online.R$id").btn_login.value; console.log("btn_login_id:", btn_login_id); var view = Java.use("android.view.View");
view.setOnClickListener.implementation = function (a) { if(this.getId() == btn_login_id){ console.log("view.id: " + this.getId()); console.log("view.setOnClickListener is called");
         printStacks();
     } return this.setOnClickListener(a);
}

簡單用法

在嘟嘟牛這個app中,最后使用的是DES算法,并且base64結(jié)果展示加密的內(nèi)容。

原生安卓開發(fā)app的框架frida常用關(guān)鍵代碼定位

所以就hook一下base64試試

代碼

Java.perform(function () { //打印堆棧 function printStacks() { console.log(
            Java.use("android.util.Log")
                .getStackTraceString(
                    Java.use("java.lang.Throwable").$new()
                )
        );
    } //base64 var base64 = Java.use("android.util.Base64");
    base64.encodeToString.overload('[B', 'int').implementation = function (a, b) { console.log("base64.encodeToString: ", JSON.stringify(a)); var result = this.encodeToString(a, b); console.log("base64.encodeToString result: ", result)
        printStacks(); return result;
    }
})

hook結(jié)果

原生安卓開發(fā)app的框架frida常用關(guān)鍵代碼定位

所以如果說,你如果看結(jié)果像是base或者md5或者h(yuǎn)ex等,直接就使用這些常用的hook代碼試一下,并且拋出堆棧。

就可以很好分析代碼了。

總結(jié)

雖然寫的是關(guān)鍵代碼定位,其實只不過是常用的代碼罷了,上面這些使用在逆向app時總結(jié)的hook代碼。

當(dāng)然,實際肯定不止這么少,根據(jù)需求來,經(jīng)驗越多,輪子就越多。

數(shù)據(jù)分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進(jìn)行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個參數(shù)驗證碼對象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺檢測極驗服務(wù)器是否宕機 new_captcha: data.new_captcha, // 用于宕機時表示是新驗證碼的宕機 product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說明請參見:http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計時完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }