frida復現某app算法
VSole2023-01-11 10:44:51
獲取數據
某app的登錄界面抓包,發現參數都加密了

查驗一下殼,未加殼,可以進行反編譯

使用jadx進行反編譯,嘗試搜索一下參數名”Encrypt”,發現兩個JsonRequest類的方法存在

運用frida及其下面的代碼在java層進行hook,發現只調用了addRequestMap方法
Java.perform(function (){
console.log("hook demo")
var jsonRequest = Java.use("com.online.http.JsonRequest");
jsonRequest.addRequestMap .overload('java.util.Map', 'int').implementation = function (addMap,a){
console.log("jsonRequest.addRequestMap is called");
this.addRequestMap(addMap,a);
}
jsonRequest.paraMap.implementation = function (addMap){
console.log("jsonRequest.paraMap is called");
this.paraMap(addMap);
}
});

跟進addRequestMap方法,了解其使用des加密,hook該方法可獲取明文及加密結果

hook代碼
Java.perform(function () {
var requestUtil = Java.use("com.online.http.RequestUtil");
requestUtil.encodeDesMap.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function (code,desKey,desIV){
console.log("requestUtil.encodeDesMap is called")
console.log("code:",code,"desKey:",desKey,"desIv:",desIV)
var encodeDesMap = this.encodeDesMap(code,desKey,desIV);
console.log("cncodeDesMap:",encodeDesMap);
return encodeDesMap;
}
});

保存一下獲得的數據
code: {"equtype":"ANDROID","loginImei":"Android353627076818049","sign":"659E9DABB1D2F8B5DB14B40E99E87FAB","timeStamp":"1671622897913","userPwd":"123456","username":"13000000000"} desKey: 65102933 desIv: 32028092
cncodeDesMap: NIszaqFPos1vd0pFqKlB42Np5itPxaNH//FDsRnlBfgL4lcVxjXii8evWfX6JfTMfsYOA4+U92V8
mjn/SBdwCqLUJu44fM3zNeGVKZD6MFQWLguggVL6k55XB7aoJ+ZRBAgKzq5Q69AeVzzkrW7ljbx9
O24XBjMdNIKIWHkE5JL5MnS1ph86fs18lEqa3ilNtvTZFOVz8DX72SSPgVVHRnOavHemZ5807s9P
wmTqWlw=
明文中存在desKey和desIv,跟進代碼,可以看到這兩值是固定的


數據中還有sign值不知道怎么來的
code數據都為paraMap方法中得來

跟進該方法,md5加密前對數據進行了處理,hook該Utils.md5的方法的傳參即可了解加密得到sign值的明文

hook代碼
Java.perform(function () {
var requestUtil = Java.use("com.online.http.RequestUtil");
requestUtil.encodeDesMap.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function (code,desKey,desIV){
console.log("requestUtil.encodeDesMap is called")
console.log("code:",code,"desKey:",desKey,"desIv:",desIV)
var encodeDesMap = this.encodeDesMap(code,desKey,desIV);
console.log("cncodeDesMap:",encodeDesMap);
return encodeDesMap;
}
});

保存一下獲得的數據
string: equtype=ANDROID&loginImei=Android353627076818049&timeStamp=1671624199001&userPwd=123456&username=13000000000&key=sdlkjsdljf0j2fsjk sign: d13d25dc2dc064491b748d5c97430398
有一個key值

跟進發現為固定值

以上就獲取了所有需要的信息,可以嘗試進行加密算法復現了
sign明文:
string:equtype=ANDROID&loginImei=Android353627076818049&timeStamp=1671624199001&userPwd=123456&username=13000000000&key=sdlkjsdljf0j2fsjk
sign: d13d25dc2dc064491b748d5c97430398
加密算法:md5
des明文:
code: {"equtype":"ANDROID","loginImei":"Android353627076818049","sign":"659E9DABB1D2F8B5DB14B40E99E87FAB","timeStamp":"1671622897913","userPwd":"123456","username":"13000000000"} desKey: 65102933 desIv: 32028092
加密算法:des
還需要了解des算法的工作模式和填充方式

跟進encodeDesMap方法

跟進DesSecurity類的實例化,了解到工作模式為CBC,填充方式為PKCS5Padding

至此,所有需要的信息都收集完畢了
算法復現
借助CryptJS獲取sign的值
function getSign(user, pass, time) {
var plaintext = "equtype=ANDROID&loginImei=Android353627076818049&timeStamp=" + time + "&userPwd=" + pass + "&username=" + user + "&key=sdlkjsdljf0j2fsjk";
return CryptoJS.MD5(CryptoJS.enc.Utf8.parse(plaintext)).toString();
}
console.log(getSign("13000000000","123456","1671624199001"))

重新加密,由于填充方式為PKCS5Padding,每次填充的值不一樣,每次加密整體結果不同,但未填充部分加密結果一樣
function encrypt(user, pass, time) {
var sign = getSign(user,pass,time);
var plaintext = '{"equtype":"ANDROID","loginImei":"Android353627076818049","sign":"' + sign + '","timeStamp":"' + time + '","userPwd":"' + pass + '","username":"' + user + '"}';
var key = CryptoJS.enc.Hex.parse(CryptoJS.MD5("65102933").toString());
var iv = CryptoJS.enc.Utf8.parse("32028092");
var result = CryptoJS.DES.encrypt(plaintext, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString();
return result;
}
console.log(encrypt("13000000000","123456","1671622897913"))

VSole
網絡安全專家