Archive

Tag Archives: malware

This posting is based on the theory that if you poke a sleeping bear hard enough, it may get very exciting for a short period of time. So this is me Poking the Nessus Bear.

Tenable talks about the adaptability and customisation that is available for customers that use the Nessus product. The availability of all their plugins to be easily readable by end users apparently is enough to allow their customers to create their own plugins for their specific environment requirements. In the case that customers need additional guidance on the NASL programming language, we are provided the NASL2 reference guide that was” recently” written in 2009. I am periodically disappointed when I get the urge to actually extend my Nessus scanner with a custom script and I go searching for updated references and documented samples in the hope that Tenable was finally helping the customers by providing real support for writing custom plugins.

  • Where is the documentation for the common functions/API’s used across plugins that have existed for a long period (e.g. smb*.inc)?
  • Where is the community forum dedicated to discussing NASL coding, and sample sharing?
  • Where is the community plugin repository so we can effectively share plugins that may be useful, but are not included in the standard product?
  • Where is the real capability to produce output that can be ingested as input into other scripts and programs (aka Unix PIPEs style)?
  • Where are the blog posts that walk through example plugin’s and what each part of the NASL script does?

Am I being antagonistic towards Tenable with the introduction to this blog. Yes, but remember I am trying to poke the Nessus Bear in the hope things may get exciting.

If you are a customer and have the same frustrations then let Tenable know. Yes I know they are a business, and they will focus on what is important to their customers. However, they need to know its important. One thought is if you agree some of my frustrations then you could log a support call with the subject (exactly) as “Poking the Nessus Bear”, and add any personal comments in the body. By using the same subject line, then Tenable can easily prioritise the call as a non-operational impacting call, but can also easily gather statistics on the numbers. The last thing I would advocate is causing a disruption to Tenable’s ability to support its customers.

Its very easy to post a blog entry and complain about what’s wrong without offering anything back to try improve the situation. So, in the hope to increase the NASL knowledge in the community I will attempt to document one of my custom NASL scripts in a way that may be useful as a reference to those who wish to try their hand at NASL.

The NASL script that I am going to use was created to read the registry of the scanned computers and print out the Services that are configured to run. This was to make it easier to check suspected infected computers to see if an unknown Service was configured during an infection event. Due to write permissions, you will find that many malware if they configure a new service will not try install itself in the %SYSTEMROOT%. Therefore, in the output of the script I separate the services into those services loaded outside of %SYSTEMROOT% and those installed in %SYSTEMROOT%.

Onto the meat of the script. I will skip over quickly the preamble of the script as this is one part that is defined by the available documentation on NASL writing.
#
#

include(“compat.inc”);

if(description)
{
 script_id(95001);
 script_version (“$Revision: 1.40 $”);

 script_name(english:”Malware – Microsoft Windows SMB Service Enumeration”);
 script_set_attribute(attribute:”synopsis”, value:”It is possible to enumerate remote services.” );
 script_set_attribute(attribute:”description”, value: “This plugin implements the SvcOpenSCManager() and SvcEnumServices() calls to obtain, using the SMB protocol, the list of active and inactive services of the remote host. An attacker may use this feature to gain better knowledge of the remote host.” );
 script_set_attribute(attribute:”solution”, value: “To prevent the listing of the services for being obtained, you should either have tight login restrictions, so that only trusted users can access your host, and/or you should filter incoming traffic to this port.” );
 script_set_attribute(attribute:”cvss_vector”, value: “CVSS2#AV:N/AC:H/Au:N/C:P/I:N/A:N” );

 script_set_attribute(attribute:”plugin_publication_date”, value: “2011/05/26”);
 script_cvs_date(“$Date: 2011/05/26 18:32:20 $”);
script_set_attribute(attribute:”plugin_type”, value:”local”);
script_end_attributes();

 script_summary(english:”Enumerates the list of remote services”);
 script_category(ACT_GATHER_INFO);
 script_copyright(english:”This script is Copyright (C) 2000-2011 Tenable Network Security, Inc.”);
 script_family(english:”Windows”);
 script_dependencies(“netbios_name_get.nasl”, “smb_login.nasl”, “smb_registry_access.nasl”);
 script_require_keys(“SMB/transport”, “SMB/name”, “SMB/login”, “SMB/password”, “SMB/registry_access”);
 script_require_ports(139, 445);
 exit(0);
}

Some quick points on the preamble. Unlike what is documented, instead of using a script_id in the 50000 range I have added one above 95000. This is a good indication of how out of date the NASL documentation is. There are more than 50000 Tenable supplied plug-ins now. It would be nice to see the script_id keyspace to be increased by a power of 10. Then we can have something like 0-500,000 reserved for Tenable, 500,000-900,000 for community shared script_id’s, and 900,000+ private use only.

Some of the other attributes I did not change or update from the plug-in script I used as a base. In regards to the script_require_keys, this sets the required KB items to run in optimized mode. The problem is there is no overarching description on what the KnowledgeBase is, how it is expected to be used, and what are the naming conventions. If there are standard KB keys used, then when writing new scripts we can make sure we don’t pollute the KB namespace with similar/duplicate keys. The more the community shares NASL scripts, the bigger the issue this would be. This leads to another question. What exactly is optimized mode?

All other parts are documented in the NASL2 reference.

In the next section of my script I include smb_func.inc. This is a file that references a number of other files that define useful SMB protocol functions. These SMB functions are used for checks, and setting variables before starting the core of the script. Most of the functions are named so it is easy to understand what their purpose is. In order, my script will set the “port” variable, check if remote machine is Samba based, set the “name” variable to the SMB machine name, set the “login” and “password” variables and Windows domain to the “dom” variable. Most of the SMB functions used are actually defined in the “smb_internals.inc” file, which is included by “smb_func.inc”.

(NOTE: you will have to have a professional feed to have access to the *.inc function/api files I discuss in this post)

Interestingly, while the included SMB functions are loaded by including the “smb_func.inc” file, all the KB items that are used in the functions (e.g. SMB/domain) are set when “netbios_name_get.nasl” and “smb_login.nasl” are initially run by setting the script_dependencies in the preamble above.

include(“smb_func.inc”);

port = kb_smb_transport();
if(!port)port = 139;

# Does not work against Samba
smb = get_kb_item(“SMB/samba”);
if(smb)exit(0);

name = kb_smb_name();
if(!name)return(FALSE);

if(!get_port_state(port))return(FALSE);

login = kb_smb_login();
pass  = kb_smb_password();
if(!login)login = “”;
if(!pass) pass = “”;

dom = kb_smb_domain();

The next section of the script opens a socket to the tcp port that was set using  “port = kb_smb_transport();” the open_sock_tcp function is described in the NASL2 reference document. The “session_init” and “NetUseAdd” functions are defined when “smb_func.inc” is included in the script earlier. Specifically the “session_init” function is defined in the file “smb_internals.inc” and the “NetUseAdd” function is defined in “smb_net.inc”.The purpose of this section of the script is to establish a SMB session to the target host.

soc = open_sock_tcp(port);
if(!soc)exit(0);

session_init (socket:soc,hostname:name);
ret = NetUseAdd (login:login, password:pass, domain:dom, share:”IPC$”);
if (ret != 1)
{
 close (soc);
 exit (0);
}

In the next section of the script we establish a connecting to SC Manager so that we can pull down a list of ACTIVE services running. The list of active services is then recorded into an array called “active_list”.  The functions used to open a connection to the SC manager and then enumerate the service were defined when “smb_func.inc” was included. The “OpenSCManager” and “EnumServicesStatus” are specifically defined in “smb_svc.inc” file.

handle = OpenSCManager (access_mode:SC_MANAGER_ENUMERATE_SERVICE);
if (isnull (handle))
{
 NetUseDel();
 exit (0);
}

active_list = EnumServicesStatus (handle:handle, type:SERVICE_WIN32, state:SERVICE_ACTIVE);
CloseServiceHandle (handle:handle);

if (isnull (active_list))
  exit (1, “No services were detected.”);

This is the last bit of code used to prepare the main foreach loop that does most of the work. First we set up 4 variables that will be used later in the script. The “services” variable will be used at the end to hold the results we want printed out as a “security_note”. The variables “active_services” and “non_sys32_services” respectively will be used to hold services found in System32 directory and those outside. I should rename “active_services” as the name was set as part of the evolution of the script development and I did not get around to change it to be more reflective of its current purpose. Finally we have a variable “is_sys32_dir” that will be used in the foreach loop to determine if the service details have components outside the System32 directory.

In the second part of the following section of code we set a variable that is used to reference an open registry connection to the LOCAL_MACHINE hive of the remote machine. The “RegConnectRegistry” function was defined with the inclusion of “smb_func.inc” and its definition is specifically found in the “smb_reg.inc” file.

services = NULL;
active_services = NULL;
non_sys32_services = NULL;
is_sys32_dir = 0;

#Connect to the remote registry using the open SMB Session
hklm = RegConnectRegistry(hkey:HKEY_LOCAL_MACHINE);
if ( isnull(hklm) )
{
 NetUseDel();
 exit(0);
}

We are now at the core of the script were we loop across each ACTIVE service that was recorded in the array “active_list” earlier in the code. The variable “temp_services” will be used to hold output information in the loop that will be appended to either the “active_services” or “non_sys32_services” variables for final script output. We set the is_sys32_dir to zero at the start of each parse through the loop. The “GetService” function, which is defined in the file “smb_svc.inc”,  returns an array of information on a given service which is stored in the array “parse” for the script. We only use the first two elements of the returned array from “GetService”, with the first index (0) being the service name from the SC manager, and the second index (1) the returned service description.

The other variables are used for the registry lookups. The “regdll” and “Imagenm” variables are used to hold the returned values from the registry queries the script does, and the key1/2 and item1/2 define the specific registry keys and values that we want queried.

foreach elem (active_list)
{
 temp_services = NULL;
 is_sys32_dir = 0;
 parse = GetService (service:elem);
 regdll = NULL;
 Imagenm = NULL;
 temp_services = parse[1] + ” [ ” + parse[0] + ‘ ] ‘;
 key1 = “SYSTEM\CurrentControlSet\Services\” + parse[0] ;
 item1 = “ImagePath”;
 key2 = “SYSTEM\CurrentControlSet\Services\” + parse[0] +”\Parameters”;
 item2 = “ServiceDll”;

This is where we finally query the remote machine for the registry details for the active services. We open two of the registry keys as defined in key1 and key2, and then query for the respective values. The key registry functions “RegOpenKey” and “RegQueryValue” are defined in the file “smb_reg.inc”.

In the first registry query we are looking for the queried services ImagePath. This is the executable that holds the service code. If the ImagePath contains “ystem32” (i.e. System32 service),  then we set the “is_sys32_dir”. Similarly in the second registry query the active service is checked to see if there is an associated ServiceDll. If a ServiceDll is found, then it is checked to determine if the path of the DLL is within the System32 directory or not.

key_h = RegOpenKey(handle:hklm, key:key1, mode:MAXIMUM_ALLOWED);
if ( ! isnull(key_h) )
{
    Imagenm = RegQueryValue(handle:key_h, item:item1);
    if (!isnull (Imagenm))    temp_services += ‘\n\t’ + “ImagePath:” + Imagenm[1];
    if (“ystem32” >< Imagenm[1]) is_sys32_dir = 1;
    RegCloseKey (handle:key_h);
}

key_h = RegOpenKey(handle:hklm, key:key2, mode:MAXIMUM_ALLOWED);
if ( ! isnull(key_h) )
{
    regdll = RegQueryValue(handle:key_h, item:item2);
    if (!isnull (regdll)) temp_services += ‘\n\t’ + “ServiceDLL:” + regdll[1];
    # if imagename has not been set and regdll is in system32
    if ((‘ystem32’ >< regdll[1]) && !Imagenm[1])
            is_sys32_dir = 1;

    # Else if ImageName is set, and regdll not in system32 unset
    if ( !isnull(regdll[1]) && !(‘ystem32’ >< regdll[1]))
            is_sys32_dir = 0;
    RegCloseKey (handle:key_h);
}

This is the last part of the main foreach loop where we assign what we held in the variable “temp_services” to the variables “non_sys32_services” or “active_services” depending on if the “is_sys32_dir” was set or not. The reason we keep the services separate is so that we can print them out separately depending on their location.

I also have created two new KB items that will record that the service as being active and the service display_name. This is where it would be nice to have some guidance and structure around the KB namespace. I am sure as people write their own scripts and create KB’s, that referencing those KB’s in other scripts would be helpful.

temp_services += ‘\n\n’;
if ( is_sys32_dir == 0 )
    {
        non_sys32_services += temp_services;
    }
    else
    {
        active_services += temp_services;
    }
set_kb_item(name:”SMB/svc/” + parse[0], value:SERVICE_ACTIVE);
set_kb_item(name:”SMB/svc/” + parse[0] + “/display_name”, value:parse[1]);
}
# end of foreach elem (active_list)

NetUseDel ();

And finally we get to the end of the script. Here the “services” variable is set up ready to print the output to for the nessus report using a “security_note” at the end. As per the NASL2 reference document, a security_note is used to report miscellaneous information. Also, a new KB is created that will dump a list of all the active services and their registry details.

 if (max_index(active_list) > 0 )
{
    services += ‘\nActive NON System32 Services :\n\n’ + non_sys32_services;
    services += ‘\n\nActive System32 Services :\n\n’ + active_services;
    fullsrv = active_services + non_sys32_services;
    set_kb_item(name:”SMB/svcs/all”, value:fullsrv);
}

if(services)
 security_note(extra: services, port:port);

#end of script

I have been thinking that in the future I may be able to define a variable based on a policy file. Then depending on the variable I can modify the layout of the information printed by the security_note(). If I want a script to parse output at scan completion, then I could have a variable set and maybe print out a common separated list of services and details, or a name=value pair. What would be even better is if there was another function to store machine parsable output in the Nessus core library. This may mean in the final .nessus report we would only have to look for our section, or potentially we can call nessus from the  command line with an option to only print the machine parsable output.

In my last post, I used the regtime.pl and mactime tools to help determine the potential time a malware infection occurred. In this post, which is very similar to the previous post, I will follow the same steps, however this time I will use the Sleuthkit tools and mactime to analyse the file system changes to determine potential infection time. Normally, you would start with either the registry or the file system mactime, and then move to the alternative based on your findings. However, I thought it would be beneficial to show how the timeline generation and analysis is the same no matter which you start with.

This time using the SANS Forensics SIFT Workstation VM image, I will use the SleuthKits fls and ils commands to produce file system information that can be used by the mactime utility to produce a timeline.

After starting the SIFT workstation I mounted the suspect hard drive to a read-only mount point.

Using the command format of “fls –r –m C: <filepath> > /tmp/fls.log” the file system on the suspect drive was processed for to retrieve any information on allocated or unallocated files in the file system.

The options used were:-

-m

mactime output

-r

recursive

<filepath>

/dev/sdc1   – This is the device file for the partition being analysed

Using the command format of “ils –m <filepath> > /tmp/ils.log” the filesystem on the suspect drive was processed to retrieve any unallocated inodes on the partition being analysed.

The options used were:-

-m

mactime output

<filepath>

/dev/sdc1   – This is the device file for the partition being analysed

Once I had the separate output files I then ran “cat” to join them all together. This was done by using the command:

cat <filename> >> /tmp/mactime-body

Then I ran the Sleuthkit mactime program across the mactime body file in 3 ways.

    1. Mactime -b /tmp/mactime-body > /tmp/mactime-body.log
    2. Mactime -b /tmp/mactime-body -d -m > /tmp/mactime-body.csv
    3. Mactime -b /tmp/mactime-body -d -m 2009-01-01 > /tmp/mactime-body2009.csv
-b format output in mactime body format
-d create a comma delimited file
-m use numeric months and not named (i.e. 01 not Jan)
2009-01-01 print only timestamps after this date

The first one will give a full dump in standard Sleuthkit mactime default output. The second one will output a full mactime file in a comma delimited format where each line has its own timestamp. The last one is the same as the second except I am only outputting any information that changed after the 1st Jan 2009.

From there I copied the processed mactime files from the SIFT virtual workstation onto a machine with Excel2007 on it. You really want to be using Office2007 to get around the row limit in previous versions of excel. The benefit of using Excel is that it can be quick and easy to sort, search and filter information that may be of interest in the mactime output files. For example, loading up the mactime-body2009.csv file I can do a find all on .exe files that are modified (including created and deleted) in the C:\Windows\system32 directory. The main reason any  .exe should be modified here is if there is a Microsoft patch installed. However, since this directory is included normally in the execution search path, malware likes to be dropped in here to avoid execution issues.

image

Attached is a copy of the the output of the find all command in Excel 2007. When reviewing the timeline we can locate the same time period that was determine in the previous blog as a point in time of interest.

The following is an overview of how I used the SANS Forensics SIFT Workstation VM image to investigate a laptop that was infected with malware. The goal of the investigation was to determine if possible how the machine got infected, and when it was infected. To this end I used the regtime.pl utility that is supplied with the image.

The regtime.pl utility will process the timestamps in each key of a registry HIVE and produce output that is compliant to the SleuthKit’s mactime format.

After starting the SIFT workstation I mounted the suspect hard drive to a read-only mount point. The regtime.pl utility can be found in the the “/usr/local/src/windows-perl/” directory.

cd /usr/local/src/windows-perl/

Using the command format of “perl regtime.pl -m <HIVENAME> -r <filepath> > /tmp/regtime-<HIVENAME>” the regtime.pl each HIVE on the suspect drive was processed.

The options used were:-

-m

mactime output

<HIVENAME>

HKLM/SAM
HKLM/SECURITY
HKLM/Software
HKLM/SYSTEM
HKLU

<filepath>

/<read-only mount path>/windows/system32/config/SECURITY

/<read-only mount path>/windows/system32/config/system

/<read-only mount path>/windows/system32/config/software

/<read-only mount path>/Document & Settings/<username>/NTUSER.DAT

Once I had the separate output files I then ran “cat” to join them all together. This was done by using the command:

cat <filename> >> /tmp/regtime-body

Then I ran the Sleuthkit mactime program across the mactime body file in 3 ways.

    1. Mactime -b /tmp/regtime-body > /tmp/regtime-mactime
    2. Mactime -b /tmp/regtime-body -d -m > /tmp/regtime-mactime.csv
    3. Mactime -b /tmp/regtime-body -d -m 2009-01-01 > /tmp/regtime-mactime2009.csv
-b format output in mactime body format
-d create a comma delimited file
-m use numeric months and not named (i.e. 01 not Jan)
2009-01-01 print only timestamps after this date

The first one will give a full dump in standard Sleuthkit mactime default output. The second one will output a full mactime file in a comma delimited format where each line has its own timestamp. The last one is the same as the second except I am only outputting any information that changed after the 1st Jan 2009.

From there I copied the processed mactime files from the SIFT virtual workstation onto a machine with Excel2007 on it. You really want to be using Office2007 to get around the row limit in previous versions of excel. The benefit of using Excel is that it can be quick and easy to sort, search and filter information that may be of interest in the mactime output files. For example, loading up the regtime-mactime2009.csv file I can do a find all on common registry keys that malware play with.

image

Attached is a copy of the first item found in the registry and the items around it. When reviewing the timeline there is a 3 minute interval where a number of registry keys are modified, however there is no other activity for hours on either side of this activity. This would be a good indication that we may want to look at exactly what changes were made in the registry (if they still exist) to see if this was malware activity.

In the next blog post, I will use the same process using the Sleuthkit tools.