If you’ve read my blog over the past few days, you already know that I now work for Tanium. Tanium has a self-named product that is used at many of the top fortune 50 businesses to help them manage and get instant answers on the most common security and systems management questions they face in mere seconds!
I thought I’d start sharing some how-to articles related to the product. I’m still learning myself so I will share as I learn. For this first article, I thought I’d start slightly after the beginning. I’m sure anyone reading this has gotten the full intro and some basic training from their assigned Technical Account Managers. And if you have any questions, the TAMs are always listening and willing to help!
Now, for this first article I want to tackle a problem that comes up all too often when distributing software that might be used by the Tanium client itself. In the example below, I will teach you how to distribute the Sysinternals tool called SigCheck. To do this you will need to produce a few pieces of content:
1. “Has SigCheck” is a sensor that checks your endpoints and determines if you have the utility already installed or not. This sensor allows you to ask the following question: Get Has SigCheck from all machines. This question needs to return a Yes or No depending on the presence of the sigcheck.exe utility.
2. “Distribute SigCheck” is a package that pulls the SigCheck.zip from the Sysinternals website, it also pulls an unzip utility from our Tanium content site and since we’re building this on the Community website, pulls the distributesigcheck.vbs from the Tanium Community website.
The logical process once our content is built is as follows:
1. Ask the question “Get Has SigCheck from all machines”
2. Select the No answer and deploy an action, choose the “Distribute SigCheck” package and you’re execute.
“Has SigCheck” Sensor
Of course this all starts with the basic “has” sensor. To build this we’ll be writing an extremely simple sensor that will check the existence of our file within the Tools directory of our Tanium Client. This vbscript will look a little something like this:
‘======================================== ’ Has SigCheck Utility ’======================================== ’ This sensor will report on the existence of the sigcheck file. Option Explicit Dim objFSO Dim strTaniumToolsDir, strFile Set objFSO = CreateObject(“Scripting.FileSystemObject”) strFile = “sigcheck.exe” strTaniumToolsDir = GetTaniumDir(“Tools\Sigcheck”) If objFSO.FileExists(strTaniumToolsDir&strFile) Then WScript.Echo “Yes” Else WScript.Echo “No” End If Function GetTaniumDir(strSubDir) ‘GetTaniumDir with GeneratePath, works in x64 or x32 ‘looks for a valid Path value Dim objShell Dim keyNativePath, keyWoWPath, strPath Set objShell = CreateObject(“WScript.Shell”) keyNativePath = “HKLM\Software\Tanium\Tanium Client” keyWoWPath = “HKLM\Software\Wow6432Node\Tanium\Tanium Client” ’ first check the Software key (valid for 32-bit machines, or 64-bit machines in 32-bit mode) On Error Resume Next strPath = objShell.RegRead(keyNativePath&“\Path”) On Error Goto 0 If strPath = "“ Then ’ Could not find 32-bit mode path, checking Wow6432Node On Error Resume Next strPath = objShell.RegRead(keyWoWPath&”\Path“) On Error Goto 0 End If If Not strPath = ”“ Then If strSubDir <> ”“ Then strSubDir = ”" & strSubDir End If Dim fso Set fso = WScript.CreateObject(“Scripting.Filesystemobject”) If fso.FolderExists(strPath) Then If Not fso.FolderExists(strPath & strSubDir) Then ’’Need to loop through strSubDir and create all sub directories GeneratePath strPath & strSubDir, fso End If GetTaniumDir = strPath & strSubDir & “" Else ’ Specified Path doesn’t exist on the filesystem WScript.Echo ”Error: “ & strPath & ” does not exist on the filesystem“ GetTaniumDir = False End If Else WScript.Echo ”Error: Cannot find Tanium Client path in Registry" GetTaniumDir = False End If End Function ’GetTaniumDir Function GeneratePath(pFolderPath, fso) GeneratePath = False If Not fso.FolderExists(pFolderPath) Then If GeneratePath(fso.GetParentFolderName(pFolderPath), fso) Then GeneratePath = True Call fso.CreateFolder(pFolderPath) End If Else GeneratePath = True End If End Function ’GeneratePath
Notice that I have copied code from existing sensors, namely the GetTaniumDir function (also requires GeneratePath and RegKeyExists) which reads the registry to determine where our client is installed. Providing an argument will append that to the end of the Tanium directory that was read. The new community will soon have the feature to add reusable code blocks like this with a simple checkbox. But until then, simply copy-paste the functions needed from other code.
“Distribute SigCheck” Package
The distribution package has multiple components that are a bit complicated when combined together. I will boil down each component and help you build this package. The Tanium Client will automatically download all files related to the package for us… they’ll all be sitting in the working directory of the command line we specify. Typically that is Tanium Client\Downloads\Action_XXXX. Knowing that, let’s look at the overall logic we’ll be using:
1. Unzip the SigCheck.zip file
2. Get the Tanium client directory using the same reusable code we added to the sensor.
3. Copy the SigCheck.exe into the Tools directory under the Tanium Client directory.
4. Agree to the Sysinternals EULA by indicating agreement within the Registry. (this is required or the SigCheck utility will hang every time waiting for user input which will never come since you’re running as SYSTEM on the endpoint).
Steps 1, 2, and 3: Unzip SigCheck.zip into Tools Directory
To unzip our utility we acquired from Microsoft, we’ll need to use a command line unzip utility. In the official content, we often use 7za.exe. It is an extremly small utility we will add to our package with the following details:
Check for Updates: Never
The following reusable code block will be used to unzip our utility zip file:
Sub Unzip(strZipFilePath, strTargetDir) ’ Takes full file path to zip file, path to target directory ’ will extract to target directory as a subdirectory ’ overwriting anything in the subdirectory and showing no UI. Dim objShell, objFSO, strCurrentDir, strZipUtil Dim strTempDir, strZipFileName, strCommand, intResult Set objShell = WScript.CreateObject("WScript.Shell") Set objFSO = CreateObject("Scripting.FileSystemObject") strCurrentDir = Replace(WScript.ScriptFullName, WScript.ScriptName, "") If Not objFSO.FileExists(strZipFilePath) Then WScript.Echo "Cannot continue - " & strZipFilePath & " does not exist" Exit Sub End If strZipUtil = strCurrentDir & "7za.exe" If Not objFSO.FileExists(strZipUtil) Then WScript.Echo "Cannot continue - " & strZipUtil & " does not exist" Exit Sub End If If Not objFSO.FolderExists(strTargetDir) Then objFSO.CreateFolder(strTargetDir) End If strZipFileName = objFSO.GetFile(strZipFilePath).Name ' remove .zip from end" If InStr(LCase(strZipFileName),".zip") = Len(strZipFileName) - 3 Then ' ends in zip strZipFileName = Left(strZipFileName,Len(strZipFileName) - 4) End If strTempDir = strCurrentDir & strZipFileName WScript.Echo "Unzipping to " & strTempDir If Not objFSO.FolderExists(strTempDir) Then objFSO.CreateFolder strTempDir End If strCommand = Chr(34) & strZipUtil & Chr(34) & " x -y -o" & Chr(34) & strTempDir & Chr(34) & " " & Chr(34) & strZipFilePath & Chr(34) WScript.Echo "running unzip:" WScript.Echo " command: " & strCommand objShell.Run strCommand, 0, True If objFSO.FolderExists(strTempDir) Then WScript.Echo "Copying " & strTempDir & " to " & strTargetDir On Error Resume Next intResult = objFSO.CopyFolder(strTempDir,strTargetDir,True) ' overwrite On Error Goto 0 If intResult = 0 Then WScript.Echo "Success" Else WScript.Echo "Failure - result is " & intResult End If End If End Sub ’Unzip
This function allows us to unzip with a single command: Unzip Source-Zip-File Destination-Folder
We’ll accomplish steps 1–3 in one fail swoop after setting up a few variables for use. We need the full path of our zip file as well as the destination folder to extract into. To get our current working directory where the zip file was downloaded for us, we can use the filesystem object as follows:
Set objShell = CreateObject(“WScript.shell”) strCurrentDir = objShell.CurrentDirectory To get the destination folder, we’ll reuse the technique we learned from the sensor above to get the tanium client directory: strTaniumDir = GetTaniumDir(“Tools”) Now accomplishing steps 1 through 3 is as easy as: Unzip strCurrentDir&“\SigCheck.zip”, strTaniumDir
Step 4: Agree to Sysinternals EULA
Before we can execute the SigCheck utility, Sysinternals requires you to agree to their EULA. When you execute it for the first time a popup box appears with the EULA with an Agree or Cancel button. After some research I learned the EULA agreement flag is stored in the users profile inside of the registry. (HKEY_CURRENT_USER\Software\Sysinternals\SigCheck)
Before the Tanium Client can use this utility, the SYSTEM user must agree to the EULA. This presents a problem since SYSTEM doesn’t have a UI nor are we sitting at the thousands of machines we want to run the utility on. Thus we will need to indicate agreement by adding the “EulaAccepted” registry value. We’ll do that with the following code:
Dim WshShell Set WshShell = WScript.CreateObject(“WScript.Shell”) WshShell.RegWrite “HKEY_CURRENT_USER\Software\Sysinternals\SigCheck\EulaAccepted”, “1”, “REG_DWORD” set WshShell = Nothing
You can download the “Has SigCheck” sensor from the Tanium Community website at: https://community.tanium.com/repo/sensor/788
I’m still building the packages feature of our Community so I’ll follow up later with the package download link.
Bonus… Distribute SigCheck Automatically
All done! To review, we built a sensor to check the existance of our SigCheck utility and built a package to distribute it to our computers. The only problem now is we may want to have distribution occur anytime an endpoint comes online and doesn’t have the utliity. To accomplish this we’ll need to ask our new sensor question and deploy our new package with the reissue option specified. The following is a screen shot of what this looks like: