1. 程式人生 > >Linux獲取so/ko文件版本號教程

Linux獲取so/ko文件版本號教程

code del col 掃描 info 實現 沒有 contains windows

一、需要獲取版本號的原因

從使用角度而言,有時只有特定版本的庫才支持某些功能,所以我們需要確定庫文件版本號。

從安全加固角度而言,有些版本存在漏洞有些版本不存在漏洞,所以我們需要獲取版本號以確定當前使用版本是否需要處理。

不過就實際來看,針對庫文件(尤其是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文件版本號教程