3. QueueUserAPC

#processinjection #queueUserAPC #golang #maldev #malwaredevelopment

This technique is a combination of the two previous techniques. Unlike process hollowing it will not overwrite the contents of the main thread but allocate a new memory region. The main difference is that QueueUserAPC will be used to execute our shellcode when the main thread is resumed.

The benefit is that we won't be calling the CreateRemoteThread API.

The Windows APIs required to perform this technique are the following:

Create suspended process

Starting a process can be achieved by calling the CreateProcess API.

BOOL CreateProcessA(
  [in, optional]      LPCSTR                lpApplicationName,
  [in, out, optional] LPSTR                 lpCommandLine,
  [in, optional]      LPSECURITY_ATTRIBUTES lpProcessAttributes,
  [in, optional]      LPSECURITY_ATTRIBUTES lpThreadAttributes,
  [in]                BOOL                  bInheritHandles,
  [in]                DWORD                 dwCreationFlags,
  [in, optional]      LPVOID                lpEnvironment,
  [in, optional]      LPCSTR                lpCurrentDirectory,
  [in]                LPSTARTUPINFOA        lpStartupInfo,
  [out]               LPPROCESS_INFORMATION lpProcessInformation
);

The most important parameter is the dwCreationFlags should be set to CREATE_SUSPENDED (0x04)

Process Created
Suspended Chrome.exe process

Allocating memory on remote process

VirtuallAllocEx will be used for allocating memory for our shellcode in the remote memory.

  • hProcess: Process Handle returned by the CreateProcess API

  • lpAddress: We will let the API decide where to allocate the memory, therefore this value will be set to 0

  • dwSize: Will be the size of our shellcode

  • flAllocationType: We need to reserve and commit memory

  • flProtect: This can be done in a number of ways. To write and execute shellcode we will need rx permissions.

Writing shellcode to remote process

WriteProcessMemory winapi will be used to write shellcode to the remote memory

  • hProcess: Process Handle returned by the CreateProcess API

  • lpBaseAddress: Value returned from VirtualAllocEx

  • lpBuffer: A pointer to the beginning of our shellcode byte array

  • nSize: Size of our shellcode

  • lpNumberOfBytesWritten: Ouputs the number of bytes written to the destination address

Add a user-mode APC ( Asynchronous Procedure Call)

pfnAPC: This will be the address returned by VirtualAllocEx

hThread: Returned by the createprocess API

dwData: Set to 0

Resume Execution

To resume execution we only have to resume the suspended thread. The ResumeThread API will be used to achieve that.

We simply pass the handle returned by the CreateProcess API.

Calculator Executed

Complete Code

Last updated

Was this helpful?