获取数据
某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"))