Detection rules › Kusto

Suspicious MSC File Launched

Group by
DeviceId, FolderPath, MscFile
Author
FalconForce
Source
github.com/FalconForceTeam/FalconFriday

The query searches for suspicious MSC files that are launched on the system. The following types of suspicious files are detected: MSC files downloaded by web browsers, MSC files in the Downloads folder, MSC files extracted from ZIP files, and MSC files with Mark Of The Web (MOTW).

Known false positives

  • Administrators might share MSC files using SharePoint or other file sharing services. These might have to by filtered out.

MITRE ATT&CK coverage

References

Telemetry coverage

Rule body

let timeframe = 2*1h;
let RegexValidateTempZipPath = @"((?i)[^=|\/]*?AppData\\Local\\Temp\\(7z.........\\|wz....\\|Temp\d{1,3}_\w+)\b[^( ;)|]*)";
let MscRenamedFromCrDownload=(
    DeviceFileEvents
    | where ingestion_time() >= ago(timeframe)
    | where ActionType == "FileRenamed"
    | where FileName endswith ".msc"
    | where PreviousFileName endswith ".crdownload"
    | extend SuspiciousReason="MSC file downloaded by web browser."
);
let MscWrittenByBrowser=(
    DeviceFileEvents
    | where ingestion_time() >= ago(timeframe)
    | where ActionType == "FileRenamed" or ActionType == "FileCreated"
    | where FileName endswith ".msc"
    | where InitiatingProcessFileName in~ ("chrome.exe", "msedge.exe", "brave.exe", "opera.exe", "vivaldi.exe", "iexplore.exe", "msedgewebview2.exe", "firefox.exe")
    | extend SuspiciousReason="MSC file downloaded by web browser."
);
let MscInDownloadsFolder=(
    DeviceFileEvents
    | where ingestion_time() >= ago(timeframe)
    | where ActionType == "FileRenamed" or ActionType == "FileCreated"
    | where FileName endswith ".msc"
    | where FolderPath contains @"\downloads\"
    | extend SuspiciousReason="MSC file downloaded by web browser."
);
let MscDecompressed=(
    DeviceFileEvents
    | where ingestion_time() >= ago(timeframe)
    | where ActionType == "FileRenamed" or ActionType == "FileCreated"
    | where FileName endswith ".msc"
    | where InitiatingProcessFileName in~ ("7zfm.exe", "7zg.exe", "7z.exe", "winzip64.exe", "winrar.exe", "winzip.exe")
    or FolderPath matches regex RegexValidateTempZipPath
    or FolderPath contains @".zip\"
    | extend SuspiciousReason="MSC file extracted from zip file."
);
let MscMOTW=(
    DeviceFileEvents
    | where ingestion_time() >= ago(timeframe)
    | where ActionType == "FileRenamed" or ActionType == "FileCreated"
    | where FileName endswith ".msc"
    | where isnotempty(FileOriginUrl)
    | extend SuspiciousReason="MSC file with Mark Of The Web (MOTW)."
);
let SuspiciousMscFiles=(
    union MscRenamedFromCrDownload, MscWrittenByBrowser, MscInDownloadsFolder, MscDecompressed, MscMOTW
    | distinct FolderPath=tolower(FolderPath), DeviceId, FileOriginUrl, MscSHA1=SHA1, SuspiciousReason, MscCreatedBy=InitiatingProcessFolderPath, MscCreatedByCommandLine=InitiatingProcessCommandLine
);
DeviceProcessEvents
| where ingestion_time() >= ago(timeframe)
| where ActionType == "ProcessCreated"
| where FileName =~ "mmc.exe"
| extend ParsedCommandLine=parse_command_line(ProcessCommandLine, "windows")
// Look for process creations of mmc.exe where the .msc file is on the command-line, indicating that the user clicked on the .msc file.
| where tostring(ParsedCommandLine) contains ".msc"
// When a .msc file is opened in MMC, the file path is passed as an argument to MMC.
// Based on testing this is the first argument in the command line. In some cases a command-line switch /32 is passed as the first argument
// and the file path is the second argument. This is handled by the iif statement below.
| extend MscFile=ParsedCommandLine[1]
| extend MscFile=iif(MscFile startswith "/", ParsedCommandLine[2], MscFile)
| extend MscFile=tolower(MscFile)
| lookup kind=inner SuspiciousMscFiles on DeviceId, $left.MscFile == $right.FolderPath
| project-reorder Timestamp, DeviceId, DeviceName, SuspiciousReason, MscFile,  MscCreatedBy, MscCreatedByCommandLine, MscSHA1
// Begin environment-specific filter.
// End environment-specific filter.

Stages and Predicates

Parameters

let timeframe = 2*1h;

Let binding: RegexValidateTempZipPath

let RegexValidateTempZipPath = @"((?i)[^=|\/]*?AppData\\Local\\Temp\\(7z.........\\|wz....\\|Temp\d{1,3}_\w+)\b[^( ;)|]*)";

Let binding: MscRenamedFromCrDownload used in Stage 1

let MscRenamedFromCrDownload = (
    DeviceFileEvents
    | where ingestion_time() >= ago(timeframe)
    | where ActionType == "FileRenamed"
    | where FileName endswith ".msc"
    | where PreviousFileName endswith ".crdownload"
    | extend SuspiciousReason="MSC file downloaded by web browser."
);

Let binding: MscWrittenByBrowser used in Stage 2

let MscWrittenByBrowser = (
    DeviceFileEvents
    | where ingestion_time() >= ago(timeframe)
    | where ActionType == "FileRenamed" or ActionType == "FileCreated"
    | where FileName endswith ".msc"
    | where InitiatingProcessFileName in~ ("chrome.exe", "msedge.exe", "brave.exe", "opera.exe", "vivaldi.exe", "iexplore.exe", "msedgewebview2.exe", "firefox.exe")
    | extend SuspiciousReason="MSC file downloaded by web browser."
);

Let binding: MscInDownloadsFolder used in Stage 3

let MscInDownloadsFolder = (
    DeviceFileEvents
    | where ingestion_time() >= ago(timeframe)
    | where ActionType == "FileRenamed" or ActionType == "FileCreated"
    | where FileName endswith ".msc"
    | where FolderPath contains @"\downloads\"
    | extend SuspiciousReason="MSC file downloaded by web browser."
);

Let binding: MscDecompressed used in Stage 4

let MscDecompressed = (
    DeviceFileEvents
    | where ingestion_time() >= ago(timeframe)
    | where ActionType == "FileRenamed" or ActionType == "FileCreated"
    | where FileName endswith ".msc"
    | where InitiatingProcessFileName in~ ("7zfm.exe", "7zg.exe", "7z.exe", "winzip64.exe", "winrar.exe", "winzip.exe")
    or FolderPath matches regex RegexValidateTempZipPath
    or FolderPath contains @".zip\"
    | extend SuspiciousReason="MSC file extracted from zip file."
);

Let binding: MscMOTW used in Stage 5

let MscMOTW = (
    DeviceFileEvents
    | where ingestion_time() >= ago(timeframe)
    | where ActionType == "FileRenamed" or ActionType == "FileCreated"
    | where FileName endswith ".msc"
    | where isnotempty(FileOriginUrl)
    | extend SuspiciousReason="MSC file with Mark Of The Web (MOTW)."
);

Let binding: SuspiciousMscFiles used in Stages 6, 14

let SuspiciousMscFiles = (
    union MscRenamedFromCrDownload, MscWrittenByBrowser, MscInDownloadsFolder, MscDecompressed, MscMOTW
    | distinct FolderPath=tolower(FolderPath), DeviceId, FileOriginUrl, MscSHA1=SHA1, SuspiciousReason, MscCreatedBy=InitiatingProcessFolderPath, MscCreatedByCommandLine=InitiatingProcessCommandLine
);

Stage 1: source

let MscRenamedFromCrDownload

Stage 2: source

let MscWrittenByBrowser

Stage 3: source

let MscInDownloadsFolder

Stage 4: source

let MscDecompressed

Stage 5: source

let MscMOTW

Stage 6: source

let SuspiciousMscFiles

Stage 7: source

DeviceProcessEvents

Stage 8: where

where ...

Stage 9: where

where ActionType =~ "ProcessCreated"

Stage 10: where

where FileName =~ "mmc.exe"

Stage 11: extend

extend ParsedCommandLine

Stage 12: where

where ParsedCommandLine contains ".msc"

Stage 13: extend (3 consecutive steps)

extend MscFile

Stage 14: kusto:lookup

lookup kind=inner (SuspiciousMscFiles) on DeviceId, MscFile, FolderPath

Stage 15: project-reorder

project-reorder

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
ActionTypeeq
  • FileCreated
  • FileRenamed
  • ProcessCreated
field:"ActionType" kind:eq
FileNameends_with
  • .msc
field:"file_name" kind:ends_with value:".msc"
FileNameeq
  • mmc.exe
field:"file_name" kind:eq value:"mmc.exe"
FileOriginUrlis_not_null
  • (no value, null check)
field:"FileOriginUrl" kind:is_not_null
FolderPathcontains
  • .zip\
  • \downloads\
field:"Image" kind:contains
FolderPathregex_match
  • ((?i)[^=|\/]*?AppData\Local\Temp\(7z.........\|wz....\|Temp\d{1,3}_\w+)\b[^( ;)|]*)
field:"Image" kind:regex_match value:"((?i)[^=|\/]*?AppData\Local\Temp\(7z.........\|wz....\|Temp\d{1,3}_\w+)\b[^( ;)|]*)"
InitiatingProcessFileNamein
  • 7z.exe
  • 7zfm.exe
  • 7zg.exe
  • brave.exe
  • chrome.exe
  • firefox.exe
  • iexplore.exe
  • msedge.exe
  • msedgewebview2.exe
  • opera.exe
  • vivaldi.exe
  • winrar.exe
  • winzip.exe
  • winzip64.exe
field:"parent_process_name" kind:in
ParsedCommandLinecontains
  • .msc transforms: tostring
field:"ParsedCommandLine" kind:contains value:".msc"
PreviousFileNameends_with
  • .crdownload
field:"PreviousFileName" kind:ends_with value:".crdownload"

Output fields

These fields are emitted when the rule matches.

FieldSource
ParsedCommandLineextend
MscFileextend