工具篇——AESCBCUtil(用于AES加密解密)

本文介绍了如何在Android中实现AES-128-CBC的加密解密,包括十六进制字符串与byte数组之间的转换。文章提供了详细的操作步骤和代码示例,并给出了在实际项目中的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写代码的四点:

     1.明确需求。要做什么?

     2.分析思路。要怎么做?(1,2,3……)

     3.确定步骤。每一个思路要用到哪些语句、方法和对象。

     4.代码实现。用具体的语言代码将思路实现出来。

学习新技术的四点:

     1.该技术是什么?

     2.该技术有什么特点?(使用需注意的方面)

     3.该技术怎么使用?(写Demo)

     4.该技术什么时候用?(在Project中的使用场景 )

----------------------早计划,早准备,早完成。-------------------------

代码如下:

package com.wy.test.other;

import java.util.Locale;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES加密解密字符串工具类
 * 概述:AES高级加密标准,是对称密钥加密中最流行的算法之一;
 *       工作模式包括:ECB、CBC、CTR、OFB、CFB;
 * 使用范围:该工具类仅支持CBC模式下的:
 *              填充:PKCS7PADDING
 *              数据块:128位
 *              密码(key):32字节长度ÿ
<think>好的,用户遇到了“Unable to handle kernel NULL pointer dereference at virtual address 0000000000000038”这个错误,我需要详细解释这个问题以及解决方法。首先,我得确定用户对这个错误的了解程度。他们可能是一个Linux系统开发者或者运维人员,遇到了内核崩溃的问题,需要排查原因。 这个错误通常是因为内核代码试图访问一个空指针,具体地址是0x38,看起来像是某个结构体的成员偏移量。比如,可能是一个结构体指针为NULL,然后代码试图访问该结构体的0x38偏移处的成员。例如,task_struct结构体中的某个成员可能位于这个偏移量,所以用户可能是在操作进程管理相关的代码时出了问题。 接下来,我需要解释这个错误的原因。可能的原因包括未正确初始化的指针、内存释放后未置空导致的Use-after-free,或者并发访问导致的竞态条件。需要分步骤说明如何分析这个问题,比如查看Oops日志,使用drgn或crash工具分析转储文件,以及检查代码中的潜在问题。 用户可能需要具体的命令示例,比如如何用drgn查找引发问题的指针,或者如何从Oops日志中获取调用堆栈。同时,还要提醒他们在生产环境中如何处理,比如启用kdump,保留调试符号等。此外,预防措施也很重要,比如代码审查、静态分析工具的使用,以及利用内核内置的调试功能。 需要确保语言通俗易懂,结构清晰,分点列出原因、分析步骤、解决方法和预防措施。还要注意使用用户提到的工具drgn,给出实际案例,比如如何通过drgn找到引发问题的结构体实例。同时,提醒用户注意内核版本差异,不同版本的结构体偏移可能不同,需要确认具体的内核版本信息。</think>以下是对 **"Unable to handle kernel NULL pointer dereference at virtual address 0000000000000038"** 内核错误的全方位解析与处理指南: --- ### **一、错误本质剖析** 该错误表示内核尝试访问地址 `0x38`,但此地址对应的内存页未被映射(即 **NULL指针解引用**)。具体特征: - `0x38` 通常是结构体成员的偏移量(如 `struct task_struct` 的 `files` 字段偏移量是 `0x38`) - 触发场景:当指针本身为 NULL 时,访问其 `+0x38` 偏移位置 - 常见于:进程管理、文件操作、设备驱动等涉及结构体操作的场景 --- ### **二、错误根源分类** | 错误类型 | 典型场景 | 示例代码片段 | |-------------------------|---------------------------------------------|--------------------------------| | **未初始化指针** | 结构体指针未分配内存即访问成员 | `p->member`(`p` 未初始化) | | **Use-After-Free** | 对象释放后未置空指针仍被访问 | `kfree(obj); obj->func()` | | **竞态条件** | 并发操作导致指针被意外置空 | 未加锁的共享资源访问 | | **硬件寄存器误读** | 驱动未检查设备状态直接访问寄存器 | `readl(dev->reg_base + 0x38)` | --- ### **三、诊断步骤** #### 1. 分析内核 Oops 日志 ```bash [ 1273.451699] BUG: unable to handle kernel NULL pointer dereference at 0000000000000038 [ 1273.452412] PGD 0 P4D 0 [ 1273.452728] Oops: 0000 [#1] SMP PTI [ 1273.453153] CPU: 2 PID: 1815 Comm: my_module Tainted: G OE 4.19.0-17-generic [ 1273.453912] RIP: 0010:my_module_func+0x42/0x60 [my_module] # 关键行:定位出错函数 [ 1273.454696] RSP: 0018:ffffb77b827a3d80 EFLAGS: 00010246 [ 1273.455271] RAX: 0000000000000000 RBX: ffff9263cf5e8000 RCX: 0000000000000000 [ 1273.456025] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 [ 1273.456767] RBP: ffffb77b827a3da0 R08: 0000000000000000 R09: 0000000000000000 [ 1273.457514] R10: 0000000000000000 R11: 0000000000000000 R12: ffff9263cf5e8000 [ 1273.458258] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 [ 1273.459008] FS: 00007f8a7f5e7740(0000) GS:ffff9263d6c80000(0000) knlGS:0000000000000000 [ 1273.459864] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1273.460435] CR2: 0000000000000038 CR3: 00000001c220a002 CR4: 00000000003606e0 ``` 重点关注: - **RIP**:定位崩溃的函数 (`my_module_func+0x42`) - **CR2**:确认故障地址 (`0x38`) - **调用栈**:回溯函数调用链 #### 2. 使用 drgn 动态分析 ```python # 启动 drgn 调试运行中的内核 sudo drgn -k # 定位出错地址对应的结构体 >>> prog = drgn.program() >>> task = find_task(pid) # 替换为实际 PID >>> hex(task.address_of_().value_() + 0x38) # 验证是否为合法成员 '0xffff88800345d038' # 检查指针是否 NULL >>> ptr = prog['my_global_var'] >>> print(ptr.value_()) (nil) # 如果输出 nil 表示指针为 NULL ``` #### 3. 反汇编定位代码 ```bash # 使用 objdump 反汇编内核模块 objdump -dS my_module.ko > disassembly.txt # 在反汇编结果中搜索偏移量 0x42(根据 Oops 中的 RIP+0x42) grep -A 10 '42:' disassembly.txt ``` --- ### **四、修复方案** #### 1. 基础防护 ```c // 在访问指针前增加判空检查 if (likely(ptr != NULL)) { access_ptr->member = value; // 安全访问 } else { pr_warn("NULL pointer detected at %s\n", __func__); return -EINVAL; } ``` #### 2. 高级防御(内核机制) ```c // 使用 RCU 安全访问 rcu_read_lock(); struct my_struct *p = rcu_dereference(ptr); if (p) { // 安全操作 tmp = p->member; } rcu_read_unlock(); // 使用 refcount 引用计数 if (refcount_inc_not_zero(&obj->refcount)) { // 安全操作 refcount_dec(&obj->refcount); } ``` #### 3. 内存调试工具 ```bash # 启用 KASAN(内核地址消毒剂) CONFIG_KASAN=y CONFIG_KASAN_INLINE=y # 启用 SLUB 调试 CONFIG_SLUB_DEBUG=y CONFIG_SLUB_DEBUG_ON=y # 使用 kmemleak 检测内存泄漏 echo scan > /sys/kernel/debug/kmemleak ``` --- ### **五、实战案例** #### 案例:task_struct 的 files 成员访问崩溃 ```c // 错误代码 struct task_struct *tsk = NULL; struct files_struct *files = tsk->files; // 访问 tsk+0x38 // 修复代码 struct task_struct *tsk = get_current(); // 正确获取当前任务 if (tsk && tsk->files) { struct files_struct *files = tsk->files; } ``` --- ### **六、生产环境处理流程** 1. **紧急响应** ```bash # 捕获崩溃现场 echo c > /proc/sysrq-trigger
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值