Tip: Comparing really long REG_BINARY value (Sysmon Ruleset)

Curious whether anyone has a better/simpler way to do this? - there may be easier ways but I wanted to post this before I lost track of it.

I wanted Relevance to check for the rule configuration of Sysmon, which is stored in a single really long REG_BINARY value.

I mean really long:

q: length of (value "Rules" of key "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters" of registry as string)
A: 417744

I can’t directly build a string 417,744 characters long because “…contained a very long string”. So I build a concatenation of multiple strings of 128 characters each, and compare that concatenation to the original string. Looping back on “Relevance Generating Relevance”, I create my string set by splitting a known-good registry value into “chunks of 128-characters, followed by whatever’s leftover”:

  • The “number of chunks” are represented by (length of it / 128)

  • they can be numbered as (integers in (0, length of it / 128))

  • the starting position of each chunk can be found as (128 * it) of (integers in (0, length of it / 128)

  • The content of a “chunk” is the 128 characters beginning at each starting position substrings ((128 * it) of (integers in (0,length of it / 128 )), 128) of it

  • Plus there may be a final substring of less than 128 bytes, the last (length of it mod 128) of it

So the following will give all of the “substrings” of 128 bytes, and the last (smaller-than-128 byte) contained in the registry key (I include the starting positions of each here for clarity but will not keep that in the final query):

q: (start of it, it) of ( substrings ((128 * it) of (integers in (0,length of it / 128 )), 128) of it ; last (length of it mod 128) of it)of (value "Rules" of key "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters" of registry as string)
A: 0, 000008001c000000100000000a0004000100000000000000f8610000280000000f00000000000000000000000000000000000000000000000000000000000000
A: 128, 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
...many, many more
A: 417536, 000000000a0000002e0073006300720000000000000000001100000001000000a82f0300000000001200000001000000b82f0300000000001300000000000000
A: 417664, c82f0300000000001400000000000000d82f03000000000015000000000000000000000000000000

I can reformat that into a form that is easier to copy-and-paste into the final relevance query:

q: concatenation ";" of ("%22" & it & "%22") of ( substrings ((128 * it) of (integers in (0,((length of it / 128) -1))), 128) of it ; last (length of it mod 128) of it)of (value "Rules" of key "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters" of registry as string)
A: "000008001c000000100000000a0004000100000000000000f8610000280000000f00000000000000000000000000000000000000000000000000000000000000";"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";"many more";"c82f0300000000001400000000000000d82f03000000000015000000000000000000000000000000"

Now we can paste that into the Fixlet Relevance we would use to see whether the value is present and correct, avoid the use of one “very long string” by replacing with a concatenation of “many, shorter strings”

q: not exists (key "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters" of registry) whose ( value "Rules" of it as string = concatenation of ("000008001c000000100000000a0004000100000000000000f8610000280000000f00000000000000000000000000000000000000000000000000000000000000";"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";"much,much,more"))
A: False
T: 84.552 ms

I would read it like this:

(concatenations of (characters of it) whose(it != "%00") of it) of (hexadecimal strings it) of unique values of (it as string) of values "Rules" of keys "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters" of (x64 registries;x32 registries)

Here is a working example that should work on any system:

(concatenations of (characters of it) whose(it != "%00") of it) of (hexadecimal strings it) of unique values of (it as string) of values "blob" of keys of keys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\CA\Certificates" of (x64 registries;x32 registries)

Here is this taken further to filter out all non-ASCII chars:

( concatenations of ( characters of it) whose( exists (hexadecimal integer (it as hexadecimal) ) whose(it >= 32 AND it <= 126) of it ) ) of (hexadecimal strings it) of unique values of (it as string) of values "blob" of keys of keys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\CA\Certificates" of (x64 registries;x32 registries)

Example:

Q: ( concatenations of ( characters of it) whose( exists (hexadecimal integer (it as hexadecimal) ) whose(it >= 32 AND it <= 126) of it ) ) whose(it contains "Microsoft Windows Hardware Compatibility Intermediate CA") of (hexadecimal strings it) of unique values of (it as string) of values "blob" of keys of keys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\CA\Certificates" of (x64 registries;x32 registries)
A: ?RAeD- hZ+SfNoE`X Ex+i|t3&]/`}!oZTPmQm\ 00?i0*H0p1+0)U"Copyright (c) 1997 Microsoft Corp.10UMicrosoft Corporation1!0UMicrosoft Root Authority0971001070000Z021231070000Z01+0)U"Copyright (c) 1997 Microsoft Corp.1A0?U8Microsoft Windows Hardware Compatibility Intermediate CA10UMicrosoft Corporation110/U(Microsoft Windows Hardware Compatibility00*H0N!`Z>wZ).N]DK"0;'x@+yV6rc_fI<&baL?ECjfd,u&efI=szq00U00U%250++70U0[pir#Q~Mr0p1+0)U"Copyright (c) 1997 Microsoft Corp.10UMicrosoft Corporation1!0UMicrosoft Root Authority<<>c@0*HXv`IX,dM@-M_}<TR((e^q$D$-QTDK{q:5|tm9Djy[*c"bbS`G1Wa6-SV3)'Q&Al^[PJC*o_u(6>E\#=YxQF9mR9FRTq~nJIQ`Ut,
T: 6.881 ms

Related: Parsing Registry.pol (Local Group Policy) / Get numeric ASCII values of characters in a string?