Hack the Box Phantom Check Malarum, December 5, 2025December 5, 2025 Today I will be doing a write up of the Hack the Box DFIR Challenge Phantom Check. This challenge puts you in the role of an analyst requiring you to analyze event logs to determine the anti-virtualization techniques carried out by the threat actor. The user is given 2 logs to answer a series of questions and complete this challenge. First we load these logs into our isolated virtual environment and start the analysis. To do this analysis I used the built in Powershell tool Get-WinEvent. I then got to work conducting my investigation. The first thing I did was take a general look at the logs to see what the log output was. I quickly saw that it was powershell logs showing both what was executed and scripts that were ran. TimeCreated : 1/25/2025 5:13:48 AM ProviderName : PowerShell Id : 400 Message : Engine state is changed from None to Available. Details: NewEngineState=Available PreviousEngineState=None SequenceNumber=13 HostName=ConsoleHost HostVersion=5.1.26100.1591 HostId=0114327f-6ec0-44d4-b764-2a04d92056cc HostApplication=C:\WINDOWS\SysWOW64\\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -Noninteractive -File C:\Program Files (x86)\Microsoft Visual Studio\Installer\PrecheckTools\Microsoft.VisualStudio.Setup.TestPowerShell.ps1 EngineVersion=5.1.26100.1591 RunspaceId=d731ceed-2be1-48ad-ab36-8bc08c31b3f6 PipelineId= CommandName= CommandType= ScriptName= CommandPath= CommandLine= TimeCreated : 4/8/2025 5:06:37 AM ProviderName : Microsoft-Windows-PowerShell Id : 4104 Message : Creating Scriptblock text (20 of 33): .Add($__cmdletization_methodParameter) [object]$__cmdletization_defaultValue = $null [object]$__cmdletization_defaultValueIsPresent = $false if ($PSBoundParameters.ContainsKey('StorageNodeName')) { [object]$__cmdletization_value = ${StorageNodeName} $__cmdletization_methodParameter = [Microsoft.PowerShell.Cmdletization.MethodParameter]@{Name = 'StorageNodeName'; ParameterType = 'System.String'; Bindings = 'In'; Value = $__cmdletization_value; IsValuePresent = $true} } else { $__cmdletization_methodParameter = [Microsoft.PowerShell.Cmdletization.MethodParameter]@{Name = 'StorageNodeName'; ParameterType = 'System.String'; Bindings = 'In'; Value = $__cmdletization_defaultValue; IsValuePresent = $__cmdletization_defaultValueIsPresent} } $__cmdletization_methodParameters.Add($__cmdletization_methodParameter) [object]$__cmdletization_defaultValue = $null [object]$__cmdletization_defaultValueIsPresent = $false if ($PSBoundParameters.ContainsKey('Access')) { [object]$__cmdletization_value = ${Access} $__cmdletization_methodParameter = [Microsoft.PowerShell.Cmdletization.MethodParameter]@{Name = 'Access'; ParameterType = 'Microsoft.PowerShell.Cmdletization.GeneratedTypes.SetVirtualDisk.Access'; Bindings = 'In'; Value = $__cmdletization_value; IsValuePresent = $true} } else { $__cmdletization_methodParameter = [Microsoft.PowerShell.Cmdletization.MethodParameter]@{Name = 'Access'; ParameterType = 'Microsoft.PowerShell.Cmdletization.GeneratedTypes.SetVirtualDisk.Access'; Bindings = 'In'; Value = $__cmdletization_defaultValue; IsValuePresent = $__cmdletization_defaultValueIsPresent} } $__cmdletization_methodParameters.Add($__cmdletization_methodParameter) [object]$__cmdletization_defaultValue = [System.Management.Automation.LanguagePrimitives]::ConvertTo('Microsoft.PowerShell', 'System.String') [object]$__cmdletization_defaultValueIsPresent = $true $__cmdletization_methodParameter = [Microsoft.PowerShell.Cmdletization.MethodParameter]@{Name = 'cim:operationOption:SourceCaller'; ParameterType = 'System.String'; Bindings = '0'; Value = $__cmdletization_defaultValue; IsValuePresent = $__cmdletization_defaultValueIsPresent} $__cmdletization_methodParameters.Add($__cmdletization_methodParameter) ...snip... 1. Which WMI Class did the attacker use to retrieve model and manufacturer information for virtualization detection Given that I knew the event file Microsoft-Windows-Powershell.evtx was holding command output, I looked in this log for this information. I knew that to get Windows Management Instrumentation information we would use the Powershell CMDlet Get-WmiObject. I filtered my log for that information with the following command: Get-WinEvent -Path .\Microsoft-Windows-Powershell.evtx | Where-Object {$_.Message -like "*Get-WMI*"} | fl ...snip... TimeCreated : 4/9/2025 2:19:10 AM ProviderName : PowerShell Id : 800 Message : Pipeline execution details for command line: $Manufacturer = Get-WmiObject -Class Win32_ComputerSystem | select-object -expandproperty "Manufacturer". Context Information: DetailSequence=1 DetailTotal=1 SequenceNumber=19 UserId=DESKTOP-M3AKJSD\User HostName=ConsoleHost HostVersion=5.1.26100.2161 HostId=0fad0cf8-6cb6-4657-86f7-655ec22eed9f HostApplication=C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe EngineVersion=5.1.26100.2161 RunspaceId=2aeeba59-d0f6-4ce7-b41c-e07625b3beec PipelineId=5 ScriptName= CommandLine=$Manufacturer = Get-WmiObject -Class Win32_ComputerSystem | select-object -expandproperty "Manufacturer" Details: CommandInvocation(Get-WmiObject): "Get-WmiObject" ParameterBinding(Get-WmiObject): name="Class"; value="Win32_ComputerSystem" CommandInvocation(Select-Object): "Select-Object" ParameterBinding(Select-Object): name="ExpandProperty"; value="Manufacturer" ParameterBinding(Select-Object): name="InputObject"; value="\\DESKTOP-M3AKJSD\root\cimv2:Win32_ComputerSystem.Name="DESKTOP-M3AKJSD"" I then saw the above output and knew that this would give system information about the system as the manufacturer value will give information on if it is a vm. We submit that answer and find it is correct and can move onto question 2! 2. Which WMI query did the attacker execute to retrieve the current temperature value of the machine? This question again is using Get-WMIObject so I knew that I could look the same query I originally made. Checking the output I observed this entry: TimeCreated : 4/9/2025 2:20:12 AM ProviderName : PowerShell Id : 800 Message : Pipeline execution details for command line: Get-WmiObject -Query "SELECT * FROM MSAcpi_ThermalZoneTemperature" -ErrorAction SilentlyContinue. Context Information: DetailSequence=1 DetailTotal=1 SequenceNumber=53 UserId=DESKTOP-M3AKJSD\User HostName=ConsoleHost HostVersion=5.1.26100.2161 HostId=0fad0cf8-6cb6-4657-86f7-655ec22eed9f HostApplication=C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe EngineVersion=5.1.26100.2161 RunspaceId=2aeeba59-d0f6-4ce7-b41c-e07625b3beec PipelineId=21 ScriptName= CommandLine=Get-WmiObject -Query "SELECT * FROM MSAcpi_ThermalZoneTemperature" -ErrorAction SilentlyContinue Details: CommandInvocation(Get-WmiObject): "Get-WmiObject" ParameterBinding(Get-WmiObject): name="Query"; value="SELECT * FROM MSAcpi_ThermalZoneTemperature" ParameterBinding(Get-WmiObject): name="ErrorAction"; value="SilentlyContinue" NonTerminatingError(Get-WmiObject): "Invalid class "MSAcpi_ThermalZoneTemperature"" This log clearly indicated temperature values of the machine. The answer to this question is SELECT * FROM MSAcpi_ThermalZoneTemperature 3. The attacker loaded a PowerShell script to detect virtualization. What is the function name of the script? For this question, we want to switch to the other event log Windows-Powershell-Operational.evtx. To find the answer to this question, I know i want to look for virtualization so I searched for words that related to virtualization. I also know that I am looking for a function so I searched for the word function. I chose to search for the vendor “VMWare” as I knew this would likely be one of the platforms checked. Get-WinEvent -Path .\Windows-Powershell-Operational.evtx | Where-Object {$_.Message -like "*vmware*" -and $_.Message -like "*function*"} | fl TimeCreated : 4/9/2025 2:20:53 AM ProviderName : Microsoft-Windows-PowerShell Id : 4104 Message : Creating Scriptblock text (1 of 1): function Check-VM { <# .SYNOPSIS Nishang script which detects whether it is in a known virtual machine. .DESCRIPTION This script uses known parameters or 'fingerprints' of Hyper-V, VMWare, Virtual PC, Virtual Box, Xen and QEMU for detecting the environment. .EXAMPLE PS > Check-VM .LINK http://www.labofapenetrationtester.com/2013/01/quick-post-check-if-your-payload-is.html https://github.com/samratashok/nishang .NOTES The script draws heavily from checkvm.rb post module from msf. https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/gather/checkvm.rb #> [CmdletBinding()] Param() $ErrorActionPreference = "SilentlyContinue" #Hyper-V $hyperv = Get-ChildItem HKLM:\SOFTWARE\Microsoft if (($hyperv -match "Hyper-V") -or ($hyperv -match "VirtualMachine")) { $hypervm = $true } if (!$hypervm) { $hyperv = Get-ItemProperty hklm:\HARDWARE\DESCRIPTION\System -Name SystemBiosVersion if ($hyperv -match "vrtual") { $hypervm = $true } } ...snip... We immediately find out match! We can see in the message there is a function called Check-VM! We can now move onto the next question. 4. Which registry key did the above script query to retrieve service details for virtualization detection? This question I went back to the log showing command line and script output as I knew they would likely be using either reg query or Get-ChildItem. I do parse for what I know is going to be searched for which is a registry key. I also know that the most likely registry hive this would belong in is “HKLM” so I narrow my search for logs with that message. Get-WinEvent -Path .\Microsoft-Windows-Powershell.evtx | Where-Object {$_.Message -like "*HKLM*"} | fl This outputs quite a bit of information to sift through. We do have 1 log entry that stands out however TimeCreated : 4/9/2025 2:20:56 AM ProviderName : PowerShell Id : 800 Message : Pipeline execution details for command line: $hyperv = Get-ChildItem HKLM:\SYSTEM\ControlSet001\Services . Context Information: DetailSequence=1 DetailTotal=1 SequenceNumber=109 UserId=DESKTOP-M3AKJSD\User HostName=ConsoleHost HostVersion=5.1.26100.2161 HostId=0fad0cf8-6cb6-4657-86f7-655ec22eed9f HostApplication=C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe EngineVersion=5.1.26100.2161 RunspaceId=2aeeba59-d0f6-4ce7-b41c-e07625b3beec PipelineId=43 ScriptName= CommandLine= $hyperv = Get-ChildItem HKLM:\SYSTEM\ControlSet001\Services Details: CommandInvocation(Get-ChildItem): "Get-ChildItem" ParameterBinding(Get-ChildItem): name="Path"; value="HKLM:\SYSTEM\ControlSet001\Services" If we google this registry key we can see that it holds information about running services. We submit this and find that it was the right answer! 5. The VM detection script can also identify VirtualBox. Which processes is it comparing to determine if the system is running VirtualBox? For this question we are going to to go back to the script that we found earlier and search for VirtualBox and we immediately find this block of code #Virtual Box $vb = Get-Process if (($vb -eq "vboxservice.exe") -or ($vb -match "vboxtray.exe")) { $vbvm = $true } if (!$vbvm) { $vb = Get-ChildItem HKLM:\HARDWARE\ACPI\FADT if ($vb -match "vbox_") { $vbvm = $true } } if (!$vbvm) { $vb = Get-ChildItem HKLM:\HARDWARE\ACPI\RSDT if ($vb -match "vbox_") { $vbvm = $true } } if (!$vbvm) { $vb = Get-Childitem hklm:\hardware\devicemap\scsi -recurse | gp -Name identifier if ($vb -match "vbox") { $vbvm = $true } } if (!$vbvm) { $vb = Get-ItemProperty hklm:\HARDWARE\DESCRIPTION\System -Name SystemBiosVersion if ($vb -match "vbox") { $vbvm = $true } } if (!$vbvm) { $vb = Get-ChildItem HKLM:\SYSTEM\ControlSet001\Services if (($vb -match "VBoxMouse") -or ($vb -match "VBoxGuest") -or ($vb -match "VBoxService") -or ($vb -match "VBoxSF")) { $vbvm = $true } } if ($vbvm) { "This is a Virtual Box." } We find that it is looking for VirtualBox! We know the question is asking for running processes. Looking at the first line of this section of the script we find: $vb = Get-Process if (($vb -eq "vboxservice.exe") -or ($vb -match "vboxtray.exe")) { $vbvm = $true } We have our 2 answers! vboxservice.exe, vboxtray.exe. We can now move onto the final question. The VM detection script prints any detection with the prefix ‘This is a’. Which two virtualization platforms did the script detect? We know we want to go back to script output so we can run the following command to find this output Get-WinEvent -Path .\Microsoft-Windows-Powershell.evtx | Where-Object {$_.Message -like "*This is a*"} | fl This outputs the following event: TimeCreated : 4/9/2025 2:20:57 AM ProviderName : PowerShell Id : 800 Message : Pipeline execution details for command line: . Context Information: DetailSequence=1 DetailTotal=1 SequenceNumber=145 UserId=DESKTOP-M3AKJSD\User HostName=ConsoleHost HostVersion=5.1.26100.2161 HostId=0fad0cf8-6cb6-4657-86f7-655ec22eed9f HostApplication=C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe EngineVersion=5.1.26100.2161 RunspaceId=2aeeba59-d0f6-4ce7-b41c-e07625b3beec PipelineId=43 ScriptName= CommandLine= Details: CommandInvocation(Out-Default): "Out-Default" ParameterBinding(Out-Default): name="InputObject"; value="This is a Hyper-V machine." ParameterBinding(Out-Default): name="InputObject"; value="This is a VMWare machine." We have the final 2 answers! Hyper-V and VMWare. We have now solved this challenge! Congratulations and happy hacking! Hack the Box