原生安卓开发app的框架frida自吐算法开发

点击上方“Python爬虫与数据挖掘”,进行关注

回复“书籍”即可获赠Python从入门到进阶共10本电子书

繁华事散逐香尘,流水无情草自春。

大家好,我是码农星期八。本教程只用于学习探讨,不允许任何人使用技术进行违法操作,阅读教程即表示同意!

前言

大家好,我是码农星期八,上次有一篇密码学的文章,里面大概说了一下常用的安卓加密。

本次来搞一下Java层的自吐算法。

前置工作

因为加密算法最终的格式都需要转成base64或者hex,所以需要把这些函数先定义一下

//打印堆栈
function showStacks() {
    console.log(
        Java.use("android.util.Log")
            .getStackTraceString(
                Java.use("java.lang.Throwable").$new()
            )
    );
}

var ByteString = Java.use("com.android.okhttp.okio.ByteString");
//输出base64格式数据
function toBase64(tag, data) {
    console.log(tag + " Base64: ", ByteString.of(data).base64());
}
//输出hex格式数据
function toHex(tag, data) {
    console.log(tag + " Hex: ", ByteString.of(data).hex());
}
//输出10格式数据
function toUtf8(tag, data) {
    console.log(tag + " Utf8: ", ByteString.of(data).utf8());
}

什么是自吐算法

我们在进行安卓开发的时候,如果想使用Java层的加密函数进行加密,那必定是要触发相关函数的。

并且即使是字符串混淆,这些系统的关键字是不能混淆的。

比如MD5是由MessageDigest这个类生成的。

e4472949c5c3af1b125d1ec8e6221cea.png

所以如果我们整理一下,hook了相关的关键字,如果调用了相关加密库,必定是要经过我们的hook。

这样,嘿嘿嘿,似乎又方便了一步。

MD5和SHA1自吐

MD5加密主要逻辑

02b1ec5b1f9d785a3f912eca81d75d27.png

SHA加密主要逻辑

10eb315515808cb602363dadda70cbe6.png

其实可以发现,MD5和SHA1的流程基本是一样的,除了后面写入的算法名不同。

所以这俩是可以用一个的。

根据整理,需要hook updatedigest即可。

  • update拿到的是压入的数据。

  • digest可以拿到压入的数据和返回的加密数据。

代码

var messageDigest = Java.use("java.security.MessageDigest");
messageDigest.update.overload('byte').implementation = function (data) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("MessageDigest.update('byte') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data);
}
messageDigest.update.overload('java.nio.ByteBuffer').implementation = function (data) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("MessageDigest.update('java.nio.ByteBuffer') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data);
}
messageDigest.update.overload('[B').implementation = function (data) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("MessageDigest.update('[B') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " update data";
    toUtf8(tag, data);
    toHex(tag, data);
    toBase64(tag, data);
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data);
}
messageDigest.update.overload('[B', 'int', 'int').implementation = function (data, start, length) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("MessageDigest.update('[B', 'int', 'int') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " update data";
    toUtf8(tag, data);
    toHex(tag, data);
    toBase64(tag, data);
    console.log("start:", start);
    console.log("length:", length);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data, start, length);
}
messageDigest.digest.overload().implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("MessageDigest.digest() is called!");
    var result = this.digest();
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " digest result";
    toHex(tag, result);
    toBase64(tag, result);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return result;
}
messageDigest.digest.overload('[B').implementation = function (data) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("MessageDigest.digest('[B') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " digest data";
    toUtf8(tag, data);
    toHex(tag, data);
    toBase64(tag, data);
    var result = this.digest(data);
    var tags = algorithm + " digest result";
    toHex(tags, result);
    toBase64(tags, result);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return result;
}
messageDigest.digest.overload('[B', 'int', 'int').implementation = function (data, start, length) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("MessageDigest.digest('[B', 'int', 'int') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " digest data";
    toUtf8(tag, data);
    toHex(tag, data);
    toBase64(tag, data);
    var result = this.digest(data, start, length);
    var tags = algorithm + " digest result";
    toHex(tags, result);
    toBase64(tags, result);
    console.log("start:", start);
    console.log("length:", length);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return result;
}

效果

adc8d626a61f3b880acb4f2f939b298c.png

MAC自吐

MAC加密主要逻辑

a26bad93c97c091f080fee41453e6183.png

MAC主要是需要一个密钥。压入数据用的是update。获取数据用的是doFinal

所以需要hook initupdatedoFinal

代码

var mac = Java.use("javax.crypto.Mac");
mac.init.overload('java.security.Key', 'java.security.spec.AlgorithmParameterSpec').implementation = function (key, AlgorithmParameterSpec) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Mac.init('java.security.Key', 'java.security.spec.AlgorithmParameterSpec') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.init(key, AlgorithmParameterSpec);
}
mac.init.overload('java.security.Key').implementation = function (key) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Mac.init('java.security.Key') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " init Key";
    var keyBytes = key.getEncoded();
    toUtf8(tag, keyBytes);
    toHex(tag, keyBytes);
    toBase64(tag, keyBytes);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.init(key);
}
mac.update.overload('byte').implementation = function (data) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Mac.update('byte') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data);
}
mac.update.overload('java.nio.ByteBuffer').implementation = function (data) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Mac.update('java.nio.ByteBuffer') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data);
}
mac.update.overload('[B').implementation = function (data) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Mac.update('[B') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " update data";
    toUtf8(tag, data);
    toHex(tag, data);
    toBase64(tag, data);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data);
}
mac.update.overload('[B', 'int', 'int').implementation = function (data, start, length) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Mac.update('[B', 'int', 'int') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " update data";
    toUtf8(tag, data);
    toHex(tag, data);
    toBase64(tag, data);
    console.log("start:", start);
    console.log("length:", length);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data, start, length);
}
mac.doFinal.overload().implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Mac.doFinal() is called!");
    var result = this.doFinal();
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " doFinal result";
    toHex(tag, result);
    toBase64(tag, result);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return result;
}

示例

59a0ffb967aa0fdf1a9be7b24f1d588e.png

DES/DESede/AES/RSA

DES/DESede/AES/RSA这几个加密。都是通过Cipher来进行实例化的。

基本加密逻辑一样

  • init压入key。

  • 因为DES/DESede/AES/RSAupdate压入有问题,所以直接hook doFinal就好了。

c22171ebade622abb638cda85f1813e8.png

代码

// DES/DESede/AES/RSA
var cipher = Java.use("javax.crypto.Cipher");
cipher.init.overload('int', 'java.security.cert.Certificate').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.init('int', 'java.security.cert.Certificate') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key', 'java.security.SecureRandom').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.init('int', 'java.security.Key', 'java.security.SecureRandom') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.cert.Certificate', 'java.security.SecureRandom').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.init('int', 'java.security.cert.Certificate', 'java.security.SecureRandom') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters', 'java.security.SecureRandom').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.init('int', 'java.security.Key', 'java.security.AlgorithmParameters', 'java.security.SecureRandom') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec', 'java.security.SecureRandom').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.init('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec', 'java.security.SecureRandom') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.init('int', 'java.security.Key', 'java.security.AlgorithmParameters') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.init.apply(this, arguments);
}

cipher.init.overload('int', 'java.security.Key').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.init('int', 'java.security.Key') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " init Key";
    var className = JSON.stringify(arguments[1]);
    if (className.indexOf("OpenSSLRSAPrivateKey") === -1) {
        var keyBytes = arguments[1].getEncoded();
        toUtf8(tag, keyBytes);
        toHex(tag, keyBytes);
        toBase64(tag, keyBytes);
    }
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.init('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " init Key";
    var keyBytes = arguments[1].getEncoded();
    toUtf8(tag, keyBytes);
    toHex(tag, keyBytes);
    toBase64(tag, keyBytes);
    var tags = algorithm + " init iv";
    var iv = Java.cast(arguments[2], Java.use("javax.crypto.spec.IvParameterSpec"));
    var ivBytes = iv.getIV();
    toUtf8(tags, ivBytes);
    toHex(tags, ivBytes);
    toBase64(tags, ivBytes);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.init.apply(this, arguments);
}

cipher.doFinal.overload('java.nio.ByteBuffer', 'java.nio.ByteBuffer').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.doFinal('java.nio.ByteBuffer', 'java.nio.ByteBuffer') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.doFinal.apply(this, arguments);
}
cipher.doFinal.overload('[B', 'int').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.doFinal('[B', 'int') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.doFinal.apply(this, arguments);
}
cipher.doFinal.overload('[B', 'int', 'int', '[B').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.doFinal('[B', 'int', 'int', '[B') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.doFinal.apply(this, arguments);
}
cipher.doFinal.overload('[B', 'int', 'int', '[B', 'int').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.doFinal('[B', 'int', 'int', '[B', 'int') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.doFinal.apply(this, arguments);
}
cipher.doFinal.overload().implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.doFinal() is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.doFinal.apply(this, arguments);
}

cipher.doFinal.overload('[B').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.doFinal('[B') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " doFinal data";
    var data = arguments[0];
    toUtf8(tag, data);
    toHex(tag, data);
    toBase64(tag, data);
    var result = this.doFinal.apply(this, arguments);
    var tags = algorithm + " doFinal result";
    toHex(tags, result);
    toBase64(tags, result);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return result;
}
cipher.doFinal.overload('[B', 'int', 'int').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Cipher.doFinal('[B', 'int', 'int') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " doFinal data";
    var data = arguments[0];
    toUtf8(tag, data);
    toHex(tag, data);
    toBase64(tag, data);
    var result = this.doFinal.apply(this, arguments);
    var tags = algorithm + " doFinal result";
    toHex(tags, result);
    toBase64(tags, result);
    console.log("arguments[1]:", arguments[1],);
    console.log("arguments[2]:", arguments[2]);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return result;
}

效果

5f6e6e48187f989c4a371c9a442c362d.png

签名算法

签名算法是混合算法,先记着就行。

代码

//签名算法
var signature = Java.use("java.security.Signature");
signature.update.overload('byte').implementation = function (data) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Signature.update('byte') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data);
}
signature.update.overload('java.nio.ByteBuffer').implementation = function (data) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Signature.update('java.nio.ByteBuffer') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data);
}
signature.update.overload('[B', 'int', 'int').implementation = function (data, start, length) {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Signature.update('[B', 'int', 'int') is called!");
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " update data";
    toUtf8(tag, data);
    toHex(tag, data);
    toBase64(tag, data);
    console.log("start:", start);
    console.log("length:", length);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.update(data, start, length);
}
signature.sign.overload('[B', 'int', 'int').implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Signature.sign('[B', 'int', 'int') is called!");
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return this.sign.apply(this, arguments);
}
signature.sign.overload().implementation = function () {
    console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
    console.log("Signature.sign() is called!");
    var result = this.sign();
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " sign result";
    toHex(tag, result);
    toBase64(tag, result);
    showStacks();
    console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
    return result;
}

实战效果

xx牛.apk
6343caec4cc8670416a9e5ba63b8f83b.png

只要用了Java层的加密,这个方式就能直接都hook出来。

完整代码

z_Java层自吐.js

总结

可能你会想,wc,这个家伙岂不是无敌了?别想太多。自吐算法只是辅助工具罢了,并且打印出来堆栈,更方便的分析罢了。

人生没有白走的路,加油!如果在操作过程中有任何问题,记得下面留言,我们看到会第一时间解决问题。

越努力,越幸运。我是码农星期八,如果觉得还不错,记得动手点赞一下哈。感谢你的观看。

564505c25beef758094b01ea8c4a5fff.png

小伙伴们,快快用实践一下吧!如果在学习过程中,有遇到任何问题,欢迎加我好友,我拉你进Python学习交流群共同探讨学习。

ab5f00918a820f3c7303520a409359d6.png

------------------- End -------------------

往期精彩文章推荐:

9331e1f9bcf806590a8755d93a68bce3.png

欢迎大家点赞,留言,转发,转载,感谢大家的相伴与支持

想加入Python学习群请在后台回复【入群

万水千山总是情,点个【在看】行不行

/今日留言主题/

随便说一两句吧~~

### 回答1: Frida自吐算法脚本,是指利用Frida开源的动态二进制插桩工具,通过修改和注入代码,实现在运行时拦截、控制和跟踪应用程序的操作的过程。算法脚本是指针对算法中的特定代码段或函数,使用Frida进行动态插桩修改的脚本,这种脚本可以帮助开发人员更好地理解和优化应用程序的算法性能。 Frida自吐算法脚本主要应用于安全测试、逆向工程和代码分析等领域,可以用于提取和注入数据、绕过任务限制和加密等功能,还可以用于跟踪调用堆栈、内存分配和资源管理等操作,帮助分析程序的行为和性能瓶颈。 在使用Frida自吐算法脚本时,需要有一定的编程基础和算法知识,同时也需要对目标应用程序的结构和功能有一定的了解。通过修改算法脚本,可以实现各种定制化的功能,并利用Frida的灵活性和可扩展性,为应用程序的安全和性能提供有效的保障。 ### 回答2: Frida自吐算法脚本,顾名思义就是使用Frida工具自己编写算法脚本的过程,Frida是一款非常强大的动态代码注入工具,可以用来分析、修改和监控Android、iOS和Windows应用程序,因此也广泛应用于应用程序逆向工程、渗透测试以及安全研究等领域中。在这些应用场景中,Frida算法脚本是一项非常重要的功能,能够帮助用户快速准确地定位程序漏洞、查找敏感信息、绕过安全措施等。 Frida自吐算法脚本需要掌握一些基础知识,比如JavaScript语言、Frida API、应用程序逆向分析等等。对于一些简单的应用程序,用户可以通过Frida Graphical User Interface(GUI)来进行自吐算法脚本的编写和测试;而对于一些复杂的应用程序,则需要使用命令行来编写脚本,并通过Frida Server进行调试和测试。 自吐算法脚本的编写过程需要结合具体的应用程序进行,通常需要先进行应用程序逆向分析,分析出应用程序的运行机制、加密算法、网络通信协议等信息,然后再根据这些信息编写脚本,实现各种功能,例如Hook函数、修改函数返回值、截取数据包等。 总之,Frida自吐算法脚本是一项非常实用的技能,能够帮助用户更加高效地完成应用程序安全研究和渗透测试等任务,对于安全从业人员来说具有非常重要的意义。 ### 回答3: Frida是一个非常强大的反调试和反反混淆工具,而自吐算法脚本可以让我们更加方便地使用Frida来进行应用程序的Hook。 在使用Frida进行Hook时,我们通常需要通过编写JavaScript脚本来操作目标应用程序中的代码。而自吐算法脚本能够根据应用程序的特征自动生成Hook所需要的JavaScript脚本,从而省去了手动编写脚本的复杂过程。 具体来说,自吐算法脚本采用动态分析的方式来分析目标应用程序的代码结构和函数调用关系。通过这种方式,自吐算法脚本可以自动识别目标应用程序中的函数,并生成Hook所需要的JavaScript代码。 使用自吐算法脚本可以大大提高我们进行应用程序Hook的效率和准确性。不必手动编写脚本,避免因为手误或者知识缺失导致Hook失败的情况。同时,自吐算法脚本也可以提高我们对于目标应用程序的了解,深入了解其代码结构和核心逻辑,从而更加精准地进行应用程序测试和渗透攻击。 总之,自吐算法脚本是一种非常实用的Frida工具,可以大大提高我们的工作效率和准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值