Linux 软件分析基础

Linux 软件分析基础
基础工具
busybox
BusyBox 是一个集成了许多常用 Unix 工具的轻量级软件包。它将多个标准 Unix 命令(如 ls
、cp
、cat
、mv
等)压缩到一个单独的二进制文件中,因此非常适合用于资源受限的环境,比如嵌入式系统或小型 Linux 系统。
通常我们分析的 Linux 软件所在的 Linux 系统可能缺少很多分析工具,并且缺少安装软件的源或者不能联网,此时可以上传一个 busybox
到 bin
目录可以方便很多。
编译
获取 BusyBox 源代码
使用 Git 获取源代码:
1
2git clone https://git.busybox.net/busybox.git
cd busybox访问 BusyBox 官方网站 下载最新的稳定版本,然后解压缩:
1
2
3wget https://busybox.net/downloads/busybox-1.37.0.tar.bz2
tar -xjvf busybox-1.37.0.tar.bz2
cd busybox-1.37.0
配置 BusyBox
1 | make menuconfig |
期间可能会报下面这个错
1 | <command-line>: fatal error: curses.h: No such file or directory |
这里缺少的 curses.h
头文件是用来支持命令行界面工具(如 make menuconfig
)的库文件。curses
库通常用于终端界面的开发(如在 menuconfig
中显示菜单)。要解决这个问题,你需要安装 ncurses
的开发包。
1 | sudo apt-get install libncurses5-dev libncursesw5-dev |
下载
使用
获取 linux shell
我们可以通过下面这条命令来开启一个 telnet
服务来远程访问软件所在系统的终端。其中 -p
指定 telnet
服务开启的端口,默认为 23 端口。
1 | # 使用 busybox 内置的 sh |
gdb & gdbserver
strace
网络通信
系统端口开放情况
iptables
是 Linux 系统上最广泛使用的防火墙工具,基于内核中的 Netfilter 框架工作。它通过创建和管理链(chains)来处理网络流量,允许管理员定义规则来处理进出系统的所有数据包。
查看当前防火墙规则和策略:
1 | sudo iptables -L -n |
1 | bash-4.2# iptables -L -n |
设置默认策略为 ACCEPT
:
INPUT
链:控制进入主机的流量。OUTPUT
链:控制从主机发出的流量。FORWARD
链:控制通过主机转发的流量。
1 | sudo iptables -P INPUT ACCEPT |
进程端口通信情况
netstat
(network statistics)是一个用于显示网络连接、路由表、接口状态等网络信息的命令行工具。它可以帮助系统管理员或开发人员了解系统的网络状态、诊断网络问题、查看开放端口和监听服务等。
netstat
命令的常用选项
netstat
命令有许多选项可以用来过滤或详细显示网络连接的不同信息。以下是一些常用的选项:
- **
-t
**:显示 TCP 连接。 - **
-u
**:显示 UDP 连接。 - **
-l
**:仅显示监听状态的套接字(也就是在等待连接的端口)。 - **
-n
**:以数字形式显示地址和端口(不解析为主机名或服务名)。 - **
-p
**:显示哪个进程正在使用该端口(需要管理员权限)。 - **
-a
**:显示所有连接和监听的套接字。 - **
-r
**:显示路由信息。 - **
-i
**:显示网络接口信息。 - **
-s
**:显示各种网络统计信息(例如协议、接口统计等)。
网络连接状态
- LISTEN:表示该端口正在监听,等待来自外部的连接。
- ESTABLISHED:表示连接已经成功建立,可以进行数据传输。
- TIME_WAIT:连接关闭后,等待一定时间以确保数据完全传输。
- CLOSE_WAIT:表示对方关闭了连接,但本方还没有关闭连接。
- SYN_SENT:表示连接正在尝试建立(即 TCP 的三次握手的第一步)。
- SYN_RECV:表示连接已进入三次握手的第二步。
- FIN_WAIT1:表示本方请求关闭连接。
- FIN_WAIT2:表示对方同意关闭连接,并已关闭发送端。
网络地址类型
在使用 netstat
命令查看网络连接和监听端口时,你会看到不同的 IP 地址,例如 0.0.0.0
、127.0.0.1
、本机的具体 IP 地址以及其他一些地址。这些地址表示不同的绑定方式和监听范围。
0.0.0.0
:全网卡监听1
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1234/nginx
- 含义:表示该服务监听 所有可用的网络接口。无论是本地回环接口(
127.0.0.1
)还是其他网卡的 IP 地址,该服务都可以接受来自任何接口的连接请求。 - 适用场景:适用于需要被多网络接口访问的服务。例如,一个需要被局域网内的其他机器访问的 Web 服务器,可以绑定到
0.0.0.0
,使其在所有网络接口上可用。
- 含义:表示该服务监听 所有可用的网络接口。无论是本地回环接口(
127.0.0.1
:本地回环监听1
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 5678/mysqld
- 含义:
127.0.0.1
是 回环地址(Loopback Address),表示该服务只监听 本地机器内部 的连接请求,无法被外部机器访问。 - 适用场景:适用于仅本地访问的服务。例如,数据库服务如 MySQL 通常绑定到
127.0.0.1
,仅允许本地应用程序连接。
- 含义:
本机 IP 地址:特定接口监听
1
tcp 0 0 192.168.1.100:22 0.0.0.0:* LISTEN 2222/sshd
- 含义:服务绑定到 某一个具体的 IP 地址,只在该网络接口上监听连接请求。例如,如果本机有多个网络接口(如以太网和 Wi-Fi),可以选择性地绑定到其中一个接口的 IP 地址。
- 适用场景:适用于需要限制监听接口的服务。例如,Web 服务器只需要在内部网络接口上提供服务,而不希望通过公共网络接口访问。
::
和::1
:支持 IPv6 的服务1
2tcp6 0 0 :::443 :::* LISTEN 1234/nginx
tcp6 0 0 ::1:5432 :::* LISTEN 5678/postgres::
:相当于 IPv4 的0.0.0.0
,表示 所有 IPv6 网络接口。::1
:相当于 IPv4 的127.0.0.1
,表示 本地回环地址,仅监听本地连接。
::ffff:127.0.0.1
:兼容性地址
1 | tcp6 0 0 ::ffff:127.0.0.1:6379 :::* LISTEN 8888/redis-server |
表示一个 IPv4 地址通过 IPv6 映射方式表示,例如 ::ffff:127.0.0.1
实际上是 IPv4 的 127.0.0.1
。
查找监听指定端口的进程
使用 netstat
命令
netstat
是一个网络相关的命令,可以显示网络连接、路由表、接口统计信息等。要查找监听 4080 端口的进程,可以使用以下命令:
1 | netstat -tuln | grep :4080 |
解释:
-t
:显示 TCP 连接。-u
:显示 UDP 连接。-l
:显示正在监听的端口。-n
:显示数字格式的地址和端口(不解析主机名和服务名)。
这个命令会列出监听 4080 端口的网络连接。如果该端口有进程在监听,输出将类似于:
1 | tcp 0 0 0.0.0.0:4080 0.0.0.0:* LISTEN |
要查看监听该端口的进程 PID,你可以添加 -p
参数来显示进程信息:
1 | netstat -tulnp | grep :4080 |
此命令会显示类似于下面的输出:
1 | tcp 0 0 0.0.0.0:4080 0.0.0.0:* LISTEN 1234/myprocess |
其中 1234/myprocess
就是监听 4080 端口的进程的 PID 和名称。
使用 ss
命令
ss
是比 netstat
更快速和现代化的工具,功能与 netstat
类似,也可以用于查看网络连接状态和监听的端口。要查找监听 4080 端口的进程,可以运行:
1 | ss -tuln | grep :4080 |
如果要查看监听端口的进程 PID 和名称,可以加上 -p
参数:
1 | ss -tulnp | grep :4080 |
输出示例:
1 | LISTEN 0 128 0.0.0.0:4080 0.0.0.0:* users:(("myprocess",pid=1234,fd=3)) |
这里的 myprocess
和 1234
就是监听 4080 端口的进程名称和 PID。
使用 lsof
命令
lsof
命令可以列出当前打开的文件,包括网络连接。你可以通过以下命令查找哪个进程在监听 4080 端口:
1 | lsof -i :4080 |
输出可能类似于:
1 | COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME |
其中,myprocess
是监听该端口的进程名,1234
是进程的 PID。
使用 fuser
命令
fuser
命令可以显示哪些进程正在使用某个文件或端口。要查找监听 4080 端口的进程,可以运行:
1 | fuser 4080/tcp |
输出类似于:
1 | 4080/tcp: 1234 |
这里的 1234
就是监听 4080 端口的进程的 PID。
查询指定进程监听的端口
使用 ss
命令
ss
是一个高效的工具,用于查看网络连接信息,包括监听的端口。你可以使用 ss
结合 -p
参数来查看特定进程监听的端口。
1 | ss -tulnp | grep <pid> |
-t
: 显示 TCP 套接字。-u
: 显示 UDP 套接字。-l
: 显示监听的端口。-n
: 显示数字形式的地址和端口。-p
: 显示使用该套接字的进程信息。
使用 lsof
命令
lsof
是一个非常强大的工具,用于列出系统中打开的文件,包括网络套接字。你可以通过 lsof
查看某个进程监听的端口。
1 | lsof -i -a -p <pid> |
-i
: 显示网络连接(包括 TCP、UDP)。-a
: 只显示同时满足多个条件的项。-p <pid>
: 显示指定进程的文件信息。
使用 netstat
命令
netstat
是一个经典的网络工具,也可以用来查看进程监听的端口,但在某些系统上,netstat
可能已经被 ss
替代。
1 | netstat -tulnp | grep <pid> |
-t
: 显示 TCP 套接字。-u
: 显示 UDP 套接字。-l
: 只显示监听的端口。-n
: 显示数字形式的地址和端口。-p
: 显示进程 ID 和进程名称。
进程行为
pstree
pstree
是一个非常实用的命令,它可以以树形结构显示系统中所有进程的层次关系。显示指定进程及其所有子进程和父进程
1 | pstree -p -s <pid> |
{}
包裹的进程:表示这些进程是线程。多个线程共享相同的地址空间和资源,通常它们都是由同一个父进程(通常是主进程)创建的,并且它们的 PID 是通过pthread
等线程库管理的。线程并不像独立的进程那样拥有独立的资源,它们共享父进程的资源。- 线程与进程的关系:在 Linux 中,线程是一种特殊类型的进程,它们共享父进程的内存空间和文件描述符等资源。通常,这些线程的 PID 会被标识为进程的 TID(线程 ID)。在
pstree
中,所有属于同一线程组的线程会被表示在一个{}
中,表示它们属于同一组的进程(线程组)。
假设你运行 pstree -p -s <pid>
时看到如下输出:
1 | init(1)─┬─sshd(1234)─┬─sshd(1256)─┬─{sshd}(1267) |
- 在这个例子中,
sshd
是一个主进程,PID 为1234
,它启动了两个子进程:sshd(1256)
和sshd(1258)
。 sshd(1256)
启动了两个线程:{sshd}(1267)
和{sshd}(1258)
,这些线程是sshd
进程的一部分,并且共享相同的资源。- 其中,
{sshd}(1267)
和{sshd}(1258)
这两个进程 PID 被包裹在{}
中,表示它们是sshd
进程中的线程。
strace
strace
是一个用于追踪进程发出的系统调用(system calls)和信号(signals)的工具。通过 strace
,你可以看到程序是如何与操作系统交互的,例如它如何打开文件、读写数据、进行网络通信等。
监控指定进程及其子进程(线程)的系统调用:
1 | strace -s 1024 -fp <pid> |
-s <length>
设置系统调用参数输出长度。-f
选项表示 跟踪子进程。当你使用-f
时,strace
不仅会跟踪你指定的进程,还会跟踪它创建的 所有子进程 和 线程。-p <pid>
选项表示 附加到进程<pid>
上并开始跟踪它的系统调用。<pid>
是你想要跟踪的目标进程的进程 ID。
文件操作
查看文件描述符
lsof
列出进程打开的文件,包括普通文件、套接字、管道等。
1 | lsof -p <pid> |
搜索文件
1 | grep -r "特定内容" /path/to/directory |
查看日志
1 | tail -n <行数> <日志路径> |
依赖分析
搜索导出指定函数的so库
你可以使用 nm
工具来查看 .so
文件中导出的符号。以下是一个简单的步骤:
使用
find
命令查找所有的.so
文件:1
find /path/to/directory -name "*.so"
使用
nm
命令查看每个.so
文件中的符号,找出wgarchive_extract
:1
nm -D /path/to/library.so | grep wgarchive_extract
这将会显示出包含
wgarchive_extract
函数的.so
文件。如果该函数导出,nm
会列出它的符号。将这两者结合在一起: 你可以将
find
命令和nm
命令结合,自动对所有.so
文件进行检查:1
find /path/to/library.so -name "*.so" -exec sh -c 'echo "{}"; nm -D "{}"' \; > res
这个命令会在指定目录下查找所有
.so
文件,并使用nm
命令检查每个.so
文件中是否导出了wgarchive_extract
函数。
- Title: Linux 软件分析基础
- Author: sky123
- Created at : 2025-01-03 12:43:33
- Updated at : 2025-02-27 05:08:23
- Link: https://skyi23.github.io/2025/01/03/Linux 软件分析基础/
- License: This work is licensed under CC BY-NC-SA 4.0.