Skip to content
Please update to the latest release 0.77.3 to address Multiple CVEs.
Linux.Sys.Modinfo

Linux.Sys.Modinfo

Collects detailed metadata about Linux kernel modules using modinfo. Useful for malicious kernel module hunting.

  • Live mode (default) - Parses /proc/modules, then runs modinfo for each loaded module. Default search is /lib/modules/$(uname -r)/**/.ko
  • Disk mode - If ModuleTargetGlob is supplied, skips live enumeration and instead uses glob, running modinfo for every matching glob hit. 

Both modes use ModuleNameRegex to filter by name.


name: Linux.Sys.Modinfo
author: Matt Green - @mgreen27
description: |
    Collects detailed metadata about Linux kernel modules using modinfo. Useful for 
    malicious kernel module hunting.

    - Live mode (default) - Parses /proc/modules, then runs modinfo <name> for each loaded
    module. Default search is /lib/modules/$(uname -r)/**/<name>.ko
    - Disk mode - If ModuleTargetGlob is supplied, skips live
    enumeration and instead uses glob, running modinfo <path> for every matching glob hit. 
    
    Both modes use ModuleNameRegex to filter by name.
parameters:
  - name: ModuleNameRegex
    default: .
  - name: ModuleTargetGlob
    description: Glob to target. If set will bypass live analysis and use glob instead.
    
required_permissions:
  - EXECVE
  
sources:
  - precondition: |
       SELECT OS
       FROM info()
       WHERE OS = 'linux'

    query: |
       LET proc_mod = SELECT Name,
                             dict(Source='/proc/mod',
                                  Name=Name,
                                  Size=Size,
                                  UseCount=UseCount,
                                  UsedBy=UsedBy,
                                  Status=Status,
                                  Address=Address) AS SourceInfo
         FROM Artifact.Linux.Proc.Modules()
         WHERE Name =~ ModuleNameRegex
       
       LET target_glob = SELECT OSPath AS Name,
                                dict(Source='glob',
                                     OSPath=OSPath,
                                     Size=Size,
                                     Mtime=Mtime,
                                     Magic=magic(path=OSPath)) AS SourceInfo
         FROM glob(globs=ModuleTargetGlob)
       
       SELECT
           SourceInfo,
           if(condition=Extracted.filename, then=Extracted.filename, else=Stderr) AS Filename,
           if(
             condition=Extracted.name,
             then=Extracted.name,
             else=SourceInfo.Name) AS Name,
           Extracted.alias AS Alias,
           Extracted.license AS License,
           Extracted.description AS Description,
           Extracted.author AS Author,
           Extracted.srcversion AS SrcVersion,
           Extracted.depends AS Depends,
           Extracted.retpoline AS Retpoline,
           Extracted.intree AS Intree,
           Extracted.vermagic AS Vermagic,
           if(
             condition=Extracted.filename
              and (Extracted.signature OR Extracted.sig_key),
             then=dict(
               Id=Extracted.sig_id,
               Signer=Extracted.signer,
               Key=Extracted.sig_key,
               Hashalgo=Extracted.sig_hashalgo,
               Signature=Extracted.signature),
             else='') AS Signature
       FROM foreach(
         row=if(
           condition=ModuleTargetGlob,
           then=target_glob,
           else=proc_mod),
         query={
           SELECT
           SourceInfo,
           parse_string_with_regex(
             string=Stdout,
             regex=[
                '''filename:\s+(?P<filename>[^\n]*)\n''', 
                '''alias:\s+(?P<alias>[^\n]*)\n''', 
                '''license:\s+(?P<license>[^\n]*)\n''', 
                '''description:\s+(?P<description>[^\n]*)\n''', 
                '''author:\s+(?P<author>[^\n]*)\n''', 
                '''srcversion:\s+(?P<srcversion>[^\n]*)\n''', 
                '''depends:\s+(?P<depends>[^\n]*)\n''', 
                '''retpoline:\s+(?P<retpoline>[^\n]*)\n''', 
                '''intree:\s+(?P<intree>[^\n]*)\n''', 
                '''name:\s+(?P<name>[^\n]*)\n''', 
                '''vermagic:\s+(?P<vermagic>[^\n]*)\n''', 
                '''sig_id:\s+(?P<sig_id>[^\n]*)\n''', 
                '''signer:\s+(?P<signer>[^\n]*)\n''', 
                '''sig_key:\s+(?P<sig_key>[A-Z0-9:\s]*)\n[^\t]''', 
                '''sig_hashalgo:\s+(?P<sig_hashalgo>[^\n]*)\n''',
                '''signature:\s+(?P<signature>[A-Z0-9:\n\t]*)\n([a-z]|$)'''
                    ]) AS Extracted,
           Stderr
           FROM execve(
             argv=["modinfo", Name])
         })
       WHERE Name =~ ModuleNameRegex