Forensic Investigation Operations — Windows Base I
In this series of articles, we will show you in a laboratory environment what kind of analysis you should perform against Windows machines that have been hacked or are somehow compromised in the system. In the scenario in the lab environment, we will be showing the threat intelligence capabilities and some DFIR methods we have.
You may see that the IPs change from time to time, do not care, we will be using different machines as we progress. The entire methodology is the same.
The machine we will use in this scenario was hacked by a hacker, this is the only fact we know. We must discover the evidence in the system and the attacker’s mentality.
First, let’s get a general insight and information about the system.
Get system information: Get-ComputerInfo
Based on the output, we have some useful information about the system.
- Operating System: Windows Server 2016 Datacenter
- Build Information: 14393.2791.amd64fre.rs1_release.190205–1511
- Installation Date: March 2, 2019
- Product ID: 00376–40000–00000-AA753
- Registered Organization: Amazon.com
- Registered Owner: EC2 (indicating it’s likely an AWS EC2 instance)
- BIOS Version: Default System BIOS by Amazon
Get operating system details: Get-WmiObject -Class Win32_OperatingSystem
You get a summary with the above command.
Get hardware information: Get-WmiObject -Class Win32_ComputerSystem
Based on this additional information, we know:
- Domain: WORKGROUP (not joined to a domain)
- Manufacturer: Amazon EC2
- Model: t3.small (instance type)
- System Name: EC2AMAZ-I8UHO76
- Primary Owner Name: EC2
- Total Physical Memory: Approximately 2 GB
Get installed softwares: Get-WmiObject -Class Win32_Product
The list you get from here may be long. However, if there is a software or application that catches your eye and should not normally be there, you should take note.
Amazon SSM Agent:
- Vendor: Amazon Web Services
- Version: 2.3.444.0
- Purpose: Amazon SSM Agent is used for managing and configuring AWS instances via AWS Systems Manager.
AWS Tools for Windows:
- Vendor: Amazon Web Services
- Version: 3.15.666
- Purpose: A set of tools and utilities to interact with AWS services from Windows environments.
AWS PV Drivers:
- Vendor: Amazon Web Services
- Version: 8.2.6
- Purpose: Paravirtual drivers for better performance of AWS instances.
aws-cfn-bootstrap:
- Vendor: Amazon Web Services
- Version: 1.4.31
- Purpose: Utilities for AWS CloudFormation to bootstrap instances.
Now let’s check the information of existing users: Get-LocalUser
We have users:
- Administrator
- DefaultAccount
- Guest
- Jenny
- John
The cyber attack may have been carried out through one of these users.
Get the last logon time for the user “John” by using net user
command: net user John | Select-String “Last logon”
To retrieve information about users and their last logon times, you can use the following PowerShell commands: Get-LocalUser | Select-Object Name, Enabled, LastLogon
John logged in in the evening of 3/2/2019, which matches the time period of the attack.
To get more detailed information, including last logon times, you can use the NetUser
command:
Get-LocalUser | ForEach-Object {
$user = $_.Name
$details = net user $user
[PSCustomObject]@{
UserName = $user
Enabled = $_.Enabled
FullName = ($details | Select-String "Full Name" | ForEach-Object { $_ -replace ".*Full Name *" })
LastLogon = ($details | Select-String "Last logon" | ForEach-Object { $_ -replace ".*Last logon *" })
}
} | Format-Table -AutoSize
John is a suspicious user here, we need to investigate this. Retrieve detailed information about the user “John”: Get-LocalUser -Name John | Format-List *
List the groups that the user “John” is a member of:
Get-LocalGroup | ForEach-Object {
$group = $_.Name
$members = Get-LocalGroupMember -Group $group
$members | Where-Object { $_.Name -eq "John" } | Select-Object @{Name="GroupName";Expression={$group}}, Name
}
It retrieves nothing.
- Enabled: True (The account is active)
- PasswordRequired: True (A password is required for the account)
- UserMayChangePassword: True (The user is allowed to change their password)
- PasswordLastSet: 3/2/2019 5:48:19 PM (This seems to be an incomplete date; we need to verify this information)
- LastLogon: 3/2/2019 5:48:32 PM (This also appears incomplete and needs verification)
- SID: S-1–5–21–3685962493–259677494–3116396707–1009 (A unique identifier for the user account)
- PrincipalSource: Local (The account is local to this machine)
Password setting and change dates are critical. There is still a doubt here. Make a note of these.
We will get back to analyzing this user in detail. Before that let’s continue with our general forensics approaches.
Get network configuration: Get-NetIPConfiguration
Get active network connections: Get-NetTCPConnection
Here we discovered a connection to an external IP, which could be an internal IP or the attacker’s C2 server. For this reason, you should learn the network structure of the system you will analyze. Other IPs:
- 20.12.23.50
- 23.72.36.34
- 10.34.2.3
- 10.100.2.58
Now use Get-NetIPAddress
:
Check the values, network interface and IP information defined here carefully. If you see anything suspicious, make a note of it.
Let’s try to get DNS information: Get-DnsClientServerAddress
Check if there is a record defined with the Resolve-DnsName
command.
We captured the records of those defined in the internal structure, but there are also values that are not defined. You can also do this manually by accessing the following file: C:\ > Windows > System32 > drivers > etc
Use: type C:\Windows\System32\drivers\etc\hosts
What google.com…
The /etc/hosts
file is used to map hostnames to IP addresses locally, bypassing DNS resolution. If an entry for google.com
or www.google.com
exists in the /etc/hosts
file, it could potentially be used to redirect traffic intended for Google to a malicious server.
Just ping it.
This is not a real IP of google.com. For this reason, it may be a C2 server.
List network routes now: Get-NetRoute
We need to do some more detailed research:
Get-NetTCPConnection | Where-Object { $_.RemoteAddress -eq “10.34.2.3” -and $_.LocalPort -eq 445 } | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, State, OwningProcess
And:
Get-NetTCPConnection | Where-Object { $_.RemoteAddress -eq “10.34.2.3” -and $_.LocalPort -eq 139 } | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, State, OwningProcess
You probably won’t get any answers.
We made these queries over an IP that we exposed. You can try to write our own machine IP value and try it.
The following 10.34.2.3
IP connects remotely to ports 139 and 445.
Port 139 (NetBIOS Session Service)
- Protocol: NetBIOS (Network Basic Input/Output System)
- Description: Port 139 was originally used by the NetBIOS Session Service for communication between machines on a LAN. It facilitates the establishment of sessions for communication, such as file sharing and printer sharing.
- Usage: In modern environments, Port 139 is typically used for legacy SMB operations and NetBIOS over TCP/IP (NetBT).
Port 445 (SMB over TCP)
- Protocol: SMB (Server Message Block)
- Description: Port 445 is used by SMB to provide file and printer sharing services over TCP/IP. It supports more efficient and secure operations compared to the older NetBIOS-based methods using Port 139.
- Usage: Port 445 is the default port for SMB operations in modern Windows operating systems and is used for various tasks including file sharing, remote administration, and communication between Windows machines.
To see if ports 139 and 445 are actively listening on your system: Get-NetTCPConnection | Where-Object { $_.LocalPort -eq 139 -or $_.LocalPort -eq 445 -or $_.RemotePort -eq 139 -or $_.RemotePort -eq 445 }
Yes. They are active.
To inspect firewall rules related to ports 139 and 445: Get-NetFirewallRule | Where-Object { $_.LocalPort -eq 139 -or $_.LocalPort -eq 445 }
Nothing to show. A security layer may not have been specified for these.
To identify which processes are using ports 139 or 445: Get-Process -IncludeUserName | Where-Object { $_.TCPConnections.LocalEndPoint.Port -eq 139 -or $_.TCPConnections.LocalEndPoint.Port -eq 445 }
This command lists processes and their associated users that have active TCP connections on ports 139 or 445. We couldn’t get anything from here either.
To verify SMB configuration and settings:
Get-SmbServerConfiguration
Get-SmbClientConfiguration
You should check whether there is a general security hole in such outputs. These settings govern various aspects of how the SMB client interacts with servers, manages caches, handles file operations, and maintains connections. Understanding and configuring these parameters appropriately can optimize performance and security in SMB environments.
For example, EnableInsecureGuestLogons: Allows
, parameter is a very risky approach.
To fix this, you can use the following command: Set-SmbClientConfiguration -EnableInsecureGuestLogons $false
EnableInsecureGuestLogons:
- Risk: Enabling insecure guest logons (where authentication is not required) can lead to unauthorized access and security breaches, especially if sensitive data or resources are accessible via SMB shares.
EnableSecuritySignature and RequireSecuritySignature:
- Risk: Disabling or improperly configuring SMB signing (security signatures) can expose the system to man-in-the-middle attacks and unauthorized data tampering.
EnableMultiChannel:
- Risk: While multi-channel can improve performance by using multiple network connections, improper configuration or lack of authentication across channels can be exploited by attackers.
OplocksDisabled:
- Risk: Opportunistic locks (oplocks) improve performance by caching data locally, but disabling them can increase the risk of data corruption and concurrency issues.
EnableLargeMtu:
- Risk: Enabling large MTU (Maximum Transmission Unit) sizes without appropriate network infrastructure support can lead to fragmentation issues and potential denial-of-service (DoS) attacks.
EnableLoadBalanceScaleOut:
- Risk: Load balancing across multiple connections can enhance performance, but improper configuration or lack of authentication and authorization controls can introduce security vulnerabilities.
EnableByteRangeLockingOnReadOnlyFiles:
- Risk: Allowing byte range locking on read-only files might expose files to unintended modifications or access.
EnableBandwidthThrottling:
- Risk: Inappropriate or misconfigured bandwidth throttling settings can impact performance or lead to ineffective traffic management, affecting overall network stability and security.
You should think about all these parameters.
To determine if the machine is part of an Active Directory (AD) domain, you can use the following PowerShell command: (Get-WmiObject Win32_ComputerSystem).PartOfDomain
We may not be in AD.
Additionally, you can retrieve more detailed information about the domain membership: Get-WmiObject Win32_ComputerSystem | Select-Object Domain, DomainRole
- Domain: The computer is currently not joined to a domain (WORKGROUP).
- DomainRole: The domain role code 2 typically corresponds to a standalone workstation or member server in a workgroup environment.
Domain parameter indicates the domain name to which the computer is joined. In this case, WORKGROUP
suggests that the computer is not part of an Active Directory domain but rather is in a workgroup configuration.
Inspect user accounts and groups now:
Get-LocalUser | Select-Object Name, Enabled, LastLogon
Get-LocalGroup | Select-Object Name, Description
There are many group definitions. We can see which user we suspect belongs to. User is John.
Check membership for user “John” in each group:
Get-LocalGroupMember -Group "Administrators"
Get-LocalGroupMember -Group "Users"
Get-LocalGroupMember -Group "Remote Desktop Users"
Jenny? This user appeared before us.
John is only in the “Users” group.
Specifically, you can follow the steps below to control privilege:
# Check for user "Jenny"
$UserName = "Jenny"
Get-LocalGroupMember -Group "Administrators" | Where-Object { $_.Name -eq $UserName }
Get-LocalGroupMember -Group "Users" | Where-Object { $_.Name -eq $UserName }
Get-LocalGroupMember -Group "Remote Desktop Users" | Where-Object { $_.Name -eq $UserName }
Check if the user “John” has any scheduled tasks: Get-ScheduledTask | Where-Object { $_.Principal.UserId -eq “John” } | Select-Object TaskName, State, Actions
Check if the user “Jenny” has any scheduled tasks: Get-ScheduledTask | Where-Object { $_.Principal.UserId -eq “Jenny” } | Select-Object TaskName, State, Actions
There is no defined output. Interesting…
Get general information about tasks then:
Pay attention to the first 6 definitions… This is quite suspicious. You can get a general detail about these: Get-ScheduledTask | Get-ScheduledTaskInfo | Select-Object TaskName, Actions
To determine if a scheduled task is suspicious, focus on understanding its purpose, verifying its actions, and comparing it against known legitimate tasks in your environment.
Use: Get-ScheduledTask -TaskName “GameOver” | Get-ScheduledTaskInfo | Select-Object TaskName, Actions
Use: Get-ScheduledTask -TaskName “falshupdate22” | Get-ScheduledTaskInfo | Select-Object TaskName, Actions
Now we need to specifically look at the Clean file system entry. This is highly suspicious and attempts to destroy evidence or something like that. To gather detailed information about a scheduled task, including its properties and actions, you can use PowerShell commands effectively.
Use:
$task = Get-ScheduledTask | Where TaskName -EQ “Clean file system”
$task
$task.Actions
We found nc.ps1
. There is a task buried here that probably belongs to Netcat. Control it.
This is real proof.
Display all properties for detailed analysis about task now:
$task = Get-ScheduledTask | Where-Object { $_.TaskName -eq "NameOfSuspiciousTask" }
$task | Format-List * # Display all properties for detailed analysis
$task.Actions # Display actions configured for the task
$task.Triggers # Display triggers configured for the task
We see a script that allows you to get a reverse shell hidden under the task name Clean File System. This attempt is likely to bypass security protocols.
Monitor network activity using tools like netstat
or PowerShell commands to check for any suspicious connections established by nc.ps1
:
Get-NetTCPConnection | Where-Object { $_.OwningProcess -eq (Get-Process -Id $pid).Id }
We could not find any output.
You can perform a detailed analysis of a task by running the following commands one by one. Note these.
# Retrieve the scheduled task object
$task = Get-ScheduledTask -TaskName "Clean file system"
# Display all properties of the scheduled task
$task | Format-List *
# Display actions configured for the task
$task.Actions
# Display triggers configured for the task
$task.Triggers
# Display settings and security descriptor
$task.Settings
$task.SecurityDescriptor
# Display task principal and version
$task.Principal
$task.Version
It’s quite dangerous. There is a task token opened under Administrator authority.
The MSFT_TaskDailyTrigger
is a specific type of trigger used in Windows Task Scheduler that specifies a task should run daily. It is part of the Windows Management Instrumentation (WMI) classes used to manage and configure scheduled tasks.
The MSFT_TaskDailyTrigger
class provides properties that define how often the task runs, at what time, and any intervals or repetitions required. Here are some key properties of MSFT_TaskDailyTrigger
:
- Id: A unique identifier for the trigger.
- StartBoundary: The date and time when the trigger is activated.
- EndBoundary: The date and time when the trigger is deactivated.
- Enabled: Indicates whether the trigger is enabled or not.
- DaysInterval: Specifies the interval in days between each run of the task. For example, a value of 1 means the task runs every day.
- RandomDelay: Specifies a random delay time for the task to run after the trigger is activated.
Then use it:
$trigger = Get-ScheduledTask -TaskName "Clean file system" | Select-Object -ExpandProperty Triggers | Where-Object { $_.GetType().Name -eq 'MSFT_TaskDailyTrigger' }
$trigger | Format-List *
This is a general example for you.
Or you can use:
# Retrieve the scheduled task object
$task = Get-ScheduledTask -TaskName "Clean file system"
# Display triggers configured for the task
$task.Triggers | Where-Object { $_.GetType().Name -eq 'MSFT_TaskDailyTrigger' } | Format-List *
The HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
registry key is used to specify programs that run when a user logs on. This key is often used to ensure that certain applications or services start automatically when the system boots up or a user logs in. This can be legitimate software like antivirus programs, but it is also a common location for malware to set itself to run automatically on system startup.
To access and display the values under the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
registry key using PowerShell, you can use the Get-ItemProperty
cmdlet:
# Define the path to the registry key
$registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
# Get the registry key properties
Get-ItemProperty -Path $registryPath
Wow! We saw an IP that we previously identified as suspicious interacting. What is p.exe? You can also subject the .exe file you find here to external forensic analysis.
Now get firewall rules: Get-NetFirewallRule
If you can discover a change here that is not normally present, you should investigate.
Now get processes: Get-Process
Analyze questionable approaches here.
Review the security event logs for login activities related to the user “John”:
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624} | Where-Object { $_.Properties[5].Value -eq "John" } | Select-Object TimeCreated, Id, Message
We have accessed the log record of the login activity.
Investigate if the user “John” and “Jenny” has any scheduled tasks:
Get-ScheduledTask | Where-Object { $_.Principal.UserId -eq "John" } | Select-Object TaskName, State, Actions
Get-ScheduledTask | Where-Object { $_.Principal.UserId -eq "Jenny" } | Select-Object TaskName, State, Actions
Check for processes currently running under the user “John”:
Get-Process | Where-Object { $_.StartInfo.UserName -eq "John" } | Select-Object Name, Id, CPU, Path
Look for activities performed by the user “John” in the system and application event logs:
Get-WinEvent -FilterHashtable @{LogName='System'; Level=2} | Where-Object { $_.Properties[1].Value -eq "John" } | Select-Object TimeCreated, Id, Message
There is no clear evidence so far. Now let’s get a general detail: Get-WinEvent -FilterHashtable @{LogName=’System’; Level=2}
We discovered some interesting interactions.
Now let’s do this manually. Follow the order below.
Go to EventViewer.
Then create custom view.
Pick a custom range.
In the From: section click where it says First Event, and then click Events On from the drop down menu.
Give the suspicious date range for John.
Pick log type as security.
Then just follow.
You will see an output-page like this.
You can review these logs manually. Below we found an security state change.
Let’s try to get more details about remote connection. We need to go to the inetpub
location.
The inetpub
directory is a default directory for Microsoft Internet Information Services (IIS), which is a web server application and set of feature extension modules created by Microsoft for use with Windows. This directory is typically found on Windows servers where IIS is installed, and it serves as the root directory for hosting web content.
wwwroot
: This is the default directory for web pages and site content. When you create a website or web application, the files for the site (HTML, CSS, JavaScript, images, etc.) are typically placed here. For example,C:\inetpub\wwwroot\index.html
would be the path to the default home page of a website.logs
: This directory contains log files for IIS. These logs can include access logs, error logs, and other information that can be useful for troubleshooting and monitoring the web server's activity.ftproot
: If IIS FTP services are enabled, this directory serves as the root directory for FTP file transfers.vdirs
: Virtual directories can be configured in IIS to point to directories outside of thewwwroot
folder. This allows you to serve content from other locations on the file system.custerr
: This directory holds custom error pages that IIS can serve in response to specific HTTP status codes, such as 404 Not Found or 500 Internal Server Error.
Check these.
What is .jsp? They shouldn’t be here. You can analyze these.
The files are full of commands used to get connections from the web server… Very suspicious…
Looks like we need to control some traffic. To check the inbound rules of the Windows Firewall using PowerShell, you can use the Get-NetFirewallRule
cmdlet along with Get-NetFirewallPortFilter
and Get-NetFirewallAddressFilter
to retrieve detailed information about the rules, including ports and addresses.
# List all inbound firewall rules
Get-NetFirewallRule -Direction Inbound
Evaluate the evidence you find and capture any additional details.
Let’s give a more comprehensive code.
# Create a list to store the rule details
$ruleDetails = @()
# Get all inbound firewall rules
$inboundRules = Get-NetFirewallRule -Direction Inbound
# Loop through each rule to get detailed information
foreach ($rule in $inboundRules) {
$ruleName = $rule.Name
$ruleDisplayName = $rule.DisplayName
$ruleEnabled = $rule.Enabled
$ruleAction = $rule.Action
$ruleProfile = $rule.Profile
$ruleDescription = $rule.Description
# Get port filter details
$portFilter = Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule
$localPorts = $portFilter.LocalPort
$remotePorts = $portFilter.RemotePort
# Get address filter details
$addressFilter = Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule
$localAddresses = $addressFilter.LocalAddress
$remoteAddresses = $addressFilter.RemoteAddress
# Add the details to the list
$ruleDetails += [PSCustomObject]@{
Name = $ruleName
DisplayName = $ruleDisplayName
Enabled = $ruleEnabled
Action = $ruleAction
Profile = $ruleProfile
Description = $ruleDescription
LocalPorts = $localPorts
RemotePorts = $remotePorts
LocalAddresses = $localAddresses
RemoteAddresses = $remoteAddresses
}
}
# Export the details to a CSV file
$ruleDetails | Export-Csv -Path "InboundFirewallRules.csv" -NoTypeInformation
This script collects the detailed information and exports it to a CSV file named InboundFirewallRules.csv
.
Port 1337 is often associated with unauthorized access or backdoor activities, as it’s commonly used in hacker culture (where “1337” or “leet” is slang for “elite”). To investigate activities related to this port on your system, you can take several steps using PowerShell and other built-in Windows tools.
First, verify if port 1337 is open on your system: Get-NetTCPConnection -LocalPort 1337
Review system event logs for unusual activities related to port 1337:
# Get system event logs related to network connections on port 1337
Get-WinEvent -LogName "Microsoft-Windows-Security-Auditing" | Where-Object { $_.Message -match "1337" }
To specifically check for rules related to port 1337 (or any other port), you can filter the results using Get-NetFirewallPortFilter
:
# Get all inbound firewall rules
$inboundRules = Get-NetFirewallRule -Direction Inbound
# Loop through each rule to find those associated with port 1337
foreach ($rule in $inboundRules) {
$portFilter = Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule
if ($portFilter.LocalPort -eq 1337) {
$rule | Select-Object -Property Name, DisplayName, Enabled, Action, Profile, Description, Direction, @{Name="LocalPorts";Expression={$portFilter.LocalPort}}, @{Name="RemotePorts";Expression={$portFilter.RemotePort}}
}
}
You can also use a single command to find and display inbound firewall rules for port 1337:
# Find inbound firewall rules for port 1337
Get-NetFirewallRule -Direction Inbound | Where-Object {
$portFilter = Get-NetFirewallPortFilter -AssociatedNetFirewallRule $_
$portFilter.LocalPort -eq 1337
} | Select-Object -Property Name, DisplayName, Enabled, Action, Profile, Description
Don’t give up on hacking.
Code for good.
^-^