Skip to content

30 库文件的管理与文件正确性检查

1. 库文件管理

1.1 动态库与静态库

1.1.1 静态库

  • 扩展名: 这类的库文件通常扩展名为 libxxx.a 的类型;Windows下的扩展名为.lib
  • 编译行为: 这类库文件在编译的时候会直接整合到执行程序当中,所以利用静态库文件编译成的文件会比较大一些;
  • 独立执行的状态: 这类库文件最大的优点,就是编译成功的可执行文件可以独立执行,而不需要再向外部要求读取库文件的内容 (请参照动态库文件的说明)。
  • 升级难易度: 虽然执行文件可以独立执行,但因为库文件是直接整合到执行文件中, 因此若库文件升级时,整个执行文件必须要重新编译才能将新版的库文件整合到程序当中。 也就是说,在升级方面,只要库文件升级了,所有将此库文件纳入的程序都需要重新编译!

1.1.2 动态库

  • 扩展名: 这类库文件通常扩展名为 libxxx.so 的类型;Windows下的扩展名为.dll
  • 编译行为: 动态库文件在编译的时候,在程序里面只有一个指向 (Pointer)的位置而已。也就是说,动态库文件的内容并没有被整合到执行文件当中,而是当执行文件要使用到库文件的机制时, 程序才会去读取库文件来使用。由于执行文件当中仅具有指向动态库文件所在的指标而已, 并不包含库文件的内容,所以他的文件会比较小一点。
  • 独立执行的状态: 这类型的库文件所编译出来的程序不能被独立执行, 因为当我们使用到库文件的机制时,程序才会去读取库文件,所以库文件文件必须要存在才行,而且,库文件的所在目录也不能改变,因为我们的可执行文件里面仅有指标亦即当要取用该动态库文件时, 程序会主动去某个路径下读取。所以动态库文件可不能随意移动或删除,会影响很多依赖的程序软件!
  • 升级难易度: 虽然这类型的执行文件无法独立运作,然而由于是具有指向的功能, 所以,当库文件升级后,执行文件根本不需要进行重新编译的行为,因为执行文件会直接指向新的库文件文件 (前提是库文件新旧版本的文件名相同! )。

1.1.3 库文件的位置

绝大多数的库文件都放置在/lib64, /lib 目录下!此外,Linux 系统里面很多的库文件其实 kernel 就提供了,位于 /lib/modules 目录下。

Note

不同版本的核心提供的库文件差异性是挺大的,所以 kernel 2.4.xx 版本的系统不要想将核心换成 2.6.xx 喔! 很容易由于库文件的不同而导致很多原本可以执行的软件无法顺利运作呢!

1.2 ldconfig 与 /etc/ld.so.conf

将动态库加载到高速缓存当中:

  1. 首先,我们必须要在 /etc/ld.so.conf 里面写下 想要读入高速缓存当中的动态库所在的目录
  2. 接下来则是利用 ldconfig 这个执行文件将 /etc/ld.so.conf 的内容读入高速缓存当中;
  3. 同时也将数据记录一份在 /etc/ld.so.cache 这个文件当中。

ldconfig 还可以用来判断动态函式库的链接信息。

ldconfig [OPTION...]

OPTION
    -p, --print-cache          Print cache
# 配置
[root@dev src]# cat /etc/ld.so.conf.d/mariadb-x86_64.conf 
/usr/lib64/mysql
# 载入
[root@dev src]# ldconfig 
# 查看
[root@dev src]# ldconfig -p | grep mysql
    libmysqlclient.so.18 (libc6,x86-64) => /usr/lib64/mysql/libmysqlclient.so.18

1.3 程序的动态库解析:ldd

检查文件依赖哪些动态库。

ldd [OPTION]... FILE...

OPTIONS
    -d, --data-relocs       执行重定位并报告任何丢失的对象(仅限 ELF)。
    -r, --function-relocs   对数据对象和函数执行重定位,并报告任何缺少的对象或函数(仅限 ELF)。
    -v --verbose
[root@dev src]# ldd -v /usr/bin/ls
    linux-vdso.so.1 =>  (0x00007ffe877bf000)
    libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fbbdfcd4000)
    libcap.so.2 => /lib64/libcap.so.2 (0x00007fbbdfacf000)
    libacl.so.1 => /lib64/libacl.so.1 (0x00007fbbdf8c6000)
    ……

    Version information:
    /usr/bin/ls:
        libacl.so.1 (ACL_1.0) => /lib64/libacl.so.1
        libc.so.6 (GLIBC_2.14) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
        ……
    ……
[root@dev src]# ldd -v /lib64/libacl.so.1
    linux-vdso.so.1 =>  (0x00007fff16152000)
    ……

2. 检验文件正确性

基本上,你必须要在你的 Linux 系统上为你的这些重要的文件进行指纹数据库的建立:

  • /etc/passwd
  • /etc/shadow (假如你不让用户改密码了)
  • /etc/group
  • /usr/bin/passwd
  • /sbin/rpcbind
  • /bin/login (这个也很容易被黑!)
  • /bin/ls
  • /bin/ps
  • /bin/top

这几个文件最容易被修改了!因为很多木马程序执行的时候,还是会有所谓的“执行序, PID“,因为怕被 root 追查出来,所以他们会修改这些文件。

2.1 举例

/etc/{passwd,shadow,group} 以及系统上面所有的 SUID/SGID 文件建立文件列表:

[root@dev src]# ls /etc/{passwd,shadow,group} > important.file
[root@dev src]# find /usr/sbin /usr/bin -perm /6000 >> important.file

为该文件建立指纹文件:

[root@dev file-check]# cat important-md5-check.sh
#!/bin/sh

if [ "x$1" == "xnew" ]
then
    date_str="origin"
    origin=true
else
    date_str=$(date +"%Y%m%d%H%M%S")
fi
finger_file=important_finger_${date_str}.file

# remove important_finger_origin.file
if [ -f ${finger_file} ]
then
    chattr -i ${finger_file}
    rm ${finger_file}
fi

for file in $(cat important.file)
do
    md5sum ${file} >> ${finger_file}
done
chattr +i ${finger_file}

diff_str=$(diff important_finger_origin.file important_finger_${date_str}.file)
if [[ -n ${origin} && ${diff_str} != "" ]]
then
    diff important_finger_origin.file important_finger_${date_str}.file | mail -s "important file has been modified!" root
elif [ -z ${origin} ]
then
    chattr -i ${finger_file}
    rm ${finger_file}
fi

# 生成对比的指纹文件
[root@dev file-check]# sh important-md5-check.sh new
[root@dev file-check]# ls
important.file  important_finger_origin.file  important-md5-check.sh

为检查建立日程:

[root@dev file-check]# crontab -l
00 03 * * * cd /root/file-check; sh important-md5-check.sh