- https://redcanary.com/threat-detection-report/techniques/rename-system-utilities/
- https://attack.mitre.org/techniques/T1036/003/
Consider detecting any apparent processes executing in conjunction with command-line parameters that are generally associated with a different process. As an example, Invoke-Expressions (iex) are associated with PowerShell, so it would be highly suspicious to see an invoke expression in a command line associated with a process that appears to be something other than PowerShell.
let dirtyCommands = datatable (command:string)["Add-Type"
,"AddSecurityPackage"
,"AdjustTokenPrivileges"
,"AllocHGlobal"
,"BindingFlags"
,"Bypass"
,"CloseHandle"
,"CreateDecryptor"
,"CreateEncryptor"
,"CreateProcessWithToken"
,"CreateRemoteThread"
,"CreateThread"
,"CreateType"
,"CreateUserThread"
,"Cryptography"
,"CryptoServiceProvider"
,"CryptoStream"
,"DangerousGetHandle"
,"DeclaringMethod"
,"DeclaringType"
,"DefineConstructor"
,"DefineDynamicAssembly"
,"DefineDynamicModule"
,"DefineEnum"
,"DefineField"
,"DefineLiteral"
,"DefinePInvokeMethod"
,"DefineType"
,"DeflateStream"
,"DeviceIoControl"
,"DllImport"
,"DuplicateTokenEx"
,"Emit"
,"EncodedCommand"
,"EnumerateSecurityPackages"
,"ExpandString"
,"FreeHGlobal"
,"FreeLibrary"
,"FromBase64String"
,"GetAssemblies"
,"GetAsyncKeyState"
,"GetConstructor"
,"GetConstructors"
,"GetDefaultMembers"
,"GetDelegateForFunctionPointer"
,"GetEvent"
,"GetEvents"
,"GetField"
,"GetFields"
,"GetForegroundWindow"
,"GetInterface"
,"GetInterfaceMap"
,"GetInterfaces"
,"GetKeyboardState"
,"GetLogonSessionData"
,"GetMember"
,"GetMembers"
,"GetMethod"
,"GetMethods"
,"GetModuleHandle"
,"GetNestedType"
,"GetNestedTypes"
,"GetPowerShell"
,"GetProcAddress"
,"GetProcessHandle"
,"GetProperties"
,"GetProperty"
,"GetTokenInformation"
,"GetTypes"
,"ILGenerator"
,"ImpersonateLoggedOnUser"
,"InteropServices"
,"IntPtr"
,"InvokeMember"
,"kernel32"
,"LoadLibrary"
,"LogPipelineExecutionDetails"
,"MakeArrayType"
,"MakeByRefType"
,"MakeGenericType"
,"MakePointerType"
,"Marshal"
,"memcpy"
,"MemoryStream"
,"Methods"
,"MiniDumpWriteDump"
,"NonPublic"
,"OpenDesktop"
,"OpenProcess"
,"OpenProcessToken"
,"OpenThreadToken"
,"OpenWindowStation"
,"PasswordDeriveBytes"
,"Properties"
,"ProtectedEventLogging"
,"PtrToString"
,"PtrToStructure"
,"ReadProcessMemory"
,"ReflectedType"
,"RevertToSelf"
,"RijndaelManaged"
,"ScriptBlockLogging"
,"SetInformationProcess"
,"SetThreadToken"
,"SHA1Managed"
,"StructureToPtr"
,"ToBase64String"
,"TransformFinalBlock"
,"TypeHandle"
,"TypeInitializer"
,"UnderlyingSystemType"
,"UnverifiableCodeAttribute"
,"VirtualAlloc"
,"VirtualFree"
,"VirtualProtect"
,"WriteByte"
,"WriteInt32"
,"WriteProcessMemory"
,"ZeroFreeGlobalAllocUnicode"];
DeviceProcessEvents
| where (InitiatingProcessFileName !~ "powershell.exe" and InitiatingProcessCommandLine has_any (dirtyCommands)) or (FileName !~ "powershell.exe" and ProcessCommandLine has_any (dirtyCommands))
Consider alerting on any activity where the apparent process name is different from the internal process name or where the apparent process name executes with an unexpected hash value. While process names may change, the hash values and internal names associated with them should not. This is easier said than done, and requires the ability to collect internal names or hash values for System32 binaries and actively cross reference that list with active process execution. As an example, the internal name for powershell.exe is “PowerShell,” and its known process names include powershell.exe, powershell, posh.exe, and posh. As such, the following pseudo-analytic is an example of how you might catch renamed instances of PowerShell. You could swap out Notepad or PowerShell for any other commonly renamed system utility.
Pseudocode: process_name == notepad.exe && internal_name == PowerShell || hash_value != [expected hash value for PowerShell in your environment]*
let renamedTools = datatable (filename:string)["psexec.exe","rundll32","rclone.exe","mimikatz.exe","powershell.exe","cmd.exe"]; //list of tools or LOLBINS to monitor
DeviceImageLoadEvents
| where InitiatingProcessVersionInfoOriginalFileName has_any (renamedTools) and ( InitiatingProcessVersionInfoOriginalFileName !~ InitiatingProcessFileName )
DeviceImageLoadEvents
| where InitiatingProcessVersionInfoOriginalFileName !~ InitiatingProcessFileName | distinct InitiatingProcessFileName;
Consider alerting on any activity where a process path does not match a list of known process paths given an internal name. As an example: the known expected process path associated with cscript.exe (based on its internal name) should be system32, syswow64, and winsxs.