Reflective DLLs and You

Hey all,

This post is about reflective dynamic link libraries (DLL) and will do a simple walk-through on how to write one.  This is a technique developed by Stephen Fewer and will use his code to make the magic happen.  I realize this is a topic that has been discussed several times so I’m going to keep this post simple and tight.

References

What is a DLL? A DLL is portable code that is often shared by applications.  However, with respect to this post, a DLL is an opportunity to execute code.  Why even bother with this? If our goal is to execute code why not write an exe to disk? For a moment, consider the footprint: writing to disk, creating a process, and then doing stuff; it can add up in a hurry.  Enter DLLs and how we can go about loading them into memory.

Normally, DLLs are loaded into memory when a process is started; however, they can also be injected into an already running process.  Through DLL injection we no longer need to create a process to execute code (various DLL injection techniques); yet, we still need to write our file to disk in order to inject.  Reflective DLL injection solves this. Developed by Stephen Fewer,  this technique allows us to inject code into an existing process without ever writing to disk.  So using reflective DLL injection we go from writing to disk and creating a process to injecting our code entirely in memory … thank you Stephen.

How to Defend or Detect

Endpoint protection platforms (EPP) are starting to flag these techniques.  Personally, I would explore reflective DLL injection on an endpoint using my EPP software to identify any limitations. Additionally,  reflective DLLs will often execute malicious code by using Windows API calls, a potential detection point.  For example, createremotethread is a popular technique to execute shellcode in a remote process.

After watching Raphael’s latest post on in-memory evasion, a few other tools:

Walk-Through

This walk-through will be done using Visual Studio 2017.

  • Download Stephen Fewer’s Reflective DLL repository
  • Create a new project: C++ –> Windows Desktop –> Dynamic-Link Library
  • Remove stdafx.h, stdafx.cpp, targetver.h, and *project name*.cpp
  • From the Reflective DLL repository, copy and add ReflectiveDLLInjection.h, ReflectiveLoader.c, and ReflectiveLoader.h to the project.Pic1
  • Project –> Properties
    • Go to C/C++ –> Precompiled Headers –> Set Precompiled Headers to “Not Using Precompiled Headers” (since we removed stdafx.h)
    • C/C++ –> Preprocessor –> Preprocessor Defintions –> Set Processor Defintions to the following (WIN64 and WIN_X64 instead of WIN32 and WIN_X64 for x64 DLLs … I realize there are better ways):
WIN32;WIN_X86;NDEBUG;_WINDOWS;_USRDLL;RDLL_EXPORTS;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;

Pic2.png

  • dllmain.cpp should look something like the following:
    • Note, lpReserved is reserved for parameters (or shellcode) that can be passed to our code during execution.  I’m sure Metasploit can pass parameters, but I’m not positive on how to do that.  Cobalt Strike definitely does and works well, info can be found here @ bdllspawn.
// dllmain.cpp : Defines the entry point for the DLL application.
#include "ReflectiveLoader.h"
#include <stdio.h>
void PartyTime()
{ 
   MessageBox(0, "PartyTime", "PartyTime", MB_OK); 
   return;
}

extern "C" HINSTANCE hAppInstance;
BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{    
   switch (ul_reason_for_call)    
   { 
      case DLL_QUERY_HMODULE: 
         if (lpReserved != NULL) 
            { 
               *(HMODULE *)lpReserved = hAppInstance; 
            } 
         break; 
      case DLL_PROCESS_ATTACH: 
         hAppInstance = hModule; 
         if (!lpReserved != NULL) 
         { 
            printf("Parameter passed to Reflective DLL: %s", (char *)lpReserved); 
         } 
         else 
         { 
            printf("No parameter passed to Reflective DLL"); 
         } 
         PartyTime(); 
         fflush(stdout); 
         ExitProcess(0); 
         break;    
      case DLL_THREAD_ATTACH:    
      case DLL_THREAD_DETACH:    
      case DLL_PROCESS_DETACH:        
      break;    
   }    
   return TRUE;
}
  • Compile

With our reflective DLL compiled (hopefully), we should be able to inject without writing to disk.  Metasploit, Cobalt Strike, and Empire (assumption) all have post-exploitation modules for injecting custom written reflective DLLs.

From Metasploit

Pic6.png

And on WIN10-DM’s desktop

Pic7.png

This technique is an oldie but a goodie.  If you’ve used any of the popular C2 platforms out there, chances are you have used reflective DLL injection.  Security solutions are getting better at catching in-memory techniques like this, but advanced threat actors are also getting better in adapting their techniques.  In my opinion, it’s not a bad idea to test your security solutions against basic reflective DLL injection to see how they perform.  Post exploitation tools like Meterpreter, Empire (assume), and Cobalt Strike use reflective DLLs as well, it might be a good idea to see what exactly gets flagged and why.

Have a good one.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s