Detect whether a service is installed (blindly) and/or running (if exposing named pipes) on a remote machine without using local admin privileges.
In more detail, running this script connects to the target SMB service (445/tcp) remotely and does the following:
-
Checks if the specified service is installed through the [MS-LSAT] RPC call LsarLookupNames(). There is no need to use a privileged account, but only "blind" query is possible (cannot list the services, we can only ask the state of a specific service).
-
Checks if the specified Named Pipe exists on the target. Services (processes) may expose a named pipe characteristic to the service, which can be seen by an unprivileged user. So checking specific named pipes characteristic to services may allow us to infer whether the specific service is running or not.
This is a standalone Python script using Impacket, no need to install anything. Tested it on up-to-date Kali and Arch Linux using the latest official Impacket (0.10.0 and 0.9.24) and Python (3.9 and 3.10).
The services, service names to check, named pipes characteristic to the service are specified in JSON config files (or CSV files if it is more comfortable, what I realized later :), so a custom csv2json converter is also available) in the conf folder. For understanding the format, see the examples included.
Config files included:
- edr.json (and edr.csv): common AV/EDR services and named pipes
- webclient.json (and webclient.csv): for detecting WebClient and Print Spooler on the target (useful for my favorite HTTP → LDAP NTLM relay computer takeover attack).
- psexec.json (and psexec.csv: for detecting uncleaned Impacket PsExec services running for SYSTEM RCE using an unprivileged domain user.
Use cases may be extended by more services / named pipes, EDR config is quite incomplete, feel free to add more.
The script uses the JSON config format, but later I realized writing CSV is much more comfortable, so included the csv2json.py script to convert the CSV to JSON.
Running against a single target to enumerate AV/EDR services (or anything else) is straightforward:
./serviceDetector.py -conf conf/edr.json evil.corp/johndoe:Passw0rd1@server.ecorp.local
Kerberos authentication is also supported (KRB5CCNAME env var is pointing to the ccache file):
./serviceDetector.py -conf conf/edr.json -k -no-pass server.ecorp.local
For running against multiple targets effectively GNU parallel is super useful:
cat targets.txt | parallel -j 50 ./serviceDetector.py evil.corp/johndoe:Passw0rd1@{}
Note that before running against a bunch of targets test against one in order to prevent account lockout (e.g. in the case of a misspelled password).
Opsec Note: be aware that concurrent mass login to different targets may trigger SOC alerts.
The two techniques used here are not new.
-
[MS-LSAT] RPC call LsarLookupNames() was used earlier by Vincent Le Toux (@mysmartlogon) in the Antivirusscanner module of the awesome PingCastle tool.
-
The named pipe idea for detecting running services was inspired by this tweet from Lee Christensen (@tifkin_) when he used this for the WebClient service detection. This technique for AV/EDR detection was also used by the NamedPipeTouch tool from NSA (leaked by The Shadow Brokers group).