一、需要获取版本号的原因

从使用角度而言,有时只有特定版本的库才支持某些功能,所以我们需要确定库文件版本号。

从安全加固角度而言,有些版本存在漏洞有些版本不存在漏洞,所以我们需要获取版本号以确定当前使用版本是否需要处理。

不过就实际来看,针对库文件(尤其是ko文件)来发布的漏洞是比较少的,另一方面so和ko文件并没有强制要求实现版本号所以他们并不一定有版本号。

二、手动获取版本号方法

2.1 so文件手动获取版本号方法

2.1.1 从文件名获取版本号

很多so文件都直接将so号写到文件名中,".so"前面或后面的数字串即是其版本号,如下所示

2.1.2 使用readelf读取SONAME获取主版本号

如果文件名中没有版本号,那么退而求其次,通过readelf读取so的SONAME字段获取其主版本号。

2.2 ko文件手动获取版本号方法

2.2.1 使用modinfo获取版本号

ko文件一般不会将版本号放在文件名中,也没有类似SONAME的字段。在少数的ko文件中会设置version变量可用modinfo读取,如果没有那ko文件也就没有版本号了。

modinfo后可直接接ko文件路径,但也可以是加载到内核的模块名,已加载到内核的模块名可以用lsmod查看。

三、自动化读取so/ko文件版本python脚本

所谓自动化不过也就是将手动获取版本号的方法代码化。脚本使用python3编写,设置好main中root_dir直接运行,结果会自动保存在so_version.txt和ko_version.txt中

import os
import re
import platform class ReadLibVersion:
def __init__(self):
so_version_file = "so_version.txt"
ko_version_file = "ko_version.txt"
self.so_version_file_obj = open(so_version_file,"w+")
self.ko_version_file_obj = open(ko_version_file,"w+")
system = platform.system()
if "Windows" in system:
self.path_split = "\\"
else:
self.path_split = "/"
self.so_file_pattern = "\.so$"
self.ko_file_pattern = "\.ko$" # 遍历要扫描的目录,寻找出目录下的所有so/ko文件
def traversal_dir(self,dir):
dir_contains = os.listdir(dir)
for tmp in dir_contains:
tmp_path = f"{dir}{self.path_split}{tmp}"
if os.path.isfile(tmp_path):
# 如果是so文件,则调用so版本号获取函数获取版本号
if re.search(self.so_file_pattern,tmp_path) is not None:
# 首先从文件名获取版本号
so_version = self.read_so_version_by_name(tmp_path)
if so_version != "-":
self.so_version_file_obj.writelines(f"{tmp_path}\t\t{so_version}\r\n")
else:
# 如果从文件名获取不到版本号,那么就通过readelf读SONAME获取主版本号
so_version = self.read_so_version_by_readelf(tmp_path)
self.so_version_file_obj.writelines(f"{tmp_path}\t\t{so_version}\r\n")
# 如果是ko文件,则通过modinfo读取version变量获取版本号
elif re.search(self.ko_file_pattern,tmp_path) is not None:
ko_version = self.read_ko_version_by_modinfo(tmp_path)
self.ko_version_file_obj.writelines(f"{tmp_path}\t\t{ko_version}\r\n")
elif os.path.isdir(tmp_path):
sub_dir = tmp_path
self.traversal_dir(sub_dir) # 从文件名获取so文件版本号
def read_so_version_by_name(self,file_path):
file = file_path.split(f"{self.path_split}")[-1]
ver_pattern = "[.|\d]+\d"
so_versions = re.findall(ver_pattern,file)
if len(so_versions) >0:
so_version = so_versions[0]
else:
so_version = "-"
return so_version
pass # 使用readelf读SONAME获取so文件主版本号
def read_so_version_by_readelf(self,file_path):
so_version = "-"
readelf_result = os.popen(f"readelf -d {file_path} |grep SONAME").read().strip()
if readelf_result != "":
so_version = readelf_result.split()[-1]
return so_version
pass # 使用modinfo读取version变量获取ko文件版本号
def read_ko_version_by_modinfo(self,file_path):
ko_version = "-"
modinfo_result = os.popen(f"modinfo {file_path}|grep ^version:").read().strip()
if modinfo_result != "":
ko_version = modinfo_result.split()[-1]
return ko_version
pass def __del__(self):
self.so_version_file_obj.close()
self.ko_version_file_obj.close()
pass if __name__ == "__main__":
# 要扫描的目录
root_dir = "/usr/lib"
read_lib_version_obj = ReadLibVersion()
read_lib_version_obj.traversal_dir(root_dir)

Linux获取so/ko文件版本号教程的更多相关文章

  1. Linux 驱动程序/内核模块/ko文件

    Linux 驱动程序/内核模块/ko文件 一.内核模块加载机制 1.解析 Linux 内核可装载模块的版本检查机制 二.驱动/内核模块 编译 1.The Linux Kernel Module Pro ...

  2. [ARM-Linux开发] 嵌入式 linux如何生成ko文件

    hello.c文件如下 驱动程序: #include <Linux/***.h> 是在linux-2.6.29/include/linux下面寻找源文件. #include <asm ...

  3. linux获取目录下文件

    查看当前目录下的文件: find . -type f 查看当前目录下的文件夹: find . -type d 如果文件file1不为空: if [ -s file1 ];then      echo  ...

  4. Linux下编写和加载 .ko 文件(驱动模块文件)

    一..ko 文件介绍 .ko文件是kernel object文件(内核模块),该文件的意义就是把内核的一些功能移动到内核外边, 需要的时候插入内核,不需要时卸载. 二.优点 (1)这样可以缩小内核体积 ...

  5. Linux系列教程(四)——Linux常用命令之文件和目录处理命令

    这个系列教程的前面我们讲解了如何安装Linux系统,以及学习Linux系统的一些方法.那么从这篇博客开始,我们就正式进入Linux命令的学习.学习命令,首先要跟大家纠正的一点就是,我们不需要记住每一条 ...

  6. Linux中生成Core Dump系统异常信息记录文件的教程

    Linux中生成Core Dump系统异常信息记录文件的教程 http://www.jb51.net/LINUXjishu/473351.html

  7. Linux下编写和加载 .ko 文件(编写linux驱动)

    一..ko 文件介绍 .ko文件是kernel object文件(内核模块),该文件的意义就是把内核的一些功能移动到内核外边, 需要的时候插入内核,不需要时卸载. 二.优点 (1)这样可以缩小内核体积 ...

  8. Linux内核驱动将多个C文件编译成一个ko文件的方法——每一个C文件中都有module_init与module_exit

    以两个C文件为例: 将本该被分别编译成adc_device.ko和adc_driver.ko的adc_device.c.adc_driver.c编译成一个ko文件! 採用方法: 第一步.改动C文件 1 ...

  9. Linux+apache+mono+asp.net安装教程

    Linux+apache+mono+asp.net安装教程(CentOS上测试的) 一.准备工作: 1.安装linux系统(CentOS,这个就不多讲了) 2.下载所需软件 http-2.4.4.ta ...

随机推荐

  1. .net core 配置

    .net core 配置包括很多种 例如内存变量.命令行参数.环境变量以及物理文件配置和自定义配置 物理文件配置主要有三种,它们分别是JSON.XML和INI,对应的配置源类型分别是JsonConfi ...

  2. 发布自己的npm包、开源项目

    背景:由于最近在做项目之余想做一些其他的事,所以东找找西找找的,最后决定写一个封装一些常用原型方法的NPM包,但不仅限于此.话不多说,说一下实践过程. 一.注册NPM及如何上传NPM包参考连接:htt ...

  3. Olap学习笔记

    数据仓库建设--OLAP和数据立方体概念 http://student-lp.iteye.com/blog/2263154 OLAP(On-LineAnalysis Processing)在线分析处理 ...

  4. python 构造一个可以返回多个值的函数

    为了能返回多个值,函数直接return 一个元组就行了 看上去返回了多个值,实际上是先创建了一个元组然后返回的.这个语法看上去比较奇怪,实际上我们使用的是逗号来生成一个元组,而不是用括号 >&g ...

  5. Tensorflow serving with Kubernetes

    1.Build docker image 由于自己build镜像总是遇到问题,此处暂时借用dockerhub上的一个镜像 docker.io/mochin/tensorflow-serving 将此镜 ...

  6. 连接redis错误:ERR Client sent AUTH, but no password is set

    问题原因:没有设置redis的密码 解决:命令行进入Redis的文件夹: D:\Redis-x64-3.2.100>redis-cli.exe 查看是否设置了密码: 127.0.0.1:6379 ...

  7. LinkedList 利用的是尾插法

  8. too many open files问题

    linux环境下,程序运行时,出现了too many open files的错误. 通过名字就能看出来,是打开了太多的文件,超过了系统限制. ulimit -a 通过这个命令可以查看当前系统设置的最大 ...

  9. https真的安全吗,加密登录其实不简单

    登录,是做web开发的程序员做项目第一接触到的模块,看似简简单单的登录背后囊括了编程知识的方方面面. 登录安全吗?密码会不会泄露? 明文传输时代 互联网开始的时候,登录确实是使用明文校验的,甚至数据源 ...

  10. Docker+Consul+Registrator 实现服务注册与发现

    Docker+Consul+Registrator实现服务注册与发现 逻辑图 实现nginx节点自动化加入容器IP代理 1.三台Consul agent server作为高可用通过Consul Tem ...