zoukankan      html  css  js  c++  java
  • Linux获取so/ko文件版本号教程

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

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

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

    不过就实际来看,针对库文件(尤其是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}		{so_version}
    ")
                        else:
                            # 如果从文件名获取不到版本号,那么就通过readelf读SONAME获取主版本号
                            so_version = self.read_so_version_by_readelf(tmp_path)
                            self.so_version_file_obj.writelines(f"{tmp_path}		{so_version}
    ")
                    # 如果是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}		{ko_version}
    ")
                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)
  • 相关阅读:
    动态规划专题(二)——树形DP
    动态规划专题(一)——状压DP
    位运算相关(二)——位运算的简单变换操作
    位运算相关(一)——位运算学习笔记
    2018.10.05 TOPOI提高组模拟赛 解题报告
    【BZOJ1088】[SCOI2005] 扫雷Mine(分类讨论)
    【洛谷1273】有线电视网(树上背包)
    【洛谷2264】情书(字符串水题)
    【洛谷4287】[SHOI2011] 双倍回文(Manacher算法经典题)
    【洛谷2051】[AHOI2009] 中国象棋(烦人的动态规划)
  • 原文地址:https://www.cnblogs.com/lsdb/p/9994539.html
Copyright © 2011-2022 走看看