当前位置: 首页 > news >正文

安卓逆向之脱壳-认识一下动态加载 双亲委派(一)

在这里插入图片描述
安卓逆向和脱壳是安全研究、漏洞挖掘、恶意软件分析等领域的重要环节。脱壳(unpacking)指的是去除应用程序中加固或保护措施的过程,使得可以访问应用程序的原始代码或者数据。脱壳的重要性:

  1. 分析恶意软件:很多恶意软件采用加壳技术来隐藏其真实行为。脱壳后,安全研究人员可以更容易地理解恶意代码的实现方式、传播途径及其攻击目标,帮助开发有效的防御策略。
  2. 漏洞分析:应用程序可能存在各种漏洞,比如远程代码执行、信息泄露等。通过脱壳,可以查看原始代码,分析潜在漏洞,进而发现可能的攻击面。
  3. 破解保护机制:很多安卓应用为了保护自己的知识产权或防止被修改,会采用加壳技术或其他防篡改机制。逆向工程和脱壳可以帮助研究者绕过这些保护,获取应用的原始功能或源代码。
  4. 提升安全性:通过脱壳并分析应用的源代码,可以发现其安全缺陷并加以修复。这对安卓开发者来说,能够提升自己的应用在面对恶意攻击时的安全性。
  5. 反作弊:一些游戏或者应用采用加壳和加密技术来防止被作弊或修改。脱壳能够帮助研究者或者开发者对抗这些作弊行为,确保应用的公平性和安全性。

脱壳技术一般涉及到一些技巧,比如使用动态调试工具(如Frida, Xposed等)、静态分析工具(如IDA Pro, Ghidra等)以及一些专用的脱壳工具(如UnpackMe, Apktool等)。掌握这些工具和技巧对安卓逆向工程师来说非常重要。

1.讲述Android开发中dex文件加载的class loader机制,特别是pass class loader在加载未加壳类中的作用

在 Android 开发中,Dex(Dalvik Executable)文件是应用程序的核心,它包含了字节码,供 Android 的虚拟机(Dalvik VM 或 ART)执行。Android 系统中的 ClassLoader 是加载这些字节码并将其转换为 Java 类的关键组件。理解 ClassLoader 的工作机制,尤其是 Pass ClassLoader,对于深入理解 Android 逆向与脱壳过程具有重要意义。

1. Android 的 ClassLoader 机制概述

Android 使用多种 ClassLoader 来加载不同类型的类。默认情况下,Android 使用的是 PathClassLoader 来加载应用程序的 dex 文件。它通过以下几个步骤工作:

  • 系统 ClassLoader (BootClassLoader):它负责加载 Android 系统核心库(如 android.*java.* 等)。
  • 应用 ClassLoader (PathClassLoader):负责加载应用程序的主 dex 文件。
  • 用户 ClassLoader (DexClassLoader):在一些高级应用中,允许动态加载外部的 dex 文件(例如插件化框架)。

每个 ClassLoader 都有自己的类加载路径,它们通过层层委托的方式来加载类。委托模式意味着一个 ClassLoader 会请求父 ClassLoader 加载类,直到找到该类为止。如果父 ClassLoader 不能加载该类,它才会尝试自行加载。

2. Pass ClassLoader 的作用

Pass ClassLoader 是一个特殊的类加载器,它主要用于 加载未经过加壳或加密保护的类,特别是在进行逆向分析或破解时。为了更好地理解 Pass ClassLoader,我们需要先了解一些加壳和加密的基本概念。

在一些保护措施中,开发者可能会对应用程序的 dex 文件进行加壳或加密。加壳后,dex 文件中的字节码被封装在某种保护的形式中,需要特定的脱壳工具或机制才能提取和加载原始的类。

Pass ClassLoader 的作用:

  • 绕过壳层:对于加壳的 dex 文件,Pass ClassLoader 可以直接加载那些未经过加密保护的类,避免常规的 ClassLoader 在加载时受壳层的干扰。
  • 绕过保护:在一些反调试、反篡改或者加密的情况下,Pass ClassLoader 可以让逆向人员加载未加密的类代码,帮助分析原始逻辑。
  • 实现代码注入:在 Android 逆向过程中,有时会通过 Pass ClassLoader 动态地注入新的类或修改已有类,尤其是做插件化开发时。它能够动态加载外部的 dex 文件,支持模块化的加载机制。

3. Pass ClassLoader 在脱壳过程中的作用

在一些典型的脱壳和逆向过程中,Pass ClassLoader 是必不可少的工具。具体来说,它在脱壳中的作用体现在以下几个方面:

  • 动态加载未加壳类:在很多情况下,应用的某些类(尤其是加壳的 dex 文件)会被包装或加密,不能直接用常规的 ClassLoader 加载。这时,使用 Pass ClassLoader 就能绕过加密保护,直接加载未加壳的类。
  • 绕过防篡改机制:有些应用在加载过程中会使用复杂的防篡改机制,比如校验 dex 文件的完整性或签名。Pass ClassLoader 通过绕过这些机制,能够加载原始类,供分析和修改。
  • 支持动态调试与注入:逆向分析人员可以利用 Pass ClassLoader 动态注入自己的类或修改已有类,实现代码修改和调试。这对于破解和动态分析非常有用。

4. 实际应用中的 Pass ClassLoader

在实际的 Android 逆向过程中,Pass ClassLoader 主要应用于以下场景:

  • 加壳应用的逆向分析:对于通过加壳或加密保护的应用,通过脱壳可以恢复其原始的 dex 文件。而在一些加壳的应用中,Pass ClassLoader 用于加载脱壳后的类,使得它们可以被执行和分析。
  • 恶意软件分析:恶意软件分析时,攻击者常通过加壳技术隐藏真实的攻击代码。研究人员使用 Pass ClassLoader 绕过壳层,将恶意代码加载到内存中,以便分析其行为。
  • 插件化框架的实现:一些 Android 插件化框架(例如 RePluginXposed)使用 Pass ClassLoader 来动态加载外部 dex 文件和插件,支持运行时动态扩展和模块化。

5. 小结

在 Android 开发与逆向过程中,ClassLoader 是管理 dex 文件加载的核心组件,而 Pass ClassLoader 则是绕过加壳和加密保护、加载原始类的重要工具。在逆向分析、恶意软件分析、漏洞挖掘等场景中,理解并灵活应用 Pass ClassLoader,可以帮助研究人员突破保护措施,更加高效地进行代码审计和漏洞分析。

相关学习链接:

https://segmentfault.com/a/1190000008491597

https://blog.csdn.net/u014634338/article/details/81434327

https://segmentfault.com/a/1190000013469223

2.class loader的加载流程、脱壳点及pass list对象的重要性,展示了如何验证class loader类型及获取其加载的dex文件信息

1. ClassLoader 的加载流程

在 Android 中,ClassLoader 主要负责将字节码(即 .dex 文件中的内容)转换成类,并将其加载到 JVM 或 ART 中。类加载器的加载过程遵循以下的流程:

1.1 类加载的步骤

  1. 查找类:当程序请求加载一个类时,ClassLoader 会首先查找其缓存中是否已有该类。如果存在,就直接返回该类。如果没有,它会进入加载过程。
  2. 委托给父类加载器:按照 委托机制(父类优先),如果当前 ClassLoader 没有加载该类,它会将加载请求委托给父加载器处理。父类加载器会继续递归地查找该类。
  3. 加载类:如果父加载器无法加载该类,当前加载器才会尝试从指定的路径(通常是 .dex 文件或 .jar 包)中加载类。
  4. 字节码解析:在 ClassLoader 找到类的字节码之后,它会将字节码解析为 Class 对象,放到内存中。此时类加载完成,可以通过反射等方式进行访问。

1.2 ClassLoader的层次结构

Android 中的类加载器是按照父子关系来进行层次化管理的:

  • 系统 ClassLoader(BootClassLoader):负责加载 Java 核心类库(如 java.lang.*android.* 等)。
  • 应用 ClassLoader(PathClassLoader):负责加载应用程序的主 .dex 文件。
  • 插件类加载器(DexClassLoader):在一些动态加载的场景下(如插件化框架),会用 DexClassLoader 来加载外部的 dex 文件。

2. 脱壳点与 Pass ClassLoader 的重要性

2.1 脱壳点

在 Android 应用的逆向工程过程中,很多开发者会使用一些加壳工具(如 ProGuard、DexGuard、AndResGuard 等)来对 .dex 文件进行加密或加壳,防止代码被轻易反编译或篡改。脱壳的目的是恢复加密或加壳后的真实 .dex 文件,以便进一步分析。

脱壳的常见手段

  • 静态脱壳:使用反编译工具(如 IDA、Ghidra)静态地分析壳层和加密算法,直接恢复 dex 文件。
  • 动态脱壳:通过动态调试工具(如 Frida、Xposed)分析程序的运行时行为,提取真实的 dex 文件。

脱壳点

  • 解密算法:很多加密的 dex 文件会包含一段加密或解密的逻辑。脱壳点一般会在该解密算法的关键步骤或函数中。
  • 类加载器修改:一些加壳工具通过修改类加载器的行为来保护 dex 文件,逆向人员需要在加载类的过程中发现解密或还原 dex 文件的点。

2.2 Pass ClassLoader 的作用

Pass ClassLoader 是一个特殊的类加载器,用于在加载未加壳类时绕过一些防护机制。它的作用在于:

  • 绕过加壳保护:当 dex 文件经过加壳加密时,Pass ClassLoader 可以帮助绕过壳层,直接加载未加壳的类。
  • 动态分析:通过 Pass ClassLoader 可以帮助分析应用的实际行为,尤其是用于绕过反篡改机制,进行恶意软件分析。

3. 如何验证 ClassLoader 类型及获取加载的 Dex 文件信息

在 Android 逆向工程过程中,验证 ClassLoader 类型并获取其加载的 .dex 文件信息是一个关键步骤。以下是一些实用的技巧和方法。

3.1 验证 ClassLoader 类型

要验证当前类是通过哪个 ClassLoader 加载的,通常可以利用 Java 的反射机制来获取当前类的加载器。

ClassLoader classLoader = MyClass.class.getClassLoader();
Log.d("ClassLoader", "ClassLoader: " + classLoader);

这将返回一个 ClassLoader 对象,表示当前类的加载器。通过判断其类型,可以知道是否为 PathClassLoaderDexClassLoader 或者 BaseDexClassLoader(Android 中的父类)。

3.2 获取加载的 Dex 文件信息

要获取当前 ClassLoader 加载的 .dex 文件信息,可以通过以下步骤:

  • PathClassLoader:对于应用的主 dex 文件,可以通过反射或直接访问 PathClassLoader 的构造函数来获取它的加载路径。
PathClassLoader pathClassLoader = (PathClassLoader) MyClass.class.getClassLoader();
Field pathListField = PathClassLoader.class.getDeclaredField("pathList");
pathListField.setAccessible(true);
Object pathList = pathListField.get(pathClassLoader);Field dexElementsField = pathList.getClass().getDeclaredField("dexElements");
dexElementsField.setAccessible(true);
Object[] dexElements = (Object[]) dexElementsField.get(pathList);for (Object dexElement : dexElements) {Field dexFileField = dexElement.getClass().getDeclaredField("dexFile");dexFileField.setAccessible(true);Object dexFile = dexFileField.get(dexElement);Log.d("DexFile", "Loaded dex: " + dexFile);
}

这段代码会获取并打印出通过 PathClassLoader 加载的 .dex 文件的信息。

  • DexClassLoader:如果是使用 DexClassLoader 加载的 dex 文件,可以直接获取其 dex 路径信息。一般来说,DexClassLoader 加载的 dex 文件路径会通过构造函数传入。
DexClassLoader dexClassLoader = (DexClassLoader) MyClass.class.getClassLoader();
String dexPath = dexClassLoader.getDexPath();
Log.d("DexClassLoader", "Dex path: " + dexPath);

这将打印出 DexClassLoader 加载的 .dex 文件的路径。

3.3 动态加载 Dex 文件

在一些动态分析的场景下,可以利用 DexClassLoader 动态加载一个外部的 dex 文件:

DexClassLoader dexClassLoader = new DexClassLoader(dexPath, optimizedDirectory, null, context.getClassLoader());
Class<?> loadedClass = dexClassLoader.loadClass("com.example.DynamicClass");

通过这种方式,加载一个外部 dex 文件,可以动态地加载并执行其中的类。

4. 总结

  • ClassLoader 流程:类加载器通过查找和委托机制加载类,分为系统加载器、应用加载器、插件加载器等。
  • 脱壳点和 Pass ClassLoader:在加壳应用中,Pass ClassLoader 用于绕过加壳保护,直接加载未加壳类,尤其在动态调试与恶意软件分析中非常重要。
  • 验证 ClassLoader 和加载的 Dex 信息:通过反射和直接访问类加载器内部字段,能够验证当前类加载器的类型并获取加载的 dex 文件信息。

这些方法对于 Android 逆向工程、漏洞分析以及动态调试和脱壳过程非常有帮助。

3.提及自定义class loader和found class在加载过程中的作用,深入具体实现细节

1. 自定义 ClassLoader

在 Android 或 Java 中,我们可以创建自定义的 ClassLoader 来修改或扩展默认的类加载行为。自定义 ClassLoader 通常用于以下几种场景:

  • 动态加载外部 .dex 文件:用于插件化框架或动态加载模块。
  • 绕过安全性措施:比如绕过加壳保护、篡改默认的类加载机制等。
  • 动态代码注入与修改:通过修改 ClassLoader 的行为,注入自己的类或者修改已有类。

自定义 ClassLoader 的关键在于重写 findClass()loadClass() 方法。这里是 Java 中 ClassLoader 加载类的基本原理和我们如何自定义加载过程。

2. ClassLoader 的默认加载流程

  1. loadClass():每个 ClassLoader 都会重写 loadClass() 方法。loadClass() 方法会首先检查类是否已经加载,如果已加载,则直接返回该类。如果没有加载,它会调用 findClass() 来查找并加载类。
  2. findClass()findClass()ClassLoader 类的一个抽象方法,我们可以在自定义的 ClassLoader 中实现该方法。findClass() 负责实际的类加载工作,它通过 byte[] 数据来创建 Class 对象。
  3. 委托机制ClassLoader 是基于父类委托的机制来加载类的。也就是说,当一个 ClassLoader 请求加载类时,它会首先委托给父 ClassLoader 来加载类。如果父 ClassLoader 无法加载类,它才会自行加载。

3. 自定义 ClassLoader 的实现

下面是一个简单的自定义 ClassLoader 的例子,用于加载外部 dex 文件中的类:

public class MyClassLoader extends ClassLoader {private String dexPath;public MyClassLoader(String dexPath, ClassLoader parent) {super(parent); // 使用系统的默认类加载器作为父加载器this.dexPath = dexPath;}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {// 获取 dex 文件中的字节码数据byte[] classData = loadClassData(name);if (classData == null) {throw new ClassNotFoundException("Class " + name + " not found in dex file.");}// 将字节码数据转换成 Class 对象return defineClass(name, classData, 0, classData.length);}private byte[] loadClassData(String className) {// 将类名转换为对应的文件路径String filePath = dexPath + "/" + className.replace('.', '/') + ".dex";try (InputStream inputStream = new FileInputStream(filePath)) {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();int data;while ((data = inputStream.read()) != -1) {byteArrayOutputStream.write(data);}return byteArrayOutputStream.toByteArray();} catch (IOException e) {e.printStackTrace();return null;}}
}

在这个例子中,我们重写了 findClass() 方法来加载指定路径下的 .dex 文件中的类,并通过 defineClass() 方法将字节码转换成 Class 对象。

4. findClass()defineClass()

  • findClass():该方法是自定义 ClassLoader 中最重要的部分,它负责查找并加载字节码。它的输入是类名,通过特定的逻辑获取字节码后,调用 defineClass() 来完成类的加载。

  • defineClass():该方法将字节码(byte[])转换为 Class 对象。它的签名如下:

    protected Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError
    • name:类的全名(包括包名)。
    • b:字节码数组。
    • off:字节码数组的起始偏移。
    • len:字节码的长度。

    defineClass() 会创建一个新的 Class 对象,并加载到 JVM 中,之后可以通过该类对象进行反射操作。

5. foundClass 在加载过程中的作用

foundClass 并不是 ClassLoader 中的标准方法,但它的概念通常用于描述在加载类的过程中,ClassLoader 查找到了目标类,并将其作为 Class 对象返回。

在自定义 ClassLoader 中,findClass() 方法返回的就是 “found class”。而在 loadClass() 方法中,如果父类 ClassLoader 能够找到并加载目标类,就直接返回该类,否则会委托给 findClass() 方法。

以下是一个简化的过程说明:

  1. 请求加载类:如果请求加载的类尚未加载,loadClass() 会调用 findClass()
  2. findClass() 查找类findClass() 会尝试根据类名找到该类的字节码数据。
  3. 返回找到的类(found class):如果成功找到并加载字节码,就通过 defineClass() 返回一个 Class 对象。这时,类被认为是“已找到”(found)并成功加载。

6. 验证 ClassLoader 类型及加载的 Dex 信息

验证当前类是由哪个 ClassLoader 加载,可以使用 getClassLoader() 方法。例如:

ClassLoader classLoader = MyClass.class.getClassLoader();
Log.d("ClassLoader", "ClassLoader: " + classLoader);

这会输出当前类加载器的类型(如 PathClassLoaderDexClassLoader 或自定义的 ClassLoader)。如果你想进一步分析加载的 .dex 文件或验证具体的路径,可以使用反射来获取更详细的信息,如:

Field pathListField = PathClassLoader.class.getDeclaredField("pathList");
pathListField.setAccessible(true);
Object pathList = pathListField.get(classLoader);Field dexElementsField = pathList.getClass().getDeclaredField("dexElements");
dexElementsField.setAccessible(true);
Object[] dexElements = (Object[]) dexElementsField.get(pathList);for (Object dexElement : dexElements) {Field dexFileField = dexElement.getClass().getDeclaredField("dexFile");dexFileField.setAccessible(true);Object dexFile = dexFileField.get(dexElement);Log.d("DexFile", "Loaded dex: " + dexFile);
}

7. 总结

  • 自定义 ClassLoader:通过重写 findClass()loadClass() 方法,我们可以控制类加载的具体过程,包括加载外部 dex 文件,或修改加载机制。
  • findClass() 的角色findClass() 是自定义 ClassLoader 中查找类并返回字节码的关键方法,它将字节码数据转换为 Class 对象。
  • foundClass:指的是 ClassLoader 成功加载并返回的类。在加载过程中,类可能会经过多次查找,直到找到并返回给请求者。
  • 验证类加载器类型和加载的 dex 文件:可以通过反射获取当前 ClassLoader 和它加载的 dex 文件路径,帮助进行调试和分析。

通过自定义 ClassLoader,我们可以更灵活地控制类的加载过程,尤其是在插件化框架、动态代码注入和逆向分析等领域,这些技巧非常有用。

相关文章:

安卓逆向之脱壳-认识一下动态加载 双亲委派(一)

安卓逆向和脱壳是安全研究、漏洞挖掘、恶意软件分析等领域的重要环节。脱壳&#xff08;unpacking&#xff09;指的是去除应用程序中加固或保护措施的过程&#xff0c;使得可以访问应用程序的原始代码或者数据。脱壳的重要性&#xff1a; 分析恶意软件&#xff1a;很多恶意软件…...

Nuxt:利用public-ip这个npm包来获取公网IP

目录 一、安装public-ip包1.在Vue组件中使用2.在Nuxt.js插件中使用public-ip 一、安装public-ip包 npm install public-ip1.在Vue组件中使用 你可以在Nuxt.js的任意组件或者插件中使用public-ip来获取公网IP。下面是在一个Vue组件中如何使用它的例子&#xff1a; <template…...

babylon.js-3:了解STL网格模型

网格模型上色 本篇文章主要介绍如何在 BabylonJS 中实现STL网格模型上色。 文章目录 网格模型上色运用场景概要延申正文加载器库的支持认识 OBJ 和 STL 文件GUI 色板选择器网格模型异步加载加载动画网格模型上色官方即将弃用 ImportMesh 而推荐使用 ImportMeshAsync 说明OBJ …...

基于SpringBoot的假期周边游平台的设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

【MySQL】初始MySQL、库与表的操作

目录 基本使用 使用案例 SQL分类 存储引擎 库的操作 字符集和校验规则 查看系统默认字符集和校验规则 查看数据库支持的字符集 查看数据库支持的字符集校验规则 指定编码常见数据库 校验规则对数据库的影响 操纵数据库 库的备份与恢复 表的操作 创建表 查看表 …...

将DeepSeek接入Word,打造AI办公助手

最近&#xff0c;DeepSeek热度一路高涨&#xff0c;成为AI领域的焦点。通过开放的API&#xff0c;我们可以将DeepSeek接入Word&#xff0c;直接进行AI对话。更进一步&#xff0c;还能利用DeepSeek辅助修改文档&#xff0c;甚至提出一些排版建议。 Word报告工具已经新增“DeepS…...

Coze,Dify,FastGPT,对比

在当今 AI 技术迅速发展的背景下&#xff0c;AI Agent 智能体成为了关键领域&#xff0c;Coze、Dify 和 FastGPT 作为其中的佼佼者&#xff0c;各有千秋。 平台介绍 - FastGPT&#xff1a;由环界云计算公司发起&#xff0c;是基于大语言模型&#xff08;LLM&#xff09;的开源…...

Kafka 日志存储 — 磁盘存储

Kafka 依赖与磁盘来存储和缓存消息&#xff0c;采用文件追加的方式来写入消息。顺序写盘的速度快于随机写内存。 1 磁盘存储 除顺序写入外&#xff0c;Kafka中大量使用了页缓存、零拷贝等技术来进一步提升吞吐性能。 1.1 页缓存 页缓存是操作系统实现的一种磁盘缓存&#x…...

996引擎 - NPC-添加NPC引擎自带形象

996引擎 - NPC-添加NPC引擎自带形象 截图参考添加NPC参考资料截图参考 添加NPC 编辑NPC表:Envir\DATA\cfg_npclist.xls 1.1. 需要临时隐藏NPC时可以在id前加 // 1.2. 如果NPC朝向不对,可以调整dir 列。(按8方向,上是0顺时针数。我这里给的4) 1.3. 形象代码:NPC代码、怪物…...

GL C++显示相机YUV视频数据使用帧缓冲FBO后期处理,实现滤镜功能。

一.前言&#xff1a; GitHub地址&#xff1a;GitHub - wangyongyao1989/WyFFmpeg: 音视频相关基础实现 系列文章&#xff1a; 1. OpenGL Texture C 预览Camera视频&#xff1b; 2. OpenGL Texture C Camera Filter滤镜; 3. OpenGL 自定义SurfaceView Texture C预览Camera视…...

【hot100】刷题记录(7)-除自身数组以外的乘积

题目描述&#xff1a; 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#x…...

解决.NET程序通过网盘传到Linux和macOS不能运行的问题

问题描述&#xff1a;.net程序用U盘传到虚拟机macOS和Linux可以正常运行&#xff0c;但是网盘传过去就不行。 解决方法&#xff1a; 这是文件权限的问题。当你通过U盘将文件传输到虚拟机的macOS和Linux系统时&#xff0c;文件的权限和所有权可能得到了保留或正确设置。但如果…...

练习(复习)

大家好&#xff0c;今天我们来做几道简单的选择题目来巩固一下最近学习的知识&#xff0c;以便我们接下来更好的学习。 这道题比较简单&#xff0c;我们前面学过&#xff0c;在Java中&#xff0c;一个类只能继承一个父类&#xff0c;但是一个父类可以有多个子类&#xff0c;一个…...

Class2(2020):Shell基础(二)——Shell脚本设计基础

本系列博客为MIT的《Missing in CS Class》的课程笔记。 Class2(2020):Shell基础(二)——Shell脚本设计基础 注&#xff1a;若无特殊说明&#xff0c;本文中带有[]的部分均为可选参数。 脚本文件 脚本语言为解释执行&#xff0c;其运行需有解释器&#xff0c;如Python。Shel…...

HBase-2.5.10 伪分布式环境搭建【Mac】

文章目录 前言一、搭建单节点Zookeeper1. 解压zookeeper2. 配置环境变量3. 修改配置文件4. 启动zk 二、搭建伪分布式Hbase1. 解压hbase2. 配置环境变量3. 修改配置4. 启动HBase 前言 搭建hbase伪分布式环境 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例仅供参…...

计算机毕业设计Python+CNN卷积神经网络高考推荐系统 高考分数线预测 高考爬虫 协同过滤推荐算法 Vue.js Django Hadoop 大数据毕设

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

macos的图标过大,这是因为有自己的设计规范

苹果官方链接&#xff1a;App 图标 | Apple Developer Documentation 这个在官方文档里有说明&#xff0c;并且提供了sketch 和 ps 的模板。 figma还提供了模板&#xff1a; Figma...

2025_1_29 C语言学习中关于指针

1. 指针 指针就是存储的变量的地址&#xff0c;指针变量就是指针的变量。 1.1 空指针 当定义一个指针没有明确指向内容时&#xff0c;就可以将他设置为空指针 int* p NULL;这样对空指针的操作就会使程序崩溃而不会导致出现未定义行为&#xff0c;因为程序崩溃是宏观的&…...

解决ImportError: cannot import name ‘notf‘

解决ImportError: cannot import name ‘notf‘ 报错&#xff1a; 报错代码&#xff1a; from torch.utils.tensorboard import SummaryWriter cannot import name notf from tensorboard.compat 解决方法&#xff1a; pip install numpy1.26.0 测试代码&#xff1a; py…...

HTML<label>标签

例子 三个带标签的单选按钮&#xff1a; <form action"/action_page.php"> <input type"radio" id"html" name"fav_language" value"HTML"> <label for"html">HTML</label><br&…...

shiro学习五:使用springboot整合shiro。在前面学习四的基础上,增加shiro的缓存机制,源码讲解:认证缓存、授权缓存。

文章目录 前言1. 直接上代码最后在讲解1.1 新增的pom依赖1.2 RedisCache.java1.3 RedisCacheManager.java1.4 jwt的三个类1.5 ShiroConfig.java新增Bean 2. 源码讲解。2.1 shiro 缓存的代码流程。2.2 缓存流程2.2.1 认证和授权简述2.2.2 AuthenticatingRealm.getAuthentication…...

大数据Hadoop入门1

目录 相关资料 第一部分 1.课程内容大纲和学习目标 2.数据分析和企业数据分析方向 3.数据分析基本流程步骤 4.大数据时代 5.分布式和集群 6.Linux操作系统概述 7.VMware虚拟机概念与安装 8.centos操作系统的虚拟机导入 9.VMware虚拟机常规使用、快照 第二部分 1.课…...

《智能家居“孤岛危机”:设备孤立如何拖垮系统优化后腿》

在科技飞速发展的今天&#xff0c;智能家居不再是遥不可及的概念&#xff0c;它正逐渐走进千家万户&#xff0c;为我们描绘出舒适便捷的未来生活蓝图。想象一下&#xff0c;下班回家前&#xff0c;你可以通过手机远程开启空调&#xff0c;让室内温度恰到好处&#xff1b;到家时…...

DeepSeek介绍及使用ollama本地化部署DeepSeek-R1大模型

DeepSeek 中文名深度求索人工智能基础技术研究有限公司(简称“深度求索”或“DeepSeek”)&#xff0c;成立于2023年&#xff0c;是一家专注于实现AGI的中国公司。 在本月初推出 DeepSeek-R1后&#xff0c;该公司宣称其在执行数学、编码和自然语言推理等任务时“性能可与OpenAI…...

网络安全攻防实战:从基础防护到高级对抗

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 在信息化时代&#xff0c;网络安全已经成为企业、政府和个人必须重视的问题。从数据泄露到勒索软件攻击&#xff0c;每一次…...

9【如何面对他人学习和生活中的刁难】

我们在学习的过程中&#xff0c;会遇到很多来自于他人的刁难与嘲讽&#xff0c;如果处理不好&#xff0c;这会大大影响我们的心情&#xff0c;从而影响学习的效率 我建议&#xff0c;如果你学习或生活中也遇到了类似的问题&#xff0c;不要去生气&#xff0c;更不要发生冲突&a…...

kafka消费者详细介绍(超级详细)

文章目录 一、Kafka 消费者与消费者组1.1 Kafka 消费者&#xff08;Consumer&#xff09;概述1.1.1 消费者工作流程1.1.2 消费者的关键配置 1.2 Kafka 消费者组&#xff08;Consumer Group&#xff09;概述1.2.1 消费者组的工作原理1.2.2 消费者组的优点1.2.3 消费者组的再均衡…...

数据结构选讲 (更新中)

参考 smWCDay7 数据结构选讲2 by yyc 。 可能会补充的&#xff1a; AT_cf17_final_j TreeMST 的 F2 Boruvka算法 目录 AT_cf17_final_j Tree MST AT_cf17_final_j Tree MST link 题意 给定一棵 n n n 个点的树&#xff0c;点有点权 w i w_i wi​&#xff0c;边有边权。建立…...

OpenBMC:简介

通常在服务器主板上&#xff0c;有一个独立的微处理器&#xff0c;叫作BMC(Baseboard Manager Controller)&#xff0c;用于与主机(host)进行通信&#xff0c;提供带外的方式查询服务器的状态和信息&#xff0c;并进行管理服务器。 OpenBMC是Linux Foundation的开源BMC项目&am…...

java 正则表达式匹配Matcher 类

Matcher 类 用法 在 Java 中&#xff0c;Matcher 类是用于匹配正则表达式的工具&#xff0c;而 group() 方法是 Matcher 类中的一个重要方法&#xff0c;用于提取匹配结果中的捕获组&#xff08;captured groups&#xff09;。以下是对 group() 方法的详细解释&#xff1a; 1.…...