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