当前位置: 首页 > 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&…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...

CSS3相关知识点

CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

GraphRAG优化新思路-开源的ROGRAG框架

目前的如微软开源的GraphRAG的工作流程都较为复杂&#xff0c;难以孤立地评估各个组件的贡献&#xff0c;传统的检索方法在处理复杂推理任务时可能不够有效&#xff0c;特别是在需要理解实体间关系或多跳知识的情况下。先说结论&#xff0c;看完后感觉这个框架性能上不会比Grap…...