Linux 软件分析基础

sky123

Linux 软件分析基础

基础工具

busybox

BusyBox 是一个集成了许多常用 Unix 工具的轻量级软件包。它将多个标准 Unix 命令(如 lscpcatmv 等)压缩到一个单独的二进制文件中,因此非常适合用于资源受限的环境,比如嵌入式系统或小型 Linux 系统。

通常我们分析的 Linux 软件所在的 Linux 系统可能缺少很多分析工具,并且缺少安装软件的源或者不能联网,此时可以上传一个 busyboxbin 目录可以方便很多。

编译

获取 BusyBox 源代码
  • 使用 Git 获取源代码:

    1
    2
    git clone https://git.busybox.net/busybox.git
    cd busybox
  • 访问 BusyBox 官方网站 下载最新的稳定版本,然后解压缩:

    1
    2
    3
    wget 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
2
<command-line>: fatal error: curses.h: No such file or directory
compilation terminated.

这里缺少的 curses.h 头文件是用来支持命令行界面工具(如 make menuconfig)的库文件。curses 库通常用于终端界面的开发(如在 menuconfig 中显示菜单)。要解决这个问题,你需要安装 ncurses 的开发包。

1
sudo apt-get install libncurses5-dev libncursesw5-dev

下载

使用

获取 linux shell

我们可以通过下面这条命令来开启一个 telnet 服务来远程访问软件所在系统的终端。其中 -p 指定 telnet 服务开启的端口,默认为 23 端口。

1
2
3
4
5
6
# 使用 busybox 内置的 sh
sudo ln -s /bin/busybox sh
sudo busybox telnetd -l /bin/sh -b 0.0.0.0 -p 23

# 如果系统自带 /bin/bash
sudo busybox telnetd -l /bin/bash -b 0.0.0.0

gdb & gdbserver

strace

网络通信

系统端口开放情况

iptables 是 Linux 系统上最广泛使用的防火墙工具,基于内核中的 Netfilter 框架工作。它通过创建和管理链(chains)来处理网络流量,允许管理员定义规则来处理进出系统的所有数据包。

查看当前防火墙规则和策略:

1
sudo iptables -L -n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
bash-4.2# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
sshd all -- 0.0.0.0/0 0.0.0.0/0
ipsec_udp_ports udp -- 0.0.0.0/0 0.0.0.0/0
spread_inp udp -- 0.0.0.0/0 0.0.0.0/0 udp dpts:4803:4804
externalports_control all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp flags:!0x17/0x02
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:601
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpts:11000:11099
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:25
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:465
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:993
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:995
DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:5432
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
DROP udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:111
DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:800
DROP udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:800
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 3 code 4
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 8
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 11
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 0
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 3
DROP icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 13
DROP icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 14
ACCEPT all -f 0.0.0.0/0 0.0.0.0/0
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpts:8009:8010

Chain FORWARD (policy ACCEPT)
target prot opt source destination
DROP all -- 0.0.0.0/0 0.0.0.0/0

Chain OUTPUT (policy ACCEPT)
target prot opt source destination
spread_out udp -- 0.0.0.0/0 0.0.0.0/0 udp dpts:4803:4804

Chain externalports_control (1 references)
target prot opt source destination

Chain ipsec_udp_ports (1 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0

Chain spread_inp (1 references)
target prot opt source destination
DROP all -- 0.0.0.0/0 0.0.0.0/0

Chain spread_out (1 references)
target prot opt source destination
DROP all -- 0.0.0.0/0 0.0.0.0/0

Chain sshd (1 references)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:830
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:830

设置默认策略为 ACCEPT

  • INPUT 链:控制进入主机的流量。
  • OUTPUT 链:控制从主机发出的流量。
  • FORWARD 链:控制通过主机转发的流量。
1
2
3
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD 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.0127.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
    2
    tcp6       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))

这里的 myprocess1234 就是监听 4080 端口的进程名称和 PID。

使用 lsof 命令

lsof 命令可以列出当前打开的文件,包括网络连接。你可以通过以下命令查找哪个进程在监听 4080 端口:

1
lsof -i :4080

输出可能类似于:

1
2
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
myprocess 1234 user 3u IPv4 123456 0t0 TCP *:4080 (LISTEN)

其中,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
2
3
init(1)─┬─sshd(1234)─┬─sshd(1256)─┬─{sshd}(1267)
│ └─{sshd}(1258)
└─systemd(5678)
  • 在这个例子中,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 文件中导出的符号。以下是一个简单的步骤:

  1. 使用find命令查找所有的 .so 文件:

    1
    find /path/to/directory -name "*.so"
  2. 使用nm命令查看每个 .so 文件中的符号,找出 wgarchive_extract

    1
    nm -D /path/to/library.so | grep wgarchive_extract

    这将会显示出包含 wgarchive_extract 函数的 .so 文件。如果该函数导出,nm 会列出它的符号。

  3. 将这两者结合在一起: 你可以将 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.
Comments