Mutex
Code and executables download: From GitHub
What is a mutex
A mutex (or mutant) is, according to the Microsoft documentation, a synchronization object whose state is set to signaled when it is not owned by any thread and nonsignaled when it is owned.
What this means is that when a program has more than one thread and these threads need to access a shared object (for example, a file or a global variable), each thread might in turn lock the object to prevent the other threads from modifying it. This is often used to avoid race conditions. For example, one thread changes the value of a file while another is reading it. In that case, the reader thread would read an old value rather than the newest one.
Malware can use mutexes for different reasons, for example:
- their intended purpose, as described above,
- to coordinate different threads,
- to avoid reinfection
This discussion focuses on the last point, on why it is used and how it works.
When malware infects a system, it often creates registry entries, scheduled tasks, temporary files, and so on. The infection process can expose the malware to security tools and detection systems, so the fewer times it is performed, the better. Reducing repeated infection attempts can help the malware reduce its observable footprint.
Mutex creation
A mutex is usually created during infection, and the object is automatically deleted as soon as no processes have a handle to it. If a sample keeps running in the background indefinitely, the mutex will continue to exist until the process is terminated or the system is rebooted. Malware might also keep the mutex alive by creating a handle to it from another process or from a newly created service. For example, during infection, it creates a new mutex and a Windows service. Once the service starts, it retains a handle to the mutex.
The malware typically starts by checking for a mutex with a specific name and then creates it if it is not present.
Note that the presence of a mutex in a program does not by itself make the program malicious; legitimate software uses them routinely.
The following code is used to demonstrate the mutex creation:
#include <windows.h>#include <stdio.h>
#define RET_SUCCESS 0
int main() { HANDLE hMutex = NULL; for (int i = 1; i <= 2; i++) { hMutex = CreateMutexA(NULL, FALSE, "LearnMutex"); printf("Execution number %d\n", i); if (GetLastError() == ERROR_ALREADY_EXISTS) { printf("\tCannot create mutex\nerror: %lu \n", GetLastError()); } else { printf("\tCreated new mutex\n\n"); } } printf("Press enter to exit\n"); getchar(); return RET_SUCCESS;}Specifically, the code creates a new LearnMutex mutex. If the mutex is created, it prints: Created new mutex; otherwise, it prints an error message.
The mutex creation is done via the CreateMutex Windows API, which accepts the arguments below, as specified in the Microsoft documentation 1.
HANDLE CreateMutexA( [in, optional] LPSECURITY_ATTRIBUTES lpMutexAttributes, [in] BOOL bInitialOwner, [in, optional] LPCSTR lpName);The first two arguments are not of interest in this particular scenario, since lpMutexAttributes 2 is used to define which permissions are required on the mutex—for example, to delete a resource. The second argument determines if the process that creates the mutex is assigned as the owner of the mutex.
The lpName parameter is the relevant one here, and it is set to LearnMutex.
The last couple of lines of code are only there to allow the mutex to be located in Windows before it is deleted when the process is killed. When the code is run from a Windows terminal, it prints the following:
Execution number 1 Created new mutex
Execution number 2 Cannot create mutex error: 183
Press enter to exitAt this stage, System Informer can be used to inspect the mutex: in File handles and DLLs → filtering for “Mutant” and searching for “LearnMutex” shows two mutants, as in the screenshot below:
There are two handles, since CreateMutex has been executed twice; however, there is only one mutant, as seen from the “Name” column that points to the same file. This behavior makes sense, since the point of the mutex is to have multiple handles, one per thread, to a single object which can be acquired once at a time by each thread. This single underlying object with multiple handles matches the expected behavior of a synchronization primitive. If the for loop upper limit is changed from 2 to 10, 10 handles appear.