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:
Filename: 7za.exe
URI: https://community.tanium.com/files/7za.exe
SHA–256: c136b1467d669a725478a6110ebaaab3cb88a3d389dfa688e06173c066b76fcf
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
Downloads
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: