// question

On a Linux system, attackers may use timestamp manipulation to hide malicious changes. Investigate relevant logs to identify which file’s modification timestamp was altered by such a command.

Reference KQL answer and model-by-model comparison.

20ef1523-8758-4898-b5a2-d026cc3d2c52
question id
7/23
models correct
1
valid answer
30%
success rate
// reference answer

Human-validated correct answer for this question.

T1070.006-modification.txt
// model comparison
ModelAnswerKQL queryStatusTriesTimeCost
gemini-2.5-flash-preview-04-17
/etc/rc.local
DeviceFileEvents | where InitiatingProcessCommandLine contains "touch " | project Timestamp, DeviceName, FolderPath, FileName, InitiatingProcessCommandLine
fail114.59s0.0068
gpt-35-turbo
no answer
no query generatedfail50.00s0.0112
gpt-4-turbo-2024-04-09
no answer
no query generatedfail50.00s0.2316
gpt-4.1
/tmp/T1070.006-modification.txt
DeviceProcessEvents
| where ProcessCommandLine has "touch" and (ProcessCommandLine has "-t" or ProcessCommandLine has "-d" or ProcessCommandLine has "--date")
| extend TargetedFile = extract(@'touch\s+(?:-[td]|--date\s+[^ ]+)?\s*([^ ]+)', 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, InitiatingProcessAccountName, ProcessCommandLine, TargetedFile, FileName, FolderPath, ProcessId
| order by TimeGenerated desc
pass426.69s0.0491
gpt-4.1-finetuned
no answer
no query generatedfail50.00s0.0490
gpt-4.1-mini
/etc/rc.local
DeviceFileEvents
| where ActionType has "FileTime changed" or ActionType has "File Modified" or InitiatingProcessCommandLine has "touch" or InitiatingProcessCommandLine has "date"
| project DeviceName, FileName, FolderPath, Timestamp, InitiatingProcessCommandLine
| sort by Timestamp desc
fail220.47s0.0041
gpt-4.1-nano
no answer
no query generatedfail50.00s0.0022
gpt-4o
art-timer.timer
DeviceFileEvents
| where InitiatingProcessCommandLine has_any ("touch", "timestamp_modification", "modify")
| extend ModifiedTimestamp = tostring(parse_json(AdditionalFields).timestamp_changed)
| project FileName, FolderPath, PreviousFileName, PreviousFolderPath, ModifiedTimestamp, InitiatingProcessCommandLine, InitiatingProcessAccountName, TimeGenerated
fail428.65s0.0609
gpt-5-high
no answer
no query generatedfail50.00s0.2542
gpt-5-mini-high
/etc/rc.local
let touchProcesses = DeviceProcessEvents
| where isnotempty(ProcessCommandLine)
| where tolower(ProcessCommandLine) has "touch"
    or tolower(ProcessCommandLine) has "utime"
    or tolower(ProcessCommandLine) has "utimes"
    or tolower(ProcessCommandLine) has "os.utime"
    or tolower(ProcessCommandLine) has "utime(";

let fileEvents = DeviceFileEvents
| where isnotempty(FileName)
| project FileTime=TimeGenerated, DeviceName, InitiatingProcessId, FolderPath=tostring(FolderPath), FileName, FilePath=strcat(tostring(coalesce(tostring(FolderPath),"")),"/",FileName), ActionType, InitiatingProcessCommandLine;

touchProcesses
| project ProcessTime=TimeGenerated, DeviceName, ProcessId, ProcessCommandLine
| join kind=inner (
    fileEvents
) on $left.DeviceName == $right.DeviceName and $left.ProcessId == $right.InitiatingProcessId
| extend timeDiffSec = abs(datetime_diff('second', FileTime, ProcessTime))
| where timeDiffSec <= 120
| summarize FirstSeen=min(FileTime), LastSeen=max(FileTime), Count=count(), Devices=make_set(DeviceName), ProcessCmds=make_set(ProcessCommandLine), FileEventCmds=make_set(InitiatingProcessCommandLine), ActionTypes=make_set(ActionType) by FilePath
| order by LastSeen desc
| limit 100
fail252.93s0.0136
gpt-5-mini-low
no answer
no query generatedfail50.00s0.0308
gpt-5-mini-medium
/etc/rc.local
// Detect potential Linux timestamp manipulation by correlating suspicious process command-lines with file modification/attribute events
let suspicious_cmds = dynamic(["touch","-t","-d","--date","utime","futimes","futimens","os.utime","settimeofday","stime","python -c","perl -e","ruby -e","find . -exec touch","touch.py"]);

// Processes that include suspicious tokens in their command line
let procs = DeviceProcessEvents
| where ProcessCommandLine has_any (suspicious_cmds) or InitiatingProcessCommandLine has_any (suspicious_cmds) or tostring(AdditionalFields) has_any (suspicious_cmds)
| project ProcTime = TimeGenerated, DeviceId, DeviceName, ProcessId, AccountName, ProcessCommandLine, InitiatingProcessCommandLine, ProcessFileName = FileName, ProcessCreationTime;

// File events showing modification or attribute changes (also look for timestamp keys in AdditionalFields)
let files = DeviceFileEvents
| where ActionType has_any ("FileModified","FileCreated","FileUpdated","Modified","Change","AttributesChanged","ChangeAttributes")
    or tostring(AdditionalFields) has_any ("mtime","atime","ctime","timestamp","time")
| project FileTime = TimeGenerated, DeviceId, FileName, FolderPath, PreviousFileName, PreviousFolderPath, InitiatingProcessId, InitiatingProcessCommandLine, InitiatingProcessFileName, ActionType, AdditionalFields;

// Correlate: same device, same process performing the file action, and close in time (within 60 seconds)
procs
| join kind=inner (files) on DeviceId
| where ProcessId == InitiatingProcessId
| where abs(datetime_diff('second', FileTime, ProcTime)) <= 60
| extend FilePath = case(isnotempty(FolderPath), strcat(FolderPath, '/', FileName), FileName)
| summarize FirstSeen = min(FileTime), LastSeen = max(FileTime), Hits = count() by FilePath, DeviceName, ActionType, ProcessCommandLine, InitiatingProcessCommandLine, ProcessId, AccountName
| sort by FirstSeen desc
| take 200
fail243.34s0.0116
gpt-5-nano-high
no answer
no query generatedfail50.00s0.0081
gpt-5-nano-medium
no answer
no query generatedfail50.00s0.0073
grok-3-beta
/tmp/T1070.006-modification.txt
DeviceProcessEvents
| join kind=inner DeviceInfo on DeviceId
| where OSPlatform contains "Linux"
| where ProcessCommandLine has "touch" and (ProcessCommandLine has "-t" or ProcessCommandLine has "-r")
| project Timestamp, DeviceName, FileName, ProcessCommandLine, AccountName, DeviceId
| order by Timestamp desc
| limit 50
pass320.08s0.0574
grok-3-mini-beta
/etc/systemd/system/art-timer.timer
DeviceInfo
| where OSPlatform == 'Linux'
| join kind=inner (DeviceFileEvents) on DeviceId
| where InitiatingProcessCommandLine contains 'touch' or InitiatingProcessCommandLine contains 'date -s' or InitiatingProcessCommandLine contains 'utimensat'
| project DeviceName, FileName, FolderPath, InitiatingProcessCommandLine, Timestamp
| summarize FilesAltered=make_set(FileName), LastTimestamp=max(Timestamp) by DeviceName, FolderPath
| order by LastTimestamp desc
fail223.28s0.0031
o1-high
/tmp/T1070.006-modification.txt
DeviceInfo
| where OSPlatform == "Linux"
| distinct DeviceId
| join kind=inner (
    DeviceProcessEvents
    | where ActionType == "ProcessCreated"
    | where InitiatingProcessCommandLine has "touch"
    | where InitiatingProcessCommandLine matches regex @"touch\s+.*(-a|-c|-m|-r|-t|--date).*"
    | extend ModifiedFile = extract(@"touch\s+(\S+)", 1, InitiatingProcessCommandLine)
    | project TimeGenerated, DeviceId, DeviceName, AccountName, InitiatingProcessCommandLine, ModifiedFile
) on DeviceId
| order by TimeGenerated desc
pass258.62s0.6487
o1-low
/tmp/T1070.006-modification.txt
DeviceProcessEvents
| where Timestamp >= ago(7d)
| join kind=inner (
    DeviceInfo
    | where Timestamp >= ago(7d)
    | where OSPlatform == "Linux"
    | distinct DeviceId
) on DeviceId
| where ProcessCommandLine has "touch"
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine, FolderPath, FileName
| order by TimeGenerated desc
pass140.30s0.4528
o3-high
no answer
no query generatedfail50.00s0.1324
o3-mini-high
/tmp/T1070.006-modification.txt
DeviceProcessEvents
| where InitiatingProcessCommandLine contains "touch"
| project TimeGenerated, DeviceName, FolderPath, FileName, InitiatingProcessCommandLine
| order by TimeGenerated desc
pass114.89s0.0283
o3-mini-low
/tmp/T1070.006-modification.txt
DeviceProcessEvents
| where InitiatingProcessCommandLine has "touch"
| project TimeGenerated, DeviceName, InitiatingProcessCommandLine, FileName, FolderPath
| order by TimeGenerated desc
pass122.82s0.0248
o4-mini-high
/tmp/T1070.006-modification.txt
DeviceProcessEvents
| where FileName == "touch"
// split the command line into tokens
| extend args = split(ProcessCommandLine, " ")
// calculate the index of the last element
| extend idx = array_length(args) - 1
// extract the target file path (last token)
| extend TargetFile = tostring(args[idx])
// select the fields of interest
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine, TargetFile
pass136.12s0.0163
o4-mini-low
no answer
no query generatedfail50.00s0.0472