What is the Windows API?

The Windows API, informally WinAPI, is Microsoft’s core set of application programming interfaces (APIs) available in the Microsoft Windowsoperating systems. The name Windows API collectively refers to several different platform implementations that are often referred to by their own names (for example, Win32 API); see the versions section. Almost all Windows programs interact with the Windows API. On the Windows NT line of operating systems, a small number (such as programs started early in the Windows startup process) use the Native API.

Why do we care about Windows API?

The Windows API, with the right token privileges, allows the program to read other users memory, execute code in a higher privileges context, enumerate system, kill AV etc and much more.

Adversary simulation and pen-testing are commonplace in large enterprises, this has led to defenders improving their ability to detect and block standard tools like Metasploit with ease. However, modern adversaries have the means to carry out very advanced attacks spending years targeting an adversary with custom code.

The Windows API, with the right token privileges, allows the program to read other users memory, execute code in a higher privileges context, enumerate system, kill AV etc and much more. Using custom code calling Windows API means no fluff, no code bloat, our exploit is tightly coupled with the target environment and we can emulate powerful adversary tactics.

SE_PRIVILEGE_ENABLED token priviledge is king, we can read other users memory when this is enabled and so much more!

With debug privs we can, for example:

  • Read/write anything in memory
  • Search for and recover sensitive info like passwords, hashes and tokens

We will be looking at the following API functions to start with…

AdjustTokenPrivileges

The AdjustTokenPrivileges function enables or disables privileges in the specified access token. Enabling or disabling privileges in an access token requires TOKEN_ADJUST_PRIVILEGES access.

AdjustTokenPrivileges

The NewState parameter can specify privileges that the token does not have, without causing the function to fail. In this case, the function adjusts the privileges that the token does have and ignores the other privileges so that the function succeeds. Call the GetLastError function to determine whether the function adjusted all of the specified privileges. The PreviousState parameter indicates the privileges that were adjusted.

AdjustTokenPrivileges function
Enables or disables privileges in the specified access token. Enabling or disabling privileges in an access token…docs.microsoft.com

GetTokenInformation

The GetTokenInformation function retrieves a specified type of information about an access token. The calling process must have appropriate access rights to obtain the information.

To determine if a user is a member of a specific group, use the CheckTokenMembership function. To determine group membership for app container tokens, use the CheckTokenMembershipEx function.

GetTokenInformation(processToken, TokenPrivileges, NULL, 0, &structSize);

ShellExecuteEx

Performs an operation on a specified file.

Below you will find a reference for ShellExecuteEx info. Interestingly though, runas verb does not appear there._SHELLEXECUTEINFOA
Contains information used by ShellExecuteEx.msdn.microsoft.com

ShellExecute/Ex() with the "runas" verb is the only official way to start an elevated process programmably, especially if the executable being run does not have its own UAC manifest to invoke elevation.

info.cbSize = sizeof(SHELLEXECUTEINFO);
info.fMask = SEE_MASK_DEFAULT;
info.hwnd = NULL;
info.lpVerb = _T("runas");
info.lpFile = fileName;
info.lpParameters = NULL;
info.lpDirectory = NULL;
info.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&info);  // Also try the simpler ShellExecute

GetModuleFilename

Returns path of current process executable

// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683197(v=vs.85).aspx
GetModuleFileName(NULL, fileName, pathLen);

CreateToolhelp32Snapshot

Takes a snapshot of the specified processes, as well as the heaps, modules, and threads used by these processes.

Toolhelp32ReadProcessMemory

Copies memory allocated to another process into an application-supplied buffer.

Toolhelp32ReadProcessMemory

Copies memory allocated to another process into an application-supplied buffer.

WriteProcessMemory

Writes data to an area of memory in a specified process. The entire area to be written to must be accessible or the operation fails.

WTSEnumerateProcessesEx

Retrieves information about the active processes on the specified Remote Desktop Session Host (RD Session Host) server or Remote Desktop Virtualization Host (RD Virtualization Host) server.

WTSFreeMemoryEx

Frees memory that contains WTS_PROCESS_INFO_EX or WTS_SESSION_INFO_1 structures allocated by a Remote Desktop Services function.

LookupPrivilegeValue

The LookupPrivilegeValue function retrieves the locally unique identifier (LUID) used on a specified system to locally represent the specified privilege name.

GetCurrentProcess

Retrieves a pseudo handle for the current process.

OpenProcessToken

The OpenProcessToken function opens the access token associated with a process.

LookupAccountSid

The LookupAccountSid function accepts a security identifier (SID) as input. It retrieves the name of the account for this SID and the name of the first domain on which this SID is found.

ConvertSidToStringSidA

The ConvertSidToStringSid function converts a security identifier (SID) to a string format suitable for display, storage, or transmission.

To convert the string-format SID back to a valid, functional SID, call the ConvertStringSidToSid function.

For now, this is just a bit of info on the functions we will use, next post we will write some programs to remain stealthy!