How Code Injection really works

Discussion in 'CYBER SECURITY awareness!' started by kram7750, Jul 15, 2017.

  1. kram7750

    kram7750 Member

    Hello everybody.

    This knowledge is useful when dealing with malware analysis since it'll help you to identify DLL injection patterns/log API calls and filter for code injection attacks.

    One of the most common methods of DLL Injection usually evolves around Win32 API functions. Due to this method requiring a dependency, it means that it is not as stealth as code injection which will require none, but often DLL injection will not actually be blocked by most typical AV solutions (based on my personal testing).

    The most common way for executing this technique would be to: start by opening a handle to the target process; allocating memory to store the DLL file path; writing to the newly allocated memory to actually store the DLL file path; creating a remote thread targeting the handle of the target process to call LoadLibraryA (and then for the argument you use the file path allocated within the target process' memory).

    The Win32 API functions which can be used to carry out this task:
    - kernel32.dll!OpenProcess
    - kernel32.dll!GetProcAddress & kernel32.dll!LoadLibraryA/W
    - kernel32.dll!VirtualAllocEx
    - kernel32.dll!WriteProcessMemory
    - kernel32.dll!CreateRemoteThread

    The Native API (NTAPI) equivelent of the functions listed above would be the following:

    - ntdll.dll!NtOpenProcess
    - ntdll.dll!LdrGetProcedureAddress (although I recommend just walking the EAT yourself to get the address and making a custom wrapper for LoadLibraryA too)
    - ntdll.dll!NtAllocateVirtualMemory
    - ntdll.dll!NtWriteVirtualMemory
    - ntdll.dll!RtlCreateUserThread / ntdll.dll!NtCreateThreadEx

    When LoadLibraryA (or the Unicode version which replaces the A for W) is called, it will end up at a function called LdrLoadDll (exported by ntdll.dll). That is the Native API equivelent function for DLL loading, you can use the function by setting up the function structure with a typedef, getting the address of LdrLoadDll via GetProcAddress (or alternatively a custom GetProcAddress to walk the Export Address Table yourself) and then initializing it to the address of the function in memory. Due to LdrLoadDll being the important function for this process, you can actually set a local hook on the function which would allow you to block DLL injection attacks occurring through the LoadLibraryA remote thread injection method - the remote thread that becomes created within your process will call LoadLibraryA which means this is called within the targeted process, therefore a local hook on LdrLoadDll will intercept the attempt of DLL injection for this particular strategy.

    Using the Native API for DLL injection (a code injection attack) does provide benefits which the Win32 API simply cannot provide and one of these is the ability to inject code into a process running on another user account. Even if your process is running as administrator and you've acquired debugging rights (SeDebugPrivilege), you'll find out that you won't be able to create a remote thread with CreateRemoteThread whilst targeting a process running on another user account such as SYSTEM (NT Authority Account) (like lsass.exe, csrss.exe, winlogon.exe, etc.). Alternatively however, using RtlCreateUserThread would allow you to create a remote thread in a process running on another user account. When RtlCreateUserThread is called it will lead back to the NtCreateThreadEx stub within ntdll.dll however it is not required to use NtCreateThreadEx... RtlCreateUserThread is fine and you're bound to run into more work with the latter.

    There is another technique of DLL injection which is a lot more stealth known as "manual map injection", and this evolves around loading a DLL within a target process without it being linked to the Process Environment Blocks' ModulesList (preventing it from being detected simply by enumerating through the modules loaded within the process). To be more stealth using the common method, you could inject shell-code injection and then load the DLL, and even repair any hooks on functions like LdrLoadDll which were set locally prior to loading any DLLs.

    Another technique I have not mentioned here would be APC (Asynchronous Procedure Calls). This works similar in the way that you target a thread of a process and then use it with a function like QueueUserAPC (which will then end up at NtQueueApcThread) to force the target process to make a call to LoadLibraryA/W or just go for LdrLoadDll to start with.

    To sum up this thread:
    - The most common method of DLL injection evolves around forcing a target process to call LoadLibraryA to load the target DLL.
    - A more stealth method of DLL injection is manual mapping which will prevent the DLL from being added to the ModulesList in the PEB (Process Environment Block).
    - You can block simple DLL injection attacks through locally hooking ntdll.dll!LdrLoadDll.

    Thank you for reading.
    jasonX, Gabbs, guardian and 6 others like this.
  2. Google Adsense

  3. RGiskardR

    RGiskardR Malware Tester Silver Member

    Really very interesting and informative post! thanks!
    wwd, guardian, Trim and 4 others like this.
  4. revC0de

    revC0de MTAC Moderator Staff Member

    Thanks for analyzing this topic, really interesting! :)
    wwd, RGiskardR, guardian and 3 others like this.

Share This Page