The “Early Bird Special” – a new twist on the “Early Bird” injection technique

There are many injection techniques used by malware authors, from simply calling CreateRemoteThread to advance ones like AtomBombing, PROPagate & others.

How basic DLL injections work?

Usually when a malware initiates a DLL injection, it does the following

  1. Open or create a process for injection (via CreateProcess/OpenProcess API calls)
  2. Allocate memory in said process (via VirtualAllocEx)
  3. Write the DLL’s path to the allocated memory (via WriteProcessMemory)
  4. Call LoadLibrary[A/W] inside the remote process with the DLL’s path (via CreateRemoteThread)

The problem with this basic technique is that it’s too commonplace and detected by most AVs easily.

The “Early Bird” technique

The “Early Bird” utilizes the fact that newly created processes will call an APC function when the main thread resumes simply by replacing the CreateRemoteThread call with QueueUserAPC in step #4 above.
Since this technique also relies on allocating, writing and executing on the remote process, many AVs can detect and prevent this type of injection.

The “Early Bird Special” injection

Deceptive Bytes has discovered a new way to utilize the “Early Bird” injection that does not require allocating and writing into the remote process in order to perform the injection. The “special” trick here is to call an APC function that in itself will generate the path of the DLL to inject to the remote process.
How do we generate the path in the remote process? There are several ways but the concept is the same, we call a WinAPI function with a callback, e.g.: EnumDateFormats[A|W] which takes as the first parameter a callback function with the following signatures:

BOOL CALLBACK DateFormatProc(LPCTSTR format);

Note how this signature is similar to LoadLibrary[A|W].
The second parameter is the locale, and by using LOCALE_INVARIANT we can control the list of formats and the third parameter is the flags, we can set it to 0. With these parameters the first value returned to DateFormatProc will be “mm/dd/yyyy”, a DLL with such a relative path and “.dll” extension (in mm/dd sub-folders) will be loaded if passing LoadLibrary[A|W] as the first parameter to EnumDateFormats.
Since EnumDateFormats takes 3 parameters, we need to call NtQueueApcThread to pass the parameters for the injection to work.

POC code

This is demo code for the injection:

//tested on Windows 7 & 10.
#include <Windows.h>
#include <Winternl.h>

int wmain(int argc, wchar_t* argv[])
{
    PROCESS_INFORMATION pi = { 0 };
    STARTUPINFOW si = { sizeof(STARTUPINFOW) };
    CreateProcessW(argv[1], nullptr, nullptr, nullptr, FALSE, CREATE_SUSPENDED, nullptr, nullptr, &si, &pi);
    auto NtQueueApcThread = (NTSTATUS (NTAPI *)(HANDLE, PVOID, PVOID, PVOID, PVOID))GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueueApcThread");
    auto lpStart = (PVOID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "EnumDateFormatsW");
    auto lpProc = (PVOID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW");
    NtQueueApcThread(pi.hThread, lpStart, lpProc, (PVOID)LOCALE_INVARIANT, nullptr);
    ResumeThread(pi.hThread);
    return 0;
}

If you’d like to learn more about Deceptive Bytes and how we help organizations prevent advanced threats and the “Early Bird Special” injection, just contact us or request a demo