You are browsing the archive for Archaeology.

SC and its quirky cmd line args

August 20, 2020 in Anti-Forensics, Archaeology

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.
  • interrogate
    • Sends an INTERROGATE control request to a service.
  • continue
    • Sends a CONTINUE control request to a service.
  • stop
    • Sends a STOP request to a service.
  • 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
      • netbindadd
      • netbindremove
      • netbindenable
      • 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


WIN32_EXIT_CODE : 0 (0x0)

This is because control code 4 is actually SERVICE_CONTROL_INTERROGATE.

Typos and other obscurities that can be found inside Windows binaries

August 16, 2020 in Archaeology

When you stare at the code of OS binaries for a long time, you will eventually collect a list of curiosities that serve as an anecdotal proof that software, same as security, is… a state.

Some of these curiosities is just a legacy code that still makes it to the latest OS releases.

Some are legacy code that was there for a long time, but was eventually removed in newer OS versions. For example notepad.exe retrieving the ancient system metrics SM_PENWINDOWS (expected to return an address of a DLL!), and then resolves its function RegisterPenApp and… call it.

Some are just obvious copypasted code blocks. Despite the existence of libraries that can share code, it’s obvious that some of the projects were literally build upon the same source code that was eventually compiled into many final binaries. And funnily enough, it’s not uncommon to find binaries where one has the symbols available, or richer, or where symbols are named slightly different way than the other. Presence of the same code can be often leveraged to enrich the listings of binaries where the symbols are not available.

Some are hidden exports in drivers.

Some are Unicode characters outside of 16-bit set.

Some are references to project names and neologisms e.g. ProjectCentennialDogfood, or daVincisGarageLLC.LarryBooBoo (you will find these inside Windows 10’s explorer.exe).

And… some seem to be just silly typos that probably escaped the code / localization QA process. In fairness, the typos are actually pretty rare, so anytime I come across one I jot them down. And I am not sure if they are real typos, or perhaps some sort of way to watermark the binaries? Who knows… This is a list I came across so far:

  • ole32.dll
    • registers strangely named messages:
  • riched20.dll
  • TPSvc.dll
    • registers TOOLBAR_RESETKEYBAORD message – an obvious typo