original notes from obsidian

WinAPI Lists

Contains most used WinAPI - links, functionality, parameters, returns, interesting remarks, and personal notes


VirtualAlloc

LPVOID VirtualAlloc(
 LPVOID lpAddress,
 SIZE_T dwSize,
 DWORD flAllocationType,
 DWORD flProtect
);

LPVOID = Memory Pointer = LongPtr

  1. lpAddress = Memory allocation address

    • 0 = API choose the location automatically

  2. dwSize = Size of the allocation

  3. flAllocationType = Memory allocation type

    • Usually MEM_COMMIT | MEM_RESERVE = 0x3000

  4. flProtect = Memory protection flags

    • Usually 0x40 = RWX

    • But you know, better to alloc --> VMProtect --> Write Mem --> VMProtect --> run (but more on that later)


OpenProcess - Retrieve a handle to a remote process - based on PID

dwDesiredAccess = Access right to obtain in target process. usually PROCESS_ALL_ACCESS (0x001F0FF)

bInheritHandle = True/False on whether the handle can be inherited to child process or not. Usually False, because we just don't care.

dwProcessId = Target Process's PID


VirtualAllocEx - Allocate memory in a remote process

hProcess = Target process's handle lpAddress = Start address. Usually 0, so VirtualAllocEx can automatically choose the starting address for us

  • (Driploader changes this to trick EDR solutions, but that's another story)

dwSize = Length to allocate. Usually shellcode's length flAllocationType = Type of allocation. Usually MEM_COMMIT | MEM_RESERVE = 0x3000 flProtect = Memory protection type. Usually 0x20 (Read) or 0x40 (RWX)


VirtualProtect - Change memory protection

lpAddress = IntPtr - Page address - Start pointer of the memory address dwSize = UInt32 - Size of area wish to modify. 1 ~ 0xFFF is same. Usually 3. flNewProtect = UInt32 - Memory protection constant. RWX = 0x40, RX = 0x20 lpflOldProtect = [ref] UInt32 = Current memory protection


WriteProcessMemory - Write to a region of a memory in a remote process

hProcess = Handle to target process lpBaseAddress = Starting address to write memory. Usually alloc returned from VirtualAllocEx lpBuffer = Address of source byte array to be copied nSize = Length/Size of the lpBuffer. Usually shellcode length lpNumberOfBytesWritten = Pointer to a location in memory to output how much data was copied

  • Usually used with out keyword from C#

  • Pass by reference, not value - because it's a pointer that will hold data copied.


CreateRemoteThread

hProcess = Handle to the target process lpThreadAttributes = Thread attribute. Usually 0, unless PPID spoofing... but that's another story. dwStackSize = Usually 0 lpStartAddress = Start address of the thread. Usually alloc from VirtualAllocEx. This is where the shellcode starts. lpParameter = Pointer to variables if parameter. Since shellcodes usually don't have parameters, usually 0. dwCreationFlags = Usually IntPtr.Zero lpThreadId = Usually 0.


ReadProcessMemory = Read memory from remote process

hProcess = IntPtr / Handle to remote process lpBaseAddress = IntPtr / Base address to start reading from lpBuffer = byte[] / Destination buffer to copy the content from nSize = int / Number of bytes to be read lpNumberOfBytesRead = out / Number of bytes that were ACTUALLY read

Example


CreateProcessW - Create a Process

lpApplicationName = Name of the application - Usually null lpCommandLine = Full commandline to be executed - Usually full path of executable lpProcessAttribute & lpThreadAttribute = Specify security descriptor - Usually null and false dwCreationFlag = Creation Flag. CREATE_SUSPENDED = 0x4 lpEnvironMent, lpCurrentDirectory = Straight forward, but usually null for default. lpStartupInfo = STARTUPINFO Structure that includes values related with how new process should be configured. Included in PInvoke.net's cheatsheet lpProcessInformation = PROCESS_INFORMATION structure with handles, threads, pid, tid. Provided in PInvoke.net.

Example


ZwQueryInformationProcess - Return PEB information inside a PI (Process Information) variable

NTSTATUS (return type) = hex value from the kernel showing the status of the call.

ProcessHandle = IntPtr / Handle to process from PROCESS_INFORMATION structure ProcessInformationClass = Usually 0 ProcessInformation = ref PROCESS_BASIC_INFORMATION() / structure PorcesInformationLength = uint / Size of input structure (6 IntPtr) ReturnLength = ref uint variable that hold the size of fetched data

ex)


GetCurrentProcess - Return current process's handle


CreateNamedPipe - Creates a named pipe

lpName = string = Name of the pipe (ex. \\.\pipe\pipe_name) dwOpenMode = uint = Mode of the pipe = Mostly 3 = PIPE_ACCESES_DUPLEX dwPipeMode = uint = Mode of the pipe operation = PIPE_TYPE_BYTE|PIPE_WAIT, Usually 0. nMaxInstances = uint = Maximum number of instances of the pipe. Anything 1~255. nOutBufferSize = uint = Number of bytes to use for input/output buffer. Usually 0x1000 bytes. nInBufferSize = uint = Number of bytes to use for input/output buffer. Usually 0x1000 bytes. nDefaultTimeout = uint = Default timeout. Usually 0. lpSecurityAttributes = IntPtr = SID of clients that can interact with the pipe. Usually NULL/IntPtr.Zero, because we want any clients to connect to our dummy pipe server.


ConnectNamedPipe - Connect to a named pipe

hNamedPipe = IntPTr =Handle to the named pipe to connect to lpOverlapped = IntPtr = Pointer to a structure for advnaced cases. Usually IntPtr.Zero/Null for us.


ImpersonateNamedPipeClient - Impersonate the access token of the pipe client that connected to our pipe server. Stolen token will be assigned to the current thread of the process.

hNamedPipe = IntPtr = Handle to the named pipe (server).


OpenThreadToken - Open thread's token. Used for confirmation that impersonation was successful.

ThreadHandle = IntPtr = Handle to the thread to check its token. In this case, we want to check our thread from our process. So just use GetCurrentThread. DesiredAccess = uint = Desired Access to the thread. Usually TOKEN_ALL_ACCESS = 0xF01FF OpenAsSelf = bool = Should API use security context of current process? Usually false/no, because we are using the impersonated token of the target process. TokenHandle = IntPtr hToken; out hToken = (Out) pointer that will be populated with a handle to the token that is opened.


GetTokenInformation - Return token information from the token handle. One of those "Call twice" weird API.

TokenHandle = IntPtr = Token Handle. Usually retrieved through OpenThreadToken TokenInformationClass = uint = Enum of token information. Usually 1, which is TokenUser (SID) value. TokenInformation = IntPtr = Pointer to output buffer that will be populated by the API. TokenInformationLength = int = Size of output buffer ReturnLength = out int = Output length.

So this winAPI need to be called twice. It's because we don't know required size of the buffer.

ex)


ConvertSidToStringSid - Convert binary SID to string SID

Sid = IntPtr = Pointer to the SID. It's inside output buffer from GetTokenInformation. This needs to be extracted from a structure. StringSid = out IntPtr = Output string that will contain the SID string.

Example

Last updated