Windows APIs for AV/EDR Evasion_1

 

Windows API Quick Reference for Process Manipulation

This guide will help you quickly recall the purpose, usage, and scenarios for key Windows APIs related to process manipulation, injection, and memory modification.


1️⃣ CreateProcessW()

📌 Purpose:

  • Creates a new process and can start it in a suspended state.
  • Used for executing new processes with control over execution timing.

📌 When to Use?

✔️ If you need to start a process but prevent immediate execution (e.g., for hollowing, injection).
✔️ If you want to manipulate process memory before execution begins.
✔️ If you need to redirect or inject code into another process before it starts.

📌 Key Parameters & Structures:

  • CREATE_SUSPENDED → Ensures process starts in a paused state.
  • PROCESS_INFORMATION → Holds process and thread handles (hProcess, hThread).
  • STARTUPINFO → Holds configuration info for the process.

📌 Example Usage:

Used in:

  • Process Hollowing → Creating a process, replacing its memory, then resuming execution.
  • DLL Injection → Creating a process to inject a DLL before execution starts.
  • Shellcode Injection → Creating a process and modifying memory to execute shellcode.

2️⃣ NtQueryInformationProcess()

📌 Purpose:

  • Retrieves internal process details, including the Process Environment Block (PEB) address.
  • Allows access to low-level process metadata.

📌 When to Use?

✔️ If you need to locate the PEB of a remote process.
✔️ If you need to extract the Image Base Address (where the EXE is loaded).
✔️ If you are working with process injection, hollowing, or custom PE loaders.

📌 Key Parameters & Structures:

  • PROCESS_BASIC_INFORMATION → Stores PebBaseAddress, which points to the PEB.
  • Function Resolved Dynamically → Uses GetProcAddress() to avoid direct API calls (stealthier approach).

📌 Example Usage:

Used in:

  • Process Hollowing → Finding where the EXE is loaded before replacing it.
  • DLL Injection → Finding process memory addresses before injecting a DLL.
  • Malware Analysis → Extracting process metadata for analysis.

3️⃣ ReadProcessMemory()

📌 Purpose:

  • Reads memory from another process at a specific address.
  • Used to extract the Image Base Address or other important memory structures.

📌 When to Use?

✔️ If you need to read where an EXE is loaded in memory (Image Base Address).
✔️ If you need to inspect another process’s memory before modification.
✔️ If you are performing Process Injection, Hollowing, or DLL Injection.

📌 Key Parameters & Structures:

  • Process Handle (hProcess) → Handle to the target process.
  • Memory Address (LPVOID lpBaseAddress) → The address to read from.
  • Output Buffer (LPVOID lpBuffer) → Where the read data is stored.
  • Bytes Read (SIZE_T *lpNumberOfBytesRead) → Number of bytes successfully read.

📌 Example Usage:

Used in:

  • Extracting the Image Base Address from the PEB before modifying memory.
  • Process Injection → Reading process memory before writing shellcode.
  • Memory Analysis → Checking running processes for forensic analysis.

Summary: When to Use Each API?

Scenario API to Use Why?
Creating a new process without executing it immediately CreateProcessW() with CREATE_SUSPENDED Allows pre-execution modification (Process Hollowing, DLL Injection, etc.).
Finding where the process is loaded in memory (PEB address) NtQueryInformationProcess() Retrieves internal process structures like PEB, needed for memory manipulation.
Extracting the Image Base Address from a process ReadProcessMemory() Reads from PEB to find the base memory address of the main executable.


Example:

#include <stdio.h>
#include <Windows.h>
#include <winternl.h>  // Needed for NtQueryInformationProcess

typedef NTSTATUS(WINAPI* pNtQueryInformationProcess)(
    HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);

int main() {
    STARTUPINFO si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    si.cb = sizeof(si);

    LPCWSTR targetProcess = L"C:\\Windows\\System32\\notepad.exe";

    // Step 1️⃣: Create a suspended process
    if (!CreateProcessW(targetProcess, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
        printf("[-] Failed to create process. Error: %lu\n", GetLastError());
        return -1;
    }
    printf("[+] Suspended process created! PID: %lu\n", pi.dwProcessId);


    // Step 2️⃣: Get `NtQueryInformationProcess()` function address from ntdll.dll
    HMODULE hNtDll = GetModuleHandleW(L"ntdll.dll");
    if (!hNtDll) {
        printf("[-] Failed to load ntdll.dll.\n");
        return -1;
    }
    pNtQueryInformationProcess NtQueryInformationProcess =
        (pNtQueryInformationProcess)GetProcAddress(hNtDll, "NtQueryInformationProcess");

    if (!NtQueryInformationProcess) {
        printf("[-] Failed to resolve NtQueryInformationProcess.\n");
        return -1;
    }

    // Step 3️⃣: Query the PEB address
    PROCESS_BASIC_INFORMATION pbi;
    ULONG returnLength;

    NTSTATUS status = NtQueryInformationProcess(
        pi.hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &returnLength);

    if (status != 0) {
        printf("[-] NtQueryInformationProcess failed! Status: 0x%X\n", status);
        return -1;
    }

    printf("[+] PEB Base Address: 0x%p\n", pbi.PebBaseAddress);

    // Step 4️⃣: Resume execution & cleanup
    ResumeThread(pi.hThread);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 0;
}


*******Explanation*******

1️⃣ Process Creation (CreateProcessW)

  • API Used: CreateProcessW()
  • Concept: Creates a new process (Notepad.exe) in a suspended state.
  • Why? This prevents execution, allowing memory modifications before running.
  • Key Flag: CREATE_SUSPENDED → Ensures the process does not start execution immediately.

2️⃣ Resolving NtQueryInformationProcess from ntdll.dll

  • API Used: GetModuleHandleW() and GetProcAddress()
  • Concept: Dynamically resolves NtQueryInformationProcess(), which is an undocumented API.
  • Why? This API is not available in normal Windows headers, so it needs to be manually loaded.
  • Purpose: Used to query internal process structures like the PEB (Process Environment Block).

3️⃣ Retrieving the PEB (Process Environment Block) Address

  • API Used: NtQueryInformationProcess()
  • Concept: Retrieves low-level process details, specifically the PEB base address.
  • Why? The PEB contains critical process metadata, such as:
    • Image Base Address (EXE memory location)
    • Loaded Modules/DLLs
    • Process Execution Flags
  • Key Data Retrieved:
    • pbi.PebBaseAddress → The memory address of the PEB structure.

4️⃣ Resuming Process Execution (ResumeThread)

  • API Used: ResumeThread()
  • Concept: Resumes execution of the previously suspended process.
  • Why? After retrieving the PEB, the process is allowed to run normally.
  • Purpose: If modifications were needed (e.g., process hollowing), they would be done before resuming.

5️⃣ Cleaning Up Handles (CloseHandle)

  • API Used: CloseHandle()
  • Concept: Closes process and thread handles to avoid memory leaks.
  • Why? Proper cleanup prevents resource exhaustion.

Program Control Flow (Step-by-Step Execution)

1️⃣ Create Notepad.exe in a suspended state using CreateProcessW().

  • If creation fails, print an error and exit.

2️⃣ Get the address of NtQueryInformationProcess() dynamically from ntdll.dll.

  • If retrieval fails, print an error and exit.

3️⃣ Call NtQueryInformationProcess() to get the PEB Base Address of the created process.

  • If the query fails, print an error and exit.

4️⃣ Print the PEB Base Address (a memory location).

  • This will be used in advanced techniques like Process Hollowing.

5️⃣ Resume execution of Notepad.exe using ResumeThread().

6️⃣ Clean up resources by closing process and thread handles.


When to Use This?

Process Injection & Hollowing → Find where an EXE is loaded in memory before modifying it.
Malware Analysis & Research → Understanding process memory structure.
EDR Evasion → Dynamically resolving Windows APIs instead of linking them directly.





Comments