original notes from obsidian
WinAPI Lists
Contains most used WinAPI - links, functionality, parameters, returns, interesting remarks, and personal notes
Process Injection Related WINAPI
LPVOID = Memory Pointer = LongPtr
lpAddress = Memory allocation address
0 = API choose the location automatically
dwSize = Size of the allocation
flAllocationType = Memory allocation type
Usually MEM_COMMIT | MEM_RESERVE =
0x3000
flProtect = Memory protection flags
Usually
0x40
= RWXBut 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
Token Related WINAPI
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