Certulitis – one tool that keeps on giving

Update

EC who is one of the most technical guys I know pinged me because he figured out the meaning of that 0x00FB switch, The idea behind it is Windows archeology at its best and it goes as follows:

The code page your windows terminal uses is 437. Endash (‘–’) is an ASCII character 150 (0x96). When this character is inputted on terminal using code page 437 it will be mapped to ‘û’ which is code 0xFB.

How to use it with certutil?

You can run:

certutil ALT+150<command of your choice>

Old Post

Certutil is a really naughty tool. It accepts lots of various command line arguments that I believe are not widely known – and this post (and maybe some follow-up posts) is hoping to change that.

One of the first things I caught when I started analysing its command line arguments was the mysterious, case-insensitive command line argument comparison with the ‘uSAGE’ string. It turns out that certutil offers two different usage information depending on a command line option. If you just use ‘?’ then it’s the ‘official’ version. If it’s ‘uSAGE’ then it’s the unofficial one. Of course, once I found out I ran into Google and Twitter to find out if it is IN THE KNOWN.

Yes, it was. @0gtweet did it my favourite way – the hard way :-), @dunarth did it the right way, and @chris_ayres did it the earliest way (AFAICT).

Okay, with this out of the way, we look at the actual command line arguments.

Wait. What about the command line switches? Similarly to PowerShell, certutil accepts command line arguments using a number of different characters:

  • / (Unicode 0x002F)
  • – (Unicode 0x002D)
  • (Unicode 0x2013)
  • (Unicode 0x2212)
  • ? (Unicode 0x00FB)

I still can’t figure out why the last Unicode character on that list is being accepted. The Unicode character 0x00FB is ‘û’. If you know, please let me know and I will update the post.

Another discovery is brought to us by two unusual environment variables:

  • certsrv_rawhex – shows stuff in raw hex (e.g. certs)
  • CertSrv_Chain – enables debugging information being available for cert chain
  • CERTSRV_LOGMAX – maximum length of the certutil.log file
  • CERTSRV_DEBUG – enables certutil debug mode
  • CERTSRV_LOGFILE – name of the log file

The ‘certutil.log’ file is a log file that is created if DbgIsSSActive function imported from ‘certcli.dll’ which forwards it to ‘certca.dll’ returns true. I am kidding, it’s a convoluted way to say that certain conditions need to be met for the ‘certutil.log’ to be created, They can be either set via Registry (HKLM\Software\Microsoft\Cryptography\AutoEnrollment\Debug=XXX OR HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\Debug=XXX), or via environment variables listed below.

In fact, setting

set CERTSRV_LOGFILE=c:\test\foo.log
set CERTSRV_DEBUG=0xFFFFFFFF

will enable full logging to your main console and to the file c:\test\foo.log.

Pick up your favorite certutil command and give it a go. You will like the output as it helps to troubleshoot your manual testing 🙂

Finally, while certutil is primarily a command line application, it does create a windows called ‘CertUtil Application’ of class ‘CertUtil’, and apart from it, provides a UI for some of its commands (e..g -URL).

SC and its quirky cmd line args

I wrote it long time ago and just discovered it in my drafts folder.

Sc.exe is a popular native OS program used to control services. We see/use it pretty often but rarely look at its rich and less-known options. This post tries to map these options to APIs and control codes that are being used by sc.exe to communicate with the services.

So, yes, it turns out that many of sc.exe options are just a convenient wrapper for standard Windows Service functions. If you ever programmed and built at least one service process the commands offered by the sc.exe will sound very familiar to you. We can create a service, we can start it, we can pause it, we can query its status and its many parameters, and we can stop it. We can finally remove it. And in-between we can send various control codes to it too. Pretty straightforward.

Let’s walk through all options one by one:

  • query
    • Queries the status for a service, or enumerates the status for types of services.
    • -> EnumQueryServicesStatus
  • queryex
    • Queries the extended status for a service, or enumerates the status for types of services.
    • -> EnumQueryServicesStatus
  • start
    • Starts a service.
    • -> StartServiceW
  • pause
    • Sends a PAUSE control request to a service.
    • -> SERVICE_CONTROL_PAUSE
  • interrogate
    • Sends an INTERROGATE control request to a service.
    • -> SERVICE_CONTROL_INTERROGATE
  • continue
    • Sends a CONTINUE control request to a service.
    • -> SERVICE_CONTROL_CONTINUE
  • stop
    • Sends a STOP request to a service.
    • -> SERVICE_CONTROL_STOP
  • config
    • Changes the configuration of a service (persistent).
    • -> ChangeServiceConfig2W
  • description
    • Changes the description of a service.
    • -> ChangeServiceConfig2W
  • failure
    • Changes the actions taken by a service upon failure.
    • -> ChangeServiceConfig2W
  • failureflag
    • Changes the failure actions flag of a service.
    • -> ChangeServiceConfig2W
  • sidtype
    • Changes the service SID type of a service.
    • -> ChangeServiceConfig2W
  • privs
    • Changes the required privileges of a service.
    • -> ChangeServiceConfig2W
  • managedaccount
    • Changes the service to mark the service account password as managed by LSA.
    • -> ChangeServiceConfig2W
  • qc
    • Queries the configuration information of a service.
    • -> QueryServiceConfig2W
  • qdescription
    • Queries the description of a service.
    • -> QueryServiceConfig2W
  • qfailure
    • Queries the actions taken by a service upon failure.
    • -> QueryServiceConfig2W
  • qfailureflag
    • Queries the failure actions flag of a service.
    • -> QueryServiceConfig2W
  • qsidtype
    • Queries the service SID type of a service.
    • -> QueryServiceConfig2W
  • qprivs
    • Queries the required privileges of a service.
    • -> QueryServiceConfig2W
  • qtriggerinfo
    • Queries the trigger parameters of a service.
    • -> QueryServiceConfig2W
  • qpreferrednode
    • Queries the preferred NUMA node of a service.
    • -> ChangeServiceConfig2W
  • qmanagedaccount
    • Queries whether a services uses an account with a password managed by LSA.
    • -> QueryServiceConfig2W
  • qprotection
    • Queries the process protection level of a service.
    • -> QueryServiceConfig2
  • quserservice
    • Queries for a local instance of a user service template.
    • -> QueryLocalUserServiceName
  • delete
    • Deletes a service (from the Registry).
    • -> DeleteService
  • create
    • Creates a service. (adds it to the Registry).
    • -> CreateServiceW
  • control
    • Sends a control to a service.
    • A wrapper for ControlService
      • paramchange
        • SERVICE_CONTROL_PARAMCHANGE
      • netbindadd
        • SERVICE_CONTROL_NETBINDADD
      • netbindremove
        • SERVICE_CONTROL_NETBINDREMOVE
      • netbindenable
        • SERVICE_CONTROL_NETBINDENABLE
      • netbinddisable
        • SERVICE_CONTROL_NETBINDDISABLE
      • <any integer value>
        • any control code – either predefined, or service-specific
  • sdshow
    • Displays a service’s security descriptor.
    • -> QueryServiceObjectSecurity
  • sdset
    • Sets a service’s security descriptor.
    • -> SetServiceObjectSecurity
  • showsid
    • Displays the service SID string corresponding to an arbitrary name.
    • -> QueryServiceConfig2W
  • triggerinfo
    • Configures the trigger parameters of a service.
    • -> ChangeServiceConfig2W
  • preferrednode
    • Sets the preferred NUMA node of a service.
  • GetDisplayName
    • Gets the DisplayName for a service.
    • -> GetServiceDisplayNameW
  • GetKeyName
    • Gets the ServiceKeyName for a service.
    • -> GetServiceKeyNameW
  • EnumDepend
    • Enumerates Service Dependencies.
    • -> EnumDependentServicesW
  • boot
    • (ok | bad) Indicates whether the last boot should be saved as the last-known-good boot configuration
    • -> NdrClientCall4
  • Lock
    • Locks the Service Database
    • -> NdrClientCall4
  • QueryLock
    • Queries the LockStatus for the SCManager Database
    • -> NdrClientCall4

Now that we have this out of the way, I can reveal why I was attracted to looking at these config options in a first place. It is the bufsize= command line argument I have never used before.

It lets you decide how large the buffer will be when a specific API or control code is being sent to the service. Make it too small, and you get an error. Make it too big, and it’s an error too. Interesting.

For instance, if you run sc query, you will get a list of all services. If you run sc query bufsize= 100 though, the command will fail.

Plus, if there is a default hard-coded inside the sc.exe, then will I, by making the service parameters always outside of the default size, make sc fail to report unless I actually use the bufsize= command line argument that is allocating buffer large enough to hold all the data?

Another interesting bit is that you can use sc control command to determine the status of the service instead of sc query or sc qc e.g:

sc control SysmonDrv 4

shows:

SERVICE_NAME: SysmonDrv
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
(STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0

This is because control code 4 is actually SERVICE_CONTROL_INTERROGATE.