mytechnotalent/Core-Dump-RE
GitHub: mytechnotalent/Core-Dump-RE
详细讲解如何在 macOS 和 Linux 上利用 LLDB 调试器对 Core Dump 文件进行逆向分析与调试,涵盖从环境配置到符号加载及崩溃定位的全流程。
Stars: 0 | Forks: 0
## 免费 Reverse Engineering 自学课程 [点击此处](https://github.com/mytechnotalent/Reverse-Engineering-Tutorial)
# Core Dump 逆向工程 在 MAC 和 Linux 上使用 LLDB 进行 Core dump 逆向工程。
## 步骤 1:启用 Core Dumps 本步骤介绍如何在 macOS 和 Linux 上启用 core dumps,以便操作系统将崩溃快照写入磁盘。
## 步骤 2:带调试符号编译 本步骤介绍如何编译包含完整调试信息的易受攻击程序,将调试信息内嵌到二进制文件中。
## 步骤 3:提取符号到独立文件 本步骤介绍如何将调试符号提取到独立文件中,这相当于 Windows 上的 `.pdb` 文件。
## 步骤 4:剥离二进制文件 本步骤介绍如何从二进制文件中剥离所有调试信息,使其看起来像是一个发布的 Release 版本。
## 步骤 5:创建 Entitlements 文件(仅限 macOS) 本步骤介绍如何创建 macOS 所需的 entitlements plist,以便在 SIP 下允许 core dumps。
## 步骤 6:签名二进制文件(仅限 macOS) 本步骤介绍如何使用 `com.apple.security.get-task-allow` 权限对二进制文件进行 codesigning,以便 macOS 在 SIP 下允许 core dumps。
## 步骤 7:触发崩溃 本步骤介绍如何运行剥离后的二进制文件以触发段错误并生成 core dump。
## 步骤 8:查找 Core Dump 本步骤介绍如何在 macOS 和 Linux 上定位 core dump 文件。
## 步骤 9:在 LLDB 中打开 Core Dump 本步骤介绍如何将 core dump 和剥离后的二进制文件加载到 LLDB 中。
## 步骤 10:加载符号 本步骤介绍如何将独立的符号文件加载到 LLDB 中,这相当于在 WinDbg 中使用 `.sympath` 和 `.reload` 加载 `.pdb`。
## 步骤 11:分析崩溃 本步骤介绍如何使用 LLDB 确定调用堆栈、停止原因、寄存器、局部变量以及崩溃现场的汇编代码。
## 步骤 12:LLDB RE 命令参考 本步骤提供了用于逆向分析 core dump 的 LLDB 命令的综合参考。
# 步骤 1:启用 Core Dumps 每次重启只需执行一次此操作。 ### macOS ``` sudo launchctl limit core unlimited unlimited ``` ### Linux ``` ulimit -c unlimited ```
# 步骤 2:带调试符号编译 ``` cc -g -O0 vuln.c -o vuln ``` `-g` 将调试信息内嵌到二进制文件中。`-O0` 关闭优化,以便汇编代码与源代码逐行对应。
# 步骤 3:提取符号到独立文件 这相当于 Windows 上的 `.pdb` 文件。 ### macOS ``` dsymutil vuln ``` 这将创建 `vuln.dSYM` —— 一个包含所有调试信息(函数名、变量名、行号、类型信息)的包。 ### Linux ``` objcopy --only-keep-debug vuln vuln.debug ``` 这将创建 `vuln.debug` —— 一个包含所有调试信息的文件。
# 步骤 4:剥离二进制文件 从二进制文件中移除所有符号,使其看起来像是一个 Release 版本。 ``` strip vuln ``` 现在二进制文件已没有调试信息。如果你现在尝试调试它,你只能看到原始地址,没有源代码,也没有变量名。就像一个已发布的产品一样。
# 步骤 5:创建 Entitlements 文件(仅限 macOS) 创建一个名为 `entitlements.plist` 的文件,内容如下: ```
# 步骤 6:签名二进制文件(仅限 macOS) 除非二进制文件具有特殊权限,否则 macOS 会阻止 core dumps。 ``` codesign -s - --entitlements entitlements.plist -f ./vuln ``` 在 Linux 上请跳过此步骤。
# 步骤 7:触发崩溃 ``` ./vuln ``` 你会看到类似这样的内容: ``` [*] Vulnerable program running... Segmentation fault (core dumped) ``` 操作系统冻结了进程中的所有内容(内存、寄存器、线程)并将其写入文件。该文件就是 core dump。
# 步骤 8:查找 Core Dump ### macOS Core dumps 会存放到 `/cores/`。 ``` ls /cores/ ``` 你会看到类似 `core.12345` 的内容。 ### Linux Core dumps 通常会生成在当前目录中。 ``` ls core* ``` 你会看到 `core` 或 `core.12345`。
# 步骤 9:在 LLDB 中打开 Core Dump 你需要提供给 LLDB 两个东西:core dump(崩溃快照)和剥离后的二进制文件(无符号)。 ### macOS ``` lldb --core /cores/core.12345 ./vuln ``` ### Linux ``` lldb --core ./core ./vuln ``` 将 core 文件名替换为你在步骤 8 中找到的名称。 此时 LLDB 没有符号。如果你输入 `bt`,你只会看到原始地址。你需要加载符号文件。
# 步骤 10:加载符号 这是关键步骤。二进制文件已被剥离。符号位于单独的文件中。你需要告诉 LLDB 它们的位置。 ### macOS ``` target symbols add vuln.dSYM ``` ### Linux ``` target symbols add vuln.debug ``` 现在 LLDB 拥有了函数名、变量名、行号和类型信息。这就像在 WinDbg 中使用 `.sympath` 和 `.reload` 加载 `.pdb` 一样。
# 步骤 11:分析崩溃 你现在位于 LLDB 内部,正在查看一个已加载符号的死亡进程。逐一运行以下命令。 ### 查看调用堆栈 ``` bt ``` 这显示了崩溃时正在运行的每个函数。Frame 0 是它死亡的地方。 ### 查看停止原因 ``` thread list ``` 查找 `stop reason = signal SIGSEGV`。这意味着它试图读取或写入它不被允许接触的内存。 ### 查看 CPU 寄存器 ``` register read ``` 重要的寄存器: - `pc`(或 x86 上的 `rip`)—— 崩溃时正在运行的指令 - `rsi`、`rdi` —— 传递给函数的值 ### 查看局部变量 ``` frame variable ``` 这显示了崩溃函数中的变量。对于我们的程序,你会看到 `argc` 和 `argv`。 ### 查看汇编 ``` disassemble --frame ``` 显示崩溃附近的机器指令。`->` 箭头指向发生故障的确切指令。 ### 崩溃原因(针对此程序) 我们的程序执行了 `printf("%s", argv[100])`。 - `argc` 为 1(只有程序名) - `argv` 只有 1 个条目 - `argv[100]` 读取超出数组末尾很远位置的内存 - 该内存未映射,因此操作系统使用 SIGSEGV 终止进程 - 操作系统写入 core dump - 你在 LLDB 中打开 core dump 并证实上述所有内容
# 步骤 12:LLDB RE 命令参考 以下所有内容均在加载 core 和符号后,在 LLDB 内部运行。 ### 堆栈导航 ``` bt # full backtrace bt 5 # only top 5 frames frame select 0 # jump to frame 0 (crash site) frame select 3 # jump to frame 3 up # move one frame up (toward caller) down # move one frame down (toward callee) ``` ### 寄存器 ``` register read # all general-purpose registers register read pc # just the program counter register read rdi rsi rdx # specific registers (x86_64 args 1-3) register read x0 x1 x2 # specific registers (arm64 args 1-3) register read --format hex # force hex output ``` ### 内存 ``` memory read $pc # read memory at program counter memory read $sp # read memory at stack pointer memory read 0x7fff5a3c0000 # read memory at a specific address memory read --size 8 --format x --count 16 $sp # 16 qwords from stack memory read --size 1 --format c --count 64 $rdi # 64 bytes as chars memory read --format s $rdi # read as null-terminated string ``` ### 反汇编 ``` disassemble --frame # disassemble current frame disassemble --name main # disassemble a function by name disassemble --start-address 0x100003f40 --count 20 # 20 instructions from addr disassemble --pc # disassemble around current program counter ``` ### 变量和表达式 ``` frame variable # all locals and args in current frame frame variable argc # specific variable frame variable *argv # dereference pointer expression argc # evaluate an expression expression argv[0] # array access expression (char*)argv[0] # cast and print expression (int)argc - 1 # arithmetic ``` ### 模块和符号 ``` image list # all loaded modules (like lm in WinDbg) image lookup --address $pc # map address to source file + line image lookup --name main # find where a symbol lives image lookup --type int # look up a type image dump symtab # dump the symbol table target symbols add file.dSYM # load symbols (macOS) target symbols add file.debug # load symbols (Linux) ``` ### 线程 ``` thread list # all threads and stop reasons thread select 2 # switch to thread 2 thread info # detailed info on current thread thread backtrace all # backtrace every thread ``` ### 搜索内存 ``` memory find $sp $sp+0x1000 --expr "0x41414141" # search stack for pattern memory find $sp $sp+0x1000 -s "AAAA" # search stack for string ``` ### 进程信息 ``` process status # stop reason, signal, pid target show # binary path and arch ```
## 许可证 [MIT](https://github.com/mytechnotalent/Core-Dump-RE/blob/main/LICENSE)
标签:C++, DNS 反向解析, DNS 解析, LLDB, meg, SecList, Segmentation Fault, SIP, 二进制分析, 云安全运维, 云资产清单, 代码签名, 信息安全, 内存取证, 可观察性, 客户端加密, 崩溃分析, 技术教程, 数据擦除, 文档结构分析, 核心转储分析, 汇编, 漏洞分析, 符号表, 红队技术, 网络安全, 调试, 路径探测, 逆向工程, 配置审计, 隐私保护