Threat hunting (VII): hunting without leaving home. Process creation

See previous entries: I: intro 1, II: intro 2, III: Kibana, IV: Grafiki, V: Jupyter Notebooks, VI: Creating our víctim

Good hunters, how’s the hunt going?

I hope you have had time to play with your lab and feel more and more comfortable consulting and analyzing the data.

As I said in the previous article, now it’s time to get down into the mud and start understanding what is happening in our laboratory. In this case we are going to talk about the creation of processes, what happens when a process is created, what ways there are to create them and the traces that creation leaves behind.

Understanding the environment

Windows is organized in layers as far as interaction with the system is concerned.

The upper layers are those with which the user or the programs that he launches interacts, the lower layers those used by the operating system itself to function.

For security reasons, the upper layers are well documented and Windows offers facilities to interact with them, but with the lower layers things change, they are not documented and due to the complexity of their operation, it is very difficult or directly not possible for security reasons.

In this representation by Pavel Yosifovich, you can see how in the upper layers, the user processes or services interact with the “Subsystem DLLs” offered by the system and that they are well documented.

These libraries are the well-known “kernel32.dll”, “user32.dll”, “netapi32.dll” … which allow us to interact with the operating system for practically anything that a user or a program may need.

Later on, that library will be responsible for sending the information in the appropriate format to the lower layer and in this way abstract the user or programmer from the complexity of the lower layers, and thus, protect the lower layers from illegitimate uses.

Process creation

The topic of this article is about creating processes, one of the most underrated tasks in an operating system, and now that we have the context information it is possible to explain a little bit more about it.

The most common way to create a process is by using the functions that “win32.dll” exports.

CreateprocessA()

This is the most common function when it comes to running processes and this is its structure. This function creates a new process with the same security context as the process that runs it.

CreateProcessAsUser() & CreateProcessWithTokenW()

These functions allow us to run a process in the security context of another user. To execute these functions, it will be necessary to pass it, in addition to all the parameters of “CreateProcessA ()”, the “Access token” of the user that we want to assign the privileges to the process.

CreateProcessWithLogonW()

In this case, this function allows executing a process under the security context of another user, but this time it will be necessary to pass to the function the user, password and domain of the user to be impersonated.

ShellExecute & ShellExecuteEx

These are simplified functions for the execution of processes offered by Windows. Working with these functions allows less flexibility than the previous ones, but they are simpler.

Sysmon

To do its job, Sysmon listens to certain system functions to record when a process uses them and generates their events.

For the generation of type 1 events, Sysmon monitors 6 APIs, which as you can imagine are those mentioned above. Now we are going to do some tests.

Tests

To better understand what is going on, I leave a small, very simplified C ++ program that initially uses the “CreateProcess” function and that I have called “ProcessCreator“.

#include <iostream>
#include <windows.h>
using namespace std;

int main()
{
PROCESS_INFORMATION pi;
STARTUPINFO si = { sizeof(si) };
TCHAR name[] = TEXT("cmd");
BOOLEAN success = CreateProcess(nullptr, name, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD code;
GetExitCodeProcess(pi.hProcess, &code);
return 0;
}

This program, once compiled and executed, will launch the “cmd” process, that is, the Windows command terminal. And once it has been launched, the following can be seen with “Process Explorer”.

The process “cmd.exe” is marked as a child process of “CreadorDeProcesos.exe” and related to the user “luisf”, who is the one who launches the process creator.

This is normal behavior: the security token that the parent process has is inherited by the child processes and looks like this in the lab:

The next test is with the “CreateProcessWithLogonW” function. As mentioned before, this function allows you to create a process by impersonating another user.

This would be an example code:

#include <iostream>
#include <windows.h>
using namespace std;

int main()
{
PROCESS_INFORMATION pi;
STARTUPINFO si = { sizeof(si) };
TCHAR name[] = TEXT("cmd");
TCHAR user[] = TEXT("JuanitoP");
TCHAR pass[] = TEXT("SuperContraseña");

BOOLEAN success = CreateProcessWithLogonW(user, NULL, pass, LOGON_WITH_PROFILE, nullptr, name, 0, nullptr, nullptr, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD code;
GetExitCodeProcess(pi.hProcess, &code);
return 0;
}

As you can see in the code, this time it is necessary to pass to the function the user and password of the user to be impersonated.

It also executes a command console, but when the console executes “whoami”, the result is different.

This process has been launched in a security context of the user “JuanitoP” and Sysmon records this same information.

If you look, it is the user “JuanitoP” who has executed the process, even though it was “luisf” who executed the “ProcessCreator”, and there is no trace of the user “luisf”.

What happened internally?

Internally, a login has been made in the system to generate an “AccessToken” for the user “JuanitoP”, and with that token the child process has been created.

If there has been a login, there will be an event of it, right? Well indeed, yes, there is an event “4624” indicating that a login has been made with the user “luisf” over the user “JuanitoP”. We can also see that the type of login is type 2, interactive, that is, through credentials.

As it has been seen, Windows allows the execution of processes under the security context of another user, as long as we have an “AccessToken” of that user, but in all cases the parent process has not been modified, although it is related to another user.

Now I want to tell you another interesting thing related to creating processes. There is a universal law in Windows Internals that says that a process cannot create another process with a higher integrity level than it has.

That is, if a process has medium integrity, it can never create a high integrity child process. Surprising, isn’t it?

Surely someone is thinking:

Butwhen I launch an application as Administrator from Explorer, Explorer has medium integrity and the process I have launched has high integrity … What you are saying makes no sense.

Let’s get to work, I’m going to try to explain what happens when a privilege elevation is executed.

Privilege elevation

In this case, I will use the “ShellExecuteEx” function to launch a process with the “runas” command, which allows launching a process with elevated privileges, only if the user who runs the parent process has the privileges to do so, obviously.

int main()
{
SHELLEXECUTEINFO shExInfo = { 0 };
shExInfo.cbSize = sizeof(shExInfo);
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shExInfo.hwnd = 0;
shExInfo.lpVerb = TEXT("runas");
shExInfo.lpFile = TEXT("C:\\Windows\\System32\\cmd.exe");
shExInfo.lpDirectory = 0;
shExInfo.nShow = SW_SHOW;
shExInfo.hInstApp = 0;

if (ShellExecuteEx(&shExInfo))
{
WaitForSingleObject(shExInfo.hProcess, INFINITE);
CloseHandle(shExInfo.hProcess);
}
}

When the application is run, a “cmd.exe” process is created and this is what “Process Explorer” displays.

Indeed, a medium integrity process is the parent of a high integrity one, but what has happened behind is very different from the creation of processes that we saw before.

To facilitate this “magic” there is the service “APPInfo” or “Application Information“. If you see the service description, it looks like this:

The Application Information service (AIS) is responsible for creating a new process to run applications with elevated privileges, typically when running an administrative application while having UAC turned on. Application Information service the running of interactive applications with additional administrative privileges. If this service is stopped, users will be unable to launch applications with the additional administrative privileges they may require to perform desired user tasks.

Here’s the secret: in its facilitating task, the application that wants to run a process with elevated privileges will call this service asking for its help.

AppInfo will be in charge of creating the “consent.exe” process, the famous UAC window that will ask the user if they want to run an elevated process if they have privileges, or it will ask for the credentials of a privileged user if the user does not have privileges.

Once “consent.exe” has the user’s consent, it will return its approval to “AppInfo”, and it will be “AppInfo” who will execute the process with elevated privileges with the “CreateProcessAsUser” function, and will assign elevated privileges since it is running with system privileges.

And now comes the key to the magic. Why does Process Explorer show that the parent of the process is “ProcessCreator” if it was actually run by “AppInfo“? This happens because one of the tasks of “AppInfo”, besides launching the process, is to make a change in the process so that it appears that “CreatorDeProcesos” has launched it and voilà! We have a high integrity process that is the child of a medium integrity process.

This technique is known as “Parent Process ID Spoofing” and we will talk about it in the next article, since attackers control it to deceive hunters.

I hope you liked it, and in the next article we will use all this knowledge to better understand attackers and their techniques.

I do not want to miss the opportunity to thank Pavel Yosifovich for everything I have learned from him about these issues and how patient he is with doubts. He is a genius.

Greetings and Happy hunting!

See also in: