Various ways of DLL injection

Posted by gikon on Thu, 17 Feb 2022 10:32:15 +0100

Various ways of DLL injection

Registry injection

In Windows NT/2000/XP/2003 operating system, when it is necessary to load user32 When the program of DLL starts, user32 DLL will load the registry key HLM\Software\Microsoft\WindowsNT\CurrentVersion\Windows\AppInit_DIls all modules listed below.

Therefore, the path of the module to be injected can be written to appinit_ Under DILS key, delete appinit after the game process starts and the plug-in module is brought_ The value of DILS key to clear the trace. Its core function is as follows:

//Define key value

#define DSTKEY "SOFTWARE\\\Microsoft\\\Windows NT\\\CurrentVersion\\\Windows"
//Open primary key
RegOpenKeyEx (
	&hKey) ;

//Set appinit_ The value of DLLs key, where "cDllPath" is the path of the DLL to be annotated
RegSetValueEx (
	strlen( (char*) cDl1Path) +1
	) ;

Advantages: simple and easy to implement.

Disadvantages: first, human injection can be realized only after the system is restarted, and the requirements for the stability of DLL are relatively high. It is recommended to use it in the virtual machine. If there is a problem with the DLL, the blue screen will be displayed. Second, it is easy to be discovered by software used to monitor registry operations such as ProcessMonitor.

Remote thread injection

The core idea of far thread injection is to use the far thread mechanism provided by Windows to start a far thread loading the module in the target process, so that the module can be loaded into the address space of the game by the far thread.

The key API s used by remote threads are VirtualAllocEx, WriteProcessMemory, CreateRemoteThread and LoadLibrary. Their declarations are as follows.

LPVOID  WINAPI VirtualAllocEx(
HANDLE  hProcess,						//Remote process handle
LPVOID  lpAddress,						//Keep the memory address of the page; Generally, NULL is used for automatic allocation
SIZE_T  dwSize,							//Size of allocated memory
DWORD   flAllocationType,				
DWORD   flProtect						

BOOL WriteProcessMemory (
HANDLE hProcess,                                 //Remote process handle
LPVOID lpBaseAddress,                         //Address to be written by remote process
LPVOID lpBuffer,                                     //This process space needs to be written to the address of the remote process
DWORD nSize,                                       //The size of the space referred to by lpBuffer
LPDWORD lpNumberOfBytesWritten     //Returns the number of bytes actually written to the remote process
) ;

HANDLE CreateRemoteThread (
HANDLE hProcess,                            //Remote handle
SIZE_T dwStackSize,                        
LPTHREAD_START_ROUTINE lpStartAddress,    //Points to the address of the function executed in the remote process
LPVOID lpParameter,                        //Incoming parameters
DWORD dwCreationFlags,                    //Additional flags for creating threads
LPDWORD lpThreadId                         //Thread ID. If NULL, it is not returned

_in LPCTSTR lpFileName            //File path of the module to be added

The remote thread loading process is as follows:

(1) Call the VirtualAllocEx function to allocate memory in the far process space

(2) Call the WriteProcessMemory function to write the file path of the module to the far process space.

(3) Call the CreateRemoteThread function to start the LoadLibrary remote thread of the remote process to load the plug-in module.

This method is relatively old. The basic protection has been protected against this law, so I won't elaborate too much

Advantages: simple and easy to implement.

Disadvantages: easy to detect. As long as you monitor the call of this process to the LoadLibrary function, you can well prevent remote thread loading.

Dependent trusted process injection

In order to avoid the scanning of anti plug-in system or the analysis of analysts, sometimes relying on the transfer injection carried out by a trusted third-party process may achieve better results. Because services Exe is not easy to debug, has high permissions and good concealment, so find services through Trojan horse and plug-in Exe process is a wise choice.

Suppose this process is main Exe, the module to be injected is Zrt DL, the process to be injected is ZRP Exe, after the following.

( 1 ) Bot.exe calls WriteProcessMemory and CreateRemoteThread functions, and uses the far thread injection method to add FQ DLL is marked by services Exe process. Bot.exe calls the Sleep(35000) function to put itself into sleep.

( 2 )services. Fq.exe DLL calls createtoolhelp32sampshot and Process32Next to traverse the process and judge game Whether the EXE process starts. If you find game Exe is started, and FQ. Exe is sent by remote thread or other means DLL note to game Exe process; If game is not found Exe starts, then the loop traversal continues.

(3) The sleep state of botex process ends and starts the next step. Add: according to common sense, 35 000ms is enough for services Fq.exe in the process DLL for game Exe process.

(4) Bot.exe calls createtoolhelp32sampshot and Process32Next to traverse the process and find services Exe process. After finding the process, traverse the modules and find FQ and DLL.

(5) Bot. The EXE process calls FreeLibrary by calling the CreateRemoteThread remote thread, and the services Fq.exe DLL from services Exe process.

(1) Main.exe calls WriteProcessMemory and CreateRemoteThread functions to convert Zrt DLL injection services Exe, and then main Exe calls the Sleep function and waits for the injection to complete

(2)service. In zrt.exe Dllcreatetoolhelp32sampshot and Process32Next to traverse the process. If bot Exe, use remote thread or other methods to convert Zrt DLL note to bot Exe process

(3) Botex process sleep end

(4) Main.exe calls createtoolhelp32sampshot and Process32Next to traverse the process and find services Exe process. After finding the process, traverse the module and find FQ and DLL.

(5)Main.exe calls CreateRemoteThread far thread to call FreeLibrary, and services Fq.exe DLL from services Exe process.

Advantages: good concealment, not easy to be analyzed and found.

Disadvantages: the method of traversing the process needs to be improved and may be deceived by fake processes; It's not good to call the API directly.

APC injection

APC (asynchronous procedure call) is a function executed asynchronously in a specific thread environment. It is divided into user mode APC and kernel mode APC. Each thread has an APC queue. In user mode, when a thread calls SleepEx and WaitForSingleObjectEx to enter the "alternative waitstatus" (warning waiting state), the system will traverse the APC queue of the thread, and then execute these APCs in first in first out order.

In user mode, Microsoft provides the API QueueUserAPC to insert APC into - a thread. The following is the declaration of QueueUserAPC.

_in PAPCFUNC pfnAPC,                       //Point to an APC function
in HANDLE hThread,                             //Thread handle to insert APC
in ULONG PTR dwData                        //Parameters of APC function

Pass below APC The loaded pseudo code to analyze the loading step
// 1. Create the target process to be loaded in suspend mode
if (CreateProcess (sProcName, NULL, NULL, NULL, FALSE, CREATE_ SUSPENDED, NULL, NULL, &st, &pi) )
// 2. The target process address space allocates the DLL path space to be loaded
lpDllName = VirtualAllocEx (pi.hProcess,NULL, (strlen (sDllName) +1),MEM COMMIT,PAGE READWRITE) ;
// 3. Write the DLL path to be loaded into the target process space
if (WriteProcessMemory (pi .hProcess,lpD11Name,sD11Name, strlen(sD11Name),NULL) )
      // 4. Get the address of LoadLibrary
       LPVOID nLoadLibrary= (LPVOID) GetProcAddress (GetModuleHandle        
       ("kerne132.d1l"),"LoadLibraryA") ;
      // 5. Call QueueUserAPC to insert an APC into the remote thread, which is LoadLibrary
        if (! QueueUserAPC( (PAPCFUNC) nLoadLibrary, pi. hThread, (ULONG_PTR) 1pD1 
        1Name) )
               OutputDebugString("APCInject QueueUserAPC call error!") ;

In addition to storing the path of the DLL to be loaded in the address space of the target process through the VirtualAllocEx and WriteProcessMemory functions, the path can also be mapped through the combination of CreateFileMapping, MapViewOfFile and NtMapViewOfSection functions

Advantages: relatively hidden and simple.

Disadvantages: the implementation conditions are harsh, and you must wait for the process to enter the "alternative waitstatus" state.

Message hook injection

SetW indowsHookEx function is an API provided by Microsoft for program developers to intercept messages. However, its function can be used not only for message interception, but also for DLL injection.

The prototype declaration of SetWindowsHookEx is as follows.

HHOOK Se tWi ndowsHookEx (
Int idHook,                                 //Indicates the type of hook handling that will be installed. For example, when idHook is "WH_CALLWNDPROC", it means that a hook process is installed to monitor the message before the system sends the message to the target window process. HOOKPROC lpfn, / / points to the corresponding hook process.
HINSTANCE hMod,                   //Indicates a DLL handle. The DLL contains the hook handling procedure pointed to by the parameter lpfn.
DWORD dwThreadId                 //Indicates a thread identifier, and the hook processing procedure is related to the thread. If this parameter value is 0, the hook process is related to all existing threads.

If you want to remove the message hook, you can call the UnhookWindowsHookEx function.

The following is the core code of the injection.

//Using Windows API SetWindowsHookEx to realize DLL injection
BOOL SetWinHKInject (char* pszDllPath,char* pszProcess)
	//Load the DLL of the person to be registered into the process space
	hMod = LoadLibrary (pszDllPath) ;
	if (!hMod)
		return FALSE;
	//Get the address of the message hook procedure function exported from the DLL of the person to be noted
	lpFunc = (DWORD) GetProcAddress (hMod, "MyMessageProc") ;
	if (!lpFunc)
		FreeLibrary (hMod) ;
		return FALSE;
	//Get the thread ID of the process to be injected
	dwThreadId = GetTargetThreadIdFromProcname (pszProcess) ;
	if (!dwThreadId)
		FreeLibrary (hMod) ;
		return FALSE
	//Call SetwindowsHookEx to implement message hook annotation
	hook = SetWindowsHookEx (
	) ;
	FreeLibrary (hMod) ;
	return TRUE;

//Message hook function MyMessageProc exported by DLL of the person to be noted
_declspec (dllexport) LRESULT MyMessageProc (int code, WPARAM wParam,
LPARAM 1Param)
	//Processing of messages
	return CallNextHookEx(g_hhook,code,wParam,lParam);

Advantages: simple code and principle, easy to find.

Disadvantages: easy to find.

Hijack process creation injection

If you can get the read and write permissions of the target process before it runs, injection will be much easier. The following are the key API s and call sequences created by the process.

The API of creating process under Windows is CreateProcess, and its prototype is as follows.

BOOL CreateProcess (
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID IpEnvironment,
LPCTSTR lpCurrentDirectory,

This paper mainly introduces a value of dwCreationFlags - create_ Meaning of suspended.

When the parameter dwCreationFlags is assigned CREATE_SUSPENDED to call CreateProcess()
Function, the main thread of the process will be started in a suspended manner. To restore the operation of the main thread
Line, you need to call the ResumeThread() function. Hijacking process loading is during the period when the main thread is suspended and restored
In time, the dll or code is injected into the target process.

The steps are as follows:

(1) Call to call the CreateProcess() function in a suspended manner to create a process.

(2) The plug-in module is injected by far threading.

(3) Call the ResumThread() function to restore the main thread of the game.

However, many game processes now use the dual process protection mechanism when starting, so even through the above robbery
Holding the process to load successfully is just the first process to inject dual process protection. In order to use it again
To note the real game process with the process creation mechanism, you need to understand the function call sequence created by the process in the user state, as shown in the figure

The KiFastSystemCall() function is equivalent to a channel from ring3 to ring0. The CreateProcess() function finally enters the kernel state through the KiFastSystemCall() function. The hijacking process can be created at any level through the corresponding function of Hook to achieve the purpose of loading. For example, when ring3 is about to enter ing0, that is, when calling KiFastSystemCall() function, hijack the call of this function to realize loading.

Advantages: not easy to defend, high success rate.
Disadvantages: the hijacking time should not be too long, otherwise it will be found; After hijacking, if you need to hijack again, you need a Hook, so it is easy to be detected.


DLL injection consists of four steps:

1. Attach to target / remote process

2. Allocate memory within the target / remote process

3. Copy the DLL file path or DLL file to the memory space of the target / remote process

4. Control process running DLL file

All these steps are accomplished by calling a series of specified API functions. Each technology requires specific settings and option configurations. Each technology has its advantages and disadvantages

However, for programs with driver protection, these are injection methods at the level of 3 rings. Under the protection of 0 ring, the injection method of 3 rings is not enough to see. If you want to really compete with the driver protection program, you can only enter 0 ring to compete with it