Finding Local Admin with the Veil-Framework

[Edit 8/13/15] – Here is how the old version 1.9 cmdlets in this post translate to PowerView 2.0:

Invoke-FindLocalAdminAccess -> Find-LocalAdminAccess

-> Additionally, the -Ping command for Invoke-ShareFinder is no longer needed

Back in 2012 @zeknox wrote a great post on “Finding Local Admin with Metasploit” which I highly recommend everyone read. My team consistently runs into situations similar to what he describes, where the current user context we’re operating under doesn’t have local administrator privileges on the machine where we have our shell. This was actually one of the motivations for PowerUp (which you can read more about here).

zeknox then details the Metasploit module he wrote, local_admin_search_enum.rb, which can help you find which machines on the network your current user has administrative access to. It does this by utilizing a Win32 API function named OpenSCManagerA to attempt to open up a handle to the service control manager on a remote host with SC_MANAGER_ALL_ACCESS (0xF003F) privileges, recording if this is successful and immediately closing the manager after. If your current user is able to open up the service control manager of a remote machine with these privileges, it can manipulate remote services and therefore PSEXEC.

This module is awesome, and has proved useful for us on several assessments. As I started expanding the functionality of PowerView, it was a given that I’d want to implement this great functionality in PowerShell. PowerView’s Invoke-FindLocalAdminAccess is a nearly direct port of zeknox’s module, wrapping the function Invoke-CheckLocalAdminAccess that utilizes the same Win32 API functionality:

There are a couple more ways to use PowerView to find where you your current user likely has administrative privileges. If you run the Invoke-ShareFinder cmdlet with the -CheckAccess option, PowerView will query the domain for machines, enumerate all shares on the resulting targets, and return only shares which you have read access to. If ADMIN$ shows up in the result set, odds are you can likely PSEXEC to these boxes:

If you want to just check for this type of access, the “-CheckAdmin” flag for Invoke-ShareFinder will just check access to the ADMIN$ share on discovered machines:

Version 1.5 of PowerView implements one more method to find where your local account might have administrative privileges. The first thing you want to do is see what domain groups your current user is a part of. The easiest way to do this is with a whoami /groups (gpresult /r will work as well):

Pay attention to any domain groups that pop up, e.g. “TESTLAB\Workstation Admins” in this case. Now, let’s use some PowerView functionality to see what users and groups are local administrators on the remote WINDOWS2 machine. The function Get-NetLocalGroup will utilize the ADSI WinNT provider to query the members of a localgroup (default of Administrators) on a remote host, even from a non-privileged account. This allows you to see what users/groups are members of the local admins:

There, we see our domain group “TESTLAB/Workstation Admins” is in the Administrators localgroup on this remote machine, meaning we can PSEXEC or WMIS to it all we like. If we want to get this information for ALL machines on the network, we can use the Invoke-EnumerateLocalAdmins function to query all machines in the current domain, find the members of the Administrators remote local group and spit everything out to a sortable .csv with the “-OutFile” flag:

The ability to find what accounts have local administrator rights where will become more and more important in the post KB2871997 era, which is why I covered some of this functionality in my previous “Pass-the-Hash is Dead: Long Live Pass-the-Hash” post. Hopefully PowerView’s new functionality can help you spread laterally in your assessments and show that this KB isn’t actually the pass-the-hash-patch that some claim it to be.