Authentication and Execution Theory
Let’s take some time to discuss how PsExec, a part of the Sysinternals suite, works.
At a high level, PsExec authenticates to SMB on the target host
and accesses the DCE/RPC interface.
PsExec will use this interface to access the service control manager,
create a new service and execute it.
As part of the attack,
the binary which is executed by the service is copied to the target host.
In this section, we’ll leverage an attack that operates in a similar way.
However, we will execute our code without registering a new service
and we’ll use our previous tradecraft to do this
without writing a file to disk.
This technique involves two main tasks.
First, our code must authenticate to the target host.
Following that, it must execute the desired code.
Authentication to the DCE or RPC interface and the service control manager
is handled by the unmanaged OpenSCManagerW API.
To invoke this API, we must supply the host name of the target,
and the name of the service control database.
Supplying a null value will use the default database.
Finally, we must pass the desired access to the service control manager.
The API is executed in the context of the access token of the executing thread,
which means no password is required.
If authentication is successful,
a handle is returned that is used to interact with the service control manager.
PsExec performs the same actions when invoked,
but then it calls CreateServiceA to set up a new service.
Our approach will be more subversive.
We will instead use the OpenService API to open an existing service,
and invoke ChangeServiceConfigA to change the binary that the service executes.
This will not leave any service creation notifications and may evade detection.
Once the service binary has been updated, we will issue a call to StartServiceA,
which will execute the service binary
and give us code execution on the remote machine.
Since we control the service binary, we can use a PowerShell download cradle
to avoid saving a file to disk.
If endpoint protections such as application whitelisting are in place,
this approach may not be as straightforward
and may require a bypass.
Now that we understand the various techniques required,
let’s implement this in code.