Instant Indicators of Compromise (IIOC)s are a feature within the NetWitness Endpoint (NWE) platform that looks for defined behavioral traits such as processes execution, memory anomalies, and network activity. By default, NWE is packaged with hundreds of built-in IIOCs that are helpful for identifying malware and hunting for malicious activity. The topic of this article is relevant because new attacker techniques are constantly being discovered which can potentially be accounted for through the development of new IIOCs. In addition, individual organizations can devise active defense measures specific to their environment for the purpose of identifying potentially anomalous behavior through IIOC customization. Before diving into the details of developing IIOCs let’s review NWE documentation on the subject.
Warning: The database, in which IIOCs are dependent on, is subject to incur changes with each version of NWE which may affect custom created IIOCs. Contents within this article are based off the current version of NWE: 4.4.0.9.
The user guide provides a plethora of useful information on the subject of IIOCs and this article assumes that the reader has a baseline knowledge of attributes such as IIOC level, type, and persistent IIOCs. However, specifically regarding the creation and editing of IIOCs, there is limited information that is documented. Figure 1 is an excerpt from the NWE manual providing steps for IIOC creation.
Figure 1: Excerpt from NWE User Guide
Reviewing and modifying existing IIOC queries will often times allow users to achieve the desired behavior. It is also a great way to enhance the user’s understanding of important database tables, which will be covered more in the query section. However, there is much more that can be said on the topic of IIOC creation. Expounding on these recommendations, as well as the entire “Edit and Create IIOC” section in the user guide, building a new IIOC can be broken down into three major steps.
IIOC Creation Steps:
Before we delve into the specifics of IIOC queries, let's begin with the basics. A new IIOC can be created in the IIOC window either by clicking the "New" button in the InstantIOC sub-window or by right-clicking on a specific entry in the IIOC table and then choosing the clone option. Both of these options are circled in red in Figure 2. As the name suggests, cloning an IIOC entry will copy over most of the attributes of the designated item such as the level, type, and query. In both cases, the user must click save in the InstantIOC sub-window for any changes to remain.
Figure 2: IIOC Entry Creation Options
When creating a new IIOC make sure that the Active checkbox is not marked until the entry has been finalized. This will prevent the placeholder from executing on the server until the corresponding query has been tested and verified. The IIOC level assigned to a new entry should reflect both its severity as well as the query fidelity. For example, a query that is prone to a high number of false positives would be better suited as a higher level in order to avoid inflated IIOC scores.
There are four unique IIOC types that can be chosen from in the Type drop-down menu: Machine, Module, Event, and Network. The distinction between these types will be further elaborated on in the next section. Also, be aware that IIOCs are platform specific, so the user must ensure that the correct operating system is chosen for the specified IIOC. Changing the OS platform can be done by modifying the ‘OS Type’ field and will cause the IIOC to appear in its matching platform table.
Figure 3: IIOC Platform Tables
At this point, it is also notable that all user-defined IIOCs will automatically be given a non-persistent attribute. This means that any modules or machines associated with the matching conditions of the IIOC will only remain associated as long as the corresponding values that matched are in the database. Non-persistent behavior is potentially problematic for event tracking and scan data, which utilizes ephemeral datasets. In order to bypass this potential pitfall, the persistent field can be updated for the targeted IIOC as seen in the SQL query below.
Figure 4: Update IIOC Persistent Field
Once a placeholder entry for an IIOC has been created, it can then be altered to achieve the desired behavior by modifying the query. IIOCs are built primarily through the use of SQL select statements. If the reader does not have a fundamental knowledge of the SQL language then a review of SQL tutorials such as W3Schools[1] is recommended.
More complex IIOCs can make use of additional SQL features such as temporary tables, unions, nested queries, aggregator functions, etc. However, a basic IIOC select query can be broken down to three major components: fields, tables, and conditions.
Figure 5: Query Sections
In order to develop and test queries for IIOCs, it is highly advantageous for the user to have access to database administrative software. An example of such a tool is SQL Management Studio, which can be installed alongside the Microsoft SQL Server instance on the NWE server. There are many alternative options to choose from such as heidiSQL and DBeaver, if the user wishes to connect from a client system or a non-Windows machine. These tools can also be used to provide further visibility into the database structure and to perform direct database queries for analysis purposes.
As shown in Figure 5, IIOCs require specific fields or columns, to be selected in order to properly reference the required data in the interface. Depending on the IIOC type chosen, these fields will slightly vary, but there will always be one or more primary keys needed from tables such as machines and machinemodulepaths. Unlike the other types, machine IIOCs only require the primary key of the ‘machines’ table. Nevertheless, the NWE server still expects two returned values. In these instances, a null value can be used as the second selected field.
Furthermore, the operating system platform will affect the keys that are selected in the IIOCs. Linux does not currently support event or network tracking, and the associated tables do not exist in the NWE database. Selected keys are expected to be in the order shown in Table 1 per entry from top to bottom.
Type | Windows | OSX | Linux |
Module | PK_Machines PK_MachineModulePaths | PK_Machines PK_MacMachineModulePaths | Machines PK_LinuxMachineModulePaths |
Event | PK_Machines PK_MachineModulePaths PK_WinTrackingEvents | PK_Machines PK_MacMachineModulePaths PK_mocMacNetAddresses | N/A |
Network | PK_Machines PK_MachineModulePaths PK_mocNetAddresses | PK_Machines PK_MacMachineModulePaths PK_mocMacNetAddresses | N/A |
Machine | PK_Machines NULL | PK_Machine NULL | PK_Machine NULL |
Table 1: Required Fields by Platform
Keys selected can be either the primary keys shown in the table above or their associated foreign keys. Premade IIOC queries typically alias any selection of primary keys (PK_*) to match the prefix used for foreign keys (FK_*). However, this selection was probably chosen for consistency and does not affect the results of the query.
Moving on to the next section of the IIOC query, we will need to determine which tables are selected or joined. As shown in the previous section, there are required keys based on the IIOC type. Therefore, the selected tables for a valid IIOC query must reference these keys. The tables that are needed will also be dependent on the fields that are utilized for the IIOC conditions, which will be covered in the next section. While there are hundreds of tables in the NWE database, knowledge of a few of them will help to facilitate basic IIOC development.
Since the NWE database currently utilizes a relational database, many important attributes of various objects such as filenames, launch arguments, paths, etc. are stored within different tables. A SQL join is required when queries utilize fields from multiple tables. In most cases when joining a foreign key to a primary key, an “inner join” can be used. However, if the IIOC writer must join tables on a different data point, then an alternative join type should be considered. A similar approach should be taken for any foreign keys that do not have the “Not Null” property.
Figure 6: Tables Used in IIOC Query
As with the selected keys in the Required Fields section, in many cases, there are separate tables based on the platform being queried. In these instances, the table name will be similar to its Windows counterpart with a special prefix denoting the platform. For example, the MachineModulePaths table that contains module information on a machine specific basis is called MacMachineModulePaths for OSX and LinuxMachineModulePaths for Linux. Table 2 contains the table names in the NWE database that are most useful while creating IIOCs. Most of these tables are platform specific, however, a few correspond to all operating systems. The next section will provide additional context for some of the Windows tables and their associated fields.
Windows | MachineModulePaths | mocAutoruns | mocDrivers | mocImageHooks |
mocKernelHooks | mocLoadedFiles | mocNetAddresses | mocProcessDlls | |
mocProcesses | mocServices | mocThreads | mocWindowsHooks | |
mocWindowsTasks | WinTrackingEvents_P0 | WinTrackingEvents_P1 | WinTrackingEventsCache | |
Mac | MacMachineModulePaths | mocMacAutoruns | mocMacDaemons | mocMacKexts |
mocMacLoginItems | mocMacNetAddresses | mocMacProcessDlls | mocMacProcesses | |
mocMacTasks | mocMacTrackingEvents | |||
Linux | LinuxMachineModulePaths | mocLinuxAutoruns | mocLinuxCrons | mocLinuxDrivers |
mocLinuxProcessDlls | mocLinuxProcesses | mocLinuxServices | mocLinuxSystemdServices | |
mocLinuxBashHistory | ||||
ALL | FileNames | Paths | LaunchArguments | Machines |
Domains |
Table 2: Useful Tables for IIOC Creation
The final portion of the IIOC query pertains to the conditions that must be met in order to return valid results. In other words, it is the part of the query that defines what the IIOC is attempting to detect. For a standard SQL select IIOC this logic is contained within the where clause of the statement at the end of the query. In this segment, we will be going further in depth into the relevant database tables and covering the most pertinent fields for IIOC conditions.
To assist with elaborating on database details, this section contains simple diagrams to illustrate the relationship between the various tables and their fields. These schema diagrams, which are very condensed, are not meant to include every relevant field that the tables describe. Additionally, for the sake of brevity, these cover the Windows versions. However, a similar pattern applies to the non-Windows operating systems when applicable.
Most IIOC queries will make use of the MachineModulePaths table to some degree, as it acts as an intersection between many of the other tables used by the NWE database. For this reason, it makes for a great starting point for our database examination.
Figure 7: Module Tables
MachineModulePaths contains keys to tables such as the Paths, FileNames, and UserNames referenced by FK_FileNames, FK_Paths, and FK_UserNames__FileOwner. These keys point to tables that primarily contain what their table name describes (e.g. filenames, usernames, paths). Fields in these ancillary tables are generally valuable for filtering, regardless of IIOC type and are frequently referenced by other database tables including the ones for alternate OS platforms. The query in Figure 8 is an example of a SQL select statement that utilizes these fields by joining their associated tables with machinemodulepaths.
Figure 8: Basic Filters
At its core, MachineModulePaths contains aspects of modules that apply on a per machine basis. This includes the various tracked behaviors, associated autoruns, and network activity. Network related fields correspond to general network behavior, and not comprehensive network tracking which is stored in a different table. Table 3 provides a trimmed list of fields from the MachineModulePaths that can be potentially useful for IIOC filtering.
Field Name | Date Type | Field Name | Data Type |
BehaviorFileReadDocument | bit | BehaviorFileRenameToExecutable | bit |
BehaviorFileWriteExecutable | bit | BehaviorProcessCreateProcess | bit |
BehaviorProcessCreateRemoteThread | bit | DaysSinceCreation | int |
FileAccessDenied | bit | FileADS | bit |
FileAttributes | int | FileAutoStart | bit |
FileAutoStartWinsockProviders | bit | FileEncrypted | bit |
FileHiddenAttribute | bit | FileHiddenDifferentialView | bit |
FilenameUTCTimeAccessed | datetime2 | FilenameUTCTimeCreated | datetime2 |
FilenameUTCTimeModified | datetime2 | MarkedAsDeleted | bit |
NetworkAccessNetwork | bit | NetworkListen | bit |
ProcessAccessDenied | bit | ProcessFirewallAuthorized | bit |
ProcessTopLevelWindowHidden | bit | RecordUTCTimeModified | datetime2 |
UserModulePrivateMemory | bit |
|
|
Table 3: MachineModulePaths Fields
MachineModulePaths also has a reference to the Modules table which contains more information about the executable. Unlike MachineModulePaths, the Modules table stores data about an executable that is immutable from machine to machine. This data includes the cryptographic hashes, executable header values, entropy, etc. Similar to the table provided for MachineModulePaths, Table 4 lists useful fields found within the Modules table.
Field Name | Date Type | Field Name | Data Type |
DaysSinceCompilation | int | Description | nvarchar |
Entropy | real | HashMD5 | binary |
HashSHA1 | binary | HashSHA256 | binary |
MarkedAsDeleted | bit | ModulePacked | bit |
ModulePE32 | bit | ModulePE64 | bit |
ModuleTypeDLL | bit | ModuleTypeEXE | bit |
ModuleVersionInfoPresent | bit | NameImportedDLLs | nvarchar |
NumberImportedDLL | int | PEMachine | int |
PESizeOfImage | int | PEUTCTimeDateStamp | datetime2 |
SectionsNames | nvarchar | SignatureUTCTimeStamp | datetime2 |
Size | bigint |
|
|
Table 4: Modules Fields
Lastly, the Machines table is comprised of machine attributes that a specific module was observed executing on. This includes data such as the machine name, associated IP address, and OS version. All endpoints in NWE are listed in this table regardless of OS platform.
Next, is the event tracking table, which for Windows endpoints are represented in the WinTrackingEvents* tables. While the diagram in Figure 9 only shows the WinTrackingEventsCache table, the Windows event tracking actually utilizes two additional tables for permanent event storage (WinTrackingEvents_P0 and WinTrackingEvents_P1). Since WinTrackingEventCache contains only the most recent events it is the most efficient of these tables for IIOCs. However, with the populated data constantly migrating to another table, any IIOC that utilizes it will need to be set to persistent in order to be effective.
Figure 9: WinTrackingEventCache Table
Tracking event tables contain a reference to a secondary table called LaunchArguments, which is also used by several other tables. An IIOC will only need to join this table with WinTrackingEvents* for the source command-line arguments, as many of the target process attributes are already stored as varchar fields in the table. Booleans for various event behaviors are also extremely useful for a filtering event in these tables.
Field Name | Date Type | Field Name | Data Type |
BehaviorFileDeleteExecutable | bit | BehaviorFileOpenLogicalDrive | bit |
BehaviorFileOpenPhysicalDrive | bit | BehaviorFileReadDocument | bit |
BehaviorFileRenameToExecutable | bit | BehaviorFileSelfDeleteExecutable | bit |
BehaviorFileUnquanrantine | bit | BehaviorFileWriteExecutable | bit |
BehaviorProcessAllocateRemoteMemory | bit | BehaviorProcessCreateProcess | bit |
BehaviorProcessCreateRemoteThread | bit | BehaviorProcessOpenBrowserProcess | bit |
BehaviorProcessOpenOSProcess | bit | BehaviorProcessOpenProcess | bit |
BehaviorRegistryModifyFirewallPolicy | bit | BehaviorRegistryModifyRunKey | bit |
EventType | int | EventUTCTime | datetime2 |
FileName_Target | nvarchar | HashSHA256_Target | binary |
LaunchArguments_Target | nvarchar | Path_Target | nvarchar |
Pid | int |
|
|
Table 5: WinEventTracking Fields
The table used to store network tracking data for Windows systems is called MocNetAddresses. This table tracks unique instances of network connections and their associated execution environment such as the machine, module, and launch arguments. Unlike event tracking data, this table keeps account of the module which initiated the network request (FK_MachineModulePaths) as well as the process it resides within (*__Process). The distinction is useful in cases where a loaded library is responsible for a network request, such as a service DLL in svchost.exe. There is also a secondary table tracking the domain name of the associated request called Domains.
Figure 10: MocNetAddresses Related Tables
In addition to the domain, the IP and Port fields are also useful filters for the MocNetAddresses table. Network sessions with an RFC 1918 destination address can be disregarded using the NonRoutable field. A trimmed list of MocNetAddresses fields that can be used for IIOC conditions is provided in Table 6.
Field Name | Date Type | Field Name | Data Type |
BurstCount | int | BurstIntervalDeviation | real |
BurstIntervalMean | real | ConnectCount | int |
EProcess | bigint | EThread | bigint |
FailConnectCount | int | FirstConnectionUTC | datetime2 |
IP | nvarchar | IPIsV4 | bit |
IPIsV6 | bit | LastConnectionUTC | datetime2 |
NonRoutable | bit | OffHourNetworkTraffic | bit |
Port | int | ProcessId | int |
TotalReceived | bigint | TotalSent | bigint |
UserAgent | varchar |
|
|
Table 6: MocNetAddress Fields
Finally, we will briefly cover scan data found inside the NWE database. These tables include additional information concerning autostarts, services or crons, memory anomalies, etc. Similarly, to the module and tracking data tables, the presence of scan-related tables are OS platform specific. For example, memory anomaly tables are currently only used by Windows systems and tables such as bash history only apply to Linux endpoints.
Windows | mocAutoruns | mocDrivers | mocImageHooks | mocKernelHooks |
mocProcesses | mocLoadedFiles | mocNetAddresses | mocProcessDlls | |
mocWindowsTasks | mocServices | mocThreads | mocWindowsHooks | |
Mac | mocMacAutoruns | mocMacDaemons | mocMacLoginItems | mocMacKexts |
mocMacProcessDlls | mocMacProcesses | mocMacTasks | ||
Linux | mocLinuxAutoruns | mocLinuxCrons | mocLinuxDrivers | mocLinuxSystemdServices |
mocLinuxProcessDlls | mocLinuxProcesses | mocLinuxServices | mocLinuxBashHistory |
Table 7: Scan Data Tables by Platform
Scan data tables can also be considered ephemeral datasets that are replaced upon a new scan. Thus, persistent IIOCs should be used when referencing these tables to avoid missing IIOC matches, especially in environments where the scanning schedule is set to a high frequency of occurrence.
When attempting to determine the table and column associated with known fields in the NWE interface, it can be helpful to query the information_schema database. For instance, consider a circumstance where a user needs to create an IIOC based on a unique section name string in an executable, but does not know the corresponding column name within the database. In the UI, this field is located in the properties window of a specific module and its field name is called “Sections Names”. By querying the columns table and reviewing the results, it can be determined that a similar fieldname is located in the modules tables.
Figure 11: Information_Schema Query
In most cases, the field name in the UI will be almost identical to its corresponding column name within the database. Further filtering or sorting by the data type and expected table name can also be useful to identify the desired column when a large number of results are returned.
IIOC validation should initially be performed as part of crafting the query. Check for any errors and that the expected number of fields and values are returned when executing the query being tested. Once a new IIOC entry has been created, and the query edited, refresh the window and check for an updated “Last executed” field. Also, make sure that the Active check box in the InstantIOC sub-window is marked. Note that it may take a few minutes for the IIOCs to be executed by the server from the time that the new entry was set to active. To quickly identify any custom IIOCs that have been created, use the column filter on the “User Defined” field in the IIOC table.
Figure 12: IIOC Table Filter on “User Defined” Field
If any resulting errors occurred after the IIOCs have been executed by the database, then the entire row for the failed IIOC will be italicized. There will also be an error message located in the “Error Message” field to provide additional context as to why it occurred. In the example in Figure 13, the highlighted IIOC entry called “Test IIOC” returned an error for an invalid column name. In this case, the first selected field had a minor typo, and should have been referenced as “fk_machines”.
Figure 13: IIOC Table with Error Returned
Analyzing data directly from the back-end database is definitely outside of the scope of this article, however, a useful tip for IIOC development is to include a “human readable” query alongside any custom developed IIOCs. Doing so will allow the analyst to review all the relevant data that is related to the query instead of just seeing the machines and modules associated with the IIOC in the interface. In the example shown in Figure 14, there is an additional query that is commented out. Instead of selecting the keys listed in the Required Fields section, this query selects fields that provide additional context to the analyst typically based on the fields in the IIOC condition.
Figure 14: IIOC with Human Readable Query
Since the second query has been commented out, it does not affect the IIOC in any way. However, it does provide the analyst with the means to quickly gain additional information regarding the related events. Executing the query, as shown in Figure 15, provides previously unseen information such as source and target arguments and the event time. This information would normally only be available on a per machine basis in the interface. Reviewing data in this manner is especially useful when analyzing queries that return a high number of results and potential false positives.
Figure 15: Database Query Results
The following section covers examples of IIOCs that are currently, as of version 4.4.0.9, not included by default. Each example is based on potentially anomalous behavior or observed threat actor techniques.
There are many instances where a modified filename could be an indicator of evasive execution on a machine. In other words, it could be evidence of an attempt to avoid detection by antivirus or monitoring systems. The following IIOCs compare module attributes with the associated filename for anomalies based on observed techniques.
Copied Shell
Windows accessibility features have been a known target of replacement to regain access to a system by both malicious actors and system administrators for a long time. Furthermore, actors occasionally rename shells and scripting hosts to bypass security monitoring tools. For these reasons, the following IIOC looks for instances of the Windows shells and scripting hosts that have been renamed. It is also looking for instances where the trusted install user (“NT SERVICE\TrustedInstaller”) is no longer the owner of one of these files.
Figure 16: Copied Windows Shell
Psexesvc
Currently, there is a built-in IIOC called “Run Remote Execution Tool” that looks for instances of Psexec execution. However, a common issue in endpoint monitoring is the lack of full visibility, and consequently the machine running the client program is not always being observed. Therefore, when looking for evidence of potential lateral movement, it is important to monitor for suspect behavior of the target machine as well.
Psexec is known to create a service on the target machine using the executable “psexesvc.exe”. It also provides the ability for the user to change the name of the service, and subsequently the name of the executable to a different value. Similar to the previous example, this change in name does not affect the file description of the executable. Thus, the IIOC author can specifically look for occurrences of this name modification. The creator of this IIOC could also choose to include instances of the normal psexec service filename by omitting the second condition, but a separate IIOC with a higher IIOC level would be more appropriate.
Figure 17: Renamed PSexesvc Process
Malware and malicious actors often utilize proxied execution, or launchers, for their persistence mechanisms in order to bypass security monitoring tools. PowerShell is a prime example of a program that facilitates this behavior in Windows. Executing this program upon startup provides an attacker with a wealth of functionality within a seemingly legitimate executable. The IIOC shown in Figure 18 identifies instances of PowerShell that are associated with a persistence mechanism on an individual machine.
Figure 18: PowerShell Autostart
Typically, legitimate instances of this functionality created by system administers will simply reference a PowerShell script instead of the Powershell module itself. Nonetheless, analysts should still be cognizant of potentially valid instances. This is demonstrated in the next query in Figure 19, which contains additional conditions that the filters autostart programs or scheduled tasks that match the given keyword.
Figure 19: PowerShell Autoruns and Scheduled Tasks
This new query utilizes a SQL union to combine the results of two select statements. Instead of initially selecting from the “machinemodulepaths” table and filtering from the rows, this query uses two tables that contain additional startup program information. With these additional data points, the IIOC author can filter on attributes such as task name and registry path. An example of the latter would be a unique run key name. Since the second IIOC utilize tables from scan data, it would need to be set to persistent.
Figure 20: Floating Module in PowerShell in UI
Another attribute of a process that may be indicative of a malicious launcher is the presence of injected code. Executable files that circumvent the Windows image loader, otherwise known as reflective loading, as well as libraries that have been unreferenced from PEB ldr_data lists will show up in the NWE UI as “Floating Modules.” While there is already an IIOC looking for the presence of these modules, augmenting the existing query by including known launcher processes such as PowerShell can produce inherently more suspicious results. By increasing the specificity of the query, we now have an additional IIOC that is a higher indicator of malicious activity.
Figure 20: Floating Module in PowerShell Query
There are numerous modules other than PowerShell that can be utilized to initiate execution on Windows systems such as mshta, rundll32, regsvr32, installutil, etc. Similar IIOCs for all of these modules can be useful for monitoring evasive execution or persistence. However, in each case, there will be filtering required that is specific to an individual organization.
Hopefully this article has provided insight into custom IIOC creation. It has covered the key components of basic IIOCs and provided steps for their creation. Additionally, it has discussed the most useful backend database tables and fields used for building IIOC queries. Lastly, it has provided examples that can be used to identify real-world attacker techniques.
[1] https://www.w3schools.com/sql/
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.