1.如何将开放源代码的程序设计、加入函数库的原理、通过编译而成为可以执行的二进制程序,最后该执行文件可被我们使用的一连串的过程
2.在Linux的世界里,由于定制化的关系,有时候我们需要在Linux系统中自行安装软件,而最传统的软件安装过程是由源代码编译而来

开放源码的软件安装与升级简介

在Windows操作系统上面的软件都是一模一样的,也就是说无法修改软件源代码,如果想要增加或修改软件的某些功能,只能求助于软件发行商。。。
如果可以借由安全信息单位所提供的自定义方式进行修改,那么可以快速地自行修补好该软件的漏洞,而不必一定要等到软件开发商提供修补的程序包,而程序的漏洞永远补不完。

  • Linux上面的软件几乎都是经过GPLL的授权,所以每个软件几乎均提供源代码,并且可以自行修改该程序源代码,符合个人的需求,这就是开放源码的优点

什么是开放源码、编译器与可执行文件

  • 二进制程序
    Linux系统上真正识别的可执行文件是二进制程序(binary program),例如/usr/bin/passwd、/bin/touch这些文件为二进制文件
  • 判断是否为二进制程序
    file 命令功能:
    如果为二进制,且可执行,会显示执行文件类别(ELF 64-bit LSB executable)和是否使用动态函数库(shared libs)
    如果为一般脚本,会显示处text executable 之类的字样
    如果为其他文件,则根据具体文件类型显示其他的字样
    image.png
  • 总结
    程序源代码文件就是一般的纯文本文件。在完成这个源代码文件的编写之后,将该文件编译称为操作系统看得懂的二进制程序。编译需要编译器来操作,经过编译器的编译与连接之后,就会产生可以执行的二进制程序。
    有些时候我们会在程序当中引用、调用其他的外部子程序,或是利用其他软件提供的函数功能,则必须要在编译的过程中将该函数库加进去,编译器就可以将所有的程序代码与函数库作一个链接(link)以产生正确的执行文件
  • 开放源代码:程序代码,写给认类看的程序语言,但机器并不认识,无法执行
  • 编译器:将程序代码转译称为机器看得懂的语言
  • 可执行文件:经过编译器变成的二进制程序,机器看得懂,所以可以执行

什么是函数库

函数库类似于子程序的角色,可以被调用来执行的一段功能函数
分为动态与静态函数库

什么是make与configure

使用gcc的编译器来进行编译并不简单,除了每个主程序与子程序均需要写上一条编译过程的命令外,还需要写上最终的链接程序。可以使用make命令的相关功能来进行编译过程的简化。

make 的执行过程

当执行make时,make会在当前的目录下查找Makefile(or makefile)这个文本文件,里面记录了源代码如何编译的详细信息。make会自动地判别源代码是否经过变动了,而自动更新执行文件,

Makefile

通常软件开发商都会写一个检测程序来检测用户的操作环境,以及该操作环境是否有软件开发商所需要的其他功能,检测程序检测完毕后会主动地建立这个Makefile 的规则文件,通常这个检测程序的文件名为configure或config

检测程序检测内容 configure

  • 是否有适合的编译器可以编译本软件的程序代码
  • 是否已经存在本软件所需要的函数库,或其他需要的依赖软件
  • 操作系统平台是否适合本软件,包括Linux的内核版本
  • 内核的头文件(header include)是否存在(驱动程序必须要的检测)
    总结:个人安装软件需要执行的任务有2个:
    1.执行configure来建立Makefile
    2.以make来调用所需要的数据进行编译(调用gcc和Makefile)

因为不同Linux发行版的函数库文件放置的路径、函数库的文件名或是默认安装的编译器以及内核的版本都不同,所以理论上,同一个软件在不同的平台上面执行时,必须要重新编译,所以才需要源代码

什么是Tarball的软件

如果能将源代码通过文件的打包与压缩技术来将文件的数量与容量减小,不但让用户容易下载,软件开发商的网站带宽也能够节省很多流量,
Tarball 文件就是将软件的所有源代码文件先以tar打包,然后再以压缩技术来压缩,利用了tar与gzip的功能,扩展名一般会写成tar.gz或.tgz。由于bzip2与xz的压缩率较佳,所以也会有*.tar.bz2或*.tar.xz。
解压缩后文件一般有:

  • 源代码文件
  • 检测程序文件(可能是configure或config等文件)
  • 本软件的简易说明与安装说明(INSTALL或README)
    通常用INSTALL或README作为安装参考,比较重要

如何安装与升级软件

安装与升级原因

  • 安装:主机上没有该软件,需要用到
  • 升级:
    1.需要新的功能
    2.旧版本有信息安全上的缺陷
    3.旧版本性能不加

安装与升级方法

1.直接以源代码通过编译来安装与升级
虽然让用户在安装过程当中具有很高的弹性,但比较麻烦
2.直接以编译好的二进制程序来安装与升级
编译与运行环境相同则可以直接安装,省略检测与编译等繁杂过程

预编译的软件安装与升级

预先编译好的程序的机制存在于很多发行版,包括有:

  • Red Hat系列(Fedora/CentOS):使用RPM软件管理机制与yum在线更新模式
  • Debian:dpkg软件管理机制与APT在线更新

Tarball 安装步骤:

  • 1.将Tarball由厂商的网站下载
  • 2.将Tarball解压缩,产生很多的源代码文件
  • 3.开始以gcc进行源代码的编译(会产生目标文件 object files)
  • 4.然后以gcc进行函数库、主、子程序的链接,以生成主要的二进制文件
  • 5.将上述的二进制文件以及相关的配置文件安装至自己的主机上面

总结:上述的3、4步骤可以通过make简化,但至少必须有gcc和make 这两个软件

使用传统程序语言进行变异的简单范例

单一程序:打印Hello World

编写程序
image.png
编译脚本并执行二进制文件
image.png
在默认状态下,直接以gcc编译源代码,并且没有加上任何参数,则执行文件的文件名会被自动设置为a.out

主、子程序链接:子程序的编译

我们在一个主程序里面又调用了另一个子程序

编写主、子程序

image.png
编译:
image.png
在编译时错误,出现提示,原来我将{}写成[]且少写了",其实VIM已经出现颜色提示,只是我没有注意
重新编译如下:
image.png
由于我们的源代码文件有时并非只有一个文件,所以我们无法直接进行编译。这个时候就需要先产生目标文件,然后再以链接制作成为二进制可执行文件。

gcc的额外参数功能

man gcc
image.png

调用外部函数库:加入链接的函数库

新版的gcc会主动帮你将所需要的函数库放进来编译,所以不会出现怪异的错误信息

  • 例子:计算sin90°
    image.png
    image.png

编译时加入额外函数库链接的方式

gcc 源码文件 -l***********

gcc的简易用法(编译、参数与连接)

man gcc

  • -c:
  • -O
  • -lm
  • -L
  • -I
  • -o

用make进行宏编译

使用make简化执行编译命令的流程

为什么要用make

  • make比shell脚本的优势:
    1.make会主动判断每个目标文件相关的源代码文件,并直接予以编译,最后再直接进行链接的操作
    2.如果修改过某些源代码文件,make可以主动判断哪一个源代码与相关的目标文件有修改过,并仅更新该文件一次,可节省很多编译的时间

  • make相比直接gcc的好处
    1.简化编译时所需要执行的命令
    2.若在编译完成之后,修改了某个源代码文件,则make会针对被修改了的文件进行编译,其他的目标文件不会被修改
    3.可以依照依赖性来更新(update)执行文件

make里面最需要主义的是规则文件,即makefile文件

makefile 的基本语法与变量

  • 目标(target):目标文件1 目标文件2
  • <tab键> gcc -o 欲建立的执行文件 目标文件1 目标文件2

//TODO

Tarball 的管理与建议

Tarball 的安装是可以跨平台的,只与程序代码和编译器有关

使用源代码管理软件所需要的基础软件

制作一个二进制程序需要很多东西,包括以下这些基础软件:

编译器:gcc 或cc等

编译器进行编译

make及autoconfig等软件

make根据目标文件的依赖性而进行编译
autoconfig自行检测程序需要其进行辅助

内核提供的Library以及相关的include文件

很多软件在发展的时候都是直接使用操作系统内核提供的函数库与include文件,这样才可以与这个操作系统兼容,尤其是在驱动程序方面的模块

总结:如果希望自己可以自行安装一些以Tarball方式发布的软件时,应自行选择想要安装的软件名称。例如在CentOS或Red Hat中选择Development Tools以及Kernel Source Development 等相关的软件包。但目前前两种系统大多是以RPM来安装软件的

Tarball 安装的基本步骤

先将 Tarball 解压缩,然后到源代码所在的目录下进行makefile 的建立,再以make来进行编译与安装的操作,具体步骤如下:

1.获取原始文件

将tarball 文件在/usr/local/src 目录下解压缩

2.获取步骤流程

进入新建立的目录下面,查看INSTALL与README等相关文件内容(很重要)

3.依赖属性软件安装

根据INSTALL与README的内容查看并安装好一些依赖的软件(非必要)

4.建立makefile

以自动检测程序(configure或config)检测操作环境,并建立Makefile这个文件

5.编译

用make这个程序,并使用该目录下的Makefile 作为它的参数配置文件,来进行make(编译或其他)的操作

6.安装

以make这个程序,并以Makefile这个参数配置文件,根据install这个目标(target)的指定来安装到正确的路径

Tarball 软件安装的命令执行方式

./configure

建立Makefile 文件,这个步骤的相关信息应该要参考一下该目录下的README或INSTALL相关文件

make clean

读取Maklefile 中关于clean的工作。这个步骤不一定会有,但最好执行一下,因为它可以移除目标文件

make

make会根据Makefile 当中的默认设置进行编译的操作。将源代码编译成为可以被执行的文件,这个可执行文件放置在目前所在的目录之下,尚未被安装到预定安装的目录中

make install

make会根据Makefile 文件里关于install的选项,将上一个步骤所编译完成的内容安装到预定的目录中,从而完成安装

如果一个软件安装成功,并且是安装在一个独立的目录中,那么必须手动将这个软件的man page写入/etc/man_db.conf 中

一般Tarball软件安装的建议事项(如何删除?升级?)

删除

一般直接删除软件目录则可视为软件已删除,但实际上还要根据install里面的具体内容

升级

需要重新编译的二进制文本可能较多

默认目录

默认情况下,原本的Linux发行版发布安装的软件大多是在/usr里面,用户自行安装的软件则建议放置在/usr/local里面,Tarball放置在/usr/local/src下面

安装同一目录 /usr/local

  • 利:环境变量PATH 不用新增设置
  • 弊:则未来再想要升级或删除的时候会比较难以追查文件的来源

安装不同目录 /usr/local/具体的软件名

  • 利:目录区分,易管理
  • 弊:需使用绝对路径启动或者需要加入环境变量PATH和man page等相关配置

建议

Tarball在反安装上面具有比较高的难度(如果没有好好规划的话),所以为方便Tarball的管理,应:

  • 1.最好将Tarball的原始数据解压缩到/usr/local/src当中
  • 2.安装时,最好安装到/usr/local这个默认路径下
  • 3.考虑到未来的反安装步骤,最好可以将每个软件单独安装在/usr/local下面
  • 4.为安装到单独目录的软件的man page 加入man path 查找。例如:
    安装的软件目录为/usr/local/software/那么要在/etc/man_db.conf内添加MANPATH_MAP /usr/local/software/bin /usr/local/software/man 这样才可以使用man来查询该软件的在线文件

简单的示例shell

解压缩下载的tarball

tar -zxvf 待解压文件名

检查configure参数,创建makefile规则文件

./configure --help | more 查看可用的参数有哪些
比较重要的参数:--prefix=/path 该path为这个软件要安装到的目录,如果未指定则默认一般为/usr/local

编译与安装

  • make clean;make
  • make check
  • make install

利用patch更新源代码

一些软件的漏洞通常只是某一段程序代码写的不好所致,因此所谓的更新源代码常常是只有小部分文件内容更改,旧版本到新版本间没有修改过的文件不去理会,仅处理自定义过的文件部分即可。
通过diff 命令对比出新旧版本之间的文字差异,然后再以parch 相关命令来将旧版的文件更新。

函数库管理

函数库是个很重要的东西,很多软件之间都会互相使用彼此提供的函数库来使用其特殊功能(PAM、SSL)。

动态与静态函数库

静态库

  • 扩展名:通常为libXXX.a
  • 编译操作:编译时会直接整合到执行程序中,编译后的文件会比较大一些
  • 独立执行的状态:最大的优点为编译成功的可执行文件可以独立运行,而不需要再向外部要求读取函数库的内容
  • 升级难易度:只要函数库升级了,所有使用此函数库的程序都要重新编译

动态库

  • 扩展名:通常为libXXX.so
  • 编译操作:动态函数在编译的时候,在程序里面只有一个指针(Pointer)的位置而已。由于执行文件当中仅具有知道动态函数库所在的指针,并不包含函数库的内容,所以它的文件会比较小一点
  • 独立执行的状态:编译出来的程序不能被独立执行,函数库文件必须要存在且所在目录也不能改变。动态函数库不能随意移动或删除,会影响很多依赖的程序软件
  • 升级难易度:函数库升级后,执行文件根本不需要进行重新编译的操作

总结

Linux发行版比较倾向于动态函数库,因为只要动态函数库升级就好,其他的软件根本无须变动。
绝大多数函数库放置在/lib64与/lib 目录中,Linux系统里面很多的函数库也由内核提供(/lib/modules) 不同版本内核提供的函数库是有差异的,所以由于函数库的不同,原本可执行的软件也可能无法顺利运行

ldconfig与/etc/ld.so.conf

程序的动态函数库解析:ldd

校验软件正确性

校验下载的文件本身是否被篡改过,需要通过每个文件独特的校验特征数据来判断,可以通过 md5sum、sha1sum、sha256sum
man md5sum
image.png
md5sum/sha1sum/sha256sum [-bct] filename
md5sum/sha1sum/sha256sum [--status|--warn] --check filename
选项与参数:

  • -b:使用二进制文件的读取方式,默认使用Windows/DOS文件格式的读取方式
  • -c:检验文件校验值
  • -t:以文本方式来读取文件校验值

记录检查系统重要文件是否被篡改

/etc/passwd
/etc/shadow (如果不需要让用户更改密码)
/etc/group
/usr/bin/passwd
/sbin/rpcbind
/bin/login (很容易被破坏)
/bin/ls
/bin/ps
/bin/top
上述几个文件最容易被修改,因为很多木马程序执行的时候,还是会有PID,为了怕被root查出来,所以他们都会修改这些检查调度的文件,如果给这些文件建立校验数据库(使用md5sum检查一次,将该文件校验值记录下来,然后常常以shell脚本的方式由程序自行来检查校验表是否相同),那么对于文件系统比较安全


这个家伙很懒,啥也没有留下😋