DynamoRIO / DynamoRIO/dynamorio

HANGS when getting process information with NtQuerySystemInformation in post-hook

Open
#5,794 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
3.2k
Forks
629
Avg merge
2d 15h
Merged PRs (30d)
31

Description

**Describe the bug**
DynamoRIO hangs when a client want to access process name if an application enumerate processes with EnumProcesses
**To Reproduce**
Steps to reproduce the behavior:
1. 1) In the sample application, create the function that enumerate processes, like this (ref: MSDN):

```
void PrintProcessNameAndID(DWORD processID)
{
WCHAR szProcessName[MAX_PATH] = L"";

// Get a handle to the process.

HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID);

// Get the process name.

if (NULL != hProcess)
{
HMODULE hMod;
DWORD cbNeeded;

if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),
&cbNeeded))
{
GetModuleBaseName(hProcess, hMod, szProcessName,
sizeof(szProcessName) / sizeof(TCHAR));
}
}

// Print the process name and identifier.

printf("%ls (PID: %u)\n", szProcessName, processID);

// Release the handle to the process.

CloseHandle(hProcess);
}

void enumprocesses_EnumProcesses() {

// Get the list of process identifiers.

DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;

if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
{
return;
}

// Calculate how many process identifiers were returned.

cProcesses = cbNeeded / sizeof(DWORD);

// Print the name and process identifier for each process.

for (i = 0; i < cProcesses; i++)
{
if (aProcesses[i] != 0)
{
PrintProcessNameAndID(aProcesses[i]);
}
}
}
```
1.2) Then in the client hook the NtQuerySystemInformation using DR's default syscall APIs (like the code used in this sample tool: https://github.com/DynamoRIO/dynamorio/blob/master/api/samples/syscall.c)

1.3) When NtQuerySystemInformation class param equals to SystemProcessInformation, the second parameter will be of type SYSTEM_PROCESS_INFORMATION. Just make an access the UNICODE_STRING field of SYSTEM_PROCESS_INFORMATION parameter. The following code is provided for the post hook callback:
```
PSYSTEM_PROCESS_INFORMATION spi = (PSYSTEM_PROCESS_INFORMATION)spi_obj; // got from pre-hook with dr_syscall_get_param(drcontext, 1) and saved in a CLS structure in order to retrieve it in the post-hook;
while (spi->NextEntryOffset) // Loop over the list until we reach the last entry.
{
UNICODE_STRING str = *(UNICODE_STRING*)(spi + offsetof(SYSTEM_PROCESS_INFORMATION, ImageName));
}
```

1.3) Execute the application under DynamoRIO

2. Precise command line for running the application.
bin32\drrun.exe -c

4. Exact output or incorrect behavior.
It hangs and no output is showed

Please also answer these questions:
- What happens when you run without any client? Application execute normally
- What happens when you run with debug build ("-debug" flag to drrun/drconfig/drinject)? It hangs and no relevant information is showed

**Expected behavior**
Expected: DynamoRIO continues

**Versions**
- What version of DynamoRIO are you using? drrun version 9.0.19328 -- build 0
- Does the latest build from https://github.com/DynamoRIO/dynamorio/releases solve the problem? No
- What operating system version are you running on? ("Windows 10" is *not* sufficient: give the release number.) Win10 - Version 22H2 - OS build: 19045.2251
- Is your application 32-bit or 64-bit? Application is compiled for x86 with Visual studio

**Additional context**
If we enumerate processes using directly NtQuerySystemInformation, it would continue normally. It hangs only if the application uses EnumProcesses and we intercept the underlying matching syscall to access the process name.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.