XP X64 Library Error ? (ProcessIdToFileNameW)

c++ / delphi package - dll injection and api hooking
Post Reply
tbr
Posts: 13
Joined: Thu Mar 01, 2012 12:57 pm

XP X64 Library Error ? (ProcessIdToFileNameW)

Post by tbr »

Dear Madshi,

I am using MadCollection 2.6.2.7 with VS 2010 (C++).
In my injection-DLL callback routines I use the library function ProcessIdToFileNameW.
It works fine except on Windows XP X64 Edition in 64-Bit applications. The whole application closes (crashes without any warning window) when the first call to this function is made.

Do you have any idea on that problem?
Is that library function explicitly tested in that environment?

Thanks,
TBR
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Re: XP X64 Library Error ? (ProcessIdToFileNameW)

Post by madshi »

I've just tested this in w2k3 x64 (which has pretty much the same kernel as XP x64) and it works just fine here. Tested on own process, Explorer.exe and Smss.exe.

Do you happen to have a w2k3 x64 machine flying around somewhere to cross check this? Unfortunately I don't have an XP x64 machine ready for testing atm.

How does your code look like?
tbr
Posts: 13
Joined: Thu Mar 01, 2012 12:57 pm

Re: XP X64 Library Error ? (ProcessIdToFileNameW)

Post by tbr »

Hello Madshi,

I can reproduce the application crashes on Windows Server 2003 R2 X64 SP2, too.
It occurs when a new 64-Bit (or 32-Bit) process has been started (e.g notepad with "Win" + "R") and the shell explorer does a NtOpenProcess with the process ID of the new process. The shell explorer terminates...
Then, when I try to open the "file open" dialog, the notepad process terminates also by making a NtOpenProcess.

I simplified my hook code to the following:

Code: Select all

NTSTATUS NTAPI NtOpenProcessCallback( PHANDLE ProcessHandle, ACCESS_MASK AccessMask, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId ) {
	NTSTATUS result;
	BOOL dummy = TRUE;
	WCHAR fileName[MAX_PATH] = {0};

	ODprintf("0x%p, AccessMask = 0x%08lX, oa = 0x%p, processID = %d, ThreadID = %d", ProcessHandle, AccessMask, ObjectAttributes,  ntId->UniqueProcess, ClientId->UniqueThread);

	ProcessIdToFileNameW((DWORD)ClientId->UniqueProcess, fileName, MAX_PATH);
	ODprintf("ProcessIdToFileNameW = %S");
.
.
.
}
The process terminates before it can make the second debug output (ODprintf).

If I call ProcessIdToFileNameW from DllMain in my hook-DLL with the current process id or a non existent ID or the ID of the system process, it does not crash the current process...
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Re: XP X64 Library Error ? (ProcessIdToFileNameW)

Post by madshi »

How can I easily reproduce the crash? Is there a way without having to inject a DLL? I'm asking because it would be much easier to debug that way...
tbr
Posts: 13
Joined: Thu Mar 01, 2012 12:57 pm

Re: XP X64 Library Error ? (ProcessIdToFileNameW)

Post by tbr »

Hello Madshi,

I am a little confused. I wrote the following test c++ test application and it seems that ProcessIdToFileNameW just calls NtOpenProcess. So it runs into a stack overflow and i never see "b".

Code: Select all

NTSTATUS (NTAPI *NtOpenProcessNext)( PHANDLE ProcessHandle, ACCESS_MASK AccessMask, POBJECT_ATTRIBUTES ObjectAttributes, PHANDLE ClientId ); 

NTSTATUS NTAPI NtOpenProcessCallback(	PHANDLE ProcessHandle, ACCESS_MASK AccessMask,	POBJECT_ATTRIBUTES ObjectAttributes, PHANDLE ClientId ) {
	NTSTATUS result;
	WCHAR buf[MAX_PATH] = {0};

	printf("Hit 0x%p, AccessMask = 0x%08lX, oa = %p, processID = %d, ThreadID = %d\r\n",
		ProcessHandle, AccessMask, ObjectAttributes, ClientId[0], ClientId[1]);
	result = ProcessIdToFileNameW((DWORD)ClientId[0], buf, MAX_PATH);
	_putws(buf);
	result = NtOpenProcessNext(ProcessHandle, AccessMask, ObjectAttributes, ClientId);
	return result;
}

int _tmain(int argc, _TCHAR* argv[]) {
	WCHAR buf[MAX_PATH] = {0};
	BOOL result = FALSE;
	InitializeMadCHook();
	SetMadCHookOption( USE_NEW_IPC_LOGIC, NULL);
	CollectHooks();
	printf("hook %d\r\n", HookAPI("ntdll.dll", "NtOpenProcess", NtOpenProcessCallback, (PVOID*) &NtOpenProcessNext));
	FlushHooks();
	puts("a");
	result = ProcessIdToFileNameW(1000, buf, MAX_PATH);
	puts("b");
	_putws(buf);
	Sleep(2000);
	FinalizeMadCHook();
	return 0;
}
This Application crashes on XP 32, Server2003R2X64 and Windows 7 X64.

My hook DLL also calls ProcessIdToFileNameW in NtOpenProcessCallback. Why does it crash on XP 64 Kernel only?
On debug output i see that NtOpenProcessCallback just returns normally in all windows versions except XP X64 (Kernel).
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Re: XP X64 Library Error ? (ProcessIdToFileNameW)

Post by madshi »

Hmmmmm... Good thinking. I didn't see that there would be endless recursion, but it makes a lot of sense. ProcessIdToFileNameW *has* to open a process handle because that's the best way to get the process file name. Without a process handle that's very hard to do (the only way would be to enumerate all running processes, and it would only give you the process name, not the full path).

To be honest, I don't know why this doesn't crash in win7 x64. It really should.

In the madCodeHook 32bit library I've some extra tricks in there to automatically avoid endless recursion. That explains why it doesn't crash in 32bit. I haven't yet managed to do the same thing in x64 because the calling convention is more difficult/complicated in x64.

What you could do is hack around a bit, because you know that calling ProcessIdToFileNameW will result in an additional NtOpenProcess call. E.g. store the NtOpenProcess threadID into a global TLS slot. Then in your NtOpenProcess callback, let the call pass without calling ProcessIdToFileNameW if the requested processID matches the one in the TLS slot.

An alternative solution would be for me to offer a ProcessHandleToFileNameW function. But I can't do that in 2 minutes, so you would have to wait for that. Furthermore there's no guarantee that the handle returned by NtOpenProcess actually has enough access rights to read the process file name. So I'm not sure if this is really the best solution.
tbr
Posts: 13
Joined: Thu Mar 01, 2012 12:57 pm

Re: XP X64 Library Error ? (ProcessIdToFileNameW)

Post by tbr »

On Win7X64 ProcessIdToFileNameW does not call my NtOpenProcessCallback function...

I implemented a workaround with NtOpenProcessNext and GetModuleFileNameExW already, but (as you said) there may be access rights difficulties with that handle...
I decided to use that workaround with the TLS. It works fine in my tests.
Is it an option to internally store all *Next function Pointers (the original functions) and use them in library functions like ProcessIdToFileNameW? The library knows them at the time, when they are hooked...
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Re: XP X64 Library Error ? (ProcessIdToFileNameW)

Post by madshi »

tbr wrote:Is it an option to internally store all *Next function Pointers (the original functions) and use them in library functions like ProcessIdToFileNameW? The library knows them at the time, when they are hooked...
I'd have to do that for every API I use in any of madCodeHook's APIs. That would cost me like a lifetime to do... :shock:
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: XP X64 Library Error ? (ProcessIdToFileNameW)

Post by iconic »

This is not madCodeHook's fault or any other API hooking library as you know. APIs MUST be called during so such exposed high-level API luxuries can be afforded. Recording any/all APIs used and keeping track of a "clean" API call is possible but the overhead and work is quite unnecessary in the end. There are a million and one ways to deviate from any API hook and call a clean function within, that's your job to find out however.

--Iconic
Post Reply