免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
内容参考于:图灵Python学院
本人写的内容纯属胡编乱造,全都是合成造假,仅仅只是为了娱乐,请不要盲目相信。
工具下载:
链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd=6tw3
提取码:6tw3
复制这段内容后打开百度网盘手机App,操作更方便哦
上一个内容:19.安卓逆向-frida基础-hook分析调试技巧1-hookMD5
上一个内容里使用Frida hook了MD5算法并尝试了对一个app进行使用MD5hook找参数,本次接着继续
本次hook DES算法
下图是DES两种标准实现
package com.example.course1.suanfa; import android.util.Base64; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.IvParameterSpec; public class AES { public static String des_1(String args) throws Exception{ /** * SecretKeyFactory.getInstance("DES") 获取一个DES * generateSecret初始化DES的加密钥匙,专业术语叫做KEY * 一个des算法需要获取的就死key、iv、明文,有了这些之后就可以对参数模拟加密了 */ SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec("123456789".getBytes())); /** * new IvParameterSpec("87654321".getBytes()); IV * */ AlgorithmParameterSpec iv = new IvParameterSpec("87654321".getBytes()); /** * Cipher.getInstance("DES/CBC/PKCS5Padding"); 加密模式 */ Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); /** * cipher.init(1, secretKey, iv); 初始化,1表示加密 * */ cipher.init(1, secretKey, iv); /** * cipher.update(args.getBytes()); 把明文放到缓存区准备加密 */ cipher.update(args.getBytes()); /** * cipher.doFinal() 加密 */ return Base64.encodeToString(cipher.doFinal(), 0); } public static String des_2(String args) throws Exception{ SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec("123456789".getBytes())); AlgorithmParameterSpec iv = new IvParameterSpec("87654321".getBytes()); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); cipher.init(1, secretKey, iv); return Base64.encodeToString(cipher.doFinal(args.getBytes()), 0); } }
Frida hook脚本
function bytesToHex(arr) { var str = ""; for (var i = 0; i < arr.length; i++) { var tmp = arr[i]; if (tmp < 0) { tmp = (255 + tmp + 1).toString(16); } else { tmp = tmp.toString(16); } if (tmp.length == 1) { tmp = "0" + tmp; } str += tmp; } return str; } function bytesToBase64(e) { var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; var r, a, c, h, o, t; for (c = e.length, a = 0, r = ''; a < c;) { if (h = 255 & e[a++], a == c) { r += base64EncodeChars.charAt(h >> 2), r += base64EncodeChars.charAt((3 & h) << 4), r += '=='; break } if (o = e[a++], a == c) { r += base64EncodeChars.charAt(h >> 2), r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4), r += base64EncodeChars.charAt((15 & o) << 2), r += '='; break } t = e[a++], r += base64EncodeChars.charAt(h >> 2), r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4), r += base64EncodeChars.charAt((15 & o) << 2 | (192 & t) >> 6), r += base64EncodeChars.charAt(63 & t) } return r } function bytesToString(arr) { if (typeof arr === 'string') { return arr; } var str = '', _arr = arr; for (var i = 0; i < _arr.length; i++) { var one = _arr[i].toString(2), v = one.match(/^1+?(?=0)/); if (v && one.length == 8) { var bytesLength = v[0].length; var store = _arr[i].toString(2).slice(7 - bytesLength); for (var st = 1; st < bytesLength; st++) { store += _arr[st + i].toString(2).slice(2); } str += String.fromCharCode(parseInt(store, 2)); i += bytesLength - 1; } else { str += String.fromCharCode(_arr[i]); } } return str; } function main() { Java.perform(function () { var SecretKeyFactory = Java.use("javax.crypto.SecretKeyFactory") SecretKeyFactory.getInstance.overload('java.lang.String').implementation = function(str) { console.log(`算法是----》${str}《------------------------------------------------------------》`) return this.getInstance(str) } // 获取 key var DESKeySpec = Java.use("javax.crypto.spec.DESKeySpec") DESKeySpec.$init.overload('[B').implementation = function(str) { console.log(`DESKeySpec.$init.overload--》DES的Key bytesToString:${bytesToString(str)}`) console.log(`DESKeySpec.$init.overload--》DES的key bytesToHexKey:${bytesToHex(str)}`) return this.$init(str) } // 获取 iv var IvParameterSpec = Java.use("javax.crypto.spec.IvParameterSpec") IvParameterSpec.$init.overload("[B").implementation = function(str) { console.log(`DES IV bytesToString:${bytesToString(str)}`) console.log(`DES IV bytesToHex:${bytesToHex(str)}`) return this.$init(str) } var Cipher = Java.use("javax.crypto.Cipher") Cipher.getInstance.overload('java.lang.String').implementation = function(str) { console.log(`Cipher 加密模式 Cipher.getInstance.overload('java.lang.String'):${str}`) return this.getInstance(str) } Cipher.getInstance.overload('java.lang.String', 'java.lang.String').implementation = function(str1,str2) { console.log(`Cipher 加密模式 Cipher.getInstance.overload('java.lang.String', 'java.lang.String') :${str1} || ${str2}`) return this.getInstance(str1, str2) } Cipher.update.overload('[B').implementation = function(str) { console.log(`DES 明文 Cipher.update.overload('[B') bytesToString:${bytesToString(str)}`) return this.update(str) } Cipher.update.overload('[B', 'int', 'int').implementation = function(str,i1, i2) { console.log(`DES 明文 Cipher.update.overload('[B', 'int', 'int') :${bytesToString(str)} 入参2:${i1} 入参3:${i2}`) return this.update(str, i1, i2) } Cipher.doFinal.overload('[B').implementation = function(str) { console.log(`des密文入参 Cipher.doFinal.overload('[B') bytesToString:${bytesToString(str)}`) console.log(`des密文入参 Cipher.doFinal.overload('[B') bytesToHex:${bytesToHex(str)}`) var m = this.doFinal(str) console.log(`des密文返回值 Cipher.doFinal.overload('[B') bytesToHex:${bytesToHex(m)}`) console.log(`des密文返回值 Cipher.doFinal.overload('[B') bytesToBase64:${bytesToBase64(m)}`) return m } Cipher.doFinal.overload().implementation = function() { var m = this.doFinal() console.log(`des密文返回值 Cipher.doFinal.overload() bytesToHex:${bytesToHex(m)}`) console.log(`des密文返回值 Cipher.doFinal.overload() bytesToBase64:${bytesToBase64(m)}`) return m } }) } main()
效果图:加密的key
然后是iv,如下图iv的构造方法有两个,如果为了全面可以把两个都给使用Frida hook了(其它的方法也是一样为了全面可以把所有相同名的方法全部hook)
iv效果图,下图的Frida hook脚本里把iv的入参从字节转成了字符串,有的app这个字节的内容它是十六进制数(也就是传过来的也是被加密之后的信息)
获取加密之后的数据
使用DES在线加密网站测试,可以正常根据hook到的key、iv、明文加密成正确的密文