Collects detailed metadata about Linux kernel modules using modinfo. Useful for malicious kernel module hunting.
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