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

創(chuàng)新互聯(lián)專注于泉山企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計(jì),商城建設(shè)。泉山網(wǎng)站建設(shè)公司,為泉山等地區(qū)提供建站服務(wù)。全流程定制設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
不管沒關(guān)系,像系統(tǒng)級(jí)別的東西,Toast了等函數(shù),是不能混淆的,所以可以根據(jù)蛛絲馬跡,終究找到破解的點(diǎn)。
frida常用命令
frida
-U 連接USB設(shè)備
-F 附加到最前面的app
-l 注入的js
-o 輸出到文件
-f 重新啟動(dòng)
--no-pause 立馬執(zhí)行,中間不停頓
打印堆棧
打印堆棧的本質(zhì)就是拋異常,他的結(jié)果是從下往上看的!
代碼
function printStacks() {
console.log(
Java.use("android.util.Log")
.getStackTraceString(
Java.use("java.lang.Throwable").$new()
)
);
}執(zhí)行結(jié)果
常用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方法
這個(gè)方法通常是安卓判斷輸入框是否為空必經(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方法
這個(gè)方法似乎也挺多,去掉開頭和結(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方法
這個(gè)應(yīng)該就多了,但是這個(gè)一般在加密的上層,可以考慮使用。
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時(shí)用的聽過的,可以考慮;
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方法
這個(gè)就很多了,基本上每個(gè)app都有,但是hook這個(gè)位置又偏加密下層,因?yàn)榭隙ㄊ翘幚硗瓴艔棿埃?/p>
但是可以考慮不輸入賬號(hào)密碼直接提交,這樣位置大概在加密的上層,可以順著往下走;
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幫助我們啟動(dòng)app。
所以本次啟動(dòng)的命令為;
frida -U -f com.dodonew.online -l g_關(guān)鍵代碼快速定位.js -o 1.txt --no-pause
因?yàn)榭赡芤婚_始就綁定了很多控件,所以一開始就要開始hook。
如何找控件id
控件id可以通過
查看登錄按鈕id
所以這個(gè)登錄按鈕的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);
}
簡單用法
在嘟嘟牛這個(gè)app中,最后使用的是DES算法,并且base64結(jié)果展示加密的內(nèi)容。
所以就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é)果
所以如果說,你如果看結(jié)果像是base或者md5或者h(yuǎn)ex等,直接就使用這些常用的hook代碼試一下,并且拋出堆棧。
就可以很好分析代碼了。
總結(jié)
雖然寫的是關(guān)鍵代碼定位,其實(shí)只不過是常用的代碼罷了,上面這些使用在逆向app時(shí)總結(jié)的hook代碼。
當(dāng)然,實(shí)際肯定不止這么少,根據(jù)需求來,經(jīng)驗(yàn)越多,輪子就越多。
人生沒有白走的路,加油!
分享題目:原生安卓開發(fā)App的框架Frida常用關(guān)鍵代碼定位
轉(zhuǎn)載注明:http://www.dlmjj.cn/article/dhhhoie.html


咨詢
建站咨詢
