# original notes from obsidian

## WinAPI Lists

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

***

### Process Injection Related WINAPI

[VirtualAlloc](https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-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

```
HANDLE OpenProcess(
 DWORD dwDesiredAccess,
 BOOL bInheritHandle,
 DWORD dwProcessId
);
```

`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

```
LPVOID VirtualAllocEx(
 HANDLE hProcess,
 LPVOID lpAddress,
 SIZE_T dwSize,
 DWORD flAllocationType,
 DWORD flProtect
);
```

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

```
BOOL VirtualProtect(
 LPVOID lpAddress,
 SIZE_T dwSize,
 DWORD flNewProtect,
 PDWORD lpflOldProtect
);
```

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

```
BOOL WriteProcessMemory(
 HANDLE hProcess,
 LPVOID lpBaseAddress,
 LPCVOID lpBuffer,
 SIZE_T nSize,
 SIZE_T *lpNumberOfBytesWritten
);
```

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**

```
HANDLE CreateRemoteThread(
 HANDLE hProcess,
 LPSECURITY_ATTRIBUTES lpThreadAttributes,
 SIZE_T dwStackSize,
 LPTHREAD_START_ROUTINE lpStartAddress,
 LPVOID lpParameter,
 DWORD dwCreationFlags,
 LPDWORD lpThreadId
);
```

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

```
BOOL ReadProcessMemory(
 HANDLE hProcess,
 LPCVOID lpBaseAddress,
 LPVOID lpBuffer,
 SIZE_T nSize,
 SIZE_T *lpNumberOfBytesRead
);
```

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

```
byte[] addrBuf = new byte[IntPtr.Size];
IntPtr nRead = IntPtr.Zero;
ReadProcessMemory(hProcess, ptrToImageBaseAddress, addrBuf, addrBuf.Length, out nRead);
```

***

**CreateProcessW** - Create a Process

```
BOOL CreateProcessW(
 LPCWSTR lpApplicationName,
 LPWSTR lpCommandLine,
 LPSECURITY_ATTRIBUTES lpProcessAttributes,
 LPSECURITY_ATTRIBUTES lpThreadAttributes,
 BOOL bInheritHandles,
 DWORD dwCreationFlags,
 LPVOID lpEnvironment,
 LPCWSTR lpCurrentDirectory,
 LPSTARTUPINFOW lpStartupInfo,
 LPPROCESS_INFORMATION lpProcessInformation
);
```

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

```
STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

bool result = CreateProcess(null, @"C:\windows\system32\svchost.exe", IntPtr.Zero, IntPtr.Zero, false, 0x4, IntPtr.Zero, null, ref si, out pi); 
```

***

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

```
NTSTATUS WINAPI ZwQueryInformationProcess(
 _In_ HANDLE ProcessHandle,
 _In_ PROCESSINFOCLASS ProcessInformationClass,
 _Out_ PVOID ProcessInformation,
 _In_ ULONG ProcessInformationLength,
 _Out_opt_ PULONG ReturnLength
);
```

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)

```
PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION();
uint tmp = 0; 
IntPtr hProcess = pi.hProcess;
// PROCESS_BASIC_INFORMATION has 6 IntPtr, thus (IntPtr.Size*6)
ZwQueryInformationProcess(hProcess, 0, ref bi, (uint)(IntPtr.Size*6), ref tmp);

// Now "bi" has the PEB address. 
IntPtr ptrToImageBase = (IntPtr)((Int64)bi.PebAddress + 0x10); 
```

***

**GetCurrentProcess** - Return current process's handle

```
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
```

***

### Token Related WINAPI

`CreateNamedPipe` - Creates a named pipe

```
HANDLE CreateNamedPipeA(
 LPCSTR lpName,
 DWORD dwOpenMode,
 DWORD dwPipeMode,
 DWORD nMaxInstances,
 DWORD nOutBufferSize,
 DWORD nInBufferSize,
 DWORD nDefaultTimeOut,
 LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
```

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

```
BOOL ConnectNamedPipe(
 HANDLE hNamedPipe,
 LPOVERLAPPED lpOverlapped
);
```

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.

```
BOOL ImpersonateNamedPipeClient(
 HANDLE hNamedPipe
);
```

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

***

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

```
BOOL OpenThreadToken(
 HANDLE ThreadHandle,
 DWORD DesiredAccess,
 BOOL OpenAsSelf,
 PHANDLE TokenHandle
);
```

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.

```
BOOL GetTokenInformation(
 HANDLE TokenHandle,
 TOKEN_INFORMATION_CLASS TokenInformationClass,
 LPVOID TokenInformation,
 DWORD TokenInformationLength,
 PDWORD ReturnLength
);
```

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)

```
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool GetTokenInformation(IntPtr TokenHandle, uint TokenInformationClass, IntPtr TokenInformation, int TokenInformationLength, out int ReturnLength);

int TokenInfLength = 0;

// Calling first time, because we don't know TokenInformationLength
GetTokenInformation(hToken, 1, IntPtr.Zero, TokenInfLength, out TokenInfLength);

// Calling second time, because we now KNOW TokenInformationLength. Allocate memory of TokenInformation with the length of TokenInformationLength, and call again.
IntPtr TokenInformation = Marshal.AllocHGlobal((IntPtr)TokenInfLength);
GetTokenInformation(hToken, 1, TokenInformation, TokenInfLength, out TokenInfLength);
```

***

`ConvertSidToStringSid` - Convert binary SID to string SID

```
BOOL ConvertSidToStringSidW(
 PSID Sid,
 LPWSTR *StringSid
);
```

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

```
// Setting structure of SID. Used for SID extraction later on. 
[StructLayout(LayoutKind.Sequential)]
public struct SID_AND_ATTRIBUTES
{
 public IntPtr Sid;
 public int Attributes;
}
public struct TOKEN_USER
{
 public SID_AND_ATTRIBUTES User;
}

[DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool ConvertSidToStringSid(IntPtr pSID, out IntPtr ptrSid);

// Extracting SID(TokenUser) from the TokenInformation structure 
TOKEN_USER TokenUser = (TOKEN_USER)Marshal.PtrToStructure(TokenInformation, typeof(TOKEN_USER));

// Pointer to contain output SID string 
IntPtr pstr = IntPtr.zero;
Boolean ok = ConvertSidToStringSid(TokenUser.User.Sid, out pstr);

// Converting pointer to actual string 
string sidstr = Marshal.PtrToStringAuto(pstr);
Console.WriteLine(@"[+] Sid: ", sidstr); 
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.xn--hy1b43d247a.com/misc/winapi-list/original-notes-from-obsidian.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
