【APP测试】快速定位加密

admin 2026-01-17 02:07:29 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文介绍利用Frida进行安卓APP加密快速定位。内容包括HookHashMap、ArrayList、String等常用类追踪数据,及HookMessageDigest、Mac、Cipher等加密库实现算法自吐。提供了完整JS脚本用于打印密钥、IV、加解密数据及调用栈,有效辅助分析Java层加密逻辑。 综合评分: 88 文章分类: 移动安全,逆向分析,渗透测试,安全工具


cover_image

【APP测试】快速定位加密

原创

d0n9x1e d0n9x1e

蝉SEC

2026年1月15日 14:12 江苏

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

Java: hook系统函数、

1. HashMap的put方法

var hashMap = Java.use("java.util.HashMap");
    hashMap.put.implementation = function (a, b) {
        if(a.equals("username")){
        //打印函数栈信息
            showStacks();
            console.log("hashMap.put: ", a, b);
        }
        return this.put(a, b);
    }
function showStacks() {
        console.log(
            Java.use("android.util.Log")
                .getStackTraceString(
                    Java.use("java.lang.Throwable").$new()
                )
        );
    }

2.ArrayList的add、addAll、set方法等

var arrayList = Java.use("java.util.ArrayList");
arrayList.add.overload('java.lang.Object').implementation = function (a) {
   if(a.equals("username=15968079477")){
        showStacks();
        console.log("arrayList.add: ", a);
    }
    //console.log("arrayList.add: ", a);
    return this.add(a);
}
arrayList.add.overload('int', 'java.lang.Object').implementation = function (a, b) {
    console.log("arrayList.add: ", a, b);
    return this.add(a, b);
}

3.TextUtils的isEmpty方法

    var textUtils = Java.use("android.text.TextUtils");
    textUtils.isEmpty.implementation = function (a) {
        if(a == "2v+DC2gq7RuAC8PE5GZz5wH3/y9ZVcWhFwhDY9L19g9iEd075+Q7xwewvfIN0g0ec/NaaF43/S0="){
            showStacks();
            console.log("textUtils.isEmpty: ", a);
        }
        //console.log("textUtils.isEmpty: ", a);
        return this.isEmpty(a);
    }

4.Log

    var log = Java.use("android.util.Log");
    log.w.overload('java.lang.String', 'java.lang.String').implementation = function (tag, message) {
        showStacks();
        console.log("log.w: ", tag, message);
        return this.w(tag, message);
    }

5.Collections的sort方法

用于对列表(List)进行排序

    var collections = Java.use("java.util.Collections");
    collections.sort.overload('java.util.List').implementation = function (a) {
        showStacks();
        try{
            var result = Java.cast(a, Java.use("java.util.LinkedList"));
            console.log("collections.sort List: ", result.toString());
        }catch (e) {
            result = Java.cast(a, Java.use("java.util.ArrayList"));
            console.log("collections.sort List: ", result.toString());
        }
        return this.sort(a);
    }
    collections.sort.overload('java.util.List', 'java.util.Comparator')
        .implementation = function (a, b) {
        showStacks();
        try{
            var result = Java.cast(a, Java.use("java.util.LinkedList"));
            console.log("collections.sort List Comparator: ", result.toString());
        }catch (e) {
            result = Java.cast(a, Java.use("java.util.ArrayList"));
            console.log("collections.sort List Comparator: ", result.toString());
        }
        return this.sort(a, b);
    }

6.JSONObject的put、getString方法等

    var jSONObject = Java.use("org.json.JSONObject");
    jSONObject.put.overload('java.lang.String', 'java.lang.Object').implementation = function (a, b) {
        showStacks();
        //var result = Java.cast(a, Java.use("java.util.ArrayList"));
        console.log("jSONObject.put: ", a, b);
        return this.put(a, b);
    }
    jSONObject.getString.implementation = function (a) {
        //showStacks();
        //var result = Java.cast(a, Java.use("java.util.ArrayList"));
        console.log("jSONObject.getString: ", a);
        var result = this.getString(a);
        console.log("jSONObject.getString result: ", result);
        return result;
    }

7.Toast的show方法

显示信息提示

    var toast = Java.use("android.widget.Toast");
    toast.show.implementation = function () {
        showStacks();
        console.log("toast.show: ");
        return this.show();
    }

8.Base64

    var base64 = Java.use("android.util.Base64");
    base64.encodeToString.overload('[B', 'int').implementation = function (a, b) {
        showStacks();
        console.log("base64.encodeToString: ", JSON.stringify(a));
        var result = this.encodeToString(a, b);
        console.log("base64.encodeToString result: ", result)
        return result;
    }

java.net.URLEncoder
java.util.Base64
okio.Base64
okio.ByteString

9.String的getBytes、isEmpty方法

    var str = Java.use("java.lang.String");
    str.getBytes.overload().implementation = function () {
        showStacks();
        var result = this.getBytes();
        var newStr = str.$new(result);
        console.log("str.getBytes result: ", newStr);
        return result;
    }
    str.getBytes.overload('java.lang.String').implementation = function (a) {
        showStacks();
        var result = this.getBytes(a);
        var newStr = str.$new(result, a);
        console.log("str.getBytes result: ", newStr);
        return result;
    }

10. String构造函数的Hook

    var stringFactory = Java.use("java.lang.StringFactory");
    stringFactory.newStringFromString.implementation = function (a) {
        showStacks();
        var retval = this.newStringFromString(a);
        console.log("stringFactory.newStringFromString: ", retval);
        return retval;
    }
    stringFactory.newStringFromChars.overload('[C').implementation = function (a) {
        showStacks();
        var retval = this.newStringFromChars(a);
        console.log("stringFactory.newStringFromChars: ", retval);
        return retval;
    }

 newStringFromBytes、newStringFromChars
 newStringFromString、newStringFromStringBuffer、newStringFromStringBuilder

11. StringBuilder、StringBuffer的Hook

    var sb = Java.use("java.lang.StringBuilder");
    sb.toString.implementation = function () {
        var retval = this.toString();
        if (retval.indexOf("Encrypt") != -1) {
            showStacks();
        }
        console.log("StringBuilder.toString: ", retval);
        return retval;
    }
    var sb = Java.use("java.lang.StringBuffer");
    sb.toString.implementation = function () {
        var retval = this.toString();
        if (retval.indexOf("username") != -1) {
            showStacks();
        }
        console.log("StringBuffer.toString: ", retval);
        return retval;
    }

12. findViewById 找控件id(打印R$id的属性)

a) Java.enumerateLoadedClassesSync枚举所有已加载的类
    如果不知道类路径,可以用这个方法,然后过滤一下类名
b) frida -U -f com.dodonew.online -l HookDemo.js -o log.txt --no-pause
-f 代码让frida帮我们重新启动app,一开始就注入js
--no-pause 直接运行主线程,中途不暂停
c) R$id 内部类的访问
d) R$id.btn_login.value 类的属性的访问

var btn_login_id = Java.use("com.dodonew.online.R$id").btn_login.value;
console.log("btn_login_id", btn_login_id);
var appCompatActivity = Java.use("android.support.v7.app.AppCompatActivity");
appCompatActivity.findViewById.implementation = function (a) {
    if(a == btn_login_id){
        showStacks();
        console.log("appCompatActivity.findViewById: ", a);
    }
    return this.findViewById(a);
}

13. setOnClickListener

    hook这个函数,比对控件id,打印函数栈
var btn_login_id = Java.use("com.dodonew.online.R$id").btn_login.value;
console.log("btn_login_id", btn_login_id);

var view = Java.use("android.view.View");
view.setOnClickListener.implementation = function (a) {
    if(this.getId() == btn_login_id){
        showStacks();
        console.log("view.id: " + this.getId());
        console.log("view.setOnClickListener is called");
    }
    return this.setOnClickListener(a);
}

test代码完全体

Java.perform(function () {

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

    // var hashMap = Java.use("java.util.HashMap");
    // hashMap.put.implementation = function (a, b) {
    //     if(a.equals("username")){
    //         showStacks();
    //         console.log("hashMap.put: ", a, b);
    //     }
    //     //console.log("hashMap.put: ", a, b);
    //     return this.put(a, b);
    // }

    // var arrayList = Java.use("java.util.ArrayList");
    // arrayList.add.overload('java.lang.Object').implementation = function (a) {
    //     if (a.equals("username=15968079477")) {
    //         showStacks();
    //         console.log("arrayList.add.overload('java.lang.Object'): ", a);
    //     }
    //     return this.add(a);
    // }
    // arrayList.add.overload('int', 'java.lang.Object').implementation = function (a, b) {
    //     console.log("arrayList.add.overload('int', 'java.lang.Object'): ", a, b);
    //     return this.add(a, b);
    // }

    // var textUtils = Java.use("android.text.TextUtils");
    // textUtils.isEmpty.implementation = function (a) {
    //     if(a == "2v+DC2gq7RuAC8PE5GZz5wH3/y9ZVcWhFwhDY9L19g9iEd075+Q7xwewvfIN0g0ec/NaaF43/S0="){
    //         showStacks();
    //         console.log("textUtils.isEmpty: ", a);
    //     }
    //     //console.log("textUtils.isEmpty: ", a);
    //     return this.isEmpty(a);
    // }

    // var log = Java.use("android.util.Log");
    // log.w.overload('java.lang.String', 'java.lang.String').implementation = function (tag, message) {
    //     showStacks();
    //     console.log("log.w: ", tag, message);
    //     return this.w(tag, message);
    // }

    // var collections = Java.use("java.util.Collections");
    // collections.sort.overload('java.util.List').implementation = function (a) {
    //     try{
    //         showStacks();
    //         var result = Java.cast(a, Java.use("java.util.ArrayList"));
    //         console.log("collections.sort List: ", result.toString());
    //     }catch (e) {
    //
    //     }
    //     return this.sort(a);
    // }
    // collections.sort.overload('java.util.List', 'java.util.Comparator').implementation = function (a, b) {
    //     try{
    //         showStacks();
    //         var result = Java.cast(a, Java.use("java.util.ArrayList"));
    //         console.log("collections.sort List Comparator: ", result.toString());
    //     }catch (e) {
    //
    //     }
    //     return this.sort(a, b);
    // }

    // var jSONObject = Java.use("org.json.JSONObject");
    // jSONObject.put.overload('java.lang.String', 'java.lang.Object').implementation = function (a, b) {
    //     if (a.indexOf("Encrypt") != -1) {
    //         showStacks();
    //         console.log("jSONObject.put: ", a, b);
    //     }
    //     return this.put(a, b);
    // }
    // jSONObject.getString.implementation = function (a) {
    //     showStacks();
    //     console.log("jSONObject.getString: ", a);
    //     var result = this.getString(a);
    //     console.log("jSONObject.getString result: ", result);
    //     return result;
    // }

});

加密库相关的hook(自吐算法)

SSL相关的hook

socket相关的hook

SocketOutputStream

SocketInputStream

读写文件相关的java.io.File

证书双向验证 Keystore.load 通常有证书和密码

安卓退出进程的方式

//快速定位协议头加密okhttp3的addHeader方法

var okhttp_Builder = Java.use('okhttp3.Request$Builder');
okhttp_Builder.addHeader.implementation = function (a, b) {
showStacks();
return this.addHeader(a, b);
}

算法自吐

应用场景

加密在Java层,并且调用了标准加密库的

加密在Java层,但是使用反射调用标准加密库的

加密在so层,但是用jni调用了Java标准加密库的

app被加固,但是调用了标准加密库的

通过打印函数栈辅助定位加密代码所在类

局限性

加密在Java层,自写的标准算法或非标准算法

加密在so层,C/C++写的算法

加密在Java层,并且调用了标准加密库,但是加密前和加密后的数据都做了其他处理

注意点

会发现我们直接hook okio.ByteString会报错,是因为这是第三方的库,实际上这个库在安卓本身也有,com.android.okhttp.okio.ByteString

Java.perform(function () {

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

  function logOutPut(msg) {
    Java.use("android.util.Log").d("xiaojianbang", "frida inject: " + msg);
  }

  var ByteString = Java.use("com.android.okhttp.okio.ByteString");
  function toBase64(tag, data) {
    //logOutPut(tag + " Base64: " + ByteString.of(data).base64());
    console.log(tag + " Base64: " + ByteString.of(data).base64());
  }
  function toHex(tag, data) {
    //logOutPut(tag + " Hex: " + ByteString.of(data).hex());
    console.log(tag + " Hex: " + ByteString.of(data).hex());
  }
  function toUtf8(tag, data) {
    //logOutPut(tag + " Utf8: " + ByteString.of(data).utf8());
    console.log(tag + " Utf8: " + ByteString.of(data).utf8());
  }
  // toBase64([48,49,50,51,52]);
  // toHex([48,49,50,51,52]);
  // toUtf8([48,49,50,51,52]);
  //console.log(Java.enumerateLoadedClassesSync().join("\n"));

  var messageDigest = Java.use("java.security.MessageDigest");
  messageDigest.update.overload('byte').implementation = function (data) {
    console.log("MessageDigest.update('byte') is called!");
    showStacks();
    return this.update(data);
  }
  messageDigest.update.overload('java.nio.ByteBuffer').implementation = function (data) {
    console.log("MessageDigest.update('java.nio.ByteBuffer') is called!");
    showStacks();
    return this.update(data);
  }
  messageDigest.update.overload('[B').implementation = function (data) {
    console.log("MessageDigest.update('[B') is called!");
    showStacks();
    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("MessageDigest.update('[B', 'int', 'int') is called!");
    showStacks();
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " update data";
    toUtf8(tag, data);
    toHex(tag, data);
    toBase64(tag, data);
    console.log("=======================================================", start, length);
    return this.update(data, start, length);
  }
  messageDigest.digest.overload().implementation = function () {
    console.log("MessageDigest.digest() is called!");
    showStacks();
    var result = this.digest();
    var algorithm = this.getAlgorithm();
    var tag = algorithm + " digest result";
    toHex(tag, result);
    toBase64(tag, result);
    console.log("=======================================================");
        return result;
    }
    messageDigest.digest.overload('[B').implementation = function (data) {
        console.log("MessageDigest.digest('[B') is called!");
        showStacks();
        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);
        console.log("=======================================================");
        return result;
    }
    messageDigest.digest.overload('[B', 'int', 'int').implementation = function (data, start, length) {
        console.log("MessageDigest.digest('[B', 'int', 'int') is called!");
        showStacks();
        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, length);
        return result;
    }

    var mac = Java.use("javax.crypto.Mac");
    mac.init.overload('java.security.Key', 'java.security.spec.AlgorithmParameterSpec').implementation = function (key, AlgorithmParameterSpec) {
        console.log("Mac.init('java.security.Key', 'java.security.spec.AlgorithmParameterSpec') is called!");
        return this.init(key, AlgorithmParameterSpec);
    }
    mac.init.overload('java.security.Key').implementation = function (key) {
        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);
        console.log("=======================================================");
        return this.init(key);
    }
    mac.update.overload('byte').implementation = function (data) {
        console.log("Mac.update('byte') is called!");
        return this.update(data);
    }
    mac.update.overload('java.nio.ByteBuffer').implementation = function (data) {
        console.log("Mac.update('java.nio.ByteBuffer') is called!");
        return this.update(data);
    }
    mac.update.overload('[B').implementation = function (data) {
        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);
        console.log("=======================================================");
        return this.update(data);
    }
    mac.update.overload('[B', 'int', 'int').implementation = function (data, start, length) {
        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, length);
        return this.update(data, start, length);
    }
    mac.doFinal.overload().implementation = function () {
        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);
        console.log("=======================================================");
        return result;
    }

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

    cipher.init.overload('int', 'java.security.Key').implementation = function () {
        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);
        }
        console.log("=======================================================");
        return this.init.apply(this, arguments);
    }
    cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec').implementation = function () {
        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);
        console.log("=======================================================");
        return this.init.apply(this, arguments);
    }

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

    cipher.doFinal.overload('[B').implementation = function () {
        console.log("Cipher.doFinal('[B') is called!");
        showStacks();
        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("=======================================================");
        return result;
    }
    cipher.doFinal.overload('[B', 'int', 'int').implementation = function () {
        console.log("Cipher.doFinal('[B', 'int', 'int') is called!");
        showStacks();
        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[2]);
        return result;
    }

    var signature = Java.use("java.security.Signature");
    signature.update.overload('byte').implementation = function (data) {
        console.log("Signature.update('byte') is called!");
        return this.update(data);
    }
    signature.update.overload('java.nio.ByteBuffer').implementation = function (data) {
        console.log("Signature.update('java.nio.ByteBuffer') is called!");
        return this.update(data);
    }
    signature.update.overload('[B', 'int', 'int').implementation = function (data, start, length) {
        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, length);
        return this.update(data, start, length);
    }
    signature.sign.overload('[B', 'int', 'int').implementation = function () {
        console.log("Signature.sign('[B', 'int', 'int') is called!");
        return this.sign.apply(this, arguments);
    }
    signature.sign.overload().implementation = function () {
        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);
        console.log("=======================================================");
        return result;
    }

});

so关键函数

NewStringUTF

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:蝉SEC d0n9x1e d0n9x1e《【APP测试】快速定位加密》

Wifi钓鱼研究 网络安全文章

Wifi钓鱼研究

文章总结: 文章基于KaliLinux完整复现WiFi钓鱼:先验证无线网卡AP/监听模式,再用hostapd+dnsmasq伪造热点,通过iptablesNAT
评论:0   参与:  0