蚊章汇 - Gaurav Kamathe
type: channel
link: https://linuxcn.bwsl.wang/author/1307/
description: Gaurav Kamathe
items: 充分利用你的下一次技术会议的 7 个技巧
items: 以调试 Rust 的方式来学习 Rust
items: 在 Linux 上使用 Checksec 识别二进制文件的安全属性
items: 使用 rustup 管理你的 Rust 工具链
items: 我最喜欢的 Go 构建选项
items: 你需要了解的 Go 中的模糊测试
items: 使用 trace-cmd 追踪内核
items: 通过 ftrace 来分析 Linux 内核
items: 像查询数据库一样查询你的 Linux 操作系统信息
items: 使用开源工具进行 Linux 内存取证

充分利用你的下一次技术会议的 7 个技巧
type: item
date: 2023-04-27T15:42:17+08:00
description: 会议是科技行业的福利之一。以下是如何充分利用你所参加的会议的方法。我在 2023 年 2 月参加了两个针对开源软件的技术会议。我是比利时根特举办的 Config Management Camp 的演讲者，也是比利时布鲁塞尔 FOSDEM 的与会者。本文旨在着重讲述我在会议上的经验，并为你提供一些如何充分利用这种机会的建议。保持目的性不同的人参加会议有不同的原因。有些人是某个主题、知识或兴趣领域的演讲者。另外一些人是希望从这些讲座中获得知识并与其他志同道合的人建立联系的与会者。也有一些代表他们公司的与会者。你很可能属于其中的一类。明确你希望从会议中获得什么，这是进行一次成功会议访问的第一步。如果你是一个演讲者，这意味着你要熟练掌握你所演讲的东西。如果你是一个与会者，你应该对你想从会议中获得什么有一个认识。了解场地和会议日程FOSDEM 是一个非常大的会议，在两天的时间里至少有六千人参加。对于一个参加这样一个大型的会议的与会者来说，由于许多演讲会在同一时间举行，无法参加所有你感兴趣的会议并不奇怪。通常，这样的大型会议在大学或会议中心等宽敞的场地举行。由于面积非常大，会议会根据特定的主题分散在整个会场。这些会议会有一个固定的日程，所以有时你可能必须迅速地从场地的一边跑到另一边。场馆地图可以在场馆网站上轻松获取。在第一天早点到达会场并熟悉它是非常有用的。这有助于节省你在一个演讲结束时匆忙赶往另一个演讲的时间。记些笔记在现场集中注意力和专注于演讲当然很好。然而，你的头脑只能记住这么多。当然，有些人会试着尽可能地利用他们的手机拍摄正在演示的幻灯片（顺着演讲者的演讲节奏）。如果你想在社交媒体上快速更新你正在参加的会议信息，这是很好的。但是它不是很有效的笔记。通常幻灯片上的有效信息是最少的。但是如果演讲者在台上深入地解释了一些东西，你可能会错过这些解释。我建议你随身携带一个记事本和一支笔。你甚至可以带上笔记本电脑做笔记。这个做法的目的是在于通过在演讲中对有趣的花絮做一个简短的笔记，以便你可以在以后重温它们。而且它让你总是能在演讲快结束时回想起要向演讲者提问的问题。建立关系和促成协作会议可能是与志同道合的人彼此交往的最佳场所。他们和你一样对同样的话题感兴趣。最好利用这段时间来了解在感兴趣的话题上正在发生什么，看看人们如何解决令人感兴趣的问题，他们如何处理事情，并掌握整个行业的脉搏。你在会议上的时间有限，所以一定要把你介绍给那些从事与你有关的工作的人。这是一个收集信息的好机会，以便以后与他们沟通。你可以通过电子邮件、Mastodon、领英等方式交换个人信息。腾出时间看展位和礼品大多数技术会议都有来自各种公司或上游项目的展位，希望推销他们的产品和服务。为了吸引更多参展的人，展位上经常会有各种各样的免费的礼品（在大多数情况下）。这些礼品通常是贴纸、凉水瓶、有趣的小玩意、毛绒玩具、笔之类。一定要把它们收集起来，这样你就有东西送给你的同事和朋友了。参观展位不应该只是为了礼品。你应该利用这个机会与来自不同公司的人交谈（即使他们是竞争对手），以了解他们能提供什么。谁没准你就会得到以后的项目知识！放松参加会议不应该只是为了工作。这也让你你从平时忙碌的日程中休息一下，放松一下。很有可能你正在前往一个你还没有访问过的不同的国家或城市。会议、会谈和技术讨论都很重要。但这只是整个体验的一部分。另一半的经验是旅行，它可以使人了解另一个国家、它的文化、它的人民、食物、语言和不同的生活方式。退一步讲，享受所有这些经历，留下终生的回忆。我建议你在住宿的地方找一些著名的地标兼做。你也应该尝试当地的美食，或者你可以和当地人聊天。最后，你会发现你认为从来没有存在过的自己的另一面。写下你的经历一旦你从会议回来，不要只是忘记它然后回到你的日常生活，就好像什么都没发生一样。利用这个机会写下你的经历，并分享你认为最好的演讲以及原因。会议和旅行的主要收获是什么？你应该记录你学到的东西。你应该主动联系你在会议上遇到的人。你也可以在社交媒体上关注你可能错过的事情。总结会议是科技行业的福利之一。我建议每个人在职业生涯中的某个时候都去一次。我希望这篇文章能帮助你了解如何在参加技术会议时最大限度地利用会议。（题图：MJ/conference illustration talk meetup in high resolution, very detailed, 8k）via: https://opensource.com/article/23/4/tips-tech-conference作者：Gaurav Kamathe 选题：lkxed 译者：Taivas Jumala 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出

以调试 Rust 的方式来学习 Rust
type: item
date: 2022-12-30T18:34:00+08:00
description: Rustlings 是由 Rust 团队维护的开源项目，旨在帮助你通过调试代码的方式来学习 Rust。在我上一篇 关于 Rustup 的文章 中，我向你们展示了如何安装 Rust 工具链。但是，如果不能上手操作一下 Rust 的话下载工具链又有什么用？学习任何语言都包括阅读现有的代码和写很多的示例程序，这是精通一门语言的好方法。然而，我们还可以走第三条路：调试代码。通过调试来学习牵扯到尝试去编译一个已经写好的（满是漏洞的）示例程序，理解编译器生成的错误信息，修复示例代码，然后再重新编译。重复这个过程直到代码能够成功被编译并运行。Rustlings 是一个由 Rust 团队维护的开源项目，旨在帮助你通过调试代码来学习 Rust。它也会一路为你提供提示。如果你是一名 Rust 初学者，并且刚开始阅读或已经读完了 Rust 书籍，那么 Rustlings 就是理想的下一步。Rustllings 帮助你将运用书中所学，并转向开发更大的项目。安装 Rustlings我使用（并推荐）Fedora 电脑来体验 Rustlings，但是任何 Linux 发行版都可以。要安装 Rustlings，你必须下载并运行它的安装脚本。通常建议你以不具备任何特别权限的普通用户（非 root 用户）来运行脚本。记住，你需要 Rust 工具链来使用 Rustlings。如果你还没有这些工具链，请参考我 关于 Rustup 的文章。当你准备好时，下载这个安装脚本：$ curl -L https://raw.githubusercontent.com/rust-lang/rustlings/main/install.sh > rustlings_install.sh $ file rustlings_install.sh rustlings_install.sh: Bourne-Again shell script, ASCII text executable 阅读脚本以了解它会做什么：$ less rustlings_install.sh 然后运行安装：$ bash rustlings_install.sh [...] Installing /home/tux/.cargo/bin/rustlings Installed package `rustlings v4.8.0 (/home/tux/rustlings)` (executable `rustlings`) All done! 运行 rustlings 以开始。Rustlings 练习你现在可以使用命令 rustlings。与标志 --help 一起执行来查看可选的选项。$ rustlings --help 这个安装脚本也克隆了 Rustlings 的 Git 仓库，并安装了运行示例程序所需的依赖。你可以在 ruslings 下的 exercises 目录查阅这些示例程序。$ cd rustlings $ pwd /home/tux/rustlings $ ls AUTHORS.md Cargo.toml CONTRIBUTING.md info.toml install.sh README.md target Cargo.lock CHANGELOG.md exercises install.ps1 LICENSE src tests $ ls -m exercises/ advanced_errors, clippy, collections, conversions, enums, error_handling, functions, generics, if, intro, macros, mod.rs, modules, move_semantics, option, primitive_types, quiz1.rs, quiz2.rs, quiz3.rs, quiz4.rs, README.md, standard_library_types, strings, structs, tests, threads, traits, variables 从命令行列出所有练习命令 ruslings 提供给你一个 list 命令用以展示每个示例程序，它的完整路径，以及状态 （默认为 “待定”）。$ rustlings list Name Path Status intro1 exercises/intro/intro1.rs Pending intro2 exercises/intro/intro2.rs Pending variables1 exercises/variables/variables1.rs Pending variables2 exercises/variables/varia…

在 Linux 上使用 Checksec 识别二进制文件的安全属性
type: item
date: 2022-11-18T17:57:08+08:00
description: 这篇文章能让你了解如何使用 Checksec ，来识别一个可执行文件的安全属性，了解安全属性的含义，并知道如何使用它们。编译源代码会生成一个二进制文件（LCTT 译注：即 .o 文件）。在编译期间，你可以向 gcc 编译器提供 标志 flags ，以启用或禁用二进制文件的某些属性，这些属性与安全性相关。Checksec 是一个漂亮的小工具，同时它也是一个 shell 脚本。Checksec 可以识别编译时构建到二进制文件中的安全属性。编译器可能会默认启用一些安全属性，你也可以提供特定的标志，来启用其他的安全属性。本文将介绍如何使用 Checksec ，来识别二进制文件的安全属性，包括：Checksec 在查找有关安全属性的信息时，使用了什么底层的命令在将源代码编译成二进制文件时，如何使用 GNU 编译器套件 GNU Compiler Collection （即 GCC）来启用安全属性。安装 checksec要在 Fedora 和其他基于 RPM 的 Linux 系统上，安装 Checksec，请使用以下命令：$ sudo dnf install checksec 对于基于 Debian 的 Linux 发行版，使用对应的 apt 命令，来安装 Checksec。$ sudo apt install checksec shell 脚本在安装完 Checksec 后，能够发现 Checksec 是一个单文件的 shell 脚本，它位于 /usr/bin/checksec，并且这个文件挺大的。Checksec 的一个优点是你可以通过快速通读这个 shell 脚本，从而了解 Checksec 的执行原理、明白所有能查找有关二进制文件或可执行文件的安全属性的系统命令：$ file /usr/bin/checksec /usr/bin/checksec: Bourne-Again shell script, ASCII text executable, with very long lines $ wc -l /usr/bin/checksec 2111 /usr/bin/checksec 以下的命令展示了如何对你每天都会使用的：ls 命令的二进制文件运行 Checksec。Checksec 命令的格式是：checksec --file=，后面再跟上二进制文件的绝对路径：$ checksec --file=/usr/bin/ls RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Full RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH No Symbols Yes 5 17 /usr/bin/ls 当你在终端中对某个二进制文件运行 Checksec 时，你会看到安全属性有颜色上的区分，显示什么是好的安全属性（绿色），什么可能不是好的安全属性（红色）。我在这里说 “可能” 是因为即使有些安全属性是红色的，也不一定意味着这个二进制文件很糟糕，它可能只是表明发行版供应商在编译二进制文件时做了一些权衡，从而舍弃了部分安全属性。Checksec 输出的第一行提供了二进制文件的各种安全属性，例如 RELRO、STACK CANARY、NX 等（我将在后文进行详细解释）。第二行打印出给定二进制文件（本例中为 ls）在这些安全属性的状态（例如，NX enabled 表示为堆栈中的数据没有执行权限）。示例二进制文件在本文中，我将使用以下的 “hello world” 程序作为示例二进制文件。#include <stdio.h> int main() { printf("Hello World\n"); return 0; } 请注意，在编译源文件 hello.c 的时候，我没有给 gcc 提供任何额外的标志：$ gcc hello.c -o hello $ file hello hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, for GNU/Linux 3.2.0, not stripped $ ./hello Hello World 使用 Checksec 运行二进制文件 hello，打印的某些安全属性的状态，与上面的 ls 二进制文件的结果不同（在你的屏幕上，某些…

使用 rustup 管理你的 Rust 工具链
type: item
date: 2022-06-30T22:54:31+08:00
description: rustup 可用于 Rust 安装与更新。它还能够在稳定版、测试版和每日更新版之间无缝切换 Rust 编译器及其工具。Rust 编程语言 如今变得越来越流行，受到爱好者和公司的一致好评。它受欢迎的原因之一是 Rust 提供的令人惊叹的工具，使其成为开发人员使用的乐趣。rustup 是管理 Rust 工具的官方工具。它不仅可以安装和更新 Rust ，它还能够在稳定版、测试版和每日更新版之间无缝切换 Rust 编译器及其工具。本文将向你介绍 rustup 及其一些常用命令。默认 Rust 安装方式如果你想在 Linux 上安装 Rust，你可以使用你的包管理器。在 Fedora 或 CentOS Stream 上，你可以这样：$ sudo dnf install rust cargo 这提供了一个稳定版的 Rust 工具链，如果你是 Rust 的初学者，并想尝试编译和运行简单的程序，它会非常有用。但是，由于 Rust 是一种新的编程语言，它变化很快，并且经常添加许多新功能。这些功能是 Rust 工具链的每日更新版和之后测试版的一部分。要试用这些功能，你需要安装这些较新版本的工具链，而不会影响系统上的稳定版本。不幸的是，你的发行版的包管理器在这里无法做到。使用 rustup 安装 Rust 工具链要解决上述问题，你可以下载安装脚本：$ curl --proto '=https' --tlsv1.2 \ -sSf https://sh.rustup.rs > sh.rustup.rs 检查它，然后运行它。它不需要 root 权限，并根据你的本地用户权限安装 Rust：$ file sh.rustup.rs sh.rustup.rs: POSIX shell script, ASCII text executable $ less sh.rustup.rs $ bash sh.rustup.rs 出现提示时选择选项 1：1) Proceed with installation (default) 2) Customize installation 3) Cancel installation > 1 安装后，你必须获取环境变量以确保 rustup 命令立即可供你运行：$ source $HOME/.cargo/env 验证是否安装了 Rust 编译器（rustc）和 Rust 包管理器（cargo）：$ rustc --version $ cargo --version 查看已安装和可用的工具链你可以使用以下命令查看已安装的不同工具链以及哪个工具链是可用的：$ rustup show 在工具链之间切换你可以查看默认工具链并根据需要进行更改。如果你当前使用的是稳定版工具链，并希望尝试每日更新版中提供的新功能，你可以轻松切换到每日更新版工具链：$ rustup default $ rustup default nightly 要查看 Rust 的编译器和包管理器的完整路径：$ rustup which rustc $ rustup which cargo 检查和更新工具链要检查是否有新的 Rust 工具链可用：$ rustup check 假设一个新版本的 Rust 发布了，其中包含一些有趣的特性，并且你想要获取最新版本的 Rust。你可以使用 update 子命令来做到这一点：$ rustup update 帮助和文档以上命令对于日常使用来说绰绰有余。尽管如此，rustup 有多种命令，你可以参考帮助部分了解更多详细信息：$ rustup --help rustup 在 GitHub 上有完整的 参考手册，你可以用作参考。所有 Rust 文档都安装在你的本地系统上，不需要你连接到互联网。你可以访问包括书籍、标准库等在内的本地文档：$ rustup doc $ rustup doc --book $ rustup doc --std $ rustup doc --cargo Rust 是一种正在积极开发中的令人兴奋的语言。如果你对编程的发展方向感兴趣，请关注 Rust！via: https://opensource.com/article/22/6/rust-toolchain-rustup作者：Gaurav Kamathe 选题：lkxed 译者：geekpi 校对：turbokernel本文由 LCTT 原创编译，Linux中国 荣誉推出

我最喜欢的 Go 构建选项
type: item
date: 2022-05-01T01:21:00+08:00
description: 这些方便的 Go 构建选项可以帮助你更好地理解 Go 的编译过程。学习一门新的编程语言最令人欣慰的部分之一，就是最终运行了一个可执行文件，并获得预期的输出。当我开始学习 Go 这门编程语言时，我先是阅读一些示例程序来熟悉语法，然后是尝试写一些小的测试程序。随着时间的推移，这种方法帮助我熟悉了编译和构建程序的过程。Go 的构建选项提供了更好地控制构建过程的方法。它们还可以提供额外的信息，帮助把这个过程分成更小的部分。在这篇文章中，我将演示我所使用的一些选项。注意：我使用的“ 构建 build ”和“ 编译 compile ”这两个词是同一个意思。开始使用 Go我使用的 Go 版本是 1.16.7。但是，这里给出的命令应该也能在最新的版本上运行。如果你没有安装 Go，你可以从 Go 官网 上下载它，并按照说明进行安装。你可以通过打开一个命令提示符，并键入下面的命令来验证你所安装的版本：$ go version 你应该会得到类似下面这样的输出，具体取决于你安装的版本：go version go1.16.7 linux/amd64 基本的 Go 程序的编译和执行方法我将从一个在屏幕上简单打印 “Hello World” 的 Go 程序示例开始，就像下面这样：$ cat hello.go package main import "fmt" func main() { fmt.Println("Hello World") } 在讨论更高级的选项之前，我将解释如何编译这个 Go 示例程序。我使用了 build 命令，后面跟着 Go 程序的源文件名，本例中是 hello.go，就像下面这样：$ go build hello.go 如果一切工作正常，你应该看到在你的当前目录下创建了一个名为 hello 的可执行文件。你可以通过使用 file 命令验证它是 ELF 二进制可执行格式（在 Linux 平台上）。你也可以直接执行它，你会看到它输出 “Hello World”。$ ls hello hello.go $ file ./hello ./hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped $ ./hello Hello World Go 提供了一个方便的 run 命令，以便你只是想看看程序是否能正常工作，并获得预期的输出，而不想生成一个最终的二进制文件。请记住，即使你在当前目录中没有看到可执行文件，Go 仍然会在某个地方编译并生成可执行文件并运行它，然后把它从系统中删除。我将在本文后面的章节中解释。$ go run hello.go Hello World $ ls hello.go 更多细节上面的命令就像一阵风一样，一下子就运行完了我的程序。然而，如果你想知道 Go 在编译这些程序的过程中做了什么，Go 提供了一个 -x 选项，它可以打印出 Go 为产生这个可执行文件所做的一切。简单看一下你就会发现，Go 在 /tmp 内创建了一个临时工作目录，并生成了可执行文件，然后把它移到了 Go 源程序所在的当前目录。$ go build -x hello.go WORK=/tmp/go-build1944767317 mkdir -p $WORK/b001/ << snip >> mkdir -p $WORK/b001/exe/ cd . /usr/lib/golang/pkg/tool/linux_amd64/link -o $WORK \ /b001/exe/a.out -importcfg $WORK/b001 \ /importcfg.link -buildmode=exe -buildid=K26hEYzgDkqJjx2Hf-wz/\ nDueg0kBjIygx25rYwbK/W-eJaGIOdPEWgwC6o546 \ /K26hEYzgDkqJjx2Hf-wz -extld=gcc /root/.cache/go-build /cc \ /cc72cb2f4fbb61229885fc434995964a7a4d6e10692a23cc0ada6707c5d3435b-d /usr/lib/golang/pkg/tool/linux_amd64/buildid -w $WORK \ /b001/exe/a.out # internal mv $WORK/b001/exe/a.out hello rm -r $WORK/b001/ 这有助于解决在程序运行后却在当前目录下没有生成可执行文件的谜团。使用 -x 显示可执行文件确实在 /tmp 工作目录下创建并被执行了。然而，与 build 命令不同的是，可执行文…

你需要了解的 Go 中的模糊测试
type: item
date: 2022-03-18T18:31:29+08:00
description: Go 团队接受了新增对模糊测试的支持的提议。Go 的应用越来越广泛。现在它是云原生软件、容器软件、命令行工具和数据库等等的首选语言。Go 很早之前就已经有了内建的 对测试的支持。这使得写测试代码和运行都相当简单。什么是模糊测试？ 模糊测试 fuzz testing （fuzzing）是指向你的软件输入非预期的数据。理想情况下，这种测试会让你的应用程序崩溃或有非预期的表现。抛开最终的结果，从程序对非预期的输入数据的处理结果中你可以得到很多信息，这样你就可以增加一些合适的错误处理。任何一个软件都有对不同来源的输入或数据的接收说明，软件会对这些数据进行处理并返回适当的结果。软件开发后，测试工程师团队对其进行测试，找出软件中的错误，给出测试报告，并（由开发者）修复。通常测试的目的是验证软件的行为是否符合预期。测试又可以细分为不同的类型，如功能测试、集成测试、性能测试等等。每种测试方法关注软件功能的某一个方面，以便发现错误或者提升可靠性或性能。模糊测试在这一测试过程上更进一步，尝试向软件程序输入一些“无效”或“随机”的数据。这种输入是故意的，期望得到的结果就是程序崩溃或输出异常，这样就可以暴露程序中的错误以便由开发者来修复它们。与其他测试类似，很少需要手动进行模糊测试，业界有大量的模糊测试工具可以将这个过程自动化。Go 中的软件测试举个例子，假如你想测试 add.go 中的 Add() 函数，你可以在 add_test.go 中导入 testing 包并把测试体写在以 TestXXX() 开头的函数内。考虑如下代码：func Add(num1, num2 int) int { } 在 add_test.go 文件中，你可能有如下测试代码：import "testing" func TestAdd(t *testing.T) { } 运行测试：$ go test 新增对模糊测试的支持Go 团队已经接受了 新增对模糊测试的支持的提议，以进一步推动这项工作。这涉及到新增一个 testing.F 类型，在 _test.go 文件中新增 FuzzXXX() 函数，在 Go 工具中会新增一个 -fuzz 选项来执行这些测试。在 add_test.go 文件中：func FuzzAdd(f *testing.F) { } 执行以下代码：$ go test -fuzz 在本文编写时，这个 功能还是试验性的，但是应该会在 1.18 发布版本中包含。（LCTT 译注：Go 1.18 刚刚发布，已经包含了对模糊测试的支持）目前很多功能如 -keepfuzzing、-race 等也还没有支持。Go 团队最近发布了一篇 模糊测试教程，值得读一下。安装 gotip 来获取最新的功能如果你极度渴望在正式发布之前尝试这些功能，你可以使用 gotip 来测试即将正式发布的 Go 功能并反馈给他们。你可以使用下面的命令来安装 gotip。安装之后，你可以用 gotip 程序代替以前的 go 程序来编译和运行程序。$ go install golang.org/dl/gotip@latest $ gotip download $ gotip version go version devel go1.18-f009910 Thu Jan 6 16:22:21 2022 +0000 linux/amd64 社区对于模糊测试的观点软件社区中经常会讨论模糊测试，不同的人对模糊测试有不同的看法。有些人认为这是一种有用的技术，可以找到错误，尤其是在安全方面。然而考虑到模糊测试所需要的资源（CPU、内存），有人就认为这是一种浪费，而他们更愿意用其他的测试方法。即使在 Go 团队内部，意见也不统一。我们可以看到 Go 的联合创始人 Rob Pike 对模糊测试的使用和在 Go 中的实现是持轻微的怀疑态度的。...虽然模糊测试有助于发现某类错误，但是它会占用大量的 CPU 和存储资源，并且效益成本比率也不明确。我担心为了写模糊测试浪费精力，或者 git 仓库中充斥大量无用的测试数据~Rob Pike然而，Go 安全团队的另一个成员，Filo Sottile，似乎对 Go 新增支持模糊测试很乐观，举了很多例子来支持，也希望模糊测试能成为开发过程中的一部分。我想说模糊测试可以发现极端情况下的错误。这是我们作为安全团队对其感兴趣的原因：在极端情况下发现的错误可以避免在生产环境中成为弱点。我们希望模糊测试能成为开发的一部分 —— 不只是构建或安全方面 —— 而是整个开发过程：它能提升相关代码的质量...~Filo Sottile现实中的模糊测试对我而言，模糊测试在发现错误以及让系统变得更安全和更有弹性方面似乎非常有效。举个例子，Linux 内核也会使用名为 syzkaller 的工具进行模糊测试，这…

使用 trace-cmd 追踪内核
type: item
date: 2021-10-05T22:58:24+08:00
description: trace-cmd 是一个易于使用，且特性众多、可用来追踪内核函数的命令。在 之前的文章 里，我介绍了如何利用 ftrace 来追踪内核函数。通过写入和读出文件来使用 ftrace 会变得很枯燥，所以我对它做了一个封装来运行带有选项的命令，以启用和禁用追踪、设置过滤器、查看输出、清除输出等等。trace-cmd 命令是一个可以帮助你做到这一点的工具。在这篇文章中，我使用 trace-cmd 来执行我在 ftrace 文章中所做的相同任务。由于会经常参考那篇文章，建议在阅读这篇文章之前先阅读它。安装 trace-cmd本文中所有的命令都运行在 root 用户下。因为 ftrace 机制被内置于内核中，因此你可以使用下面的命令进行验证它是否启用：# mount | grep tracefs none on /sys/kernel/tracing type tracefs (rw,relatime,seclabel) 不过，你需要手动尝试安装 trace-cmd 命令：# dnf install trace-cmd -y 列出可用的追踪器当使用 ftrace 时，你必须查看文件的内容以了解有哪些追踪器可用。但使用 trace-cmd，你可以通过以下方式获得这些信息:# trace-cmd list -t hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop 启用函数追踪器在我 之前的文章 中，我使用了两个追踪器，在这里我也会这么做。用 function 启用你的第一个追踪器:$ trace-cmd start -p function plugin 'function' 查看追踪输出一旦追踪器被启用，你可以通过使用 show 参数来查看输出。这只显示了前 20 行以保持例子的简短（见我之前的文章对输出的解释）：# trace-cmd show | head -20 ## tracer: function # # entries-in-buffer/entries-written: 410142/3380032 #P:8 # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | gdbus-2606 [004] ..s. 10520.538759: __msecs_to_jiffies <-rebalance_domains gdbus-2606 [004] ..s. 10520.538760: load_balance <-rebalance_domains gdbus-2606 [004] ..s. 10520.538761: idle_cpu <-load_balance gdbus-2606 [004] ..s. 10520.538762: group_balance_cpu <-load_balance gdbus-2606 [004] ..s. 10520.538762: find_busiest_group <-load_balance gdbus-2606 [004] ..s. 10520.538763: update_group_capacity <-update_sd_lb_stats.constprop.0 gdbus-2606 [004] ..s. 10520.538763: __msecs_to_jiffies <-update_group_capacity gdbus-2606 [004] ..s. 10520.538765: idle_cpu <-update_sd_lb_stats.constprop.0 gdbus-2606 [004] ..s. 10520.538766: __msecs_to_jiffies <-rebalance_domains 停止追踪并清除缓冲区追踪将会在后台继续运行，你可以继续用 show 查看输出。要停止追踪，请运行带有 stop 参数的 trace-cmd 命令：# trace-cmd stop 要清除缓冲区，用 clear 参数运行它：# trace-cmd clear 启用函数调用图追踪器运行第二个追踪器，通过 function_graph 参数来启用它。# trace-cmd start -p function_graph Plugin 'function_graph' 再次使用 sho…

通过 ftrace 来分析 Linux 内核
type: item
date: 2021-09-05T23:20:00+08:00
description: 通过 ftrace 来了解 Linux 内核内部工作方式是一个好方法。操作系统的内核是最难以理解的软件之一。自从你的系统启动后，它会一直在后台运行。尽管每个用户都不与内核直接交互，但他们在内核的帮助下完成自己的计算任务。与内核的交互发生在调用系统调用或者用户日常使用的各种库或应用间接调用了系统调用。在之前的文章里我介绍了如何使用 strace 来追踪系统调用。然而，使用 strace 时你的视野是有限的。它允许你查看特定参数的系统调用。并在工作完成后，看到其返回值或状态，以表明是成功还是失败。但是你无法知道内核在这段时间内发生了什么。除了系统调用外，还有很多其他活动内核中发生，而你却视而不见。ftrace 介绍本文的旨在通过使用一个名为 ftrace 的机制来阐明追踪内核函数的一些情况。它使得任何 Linux 用户可以轻松地追踪内核，并且了解更多关于 Linux 内核内部如何工作。ftrace 默认产生的输出往往是巨大的，因为内核总是忙碌的。为了节省空间，很多情况下我会通过截断来给出尽量小的输出。我使用 Fedora 来演示下面的例子，但是它们应该在其他最新的 Linux 发行版上同样可以运行。启用 ftraceftrace 现在已经是内核中的一部分了，你不再需要事先安装它了。也就是说，如果你在使用最近的 Linux 系统，那么 ftrace 是已经启用了的。为了验证 ftrace 是否可用，运行 mount 命令并查找 tracefs。如果你看到类似下面的输出，表示 ftrace 已经启用，你可以轻松地尝试本文中下面的例子。下面有些命令需要在 root 用户下使用（用 sudo 执行是不够的）。# mount | grep tracefs none on /sys/kernel/tracing type tracefs (rw,relatime,seclabel) 要想使用 ftrace，你首先需要进入上面 mount 命令中找到的特定目录中，在那个目录下运行文章中的其他命令。# cd /sys/kernel/tracing 一般的工作流程首先，你需要理解捕捉踪迹和获取输出的一般流程。如果你直接运行 ftrace，不会运行任何特定的 ftrace 命令。相反的，基本操作是通过标准 Linux 命令来写入或读取一些文件。一般的步骤如下：通过写入一些特定文件来启用/结束追踪通过写入一些特定文件来设置/取消追踪时的过滤规则从文件中读取基于第 1 和 2 步的追踪输出从文件中清除早期输出或缓冲区缩小到你的特定用例（你要追踪的内核函数），重复 1、2、3、4 步可用的追踪器类型有多种不同的追踪器可供使用。之前提到，在运行任何命令前，你需要进入一个特定的目录下，因为需要的文件在这些目录下。我在我的例子中使用了相对路径（而不是绝对路径）。你可以查看 available_tracers 文件内容来查看所有可用的追踪器类型。你可以看下面列出了几个。不需要担心这些：$ pwd /sys/kernel/tracing $ sudo cat available_tracers hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop 在所有输出的追踪器中，我会聚焦于下面三个特殊的：启用追踪的 function 和 function_graph，以及停止追踪的 nop。确认当前的追踪器通常情况默认的追踪器设定为 nop。即在特殊文件中 current_tracer 中的 “无操作”，这意味着追踪目前是关闭的：$ pwd /sys/kernel/tracing $ sudo cat current_tracer nop 查看追踪输出在启用任何追踪功能之前，请你看一下保存追踪输出的文件。你可以用 cat 命令查看名为 trace 的文件的内容：# cat trace # tracer: nop # # entries-in-buffer/entries-written: 0/0 #P:8 # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | 启用 function 追踪器你可以通过向 current_tracer 文件写入 function 来启用第一个追踪器 function（文件原本内容为 nop，意味着追踪是关闭的）。把这个操作看成是启用追踪的一种方式：$ pwd /s…

像查询数据库一样查询你的 Linux 操作系统信息
type: item
date: 2021-07-14T17:58:31+08:00
description: 使用数据库查询操作轻松获取系统信息。Linux 提供了很多帮助用户收集主机操作系统信息的命令：列出文件或者目录的属性信息；查询安装的软件包、正在执行的命令、开机时启动的服务；或者了解系统的硬件。每个命令使用自己的输出格式列出系统的信息。你需要使用 grep、sed、awk 这样的工具过滤命令输出的结果，以便找到特定的信息。此外，很多这样的信息会频繁变动，导致系统状态的改变。将所有的信息格式化为一个数据库的 SQL 查询的输出进行查看将会十分有益。想象一下，你能够像查询具有类似名称的 SQL 数据库表一样查询 ps 和 rpm 命令的输出。幸运的是，有一个工具刚好实现了这个功能，而且功能更多：Osquery 是一个 开源的 “由 SQL 驱动的操作系统仪表、监控和分析框架”。许多处理安全、DevOps、合规性的应用，以及仓储管理管理（仅举几例）在内部依赖 Osquery 提供的核心功能。安装 OsqueryOsquery 适用于 Linux、macOS、Windows、FreeBSD。请按照 指南 为你的操作系统安装最新版本。（我会在下面的例子中使用 4.7.0 版本。）安装完成后，确保 Osquery 可以工作：$ rpm -qa | grep osquery osquery-4.7.0-1.linux.x86_64 $ $ osqueryi --version osqueryi version 4.7.0 $ Osquery 组件Osquery 有两个主要组件：osqueri 是一个交互式的 SQL 查询控制台，可以独立运行，不需要超级用户权限（除非要查询的表格需要访问权限）。osqueryd 像一个安装在主机的监控守护进程，可以定期调度查询操作执行，从底层架构收集信息。可以在不运行 osqueryd 的情况下执行 osqueri。另一个工具，osqueryctl，控制守护进程的启动、停止，并检查其状态。$ rpm -ql osquery-4.8.0-1.linux.x86_64 | grep bin /usr/bin/osqueryctl /usr/bin/osqueryd /usr/bin/osqueryi $ 使用 osqueryi 交互式命令提示符你和 Osquery 的交互与使用 SQL 数据库十分相似。事实上，osqueryi 是 SQList shell 的一个修改版。执行 osqueryi 命令进入交互式命令提示符 ，就可以执行 Osquery 的命令，通常以 . 开始：$ osqueryi Using a virtual database. Need help, type '.help' osquery> 要退出交互式命令提示符，执行 .quit 命令回到操作系统的命令提示符：osquery> osquery> .quit $ 找出可用的表如前所述，Osquery 像 SQL 查询一样输出数据，数据库中的信息通常保存在表中。但是如何在不知道表名的情况下查询这些表呢？你可以运行 .tables 命令列出所有可以查询的表。如果你是一个 Linux 长期用户或者一个系统管理员 ，就会对表名十分熟悉，因为你一直在使用操作系统命令获取同样的信息：osquery> .tables => acpi_tables => apparmor_events => apparmor_profiles => apt_sources <<裁剪>> => arp_cache => user_ssh_keys => users => yara => yara_events => ycloud_instance_metadata => yum_sources osquery> 检查各个表的模式知道表名后，可以查看每个表提供的信息。既然 ps 命令经常用于获取进程信息，就以 processes 为例。执行 .schema 命令加上表名查看表中保存的信息。如果要验证命令返回的结果，可以快速执行 ps -ef 或 ps aux，对比命令的输出和表中的内容：osquery> .schema processes CREATE TABLE processes(`pid` BIGINT, `name` TEXT, `path` TEXT, `cmdline` TEXT, `state` TEXT, `cwd` TEXT, `root` TEXT, `uid` BIGINT, `gid` BIGINT, `euid` BIGINT, `egid` BIGINT, `suid` BIGINT, `sgid` BIGINT, `on_disk` INTEGER, `wired_size` BIGINT, `resident_size` BIGINT, `tot…

使用开源工具进行 Linux 内存取证
type: item
date: 2021-05-26T19:20:06+08:00
description: 利用 Volatility 找出应用程序、网络连接、内核模块、文件等方面的情况。计算机的操作系统和应用使用主内存（RAM）来执行不同的任务。这种易失性内存包含大量关于运行应用、网络连接、内核模块、打开的文件以及几乎所有其他的内容信息，但这些信息每次计算机重启的时候都会被清除。 内存取证 Memory forensics 是一种从内存中找到和抽取这些有价值的信息的方式。Volatility 是一种使用插件来处理这类信息的开源工具。但是，存在一个问题：在你处理这些信息前，必须将物理内存转储到一个文件中，而 Volatility 没有这种能力。因此，这篇文章分为两部分：第一部分是处理获取物理内存并将其转储到一个文件中。第二部分使用 Volatility 从这个内存转储中读取并处理这些信息。我在本教程中使用了以下测试系统，不过它可以在任何 Linux 发行版上工作：$ cat /etc/redhat-release Red Hat Enterprise Linux release 8.3 (Ootpa) $ $ uname -r 4.18.0-240.el8.x86_64 $ 注意事项： 部分 1 涉及到编译和加载一个内核模块。不要担心：它并不像听起来那么困难。一些指南：按照以下的步骤。不要在生产系统或你的主要计算机上尝试任何这些步骤。始终使用测试的虚拟机（VM）来尝试，直到你熟悉使用这些工具并理解它们的工作原理为止。安装需要的包在开始之前安装必要的工具。如果你经常使用基于 Debian 的发行版，可以使用 apt-get 命令。这些包大多数提供了需要的内核信息和工具来编译代码：$ yum install kernel-headers kernel-devel gcc elfutils-libelf-devel make git libdwarf-tools python2-devel.x86_64-y 部分 1：使用 LiME 获取内存并将其转储到一个文件中在开始分析内存之前，你需要一个内存转储供你使用。在实际的取证活动中，这可能来自一个被破坏或者被入侵的系统。这些信息通常会被收集和存储来分析入侵是如何发生的及其影响。由于你可能没有可用的内存转储，你可以获取你的测试 VM 的内存转储，并使用它来执行内存取证。 Linux 内存提取器 Linux Memory Extractor （LiME）是一个在 Linux 系统上获取内存很常用的工具。使用以下命令获得 LiME：$ git clone https://github.com/504ensicsLabs/LiME.git $ $ cd LiME/src/ $ $ ls deflate.c disk.c hash.c lime.h main.c Makefile Makefile.sample tcp.c $ 构建 LiME 内核模块在 src 文件夹下运行 make 命令。这会创建一个以 .ko 为扩展名的内核模块。理想情况下，在 make 结束时，lime.ko 文件会使用格式 lime-<your-kernel-version>.ko 被重命名。$ make make -C /lib/modules/4.18.0-240.el8.x86_64/build M="/root/LiME/src" modules make[1]: Entering directory '/usr/src/kernels/4.18.0-240.el8.x86_64' << 删节 >> make[1]: Leaving directory '/usr/src/kernels/4.18.0-240.el8.x86_64' strip --strip-unneeded lime.ko mv lime.ko lime-4.18.0-240.el8.x86_64.ko $ $ $ ls -l lime-4.18.0-240.el8.x86_64.ko -rw-r--r--. 1 root root 25696 Apr 17 14:45 lime-4.18.0-240.el8.x86_64.ko $ $ file lime-4.18.0-240.el8.x86_64.ko lime-4.18.0-240.el8.x86_64.ko: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), BuildID[sha1]=1d0b5cf932389000d960a7e6b57c428b8e46c9cf, not stripped $ 加载LiME 内核模块现在是时候加载内核模块来获取系统内存了。insmod 命令会帮助加载内核模块；模块一旦被加载，会在你的系统上读取主…