mirror of
https://github.com/ppwang06/frida_js.git
synced 2026-06-05 21:07:18 +08:00
381 lines
16 KiB
JavaScript
381 lines
16 KiB
JavaScript
/**
|
||
* Java层标准算法hook
|
||
*/
|
||
|
||
Java.perform(function () {
|
||
/**
|
||
打印堆栈
|
||
*/
|
||
function showStack() {
|
||
let Throwable = Java.use("java.lang.Throwable");
|
||
let stackTraceString = Java.use("android.util.Log").getStackTraceString(Throwable.$new())
|
||
console.log(stackTraceString);
|
||
}
|
||
|
||
let ByteString = Java.use("com.android.okhttp.okio.ByteString");
|
||
|
||
/**
|
||
* 字节数组转为Base64
|
||
*/
|
||
function toBase64(tag, data) {
|
||
console.log(tag + " Base64:" + ByteString.of(data).base64());
|
||
}
|
||
|
||
/**
|
||
* 字节数组转为16进制
|
||
*/
|
||
function toHex(tag, data) {
|
||
console.log(tag + " Hex:" + ByteString.of(data).hex());
|
||
}
|
||
|
||
/**
|
||
* 字节数组转为明文
|
||
*/
|
||
function toUtf8(tag, data) {
|
||
console.log(tag + " Utf8:" + ByteString.of(data).utf8());
|
||
}
|
||
|
||
/**
|
||
* 打印字节数组对应的输出数据
|
||
*/
|
||
function printData(tag, data) {
|
||
toBase64(tag, data);
|
||
toHex(tag, data);
|
||
toUtf8(tag, data);
|
||
}
|
||
|
||
|
||
/***
|
||
* 消息摘要算法hook
|
||
* update 压入数据
|
||
* digest 返回加密结果
|
||
*/
|
||
function hookMessageDigest() {
|
||
let MessageDigest = Java.use("java.security.MessageDigest");
|
||
MessageDigest.update.overload('byte').implementation = function (b) {
|
||
showStack();
|
||
console.log("MessageDigest.update.overload('byte') is called!");
|
||
let result = this.update.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " update param", Java.array('byte', [b]))
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
MessageDigest.update.overload('[B').implementation = function (byteArr) {
|
||
showStack();
|
||
console.log("MessageDigest.update.overload('[B') is called!");
|
||
let result = this.update.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " update param", byteArr);
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
MessageDigest.digest.overload().implementation = function () {
|
||
showStack();
|
||
console.log("MessageDigest.digest.overload() is called!");
|
||
let result = this.digest.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " digest result", result);
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
MessageDigest.digest.overload('[B').implementation = function (byteArr) {
|
||
showStack();
|
||
console.log("MessageDigest.digest.overload('[B') is called!");
|
||
let result = this.digest.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " digest param", byteArr);
|
||
printData(algorithm + " digest result", result);
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
|
||
MessageDigest.digest.overload('[B', 'int', 'int').implementation = function (byteArr, start, length) {
|
||
showStack();
|
||
console.log("MessageDigest.digest.overload('[B', 'int', 'int') is called!");
|
||
let result = this.digest.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " digest param", byteArr);
|
||
printData(algorithm + " digest result", result);
|
||
console.log("============================================================" + "开始位置:" + start + " 截取长度:" + length);
|
||
return result;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Mac算法hook
|
||
* 1.init 初始化,秘钥
|
||
* 2.update 压入数据
|
||
* 3.doFinal 加密
|
||
*/
|
||
function hookMac() {
|
||
let Mac = Java.use("javax.crypto.Mac");
|
||
|
||
Mac.init.overload('java.security.Key').implementation = function (key) {
|
||
showStack();
|
||
console.log("Mac.init.overload('java.security.Key') is called!");
|
||
let result = this.init.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " init key", key.getEncoded())
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
|
||
Mac.update.overload('byte').implementation = function (b) {
|
||
showStack();
|
||
console.log("Mac.update.overload('byte') is called!");
|
||
let result = this.update.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " update param", Java.array('byte', [b]))
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
Mac.update.overload('[B').implementation = function (byteArr) {
|
||
showStack();
|
||
console.log("Mac.update.overload('[B') is called!");
|
||
let result = this.update.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " update param", byteArr)
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
Mac.update.overload('[B', 'int', 'int').implementation = function (byteArr, start, length) {
|
||
showStack();
|
||
console.log("Mac.update.overload('[B', 'int', 'int') is called!");
|
||
let result = this.update.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " update param", byteArr)
|
||
console.log("============================================================" + "开始位置:" + start + " 截取长度:" + length);
|
||
return result;
|
||
}
|
||
Mac.doFinal.overload().implementation = function () {
|
||
showStack();
|
||
console.log("Mac.doFinal.overload() is called!");
|
||
let result = this.doFinal.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " doFinal result", result)
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* DES,DESEde,AES,RSA
|
||
* 1.init 加密类型,key,iv
|
||
* 2.donFinal压入数据,得到结果 update压入结果有问题
|
||
*/
|
||
function hookCipher() {
|
||
function printResult(cipherObj, result, args) {
|
||
let algorithm = cipherObj.getAlgorithm();
|
||
let mode;
|
||
|
||
if (cipherObj.opmode.value === 1) {
|
||
mode = "加密";
|
||
} else {
|
||
mode = "解密";
|
||
}
|
||
|
||
console.log(algorithm + " mode:", mode);
|
||
if (cipherObj.getParameters() != null) {
|
||
printData(algorithm + " key", cipherObj.getParameters().getEncoded());
|
||
printData(algorithm + " iv", cipherObj.getIV());
|
||
}
|
||
printData(algorithm + " doFinal param", args[0]);
|
||
printData(algorithm + " doFinal result", result);
|
||
console.log("============================================================");
|
||
|
||
}
|
||
|
||
let Cipher = Java.use("javax.crypto.Cipher");
|
||
// 不常用重载,打印调用即可,根据堆栈信息在具体去看
|
||
// init暂时注释
|
||
Cipher.init.overload('int', 'java.security.cert.Certificate', 'java.security.SecureRandom').implementation = function (key) {
|
||
showStack();
|
||
console.log("Cipher.init.overload('int', 'java.security.cert.Certificate', 'java.security.SecureRandom') is called!");
|
||
let result = this.apply(this, arguments);
|
||
return result;
|
||
}
|
||
Cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters', 'java.security.SecureRandom').implementation = function (key) {
|
||
showStack();
|
||
console.log("Cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters', 'java.security.SecureRandom') is called!");
|
||
let result = this.apply(this, arguments);
|
||
return result;
|
||
}
|
||
|
||
// ECB模式,不带iv
|
||
Cipher.init.overload('int', 'java.security.Key', 'java.security.SecureRandom').implementation = function () {
|
||
showStack();
|
||
console.log("Cipher.init.overload('int', 'java.security.Key', 'java.security.SecureRandom') is called!");
|
||
let result = this.init.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
let mode;
|
||
if (arguments[0] === 1) {
|
||
mode = "加密";
|
||
} else {
|
||
mode = "解密";
|
||
}
|
||
console.log(algorithm + " init mode:" + mode);
|
||
try {
|
||
// RSA使用私钥调用getEncoded() 会报错,异常捕获,具体逻辑,根据堆栈,去APP分析
|
||
printData(algorithm + " init key", arguments[1].getEncoded());
|
||
} catch (e) {
|
||
console.log(e);
|
||
}
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
|
||
// CBC模式,带iv
|
||
Cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec', 'java.security.SecureRandom').implementation = function () {
|
||
showStack();
|
||
console.log("Cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec', 'java.security.SecureRandom') is called!");
|
||
let result = this.init.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
let ivParameterSpecObj = Java.cast(arguments[2], Java.use("javax.crypto.spec.IvParameterSpec"));
|
||
let mode;
|
||
if (arguments[0] === 1) {
|
||
mode = "加密";
|
||
} else {
|
||
mode = "解密";
|
||
}
|
||
console.log(algorithm + " init mode:" + mode);
|
||
printData(algorithm + " init key", arguments[1].getEncoded());
|
||
printData(algorithm + " init iv", ivParameterSpecObj.getIV());
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
|
||
Cipher.doFinal.overload().implementation = function () {
|
||
showStack();
|
||
console.log("Cipher.doFinal.overload() is called!");
|
||
let result = this.doFinal.apply(this, arguments);
|
||
printResult(this, result, arguments);
|
||
return result;
|
||
}
|
||
Cipher.doFinal.overload('[B').implementation = function () {
|
||
showStack();
|
||
console.log("Cipher.doFinal.overload('[B') is called!");
|
||
let result = this.doFinal.apply(this, arguments);
|
||
printResult(this, result, arguments);
|
||
return result;
|
||
}
|
||
Cipher.doFinal.overload('[B', 'int').implementation = function () {
|
||
showStack();
|
||
console.log("Cipher.doFinal.overload('[B', 'int') is called!");
|
||
let result = this.doFinal.apply(this, arguments);
|
||
printResult(this, result, arguments);
|
||
return result;
|
||
}
|
||
Cipher.doFinal.overload('[B', 'int', 'int').implementation = function () {
|
||
showStack();
|
||
console.log("Cipher.doFinal.overload('[B', 'int', 'int') is called!");
|
||
let result = this.doFinal.apply(this, arguments);
|
||
printResult(this, result, arguments);
|
||
return result;
|
||
}
|
||
Cipher.doFinal.overload('[B', 'int', 'int', '[B').implementation = function () {
|
||
showStack();
|
||
console.log("Cipher.doFinal.overload('[B', 'int', 'int', '[B') is called!");
|
||
let result = this.doFinal.apply(this, arguments);
|
||
printResult(this, result, arguments);
|
||
return result;
|
||
}
|
||
Cipher.doFinal.overload('[B', 'int', 'int', '[B', 'int').implementation = function () {
|
||
showStack();
|
||
console.log("Cipher.doFinal.overload('[B', 'int', 'int', '[B', 'int') is called!");
|
||
let result = this.doFinal.apply(this, arguments);
|
||
printResult(this, result, arguments);
|
||
return result;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 签名算法hook
|
||
* 私钥
|
||
*/
|
||
function hookSignature() {
|
||
let Signature = Java.use("java.security.Signature");
|
||
Signature.initSign.overload('java.security.PrivateKey').implementation = function () {
|
||
showStack();
|
||
console.log("Signature.initSign.overload('java.security.PrivateKey') is called!");
|
||
let result = this.initSign.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
try {
|
||
// RSA使用Hex编码的私钥调用getEncoded() 会报错,异常捕获,具体逻辑,根据堆栈,去APP分析
|
||
printData(algorithm + " init key", arguments[0].getEncoded());
|
||
} catch (e) {
|
||
console.log(JSON.stringify(arguments[0]) + "|" + e);
|
||
}
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
Signature.update.overload('byte').implementation = function () {
|
||
showStack();
|
||
console.log("Signature.update.overload('byte') is called!");
|
||
let result = this.update.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " update param", Java.array('byte', [b]))
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
Signature.update.overload('[B', 'int', 'int').implementation = function () {
|
||
showStack();
|
||
console.log("Signature.update.overload('[B', 'int', 'int') is called!");
|
||
let result = this.update.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " update param", arguments[0]);
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
Signature.sign.overload().implementation = function () {
|
||
showStack();
|
||
console.log("Signature.sign.overload() is called!");
|
||
let result = this.sign.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " sign result", result);
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
Signature.sign.overload('[B', 'int', 'int').implementation = function () {
|
||
showStack();
|
||
console.log("Signature.sign.overload('[B', 'int', 'int') is called!");
|
||
let result = this.sign.apply(this, arguments);
|
||
let algorithm = this.getAlgorithm();
|
||
printData(algorithm + " sign param", arguments[0]);
|
||
printData(algorithm + " sign result", result);
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Base64hook
|
||
*/
|
||
function hookBase64() {
|
||
let Base64 = Java.use("android.util.Base64");
|
||
Base64.encodeToString.overload('[B', 'int').implementation = function () {
|
||
let result = this.encodeToString.apply(this, arguments);
|
||
printData("Base64 param", arguments[0]);
|
||
console.log("-------------------------------");
|
||
console.log("Base64 result:" + result);
|
||
console.log("============================================================");
|
||
return result;
|
||
}
|
||
}
|
||
|
||
// 消息摘要算法hook
|
||
hookMessageDigest();
|
||
// Mac算法hook
|
||
hookMac();
|
||
// hookCipher
|
||
hookCipher();
|
||
// 数据签名算法hook
|
||
hookSignature();
|
||
// hookBase64编码
|
||
hookBase64();
|
||
|
||
})
|
||
|
||
|
||
|