frida自吐算法
使用方法:
frida -U -l tu.js -f com.xxxxxx --no-pause
代码:
var N_ENCRYPT_MODE = 1 var N_DECRYPT_MODE = 2 function showStacks() { var Exception = Java.use("java.lang.Exception"); var ins = Exception.$new("Exception"); var straces = ins.getStackTrace(); if (undefined == straces || null == straces) { return; } console.log("============================= Stack strat======================="); console.log(""); for (var i = 0; i < straces.length; i++) { var str = " " + straces[i].toString(); console.log(str); } console.log(""); console.log("============================= Stack end=======================\r\n"); Exception.$dispose(); } //工具相关函数 var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', base64DecodeChars = new Array((-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), 62, (-1), (-1), (-1), 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, (-1), (-1), (-1), (-1), (-1), (-1), (-1), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, (-1), (-1), (-1), (-1), (-1), (-1), 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, (-1), (-1), (-1), (-1), (-1)); function stringToBase64(e) { var r, a, c, h, o, t; for (c = e.length, a = 0, r = ''; a < c;) { if (h = 255 & e.charCodeAt(a++), a == c) { r += base64EncodeChars.charAt(h >> 2), r += base64EncodeChars.charAt((3 & h) << 4), r += '=='; break } if (o = e.charCodeAt(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.charCodeAt(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 base64ToString(e) { var r, a, c, h, o, t, d; for (t = e.length, o = 0, d = ''; o < t;) { do r = base64DecodeChars[255 & e.charCodeAt(o++)]; while (o < t && r == -1); if (r == -1) break; do a = base64DecodeChars[255 & e.charCodeAt(o++)]; while (o < t && a == -1); if (a == -1) break; d += String.fromCharCode(r << 2 | (48 & a) >> 4); do { if (c = 255 & e.charCodeAt(o++), 61 == c) return d; c = base64DecodeChars[c] } while (o < t && c == -1); if (c == -1) break; d += String.fromCharCode((15 & a) << 4 | (60 & c) >> 2); do { if (h = 255 & e.charCodeAt(o++), 61 == h) return d; h = base64DecodeChars[h] } while (o < t && h == -1); if (h == -1) break; d += String.fromCharCode((3 & c) << 6 | h) } return d } function hexToBase64(str) { return base64Encode(String.fromCharCode.apply(null, str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))); } function base64ToHex(str) { for (var i = 0, bin = base64Decode(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) { var tmp = bin.charCodeAt(i).toString(16); if (tmp.length === 1) tmp = "0" + tmp; hex[hex.length] = tmp; } return hex.join(""); } function hexToBytes(str) { var pos = 0; var len = str.length; if (len % 2 != 0) { return null; } len /= 2; var hexA = new Array(); for (var i = 0; i < len; i++) { var s = str.substr(pos, 2); var v = parseInt(s, 16); hexA.push(v); pos += 2; } return hexA; } function bytesToHex(arr) { var str = ''; var k, j; for (var i = 0; i < arr.length; i++) { k = arr[i]; j = k; if (k < 0) { j = k + 256; } if (j < 16) { str += "0"; } str += j.toString(16); } return str; } function stringToHex(str) { var val = ""; for (var i = 0; i < str.length; i++) { if (val == "") val = str.charCodeAt(i).toString(16); else val += str.charCodeAt(i).toString(16); } return val } function stringToBytes(str) { var ch, st, re = []; for (var i = 0; i < str.length; i++) { ch = str.charCodeAt(i); st = []; do { st.push(ch & 0xFF); ch = ch >> 8; } while (ch); re = re.concat(st.reverse()); } return re; } //将byte[]转成String的方法 function bytesToString(arr) { var str = ''; arr = new Uint8Array(arr); for (var i in arr) { str += String.fromCharCode(arr[i]); } return str; } function bytesToBase64(e) { 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 base64ToBytes(e) { var r, a, c, h, o, t, d; for (t = e.length, o = 0, d = []; o < t;) { do r = base64DecodeChars[255 & e.charCodeAt(o++)]; while (o < t && r == -1); if (r == -1) break; do a = base64DecodeChars[255 & e.charCodeAt(o++)]; while (o < t && a == -1); if (a == -1) break; d.push(r << 2 | (48 & a) >> 4); do { if (c = 255 & e.charCodeAt(o++), 61 == c) return d; c = base64DecodeChars[c] } while (o < t && c == -1); if (c == -1) break; d.push((15 & a) << 4 | (60 & c) >> 2); do { if (h = 255 & e.charCodeAt(o++), 61 == h) return d; h = base64DecodeChars[h] } while (o < t && h == -1); if (h == -1) break; d.push((3 & c) << 6 | h) } return d } //stringToBase64 stringToHex stringToBytes //base64ToString base64ToHex base64ToBytes // hexToBase64 hexToBytes // bytesToBase64 bytesToHex bytesToString Java.perform(function () { var secretKeySpec = Java.use('javax.crypto.spec.SecretKeySpec'); secretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function (a, b) { showStacks(); var result = this.$init(a, b); console.log("======================================"); console.log("算法名:" + b + "|str密钥:" + bytesToString(a)); console.log("算法名:" + b + "|Hex密钥:" + bytesToHex(a)); return result; } var DESKeySpec = Java.use('javax.crypto.spec.DESKeySpec'); DESKeySpec.$init.overload('[B').implementation = function (a) { showStacks(); var result = this.$init(a); console.log("======================================"); var bytes_key_des = this.getKey(); console.log("des密钥 |str " + bytesToString(bytes_key_des)); console.log("des密钥 |hex " + bytesToHex(bytes_key_des)); return result; } DESKeySpec.$init.overload('[B', 'int').implementation = function (a, b) { showStacks(); var result = this.$init(a, b); console.log("======================================"); var bytes_key_des = this.getKey(); console.log("des密钥 |str " + bytesToString(bytes_key_des)); console.log("des密钥 |hex " + bytesToHex(bytes_key_des)); return result; } var mac = Java.use('javax.crypto.Mac'); mac.getInstance.overload('java.lang.String').implementation = function (a) { showStacks(); var result = this.getInstance(a); console.log("======================================"); console.log("算法名:" + a); return result; } mac.update.overload('[B').implementation = function (a) { //showStacks(); this.update(a); console.log("======================================"); console.log("update:" + bytesToString(a)) } mac.update.overload('[B', 'int', 'int').implementation = function (a, b, c) { //showStacks(); this.update(a, b, c) console.log("======================================"); console.log("update:" + bytesToString(a) + "|" + b + "|" + c); } mac.doFinal.overload().implementation = function () { //showStacks(); var result = this.doFinal(); console.log("======================================"); console.log("doFinal结果: |str :" + bytesToString(result)); console.log("doFinal结果: |hex :" + bytesToHex(result)); console.log("doFinal结果: |base64 :" + bytesToBase64(result)); return result; } mac.doFinal.overload('[B').implementation = function (a) { //showStacks(); var result = this.doFinal(a); console.log("======================================"); console.log("doFinal参数: |str :" + bytesToString(a)); console.log("doFinal参数: |hex :" + bytesToHex(a)); console.log("doFinal结果: |str :" + bytesToString(result)); console.log("doFinal结果: |hex :" + bytesToHex(result)); console.log("doFinal结果: |base64 :" + bytesToBase64(result)); return result; } var md = Java.use('java.security.MessageDigest'); md.getInstance.overload('java.lang.String', 'java.lang.String').implementation = function (a, b) { //showStacks(); console.log("======================================"); console.log("算法名:" + a); return this.getInstance(a, b); } md.getInstance.overload('java.lang.String').implementation = function (a) { //showStacks(); console.log("======================================"); console.log("算法名:" + a); return this.getInstance(a); } md.update.overload('[B').implementation = function (a) { //showStacks(); console.log("======================================"); console.log("update:" + bytesToString(a)) return this.update(a); } md.update.overload('[B', 'int', 'int').implementation = function (a, b, c) { //showStacks(); console.log("======================================"); console.log("update:" + bytesToString(a) + "|" + b + "|" + c); return this.update(a, b, c); } md.digest.overload().implementation = function () { //showStacks(); console.log("======================================"); var result = this.digest(); console.log("digest结果 |hex:" + bytesToHex(result)); console.log("digest结果 |base64:" + bytesToBase64(result)); return result; } md.digest.overload('[B').implementation = function (a) { //showStacks(); console.log("======================================"); console.log("digest参数 |str:" + bytesToString(a)); console.log("digest参数 |hex:" + bytesToHex(a)); var result = this.digest(a); console.log("digest结果: |hex" + bytesToHex(result)); console.log("digest结果: |base64" + bytesToBase64(result)); return result; } var ivParameterSpec = Java.use('javax.crypto.spec.IvParameterSpec'); ivParameterSpec.$init.overload('[B').implementation = function (a) { //showStacks(); var result = this.$init(a); console.log("======================================"); console.log("iv向量: |str:" + bytesToString(a)); console.log("iv向量: |hex:" + bytesToHex(a)); return result; } var cipher = Java.use('javax.crypto.Cipher'); cipher.getInstance.overload('java.lang.String').implementation = function (a) { //showStacks(); var result = this.getInstance(a); console.log("======================================"); console.log("模式填充:" + a); return result; } cipher.init.overload('int', 'java.security.Key').implementation = function (a, b) { //showStacks(); var result = this.init(a, b); console.log("======================================"); if (N_ENCRYPT_MODE == a) { console.log("init | 加密模式"); } else if(N_DECRYPT_MODE == a) { console.log("init | 解密模式"); } var bytes_key = b.getEncoded(); console.log("init key:" + "|str密钥:" + bytesToString(bytes_key)); console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key)); return result; } cipher.init.overload('int', 'java.security.cert.Certificate').implementation = function (a, b) { //showStacks(); var result = this.init(a, b); console.log("======================================"); if (N_ENCRYPT_MODE == a) { console.log("init | 加密模式"); } else if(N_DECRYPT_MODE == a) { console.log("init | 解密模式"); } return result; } cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec').implementation = function (a, b, c) { //showStacks(); var result = this.init(a, b, c); console.log("======================================"); if (N_ENCRYPT_MODE == a) { console.log("init | 加密模式"); } else if(N_DECRYPT_MODE == a) { console.log("init | 解密模式"); } var bytes_key = b.getEncoded(); console.log("init key:" + "|str密钥:" + bytesToString(bytes_key)); console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key)); return result; } cipher.init.overload('int', 'java.security.cert.Certificate', 'java.security.SecureRandom').implementation = function (a, b, c) { //showStacks(); var result = this.init(a, b, c); if (N_ENCRYPT_MODE == a) { console.log("init | 加密模式"); } else if(N_DECRYPT_MODE == a) { console.log("init | 解密模式"); } return result; } cipher.init.overload('int', 'java.security.Key', 'java.security.SecureRandom').implementation = function (a, b, c) { //showStacks(); var result = this.init(a, b, c); if (N_ENCRYPT_MODE == a) { console.log("init | 加密模式"); } else if(N_DECRYPT_MODE == a) { console.log("init | 解密模式"); } var bytes_key = b.getEncoded(); console.log("init key:" + "|str密钥:" + bytesToString(bytes_key)); console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key)); return result; } cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters').implementation = function (a, b, c) { //showStacks(); var result = this.init(a, b, c); if (N_ENCRYPT_MODE == a) { console.log("init | 加密模式"); } else if(N_DECRYPT_MODE == a) { console.log("init | 解密模式"); } var bytes_key = b.getEncoded(); console.log("init key:" + "|str密钥:" + bytesToString(bytes_key)); console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key)); return result; } cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters', 'java.security.SecureRandom').implementation = function (a, b, c, d) { //showStacks(); var result = this.init(a, b, c, d); if (N_ENCRYPT_MODE == a) { console.log("init | 加密模式"); } else if(N_DECRYPT_MODE == a) { console.log("init | 解密模式"); } var bytes_key = b.getEncoded(); console.log("init key:" + "|str密钥:" + bytesToString(bytes_key)); console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key)); return result; } cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec', 'java.security.SecureRandom').implementation = function (a, b, c, d) { //showStacks(); var result = this.init(a, b, c, d); if (N_ENCRYPT_MODE == a) { console.log("init | 加密模式"); } else if(N_DECRYPT_MODE == a) { console.log("init | 解密模式"); } var bytes_key = b.getEncoded(); console.log("init key:" + "|str密钥:" + bytesToString(bytes_key)); console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key)); return result; } cipher.update.overload('[B').implementation = function (a) { //showStacks(); var result = this.update(a); console.log("======================================"); console.log("update:" + bytesToString(a)); return result; } cipher.update.overload('[B', 'int', 'int').implementation = function (a, b, c) { //showStacks(); var result = this.update(a, b, c); console.log("======================================"); console.log("update:" + bytesToString(a) + "|" + b + "|" + c); return result; } cipher.doFinal.overload().implementation = function () { //showStacks(); var result = this.doFinal(); console.log("======================================"); console.log("doFinal结果: |str :" + bytesToString(result)); console.log("doFinal结果: |hex :" + bytesToHex(result)); console.log("doFinal结果: |base64 :" + bytesToBase64(result)); return result; } cipher.doFinal.overload('[B').implementation = function (a) { //showStacks(); var result = this.doFinal(a); console.log("======================================"); console.log("doFinal参数: |str :" + bytesToString(a)); console.log("doFinal参数: |hex :" + bytesToHex(a)); console.log("doFinal结果: |str :" + bytesToString(result)); console.log("doFinal结果: |hex :" + bytesToHex(result)); console.log("doFinal结果: |base64 :" + bytesToBase64(result)); return result; } var x509EncodedKeySpec = Java.use('java.security.spec.X509EncodedKeySpec'); x509EncodedKeySpec.$init.overload('[B').implementation = function (a) { //showStacks(); var result = this.$init(a); console.log("======================================"); console.log("RSA密钥:" + bytesToBase64(a)); return result; } var rSAPublicKeySpec = Java.use('java.security.spec.RSAPublicKeySpec'); rSAPublicKeySpec.$init.overload('java.math.BigInteger', 'java.math.BigInteger').implementation = function (a, b) { //showStacks(); var result = this.$init(a, b); console.log("======================================"); //console.log("RSA密钥:" + bytesToBase64(a)); console.log("RSA密钥N:" + a.toString(16)); console.log("RSA密钥E:" + b.toString(16)); return result; } var KeyPairGenerator = Java.use('java.security.KeyPairGenerator'); KeyPairGenerator.generateKeyPair.implementation = function () { //showStacks(); var result = this.generateKeyPair(); console.log("======================================"); var str_private = result.getPrivate().getEncoded(); var str_public = result.getPublic().getEncoded(); console.log("公钥 |hex" + bytesToHex(str_public)); console.log("私钥 |hex" + bytesToHex(str_private)); return result; } KeyPairGenerator.genKeyPair.implementation = function () { //showStacks(); var result = this.genKeyPair(); console.log("======================================"); var str_private = result.getPrivate().getEncoded(); var str_public = result.getPublic().getEncoded(); console.log("公钥 |hex" + bytesToHex(str_public)); console.log("私钥 |hex" + bytesToHex(str_private)); return result; } });
或者:
// frida -U com.xxx.package -l FridaAndroidSelfVomitCrypt.js // frida -U com.wepie.snake --load FridaAndroidSelfVomitCrypt.js --output frida_out.log //{ //javax.crypto.Cipher // * Constant used to initialize cipher to encryption mode. // public static final int ENCRYPT_MODE = 1; // * Constant used to initialize cipher to decryption mode. // public static final int DECRYPT_MODE = 2; // * Constant used to initialize cipher to key-wrapping mode. // public static final int WRAP_MODE = 3; // * Constant used to initialize cipher to key-unwrapping mode. // public static final int UNWRAP_MODE = 4; class javax_crypto_Cipher{ } //} class StackUtil{ } /** * @param {String} name */ function showStacks(name="") { StackUtil.print_stack(name); } // class BytesToX { /** * * @param {Boolean} _raw * @param {Boolean} _toString * @param {Boolean} _toHex * @param {Boolean} _toBase64 * @param {Boolean} _toHex */ function BytesToX(_raw=false,_toString=false,_toHex=false,_toBase64=false) { this._raw = _raw; this._toString = _toString; this._toHex = _toHex; this._toBase64 = _toBase64; } BytesToX.prototype.toString = function dogToString() { return ` BytesToX:( _raw:${this._raw} , _toString:${this._toString } , _toHex:${this._toHex } , _toBase64:${this._toBase64} ) . `; } // } const _BytesToRawStringHex=new BytesToX(/* _raw= */true,/* _toString= */true,/* _toHex= */true); const _BytesToRaw=new BytesToX(/* _raw= */true); const _BytesToString=new BytesToX(/* _toString= */true); const _BytesToStringHex=new BytesToX(/* _raw= */false,/* _toString= */true,/* _toHex= */true,/* _toBase64= */false); //TODO t // console.log(`debug____BytesToRawStringHex:${_BytesToRawStringHex.toString()}`); // console.log(`debug_____BytesToRaw:${_BytesToRaw.toString()}`); // console.log(`debug_____BytesToString:${_BytesToString.toString()}`); // console.log(`debug_____BytesToStringHex:${_BytesToStringHex.toString()}`); // class Param { /** * * @param {String} param_name * @param {ArrayBuffer} param_value * @param {BytesToX} bytesToX */ function Param(param_name,param_value,bytesToX=_BytesToStringHex) { this.param_name = param_name; this.param_value = param_value; this.bytesToX=bytesToX; // console.log(`debug_____Param_new:${param_name} ${param_value} ${bytesToX.toString()}`); } Param.prototype.toString = function dogToString() { return ` Param:( param_name:${this.param_name} , param_value:${this.param_value } , bytesToX:${this.bytesToX.toString() } ) . `; } // } /** * * @param {String} param_name * @param {ArrayBuffer} param_value */ function NewParam(param_name,param_value){ var p = new Param(param_name,param_value); // console.log(`NewParam___:${p}`); return p; } /** * * @param {String} param_name * @param {ArrayBuffer} param_value */ function NewParam_BytesToRawStringHex(param_name,param_value){ var p= new Param(param_name,param_value,_BytesToRawStringHex); // console.log(`NewParam_BytesToRawStringHex___:${p}`); return p; } /** * * @param {String} param_name * @param {ArrayBuffer} param_value */ function NewParam_BytesToRaw(param_name,param_value){ var p= new Param(param_name,param_value,_BytesToRaw); // console.log(`NewParam_BytesToRaw___:${p}`); return p; } /** * * @param {String} param_name * @param {ArrayBuffer} param_value */ function NewParam_BytesToString(param_name,param_value){ var p= new Param(param_name,param_value,_BytesToString); // console.log(`NewParam_BytesToString___:${p}`); return p; } /** * * @param {String} param_name * @param {ArrayBuffer} param_value */ function NewParam_BytesToStringHex(param_name,param_value){ var p= new Param(param_name,param_value,_BytesToStringHex); // console.log(`NewParam_BytesToStringHex___:${p}`); return p; } /** * * @param {String} clazz * @param {...Param} param_ls * @returns {String} log */ function generate_log(clazz,...param_ls){ var log_message=`clazz:${clazz};`; // console.log(`param_ls____:${param_ls.length},${typeof(param_ls)},${typeof(param_ls[0])},${param_ls[0][1].toString()} `) for (var param of param_ls[0]) { // console.log(`param____:${param.toString()}`) if (!param.param_value){ continue; } if (param.bytesToX._raw){ log_message+=`${param.param_name}.raw:${param.param_value}~`; } if (param.bytesToX._toString){ log_message+=`${param.param_name}.str:${bytesToString(param.param_value)}~`; } if (param.bytesToX._toHex){ log_message+=`${param.param_name}.hex:${bytesToHex(param.param_value)}~`; } log_message+=";" } return log_message; } /** * @param {String} clazz * @param {...Param} param_ls */ function print_generated_log(clazz,...param_ls){ console.log( generate_log(clazz,param_ls) ); } Java.perform(function () { { const clazz='javax.crypto.spec.SecretKeySpec'; var SecretKeySpec = Java.use(clazz); // public SecretKeySpec(byte[] key, String algorithm) {} SecretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function (security_key, algorithm) { showStacks(SecretKeySpec.class.getCanonicalName()); var result = this.$init(security_key, algorithm); print_generated_log(clazz, NewParam("security_key",security_key), NewParam_BytesToRaw("algorithm",algorithm), NewParam_BytesToRaw("return_value",result) ) ; return result; } } { const clazz='javax.crypto.spec.DESKeySpec'; var DESKeySpec = Java.use(clazz); // public DESKeySpec(byte[] key) throws InvalidKeyException DESKeySpec.$init.overload('[B').implementation = function (security_key) { showStacks(DESKeySpec.class.getCanonicalName()); var result = this.$init(security_key); print_generated_log(clazz, NewParam_BytesToString("security_key",security_key), NewParam("return_value",result) ) ; return result; } // public DESKeySpec(byte[] key, int offset) throws InvalidKeyException DESKeySpec.$init.overload('[B', 'int').implementation = function (security_key, offset) { showStacks(DESKeySpec.class.getCanonicalName()); var result = this.$init(security_key, offset); print_generated_log(clazz, NewParam("security_key",security_key), NewParam("offset",offset), NewParam("return_value",result) ) ; return result; } } { const clazz='javax.crypto.Mac'; var Mac = Java.use(clazz); // public static final Mac getInstance(String algorithm) Mac.getInstance.overload('java.lang.String').implementation = function (algorithm) { showStacks(Mac.class.getCanonicalName()); var result = this.getInstance(algorithm); print_generated_log(clazz, NewParam_BytesToString("algorithm",algorithm), NewParam("return_value",result) ) ; return result; } // public final void update(byte[] input) throws IllegalStateException Mac.update.overload('[B').implementation = function (input) { showStacks(Mac.class.getCanonicalName()); this.update(input); print_generated_log(clazz, NewParam_BytesToString("input",input) ) ; } // public final void update(byte[] input, int offset, int len) Mac.update.overload('[B', 'int', 'int').implementation = function (input, offset, len) { showStacks(Mac.class.getCanonicalName()); this.update(input, offset, len) print_generated_log(clazz, NewParam("input",input), NewParam("offset",offset), NewParam("len",len), NewParam("return_value",result) ) ; } // public final byte[] doFinal() throws IllegalStateException Mac.doFinal.overload().implementation = function () { showStacks(Mac.class.getCanonicalName()); var result = this.doFinal(); print_generated_log(clazz, NewParam("return_value",result) ) ; return result; } // public final byte[] doFinal(byte[] input) throws IllegalStateException Mac.doFinal.overload('[B').implementation = function (input) { showStacks(Mac.class.getCanonicalName()); var result = this.doFinal(input); print_generated_log(clazz, NewParam("input",input), NewParam("return_value",result) ) ; return result; } } { const clazz='java.security.MessageDigest'; var MessageDigest = Java.use(clazz); // public static MessageDigest getInstance(String algorithm, String provider) MessageDigest.getInstance.overload('java.lang.String', 'java.lang.String').implementation = function (algorithm, provider) { showStacks(MessageDigest.class.getCanonicalName()); var return_value=this.getInstance(algorithm, provider); print_generated_log(clazz, NewParam("algorithm",algorithm), NewParam("provider",provider), NewParam("return_value",return_value) ) ; return return_value; } // public static MessageDigest getInstance(String algorithm) MessageDigest.getInstance.overload('java.lang.String').implementation = function (algorithm) { showStacks(MessageDigest.class.getCanonicalName()); var return_value= this.getInstance(algorithm); print_generated_log(clazz, NewParam("algorithm",algorithm), NewParam("return_value",return_value) ) ; return return_value; } // public void update(byte[] input) MessageDigest.update.overload('[B').implementation = function (input) { showStacks(MessageDigest.class.getCanonicalName()); this.update(input); print_generated_log(clazz, NewParam("input",input) ) ; return ; } // public void update(byte[] input, int offset, int len) MessageDigest.update.overload('[B', 'int', 'int').implementation = function (input, offset, len) { showStacks(MessageDigest.class.getCanonicalName()); this.update(input, offset, len) print_generated_log(clazz, NewParam("input",input), NewParam("offset",offset), NewParam("len",len) ) ; return ; } // public byte[] digest() MessageDigest.digest.overload().implementation = function () { showStacks(MessageDigest.class.getCanonicalName()); var return_value = this.digest(); print_generated_log(clazz, NewParam("return_value",return_value) ) ; return return_value; } // public byte[] digest(byte[] input) MessageDigest.digest.overload('[B').implementation = function (input) { showStacks(MessageDigest.class.getCanonicalName()); var return_value = this.digest(input); print_generated_log(clazz, NewParam("input",input), NewParam("return_value",return_value) ) ; return return_value; } } { const clazz='javax.crypto.spec.IvParameterSpec'; var IvParameterSpec = Java.use(clazz); // public IvParameterSpec(byte[] initialization_vector) IvParameterSpec.$init.overload('[B').implementation = function (initialization_vector) { showStacks(IvParameterSpec.class.getCanonicalName()); var return_value = this.$init(initialization_vector); print_generated_log(clazz, NewParam("initialization_vector",initialization_vector), NewParam("return_value",return_value) ) ; return return_value; } } { const clazz='javax.crypto.Cipher'; var Cipher = Java.use(clazz); //javax.crypto.Cipher: public static final Cipher getInstance(String transformation) throws NoSuchAlgorithmException, NoSuchPaddingException Cipher.getInstance.overload('java.lang.String').implementation = function (transformation) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.getInstance(transformation); print_generated_log(clazz, NewParam("transformation",transformation), NewParam("return_value",return_value) ) ; return return_value; } //javax.crypto.Cipher: public final void init(int operation_mode, Key security_key) throws InvalidKeyException Cipher.init.overload('int', 'java.security.Key').implementation = function (operation_mode, security_key) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.init(operation_mode, security_key); var mode_name=javax_crypto_Cipher.get_mode_name(operation_mode); //java.security.Key: public byte[] getEncoded() var security_key_encoded = security_key.getEncoded(); print_generated_log(clazz, NewParam("mode_name",mode_name), NewParam("security_key_encoded",security_key_encoded), NewParam("return_value",return_value) ) ; return return_value; } //javax.crypto.Cipher: public final void init(int operation_mode, Certificate certificate) throws InvalidKeyException Cipher.init.overload('int', 'java.security.cert.Certificate').implementation = function (operation_mode, certificate) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.init(operation_mode, certificate); var mode_name=javax_crypto_Cipher.get_mode_name(operation_mode); //java.security.cert.Certificate: public abstract byte[] getEncoded() throws CertificateEncodingException; var certificate_encoded=certificate.getEncoded(); print_generated_log(clazz, NewParam("mode_name",mode_name), NewParam("certificate_encoded",certificate_encoded), NewParam("return_value",return_value) ) ; return return_value; } // public final void init(int operation_mode, Key key, AlgorithmParameterSpec algorithmParameterSpec) throws InvalidKeyException, InvalidAlgorithmParameterException Cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec').implementation = function (operation_mode, security_key, algorithmParameterSpec) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.init(operation_mode, security_key, algorithmParameterSpec); var mode_name=javax_crypto_Cipher.get_mode_name(operation_mode); var security_key_encoded = security_key.getEncoded(); print_generated_log(clazz, NewParam("mode_name",mode_name), NewParam("security_key_encoded",security_key_encoded), NewParam("return_value",return_value) ) ; return return_value; } // public final void init(int operation_mode, Certificate certificate, SecureRandom secureRandom) throws InvalidKeyException Cipher.init.overload('int', 'java.security.cert.Certificate', 'java.security.SecureRandom').implementation = function (operation_mode, certificate, secureRandom) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.init(operation_mode, certificate, secureRandom); //忽略secureRandom(对secureRandom操作对加解密会影响?) var mode_name=javax_crypto_Cipher.get_mode_name(operation_mode); //java.security.cert.Certificate: public abstract byte[] getEncoded() throws CertificateEncodingException; var certificate_encoded=certificate.getEncoded(); print_generated_log(clazz, NewParam("mode_name",mode_name), NewParam("certificate_encoded",certificate_encoded), NewParam("return_value",return_value) ) ; return return_value; } // public final void init(int operation_mode, Key security_key, SecureRandom secureRandom) throws InvalidKeyException Cipher.init.overload('int', 'java.security.Key', 'java.security.SecureRandom').implementation = function (operation_mode, security_key, secureRandom) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.init(operation_mode, security_key, secureRandom); var mode_name=javax_crypto_Cipher.get_mode_name(operation_mode); var security_key_encoded = security_key.getEncoded(); print_generated_log(clazz, NewParam("mode_name",mode_name), NewParam("security_key_encoded",security_key_encoded), NewParam("return_value",return_value) ) ; return return_value; } // public final void init(int operation_mode, Key security_key, AlgorithmParameters algorithmParameters) throws InvalidKeyException, InvalidAlgorithmParameterException Cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters').implementation = function (operation_mode, security_key, algorithmParameters) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.init(operation_mode, security_key, algorithmParameters); var security_key_encoded = security_key.getEncoded(); var algorithmParametersToString=algorithmParameters.toString(); print_generated_log(clazz, NewParam("mode_name",mode_name), NewParam("security_key_encoded",security_key_encoded), NewParam("algorithmParametersToString",algorithmParametersToString), NewParam("return_value",return_value) ) ; return return_value; } // public final void init(int operation_mode, Key security_key, AlgorithmParameters algorithmParameters,SecureRandom secureRandom) throws InvalidKeyException, InvalidAlgorithmParameterException Cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters', 'java.security.SecureRandom').implementation = function (operation_mode, security_key, algorithmParameters, secureRandom) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.init(operation_mode, security_key, algorithmParameters, secureRandom); var security_key_encoded = security_key.getEncoded(); var algorithmParametersToString=algorithmParameters.toString(); print_generated_log(clazz, NewParam("mode_name",mode_name), NewParam("security_key_encoded",security_key_encoded), NewParam("algorithmParametersToString",algorithmParametersToString), NewParam("return_value",return_value) ) ; return return_value; } // public final void init(int operation_mode, Key security_key, AlgorithmParameterSpec algorithmParameterSpec,SecureRandom secureRandom) throws InvalidKeyException, InvalidAlgorithmParameterException Cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec', 'java.security.SecureRandom').implementation = function (operation_mode, security_key, algorithmParameterSpec, secureRandom) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.update(operation_mode, security_key, algorithmParameters, secureRandom); var security_key_encoded = security_key.getEncoded(); var algorithmParametersToString=algorithmParameters.toString(); print_generated_log(clazz, NewParam("mode_name",mode_name), NewParam("security_key_encoded",security_key_encoded), NewParam("algorithmParametersToString",algorithmParametersToString), NewParam("return_value",return_value) ) ; return return_value; } // public final byte[] update(byte[] input) Cipher.update.overload('[B').implementation = function (input) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.update(input); print_generated_log(clazz, NewParam("input",input), NewParam("return_value",return_value) ) ; return return_value; } // public final byte[] update(byte[] input, int inputOffset, int inputLen) Cipher.update.overload('[B', 'int', 'int').implementation = function (input, inputOffset, inputLen) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.update(input, inputOffset, inputLen); print_generated_log(clazz, NewParam("input",input), NewParam("inputOffset",inputOffset), NewParam("inputLen",inputLen), NewParam("return_value",return_value) ) ; return return_value; } // public final byte[] doFinal() throws IllegalBlockSizeException, BadPaddingException Cipher.doFinal.overload().implementation = function () { showStacks(Cipher.class.getCanonicalName()); var return_value = this.doFinal(); print_generated_log(clazz, NewParam("return_value",return_value) ) ; return return_value; } // public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException, BadPaddingException Cipher.doFinal.overload('[B').implementation = function (input) { showStacks(Cipher.class.getCanonicalName()); var return_value = this.doFinal(input); print_generated_log(clazz, NewParam("input",input), NewParam("return_value",return_value) ) ; //TODO bytesToBase64(return_value) return return_value; } } { const clazz='java.security.spec.X509EncodedKeySpec'; var X509EncodedKeySpec = Java.use(clazz); // public X509EncodedKeySpec(byte[] encoded_key) X509EncodedKeySpec.$init.overload('[B').implementation = function (encoded_key) { showStacks(X509EncodedKeySpec.class.getCanonicalName()); var return_value = this.$init(encoded_key); print_generated_log(clazz, NewParam("encoded_key",encoded_key), NewParam("return_value",return_value) ) ; //TODO bytesToBase64(return_value) return return_value; } } { const clazz='java.security.spec.RSAPublicKeySpec'; var RSAPublicKeySpec = Java.use(clazz); // public RSAPublicKeySpec(BigInteger modulus, BigInteger public_exponent) RSAPublicKeySpec.$init.overload('java.math.BigInteger', 'java.math.BigInteger').implementation = function (modulus, public_exponent) { showStacks(RSAPublicKeySpec.class.getCanonicalName()); var return_value = this.$init(modulus, public_exponent); //TODO bytesToBase64(modulus) print_generated_log(clazz, NewParam("modulus",modulus), NewParam("public_exponent",public_exponent), NewParam("return_value",return_value) ) ; return return_value; } } { const clazz='java.security.KeyPairGenerator'; var KeyPairGenerator = Java.use(clazz); // public KeyPair generateKeyPair() KeyPairGenerator.generateKeyPair.implementation = function () { showStacks(KeyPairGenerator.class.getCanonicalName()); var return_value = this.generateKeyPair(); var private_key = return_value.getPrivate().getEncoded(); var public_key = return_value.getPublic().getEncoded(); //change to bytesToHex(private_key) bytesToHex(public_key) print_generated_log(clazz, NewParam("private_key",private_key), NewParam("public_key",public_key), NewParam("return_value",return_value) ) ; return return_value; } // public final KeyPair genKeyPair() KeyPairGenerator.genKeyPair.implementation = function () { showStacks(KeyPairGenerator.class.getCanonicalName()); var return_value = this.genKeyPair(); var private_key = return_value.getPrivate().getEncoded(); var public_key = return_value.getPublic().getEncoded(); //TODO bytesToHex(private_key) bytesToHex(public_key) print_generated_log(clazz, NewParam("private_key",private_key), NewParam("public_key",public_key), NewParam("return_value",return_value) ) ; return return_value; } } });
python 启动
# -*- coding: UTF-8 -*- import frida, sys jsCode = """ function showStacks() { Java.perform(function () { send(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new())); }); } (function () { var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', base64DecodeChars = new Array((-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), 62, (-1), (-1), (-1), 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, (-1), (-1), (-1), (-1), (-1), (-1), (-1), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, (-1), (-1), (-1), (-1), (-1), (-1), 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, (-1), (-1), (-1), (-1), (-1)); this.stringToBase64 = function (e) { var r,a,c,h,o,t; for (c = e.length, a = 0, r = ''; a < c; ) { if (h = 255 & e.charCodeAt(a++), a == c) { r += base64EncodeChars.charAt(h >> 2), r += base64EncodeChars.charAt((3 & h) << 4), r += '=='; break } if (o = e.charCodeAt(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.charCodeAt(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 } this.base64ToString = function (e) { var r,a,c,h,o,t,d; for (t = e.length, o = 0, d = ''; o < t; ) { do r = base64DecodeChars[255 & e.charCodeAt(o++)]; while (o < t && r == -1); if (r == -1) break; do a = base64DecodeChars[255 & e.charCodeAt(o++)]; while (o < t && a == -1); if (a == -1) break; d += String.fromCharCode(r << 2 | (48 & a) >> 4); do { if (c = 255 & e.charCodeAt(o++), 61 == c) return d; c = base64DecodeChars[c] } while (o < t && c == -1); if (c == -1) break; d += String.fromCharCode((15 & a) << 4 | (60 & c) >> 2); do { if (h = 255 & e.charCodeAt(o++), 61 == h) return d; h = base64DecodeChars[h] } while (o < t && h == -1); if (h == -1) break; d += String.fromCharCode((3 & c) << 6 | h) } return d } this.hexToBase64 = function (str) { return base64Encode(String.fromCharCode.apply(null, str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))); } this.base64ToHex = function (str) { for (var i = 0, bin = base64Decode(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) { var tmp = bin.charCodeAt(i).toString(16); if (tmp.length === 1) tmp = "0" + tmp; hex[hex.length] = tmp; } return hex.join(""); } this.hexToBytes = function (str) { var pos = 0; var len = str.length; if (len % 2 != 0) { return null; } len /= 2; var hexA = new Array(); for (var i = 0; i < len; i++) { var s = str.substr(pos, 2); var v = parseInt(s, 16); hexA.push(v); pos += 2; } return hexA; } this.bytesToHex = function (arr) { var str = ''; var k,j; for(var i = 0; i<arr.length; i++) { k = arr[i]; j = k; if (k < 0) { j = k + 256; } if (j < 16) { str += "0"; } str += j.toString(16); } return str; } this.stringToHex = function (str) { var val = ""; for (var i = 0; i < str.length; i++) { if (val == "") val = str.charCodeAt(i).toString(16); else val += str.charCodeAt(i).toString(16); } return val } this.stringToBytes = function (str) { var ch, st, re = []; for (var i = 0; i < str.length; i++ ) { ch = str.charCodeAt(i); st = []; do { st.push( ch & 0xFF ); ch = ch >> 8; } while ( ch ); re = re.concat( st.reverse() ); } return re; } //将byte[]转成String的方法 this.bytesToString = function (arr) { var str = ''; arr = new Uint8Array(arr); for(i in arr){ str += String.fromCharCode(arr[i]); } return str; } this.bytesToBase64=function(e){ 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 } this.base64ToBytes=function(e){ var r,a,c,h,o,t,d; for (t = e.length, o = 0, d = []; o < t; ) { do r = base64DecodeChars[255 & e.charCodeAt(o++)]; while (o < t && r == -1); if (r == -1) break; do a = base64DecodeChars[255 & e.charCodeAt(o++)]; while (o < t && a == -1); if (a == -1) break; d.push(r << 2 | (48 & a) >> 4); do { if (c = 255 & e.charCodeAt(o++), 61 == c) return d; c = base64DecodeChars[c] } while (o < t && c == -1); if (c == -1) break; d.push((15 & a) << 4 | (60 & c) >> 2); do { if (h = 255 & e.charCodeAt(o++), 61 == h) return d; h = base64DecodeChars[h] } while (o < t && h == -1); if (h == -1) break; d.push((3 & c) << 6 | h) } return d } })(); //stringToBase64 stringToHex stringToBytes //base64ToString base64ToHex base64ToBytes // hexToBase64 hexToBytes // bytesToBase64 bytesToHex bytesToString Java.perform(function () { var secretKeySpec = Java.use('javax.crypto.spec.SecretKeySpec'); secretKeySpec.$init.overload('[B','java.lang.String').implementation = function (a,b) { showStacks(); var result = this.$init(a, b); send("======================================"); send("算法名:" + b + "|Dec**:" + bytesToString(a)); send("算法名:" + b + "|Hex**:" + bytesToHex(a)); return result; } var mac = Java.use('javax.crypto.Mac'); mac.getInstance.overload('java.lang.String').implementation = function (a) { showStacks(); var result = this.getInstance(a); send("======================================"); send("算法名:" + a); return result; } mac.update.overload('[B').implementation = function (a) { showStacks(); this.update(a); send("======================================"); send("update:" + bytesToString(a)) } mac.update.overload('[B','int','int').implementation = function (a,b,c) { showStacks(); this.update(a,b,c) send("======================================"); send("update:" + bytesToString(a) + "|" + b + "|" + c); } mac.doFinal.overload().implementation = function () { showStacks(); var result = this.doFinal(); send("======================================"); send("doFinal结果:" + bytesToHex(result)); send("doFinal结果:" + bytesToBase64(result)); return result; } mac.doFinal.overload('[B').implementation = function (a) { showStacks(); var result = this.doFinal(a); send("======================================"); send("doFinal参数:" + bytesToString(a)); send("doFinal结果:" + bytesToHex(result)); send("doFinal结果:" + bytesToBase64(result)); return result; } var md = Java.use('java.security.MessageDigest'); md.getInstance.overload('java.lang.String','java.lang.String').implementation = function (a,b) { showStacks(); send("======================================"); send("算法名:" + a); return this.getInstance(a, b); } md.getInstance.overload('java.lang.String').implementation = function (a) { showStacks(); send("======================================"); send("算法名:" + a); return this.getInstance(a); } md.update.overload('[B').implementation = function (a) { showStacks(); send("======================================"); send("update:" + bytesToString(a)) return this.update(a); } md.update.overload('[B','int','int').implementation = function (a,b,c) { showStacks(); send("======================================"); send("update:" + bytesToString(a) + "|" + b + "|" + c); return this.update(a,b,c); } md.digest.overload().implementation = function () { showStacks(); send("======================================"); var result = this.digest(); send("digest结果:" + bytesToHex(result)); send("digest结果:" + bytesToBase64(result)); return result; } md.digest.overload('[B').implementation = function (a) { showStacks(); send("======================================"); send("digest参数:" + bytesToString(a)); var result = this.digest(a); send("digest结果:" + bytesToHex(result)); send("digest结果:" + bytesToBase64(result)); return result; } var ivParameterSpec = Java.use('javax.crypto.spec.IvParameterSpec'); ivParameterSpec.$init.overload('[B').implementation = function (a) { showStacks(); var result = this.$init(a); send("======================================"); send("iv向量:" + bytesToString(a)); send("iv向量:" + bytesToHex(a)); return result; } var cipher = Java.use('javax.crypto.Cipher'); cipher.getInstance.overload('java.lang.String').implementation = function (a) { showStacks(); var result = this.getInstance(a); send("======================================"); send("模式填充:" + a); return result; } cipher.update.overload('[B').implementation = function (a) { showStacks(); var result = this.update(a); send("======================================"); send("update:" + bytesToString(a)); return result; } cipher.update.overload('[B','int','int').implementation = function (a,b,c) { showStacks(); var result = this.update(a,b,c); send("======================================"); send("update:" + bytesToString(a) + "|" + b + "|" + c); return result; } cipher.doFinal.overload().implementation = function () { showStacks(); var result = this.doFinal(); send("======================================"); send("doFinal结果:" + bytesToHex(result)); send("doFinal结果:" + bytesToBase64(result)); return result; } cipher.doFinal.overload('[B').implementation = function (a) { showStacks(); var result = this.doFinal(a); send("======================================"); send("doFinal参数:" + bytesToString(a)); send("doFinal结果:" + bytesToHex(result)); send("doFinal结果:" + bytesToBase64(result)); return result; } var x509EncodedKeySpec = Java.use('java.security.spec.X509EncodedKeySpec'); x509EncodedKeySpec.$init.overload('[B').implementation = function (a) { showStacks(); var result = this.$init(a); send("======================================"); send("RSA**:" + bytesToBase64(a)); return result; } var rSAPublicKeySpec = Java.use('java.security.spec.RSAPublicKeySpec'); rSAPublicKeySpec.$init.overload('java.math.BigInteger','java.math.BigInteger').implementation = function (a,b) { showStacks(); var result = this.$init(a,b); send("======================================"); //send("RSA**:" + bytesToBase64(a)); send("RSA**N:" + a.toString(16)); send("RSA**E:" + b.toString(16)); return result; } }); """; fw = open(sys.argv[1],'w+',encoding='utf-8') def message(message, data): if message["type"] == 'send': print(u"[*] {0}".format(message['payload'])) fw.write(u"[*] {0}\n".format(message['payload'])) fw.flush() else: print(message) process = frida.get_remote_device().attach(sys.argv[1]) script= process.create_script(jsCode) script.on("message", message) script.load() sys.stdin.read()
转自:微信公众号:移动安全王铁头
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南