Frida-Hook-Java层操作大全

附件下载

GitHub - DERE-ad2001/Frida-Labs: The repo contains a series of challenges for learning Frida for Android Exploitation.

前期准备

  1. 使用 jadx 进行逆向工程的基础知识。
  2. 应具备理解 Java 代码的能力。
  3. 具备编写小型 JavaScript 代码片段的能力。
  4. 熟悉 adb。
  5. 设备已 root。
  6. Frida环境配置

Hook(Hooking)简介

让我们从非常基础的知识开始。

什么是钩子?

Hook是指拦截和修改应用程序或Android系统中函数或方法行为的过程。例如,我们可以钩取我们应用程序中的一个方法,并通过插入我们自己的实现来改变其功能。

现在,让我们尝试在一个应用程序中钩取一个方法。我们将使用JavaScript API 来完成这个任务,但值得注意的是,Frida也支持Python。

1、使用Hook修改被调用的方法的逻辑,返回值,传入参数

基本模板

首先让我提供给你一个模板,然后我们一步步来解释。

1

2

3

4

5

6

7

8

9

10

11

12

Java.perform(function() {

  var <class_reference> = Java.use("<package_name>.<class>");

  <class_reference>.<method_to_hook>.implementation = function(<args>) {

    /*

      我们自己的方法实现

    */

  }

})

  • Java.perform 是 Frida 中用于创建一个特殊上下文的函数,让你的脚本能够与 Android 应用程序中的 Java 代码进行交互。它就像是打开了一扇门,让你能够访问并操纵应用程序内部运行的 Java 代码。一旦进入这个上下文,你就可以执行诸如钩取方法或访问 Java 类等操作来控制或观察应用程序的行为。

  • var <class_reference> = Java.use("<package_name>.<class>");
    在这里,你声明一个变量 <class_reference> 来表示目标 Android 应用程序中的一个 Java 类。你使用 Java.use 函数指定要使用的类,该函数接受类名作为参数。<package_name> 表示 Android 应用程序的包名,<class> 表示你想要与之交互的类。
    <package_name> :

  • <class_reference>.<method_to_hook>.implementation = function(<args>) {}
    在所选的类内部,通过 <class_reference>.<method_to_hook> 符号访问你想要钩取的方法。这是你可以定义自己的逻辑以在钩取的方法被调用时执行的地方。<args> 表示传递给函数的参数。

例题Frida-Labs 0x1

通过Jadx分析Frida-labs 0x1

onCreate方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public void onCreate(Bundle bundle) {

    super.onCreate(bundle);

    setContentView(C0570R.layout.activity_main);

    final EditText editText = (EditText) findViewById(C0570R.C0573id.editTextTextPassword);

    this.f103t1 = (TextView) findViewById(C0570R.C0573id.textview1);

    final int i = get_random();

    ((Button) findViewById(C0570R.C0573id.button)).setOnClickListener(new View.OnClickListener() { // from class: com.ad2001.frida0x1.MainActivity.1

        @Override // android.view.View.OnClickListener

        public void onClick(View view) {

            String obj = editText.getText().toString();

            if (TextUtils.isDigitsOnly(obj)) {

                MainActivity.this.check(i, Integer.parseInt(obj));

            else {

                Toast.makeText(MainActivity.this.getApplicationContext(), "Enter a valid number !!"1).show();

            }

        }

    });

}

可以发现,在onCreate方法中,有一个监听事件,监听了button的点击,当按钮点击下去之后,程序首先判断输入是不是数字,是数字的话,就将其从string转化为int,再进入check中与i比较,因此我们需要检查check方法。

check方法

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

26

27

28

29

30

void check(int i, int i2) {

       if ((i * 2) + 4 == i2) {

           Toast.makeText(getApplicationContext(), "Yey you guessed it right"1).show();

           StringBuilder sb = new StringBuilder();

           for (int i3 = 0; i3 < 20; i3++) {

               char charAt = "AMDYV{WVWT_CJJF_0s1}".charAt(i3);

               if (charAt < 'a' || charAt > 'z') {

                   if (charAt >= 'A') {

                       if (charAt <= 'Z') {

                           charAt = (char) (charAt - 21);

                           if (charAt >= 'A') {

                           }

                           charAt = (char) (charAt + 26);

                       }

                   }

                   sb.append(charAt);

               else {

                   charAt = (char) (charAt - 21);

                   if (charAt >= 'a') {

                       sb.append(charAt);

                   }

                   charAt = (char) (charAt + 26);

                   sb.append(charAt);

               }

           }

           this.f103t1.setText(sb.toString());

           return;

       }

       Toast.makeText(getApplicationContext(), "Try again"1).show();

   }

本方法显而易见就是检查输入是否能够满足i*2 + 4 == i2,如果满足则将flag输出到f103t1所绑定的textView控件上,其中用于判断的i则来自get_random。

get_random

1

2

3

int get_random() {

    return new Random().nextInt(100);

}

显而易见,本方法就只是普通的返回一个随机数。

Hook begin!

对于本样例程序,我们有两种方法去解决,首先我们可以直接hook程序逻辑。更改随机产生的值为一个固定值。或者hook check方法更改check方法传入的参数

Hook get_random方法
实现代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

function hook(){

    var MainActivity = Java.use("com.ad2001.frida0x1.MainActivity");

    MainActivity.get_random.implementation = function (){

        return 0;

    }

}

function main(){

    Java.perform(function (){

        hook();

    })

}

setImmediate(main);

代码解释如下:

  1. 首先定义了一个名为hook的JavaScript函数,其中包含了对目标应用特定方法的hook逻辑。

    • hook函数通过Frida的Java API来获取目标应用中的MainActivity类。
    • 然后,它通过Java.use()方法获取了MainActivity类的引用,使得我们可以访问该类的方法。
    • 最后,hook函数将MainActivity类中的get_random方法进行了修改。它用自定义的实现替换了原有方法的实现,使得每次调用get_random方法时都返回固定值0。
  2. 接着定义了一个名为main的JavaScript函数,其中包含了Frida的Java.perform()方法,用于执行指定的hook逻辑。

  3. 最后,通过setImmediate()函数调用main函数,确保在Frida脚本启动后立即执行。

hook check方法

如果我们检查check函数的参数,第一个参数i表示随机数,而第二个参数i2对应于用户输入的数字。让我们使用Frida来捕获并转储这两个参数。

在处理具有参数的方法时,重要的是使用overload(arg_type)关键字指定预期的参数类型。此外,在钩入方法时确保包括这些指定的参数在你的实现中。在这里,我们的check()函数接受两个整数参数,所以我们可以这样指定:

1

2

3

4

5

a.check.overload(int, int).implementation = function(a, b) {

  ...

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

function hook2(){

    var MainActivity = Java.use("com.ad2001.frida0x1.MainActivity");

    MainActivity.check.overload('int','int').implementation = function (a,b){

        console.log("Origin i and i2 = ",a,b);

        return this.check(a,b);

    }

}

function main(){

    Java.perform(function (){

        hook2();

    })

}

setImmediate(main);

我们可以使用console.log查看传入的a与b是什么

 

2、Hook调用静态的未被调用的方法

在之前讲到的Java.use Api中,如果我们指定的类中包含了静态的方法,则我们可以直接调用该方法。模板如下:

1

2

3

4

Java.perform(function (){

    var <class_reference> = Java.use("<package_name>.<class>");

    a.function(val);

})

例题Frida-labs 0x2

MainActivity类

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

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

package com.ad2001.frida0x2;

import android.os.Bundle;

import android.util.Base64;

import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import javax.crypto.Cipher;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;

/* loaded from: classes3.dex */

public class MainActivity extends AppCompatActivity {

    /* renamed from: t1 */

    static TextView f103t1;

    /* JADX INFO: Access modifiers changed from: protected */

    @Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(C0569R.layout.activity_main);

        f103t1 = (TextView) findViewById(C0569R.C0572id.textview);

    }

    public static void get_flag(int a) {

        if (a == 4919) {

            try {

                SecretKeySpec secretKeySpec = new SecretKeySpec("HILLBILLWILLBINN".getBytes(), "AES");

                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

                IvParameterSpec iv = new IvParameterSpec(new byte[16]);

                cipher.init(2, secretKeySpec, iv);

                byte[] decryptedBytes = cipher.doFinal(Base64.decode("q7mBQegjhpfIAr0OgfLvH0t/D0Xi0ieG0vd+8ZVW+b4="0));

                String decryptedText = new String(decryptedBytes);

                f103t1.setText(decryptedText);

            catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

}

本用例程序就一个MainActivity类,类中存在一个未被使用的静态方法get_flag,在get_flag中比较了传入的参数,如果传入的参数为4919则解密flag,设置给txtView控件,那么根据之前给出的调用模板,我们hook代码如下:

Hook代码:

1

2

3

4

5

6

7

8

9

10

11

12

function hook(){

    var MainActivity = Java.use("com.ad2001.frida0x2.MainActivity");

    MainActivity.get_flag(4919);

}

function main(){

    Java.perform(function (){

        hook();

    })

}

setImmediate(main);

但是我们发现如果使用的是setIMMediate(main)的话我们使用
frida -U -f com.ad2001.frida0x2 -l .\Hook.js
可能会导致hook不上的情况。

file

解决方法1

我们事先启动Frida 0x2应用程序。然后使用如下命令注入我们的脚本
frida -U 'Frida 0x2' -l .\Hook.js

本方法与之前的方法不同之处是该方法是直接hook入我们后台正在启动的程序,而之前的方法是根据包名再启动一个程序。

解决方法2

当我们发现使用解决方法1能够成功hook的时候,就可以推断出,是由于我们启动main函数使用的是setImmediate(main),是立即启动可能会导致脚本注入的速度比程序启动的速度快。因此我们可以改用setTimeout(main,1000),也就是延迟1秒钟启动程序。

 

3、更改类中的静态变量

类似于如下写法static int code = 0;
使用static 修饰的变量则为静态变量。我们可以用如下方法更改静态变量。

1

2

3

4

5

6

Java.perform(function (){

    var <class_reference> = Java.use("<package_name>.<class>");

    <class_reference>.<variable>.value = <value>;

})

例题 Frida-labs 0x3

MainActivity类

标记处我们可以发现,当Checker.code为512的时候点击按钮,程序则会解密并且将textView控件设置为Flag。

Hook代码

1

2

3

4

5

6

7

8

9

10

11

function hook(){

    var a = Java.use("com.ad2001.frida0x3.Checker");

    a.code.value = 512;

}

function main(){

    Java.perform(function (){

        hook();

    })

}

setImmediate(main);

4、调用非MainActivity,非静态方法

在JAVA代码中,如果创建了一个非静态的类,当我们需要使用这个类的时候需要new一个类的对象出来我们才能使用这个类的功能。类似代码如下:

1

2

Check ch = new Check();

String flag = ch.get_flag(1337);

那么在Java源码中需要new出来的实例,我们怎么使用Frida来实现呢?
模板如下:

1

2

3

4

5

6

7

Java.perform(function() {

  var <class_reference> = Java.use("<package_name>.<class>");

  var <class_instance> = <class_reference>.$new(); // Class Object

  <class_instance>.<method>(); // 调用方法

})

例题Frida-labs 0x4

MainActivity:

 

Checker中出现了get_flag方法,返回了flag。则我们使用之前的模板来Hook

Hook代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

function hook(){

    console.log("Hook Success!");

    var Check = Java.use("com.ad2001.frida0x4.Check");

    var Check_obj = Check.$new();

    var String = Check_obj.get_flag(1337);

    console.log(String);

}

function main(){

    Java.perform(function (){

        hook();

    })

}

setImmediate(main);

 

5、调用MainActivity中的非静态方法

前面有提到过如果不是MainActivity中的方法我们使用.$new()可以创建一个实例。那么如果我们将这个使用到MainActivity会发生什么呢?

1

2

3

4

function hook(){

    var MainActivity = Java.use("com.ad2001.frida0x5");

    var MainActivity_obj = MainActivity.$new();

}

 

好吧,它崩溃了。那么这是什么原因呢?

直接使用Frida创建MainActivity或任何Android组件可能会很棘手,因为Android的生命周期和线程规则。Android组件,如Activity子类,依赖于应用程序上下文进行正确运行。在Frida中,您可能缺少必要的上下文。Android UI组件通常需要具有关联Looper的特定线程。如果涉及UI任务,请确保在具有活动Looper的主线程上执行。活动是较大的Android应用程序生命周期的一部分。创建MainActivity的实例可能需要应用处于特定状态,并且通过Frida管理整个生命周期可能并不直接。总之,为MainActivity创建实例并不是一个好主意。

那么这里的解决方案是什么呢?

当Android应用程序启动时,系统会创建MainActivity的一个实例(或AndroidManifest.xml文件中指定的启动器活动)。创建MainActivity实例是Android应用程序生命周期的一部分。因此,我们可以使用frida获取MainActivity的实例,然后调用flag()方法来获取我们的标志。

在现有实例上调用方法

在现有实例上调用方法可以很容易地通过Frida完成。为此,我们将使用两个API。

  • Java.performNow:用于在Java运行时环境中执行代码的函数。

  • Java.choose:在运行时枚举指定Java类(作为第一个参数提供)的实例。

让我展示一个模板给你。

1

2

3

4

5

6

7

8

Java.performNow(function() {

  Java.choose('<包名>.<类名>', {

    onMatch: function(instance) {

      // 待办事项

    },

    onComplete: function() {}

  });

});

这里有两个回调函数:

  • onMatch
    • onMatch回调函数在Java.choose操作期间找到指定类的每个实例时执行。
    • 这个回调函数接收当前实例作为它的参数。
    • 您可以在onMatch回调中定义自定义操作,以在每个实例上执行。
    • function(instance) {}instance参数表示目标类的每个匹配实例。您可以使用任何其他名称。
  • onComplete
    • onComplete回调在Java.choose操作完成后执行操作或清理任务。此块是可选的,如果您在搜索完成后不需要执行任何特定操作,则可以选择将其留空。

例题Frida-labs 0x5

MainActivity

可以发现其中flag方法是未被调用的方法,并且是解密密文将Flag输出到TextView控件上。

BeginHook!

现在我们知道如何使用Java.choose API,让我们开始编写我们的frida脚本。

  • 包名:com.ad2001.frida0x5
  • 类名:MainActivity
  • 函数名:flag

1

2

3

4

5

6

7

8

Java.performNow(function() {

  Java.choose('com.ad2001.frida0x5.MainActivity', {

    onMatch: function(instance) {

      // 待办事项

    },

    onComplete: function() {}

  });

});

让我们在成功找到MainActivity实例时包含一个console.log语句以打印一条消息。由于在枚举完成后我们没有任何特定的操作要执行,我们可以将onComplete块留空。

1

2

3

4

5

6

7

8

Java.performNow(function() {

  Java.choose('com.ad2001.frida0x5.MainActivity', {

    onMatch: function(instance) {

      console.log("找到实例");

    },

    onComplete: function() {}

  });

});

让我们启动Frida并注入我们的脚本。

 

Hook代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

function hook(){

    Java.choose('com.ad2001.frida0x5.MainActivity',{

        onMatch:function (MainActivity){

            MainActivity.flag(1337);

            console.log("Hook Success!");

        },onComplete:function (){

        }

    })

}

function main(){

    Java.perform(function (){

        hook();

    })

}

setImmediate(main);

 

6、MainActivity中非静态并且参数为非静态变量方法调用

例题Frida-labs 0x6

我们之前已经解决过类似的问题了。在这种情况下,我们有一个get_flag()方法,在应用程序中没有被调用。如果调用此方法,它将使用AES解密标志,并将标志设置在Textview中。如果我们检查get_flag方法,它只接受一个参数,这个参数是Checker类的一个实例。参数被命名为A,其类型是Checker

1

2

3

public void get_flag(Checker A) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

    // 方法体

}

在方法内部,它检查A.num1是否等于1234,以及A.num2是否等于4321。如果条件成立,该方法将继续使用AES解密加密字符串,并将解密后的结果设置在TextView中。因此,让我们检查一下Checker类。

 

在Checker类中,我们有两个变量。

  • num1
  • num2

num1应该等于1234num2应该等于4321,以满足if条件执行解密并设置标志的代码块。请记住,这个类也没有实例。

解决方案

这个问题很容易解决,因为我们之前已经在上一篇帖子中做过了,唯一的区别是get_flag方法的参数是Checker类的一个对象。我将总结解决这个问题的步骤如下:

  • 创建一个Checker类的实例。
  • num1设置为1234,num2设置为4321。
  • 获取MainActivity的实例。
  • 使用实例作为参数调用get_flag方法。

让我们开始编写我们的frida脚本。

首先让我们创建Checker类的实例。

1

2

var checker = Java.use("com.ad2001.frida0x6.Checker");

var checker_obj = checker.$new(); // 类对象

设置num1num2的值。

1

2

checker_obj.num1.value = 1234;

checker_obj.num2.value = 4321;

现在让我们获取MainActivity的实例。我们可以使用Java.performNowJava.chooseAPI。我们在之前的挑战中已经做过了。

1

2

3

4

5

6

7

8

9

Java.performNow(function() {

  Java.choose('com.ad2001.frida0x6.MainActivity', {

    onMatch: function(instance) {

      console.log("找到实例");

    },

    onComplete: function() {}

  });

})

让我们更新脚本,加入Checker类的实例。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

Java.performNow(function() {

  Java.choose('com.ad2001.frida0x6.MainActivity', {

    onMatch: function(instance) {

      console.log("找到实例");

      var checker = Java.use("com.ad2001.frida0x6.Checker");

      var checker_obj  = checker.$new();  // 类对象

      checker_obj.num1.value = 1234;

      checker_obj.num2.value = 4321;

    },

    onComplete: function() {}

  });

});

现在唯一要做的是通过传递Checker类的实例来调用get_flag方法。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Java.performNow(function() {

  Java.choose('com.ad2001.frida0x6.MainActivity', {

    onMatch: function(instance) {

      console.log("找到实例");

      var checker = Java.use("com.ad2001.frida0x6.Checker");

      var checker_obj  = checker.$new();  // 类对象

      checker_obj.num1.value = 1234; // num1

      checker_obj.num2.value = 4321; // num2

      instance.get_flag(checker_obj); // 调用get_flag方法

    },

    onComplete: function() {}

  });

});

让我们启动frida并运行我们的脚本。

1

PS C:\Users\ajind> frida --f com.ad2001.frida0x6

 

 

当我们检查我们的手机时,TextView将显示标志。

7、Hook构造函数

如果在ARM64 设备上不工作请看issue:Android (arm64) app ignores $init hook in code executed in HandlerThread. · Issue #1575 · frida/frida · GitHub

挂钩构造函数十分简单,与挂钩方法类似。让我为您提供一个模板。

1

2

3

4

5

6

7

8

9

10

Java.perform(function() {

  var <class_reference> = Java.use("<package_name>.<class>");

  <class_reference>.$init.implementation = function(<args>){

    /*

    */

  }

});

我们可以看到,为了挂钩构造函数,我们可以使用$init关键字。

例题Frida-labs 0x7

MainActivity

 

 

可以看到程序在使用flag方法判断之前,首先使用 Checker ch = new Checker(123, 321); 创建了一个Checker实例,则123 , 321 分别对应A.num1与 A.num2。
那么我们只需要钩住构造函数即可。

Hook代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

function hook(){

    var Checker = Java.use("com.ad2001.frida0x7.Checker");

    Checker.$init.implementation = function (a,b){

        console.log("Origin num",a,b);

        this.$init(600,600);

        console.log("Hook Success");

    }

}

function main(){

    Java.perform(function (){

        hook();

    })

}

setImmediate(main);

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/442025.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mapper4生成dao层

一.项目依赖: <dependencies><!--Mybatis 通用mapper tk单独使用&#xff0c;自己独有自带版本号--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.13</version></depe…

Jmeter 使用教程(小白一学就会)

下载 官网下载地址 解压 zip 打开 进入 jmeter 的 bin 目录下mac 电脑启动&#xff0c;执行以下命令&#xff08;注意 windows 使用 jmeter.bat 启动&#xff09; ./jmeter打开成功 修改为中文 创建测试计划 添加线程组 修改线程属性 在线程组添加 HTTP 请求 设置 Web…

Graphpad Prism10.2.1(395) 安装教程 (含Win/Mac版)

GraphPad Prism GraphPad Prism是一款非常专业强大的科研医学生物数据处理绘图软件&#xff0c;它可以将科学图形、综合曲线拟合&#xff08;非线性回归&#xff09;、可理解的统计数据、数据组织结合在一起&#xff0c;除了最基本的数据统计分析外&#xff0c;还能自动生成统…

Java后端核心——Servlet

目录 一.概述 二.基础实现 1.导入坐标 2.定义实现类 3.注解 4.访问Servlet 三.执行流程 四.生命周期 1.加载和实例化 2.初始化 3.请求处理 4.服务终止 五.方法 1.init 2.service 3.destroy 4.getServletInfo 5.getServletConfig 六.体系结构 七.urlPatter…

JavaWeb基础入门——(二)MySQL数据库基础(2-SQL 结构化查询语言)

四、MySQL逻辑结构 4.1 逻辑结构 4.1 记录 五、SQL 结构化查询语言 5.1 SQL概述 SQL&#xff08;Structural Query Language&#xff09;结构化查询语言&#xff0c;用于存取、查询、更新数据以及管理关系型数据库系统 5.1.1 SQL发展 SQL是在1981年由IBM公司推出&#xff0c;…

【论文阅读笔记】Activating More Pixels in Image Super-Resolution Transformer

论文地址&#xff1a;https://arxiv.org/abs/2205.04437 代码位置&#xff1a;https://github.com/XPixelGroup/HAT 论文小结 本文方法是基于Transformer的方法&#xff0c;探索了Transformer在低级视觉任务&#xff08;如SR&#xff09;中的应用潜力。本文提升有效利用像素范…

iOS增量报告生成方案

一&#xff0c;iOS覆盖率报告生成逻辑 iOS覆盖率报告生成与Android有很大的不同&#xff0c;主要的生成逻辑如下&#xff1a; 1&#xff0c;将profraw文件&#xff0c;通过命令xcrun llvm-profdata merge -sparse转换成profdata; 2&#xff0c;再将profdata文件&#xff0c;通…

R语言自定义颜色

一、创建颜色梯度&#xff08;渐变色&#xff09; 在绘热图时&#xff0c;需要将数值映射到不同的颜色上&#xff0c;这时就需要一系列的颜色梯度colorRampPalette 函数支持自定义的创建一系列的颜色梯度。 代码示例&#xff1a; library(RColorBrewer)x <- colorRampPal…

Neo4j安装 Linux:CentOS、openEuler 适配langchain应用RAG+知识图谱开发 适配昇腾910B

目录 Neo4j下载上传至服务器后进行解压运行安装JAVA再次运行在windows端打开网页导入数据 Neo4j下载 进入Neo4j官网下载页面 向下滑动找到 Graph Database Self-Managed 选择 社区版&#xff08;COMMUNITY&#xff09; 选择 Linux / Mac Executable Neo4j 5.17.0 (tar) 单机下…

sheng的学习笔记-AI-多分类学习:ECOC,softmax

目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 基本术语&#xff1a; 若我们欲预测的是离散值&#xff0c;例如“好瓜”“坏瓜”&#xff0c;此类学习任务称为“分类”(classification)&#xff1b; 若欲预测的是连续值&#xff0c;例如西瓜成熟度0.95、0.37&#xff0c;…

公网IP与私有IP及远程互联

1.公网有私有IP及NAT 公网IP是全球唯一的IP&#xff0c;通过公网IP&#xff0c;接入互联网的设备是可以访问你的设备。但是IPV4资源有限&#xff0c;一般ISP(Internet Service Provider)并不会为用户提供公网IP。所以家里的计算机在公司是没法直接使用windows远程桌面直接访问…

【Python】新手入门:变量的作用域是什么?有哪几种作用域?作用域的查找顺序是什么?

【Python】新手入门&#xff1a;变量的作用域是什么&#xff1f;有哪几种作用域&#xff1f;作用域的查找顺序是什么&#xff1f; &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基…

LinkedHashMap、HashSet、LinkedHashSet的源码剖析。

LinkedHashMap、HashSet、LinkedHashSet的源码剖析 1. LinkedHashMap2. HashSet3. LinkedHashSet LinkedHashMap、HashSet和LinkedHashSet都是Java中常用的集合类&#xff0c;下面分别剖析一下它们的源码看看。 1. LinkedHashMap LinkedHashMap继承自HashMap&#xff0c;通过维…

软考高级:信息系统建设原则概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

谷歌浏览器连接上WiFi之后无法正常浏览网站-报错:有一款应用正在组织Chrome安全连接到此网站

现象分析&#xff1a; 出现这个报错&#xff1a;&#xff08;明明已经连接上家里的wifi却还是无法正常登录其他网站&#xff09; 解决办法&#xff1a; 是因为电脑上加了网络代理&#xff0c;删除掉就好了 直接搜索&#xff1a;网络代理 把这2个位置记得清空&#xff0c;然…

守护Web安全:了解Web攻击与防护策略

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

对某旅行APP的检测以及参数计算分析【新手向-Simplesign篇】

简要概述&#xff1a; 目标so&#xff1a;scmain.so 讨论的生成过程&#xff1a;SimpleSign 使用工具&#xff1a;IDA pro 7.7、 Binary Ninja、Frida、Frida Stalker 本篇文章实现&#xff1a; SimpleSign的计算过程&#xff0c;包括前、中、后、变换四个主体阶段&#xf…

蓝桥杯刷题(二)

参考大佬代码&#xff1a;&#xff08;区间合并二分&#xff09; import os import sysn, L map(int, input().split()) # 输入n,len arr [list(map(int, input().split())) for _ in range(n)] # 输入Li,Si def check(Ti, arr, L)->bool:sec [] # 存入已打开的阀门在…

如何防御udp攻击

UDP Flood是互联网上最经典的DDoS&#xff08;Distributed Denial of Service&#xff09;攻击之一。攻击者在短时间内向目标设备发送大量的UDP报文&#xff0c;导致链路拥塞甚至网络瘫痪。一般的UDP报文由攻击工具伪造&#xff0c;通常在数据段具备相同的特征&#xff0c;另一…

从3V到12V,升压芯片该选哪个?

在电子系统设计中&#xff0c;升压芯片很重要&#xff0c;将直接影响到系统的稳定性、效率及噪声&#xff0c;特别是在需要将3V升到12V中&#xff0c;选择合适的升压芯片尤为关键&#xff0c;那么如何针对这个需求&#xff0c;合理选择升压芯片&#xff1f; 1、如何选择升压芯片…