|
Hi,
I checked out your demo and it works fine. I downloaded the code and it turned out that When I compile the source in Debug Mode, it works fine. But when I make a release build and try running HookDemo.exe, it just pops a cmd screen and shuts down. If I then go to cmd and ask "sc query ntprocdrv", it shows that the service was created, current status is STOPPED and WIN32_EXIT_CODE is 127. Turns out the error 127 is "ERROR_PROC_NOT_FOUND". No immediate reasons for this come to mind. I may be missing something very basic but I'd appreciate if you could shed some light on why I may be getting this Error??
P.S. I placed the tunew20.dll in windows\system32 and it also has a copy in the same folder as HookDemo. Though that didn't make any difference in Debug build because it worked fine, I just though I'd state it just to be clear.
Thanx,
Numan
|
|
|
|
|
The instruction:
call [ebx]
should actually be
call ebx
I didn't think about it at first, and just assumed this was correct to do dereference ebx (which are what the the brackets mean "[]")
But when doing some testing in a VB6 app using the code bytes, it kept crashing.
BTW, if you are curious... I am using the code bytes in VB6 because I am testing out a hook Dll I am creating by hooking NtCreateThread, and then inject my Dll by changing this ThreadContext->Eax register)
After my VB6 app kept crashing, I finally realized that when doing: mov ebx, pLoadLib ... that is like saying ebx = pLoadLib. So really ebx is not a pointer to LoadLibrary's address, but is its actual address, so therefore we do NOT want to dereference it with the "[]"
Note: The follow are just some assembly tips, if you are new to it (like me :P)
If you are an assembly noob like me, then Visual Studio is your friend (I used VS2005)
You can use its debugger window (Hotkey = Alt+6, when in Debug mode) to translate C++ assembly instructions to its equivalent in assembly, and also its code bytes.
Example of using VS to translate these instructions to Asm code and Bytes:
_asm{
push 0x10000000
mov ebx, 0x2000000
call ebx
mov eax, 0x3000000
push eax
ret
}
1. Set a break point on the first instruction (or before it starts executing, to prevent any crashing)
2. Run app in debug mode (F5)
3. Open up the Disassembly window tab using the hotkey: Alt+8
4. Right click --> Check: Show Code Bytes
Note: The underscore "_" is required on the "asm" keyword. A double underscore also works "__" but it seems to do the same thing.
Now it shows the current addresses there this data currently has been placed in memory, the original source code, the assembly equivalent, and the hex byte values(AKA opcodes) that those instructions translate to
Visual studio can also do the reverse and take byte codes and translate them to assembly instructions (This trick was a little harder to find)
To do so you have to use the _emit (Technically the keyword is called "_asm _emit")
Ex:
_asm{
_emit 0xFF
_emit 0xD3
}
Notice how that translates to "call ebx"...
Unfortunately it isn't easy to place these on the same line (well it wasn't easy to figure out at least)... and no semicolons dont work at all.
Here is a mov eax, 10000000 instruction:
_asm _emit 0xB8 _asm _emit 0x00 _asm _emit 0x00 _asm _emit 0x00 _asm _emit 0x10
Yikes!
But here is a way to make it less long for each instruction:
#define bt _asm _emit
bt 0xB8 bt 0x00 bt 0x00 bt 0x00 bt 0x10
Now you can just use the custom defined "bt" keyword.
Yay!
Last Tip...
To see the bytes in a linear format: (Exactly how they appear in memory)
1. From the Disassembly, under each instruction there is an address to the far left side. - Copy it
2. Open up the memory window: Hotkey = Alt+8 (When in debug mode)
3. Type in 0x (for hex) and then paste in the address. Ex: 0x00411A1E
Hopefully this is helpful to someone out there, and also it shows the author and author that that instruction should be:
call ebx, not call [ebx]
modified on Monday, October 5, 2009 9:28 PM
|
|
|
|
|
Is this driver Vista compatible? I am asking this question because I can not see NtCreateThreadEx hooked.
|
|
|
|
|
Hi, I also ran into the "0x431" problem. Could you please possibly tell me your solution? Thanks in advance!
|
|
|
|
|
It's pretty simple - I've just found the registry hive responsible for services (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services) and deleted the key matching our kernel-intercepting service (I don't remember it's name, but it's inside the code of NTProcDrv). Then it works totally fine.
|
|
|
|
|
Hey Guys,
I also am receiving the same error . i am trying to understand your solution but can't....
What exactly did you do to solve the problem.
Michael
|
|
|
|
|
Hi
Every time I run your demo, I receive the following error:
Cannot create service. ErrorCode = 0x431
I've built the demo from source code (using Visual C++ Express Codename Orcas), both Release and Debug, but the error still appears, every time. I executed the app step by step with VC++ debugger, but it doesn't show me any satisfying results. How do I deal with this problem?
Thanks in Advance.
|
|
|
|
|
I must have had an error in my Registry - I've removed the wrong entry, and now the app works fine. BTW, did you forget to close a handle to the Service Manager?
|
|
|
|
|
I want to modify source code for Vista O.S., a handler to NtCreateThreadEx() function, I don't know the parameter type of this function. Please help me, thanks!!!
|
|
|
|
|
I've modified the dllhookapi.cpp to see
1) if I can subclass Notepad.exe successfully within DllMain.
2) if I can subclass multiple instances of Notepad.exe successfully.
The code works this way:
1) Call EnumProcesses to find out all the running processes.
2) Call Subclass with the process id array obtained above and the name of notepad for subclassing.
3) For each process id, Subclass will call EnumProcessModules and GetModuleFileNameEx to get the full module name and repeat this until we find notepad.
4) Now if we have found notepad, call EnumThreadWindows with current thread id to find out the main window to subclass.
Here the problem rises. EnumThreadWindows returns successfully, but EnumThreadWindowsProc NEVER get called. I couldn't understand why. Now I guess it is because somehow the current thread did not create any windows yet. So EnumThreadWindows return TRUE but no EnumThreadWindowsProc call!
But then, how can I subclass notepad right after the creation?
haerim
<br />
<br />
#include "stdafx.h"<br />
#include "windows.h"<br />
<br />
#include <psapi.h><br />
<br />
<br />
<br />
HWND g_hwnd = NULL;<br />
BOOL CALLBACK EnumThreadWindowsProc(HWND hwnd, LPARAM lParam);<br />
WNDPROC OldProc = NULL; <br />
LRESULT CALLBACK NewProc(HWND, UINT, WPARAM, LPARAM);<br />
<br />
<br />
void Subclass(DWORD* paProcess, DWORD nCount, LPCTSTR pName);<br />
<br />
<br />
BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)<br />
{<br />
switch (ul_reason_for_call) {<br />
case DLL_PROCESS_ATTACH:<br />
{<br />
WriteLogDebug("Before starting process.");<br />
<br />
DWORD aProcesses[1024], cbNeeded, cProcesses;<br />
if (EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded) == 0)<br />
{<br />
DWORD dwErr = GetLastError();<br />
WriteLogDebug("DllMain: dwErr=%d", dwErr);<br />
return TRUE;<br />
}<br />
<br />
cProcesses = cbNeeded / sizeof(DWORD);<br />
Subclass(aProcesses, cProcesses, "C:\\Windows\\System32\\notepad.exe");<br />
<br />
break;<br />
}<br />
case DLL_PROCESS_DETACH:<br />
{<br />
WriteLogDebug("Before ending process.");<br />
if (::SetWindowLongPtr(g_hwnd, GWL_WNDPROC, (long)OldProc) == 0)<br />
{<br />
WriteLogDebug("Failed to unsubclass back from NewProc(0x%X) to OldProc(0x%X)", GetWindowLongPtr(g_hwnd, GWL_WNDPROC), (long)OldProc);<br />
}<br />
<br />
break;<br />
}}<br />
<br />
return TRUE;<br />
}<br />
<br />
void Subclass(DWORD* paProcess, DWORD nCount, LPCTSTR pName)<br />
{<br />
WriteLogDebug("Subclass: nCount=%d, pName=%s", nCount, pName);<br />
char szProcessName[MAX_PATH] = "";<br />
<br />
unsigned int i;<br />
for (i = 0; i < nCount; i++)<br />
{<br />
DWORD dwPID = paProcess[i];<br />
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID);<br />
<br />
if (NULL == hProcess)<br />
{<br />
WriteLogDebug("Subclass: dwPID=0x%X(%d), OpenProcess failed!", dwPID, dwPID);<br />
CloseHandle(hProcess);<br />
continue;<br />
}<br />
<br />
DWORD cbNeeded = 0;<br />
HMODULE hMod;<br />
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded) == 0)
{<br />
WriteLogDebug("Subclass: hProcess=0x%X, EnumProcessModules failed!", hProcess);<br />
continue;<br />
}<br />
DWORD nModCount = cbNeeded / sizeof(HMODULE);<br />
WriteLogDebug("Subclass: nModCount=%d", nModCount);<br />
<br />
GetModuleFileNameEx(hProcess, hMod, szProcessName, sizeof(szProcessName));<br />
WriteLogDebug("Subclass: dwPID=0x%X(%u), cbNeeded=%d, %s\n", dwPID, dwPID, cbNeeded, szProcessName);<br />
if (strcmpi(szProcessName, pName) != 0)<br />
{<br />
CloseHandle(hProcess);<br />
continue;<br />
}<br />
<br />
DWORD dwTID = GetCurrentThreadId();<br />
WriteLogDebug("Subclass: dwTID=0x%X", dwTID);<br />
if (EnumThreadWindows(dwTID, EnumThreadWindowsProc, (LPARAM)dwPID) == 0)<br />
{<br />
DWORD dwErr = GetLastError();<br />
WriteLogDebug("Subclass: dwTID=0x%X, dwErr=%d, EnumThreadWindows failed!", dwTID, dwErr);<br />
CloseHandle(hProcess);<br />
continue;<br />
}<br />
<br />
CloseHandle(hProcess);<br />
}<br />
}<br />
<br />
BOOL CALLBACK EnumThreadWindowsProc(HWND hwnd, LPARAM lParam)<br />
{<br />
WriteLogDebug("EnumThreadWindowsProc(0x%X, %d)", hwnd, lParam);<br />
<br />
DWORD dwPID_hwnd = 0, dwTID_hwnd = 0;<br />
dwTID_hwnd = GetWindowThreadProcessId(hwnd, &dwPID_hwnd);<br />
<br />
TCHAR wmfn[MAX_PATH + 1] = {0};<br />
UINT nLen = GetWindowModuleFileName(hwnd, wmfn, MAX_PATH);
WriteLogDebug("EnumThreadWindowsProc: hwnd=0x%X, dwPID_hwnd =0x%X(%d), dwTID_hwnd=0x%X(%d)\n"<br />
" nLen=%d, wmfn=%s",<br />
hwnd, dwPID_hwnd, dwPID_hwnd, dwTID_hwnd, dwTID_hwnd,<br />
nLen, wmfn);<br />
return TRUE;<br />
}<br />
<br />
LRESULT CALLBACK NewProc(<br />
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)<br />
{<br />
switch (uMsg) <br />
{<br />
case WM_COMMAND:<br />
WriteLogDebug("wParam=%d, lParam, HIWORD(wParam)(nNotifyCode)=%d, LOWORD(lParam)(id)=%d=%d", wParam, lParam, HIWORD(wParam), LOWORD(lParam));<br />
if (HIWORD(wParam) == 0)<br />
{<br />
switch(LOWORD(wParam))<br />
{<br />
case 34795:<br />
::MessageBox(NULL,"NULL","hStart",MB_OK);<br />
return S_OK;<br />
case 34796:<br />
return S_OK;<br />
case 34797:<br />
return S_OK;<br />
default:<br />
break;<br />
}<br />
}<br />
}<br />
<br />
return CallWindowProc(OldProc,hwnd,uMsg,wParam,lParam);<br />
}<br />
<br />
<br />
#include <STDIO.H><br />
void inline WriteLog(char *ch, ...)<br />
{<br />
char buf[1024]; <br />
va_list arg_list;<br />
<br />
va_start( arg_list, ch );<br />
wvsprintf( buf, ch, arg_list );<br />
va_end( arg_list );<br />
<br />
FILE *file;<br />
file = fopen("dllhookapi.log", "a+");<br />
fprintf(file, "%s", buf);<br />
fclose(file);<br />
}<br />
<br />
void inline WriteLogDebug(char *ch, ...)<br />
{<br />
char buf[1024]; <br />
va_list arg_list;<br />
<br />
va_start( arg_list, ch );<br />
wvsprintf( buf, ch, arg_list );<br />
va_end( arg_list );<br />
<br />
OutputDebugString(buf);<br />
}<br />
<br />
<br />
<br />
-- modified at 17:11 Friday 5th January, 2007
|
|
|
|
|
There is an executable, A.exe. It can be run multiple times resulting in multiple processes shown in TaskManager's process list.
I care about those processes created by running A.exe only and need to inject dll into them. No other processes should be injected.
The problem is how to filter those processes?
Since NewNtCreateThread is given as
NTSTATUS NewNtCreateThread(<br />
OUT PHANDLE ThreadHandle,<br />
IN ACCESS_MASK DesiredAccess,<br />
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,<br />
IN HANDLE ProcessHandle,<br />
OUT PCLIENT_ID ClientId,<br />
IN PCONTEXT ThreadContext,<br />
IN PINITIAL_TEB InitialTeb,<br />
IN BOOLEAN CreateSuspended);
and there is ProcessHandle, somehow we should be able to get necessary information about the current process and filter out unwanted ones.
ObjectAttributes parameter is always passed as NULL, so ObjectAttributes->ObjectName can't be used at all.
This is the first time in kernel programming, and it is too hard for me to find how.
Please someone help me on this.
haerim
-- modified at 14:07 Sunday 31st December, 2006
|
|
|
|
|
The code below works for WinXP or later to find out the name of full process image name.
typedef NTSTATUS (*QUERY_INFO_PROCESS) (<br />
__in HANDLE ProcessHandle,<br />
__in PROCESSINFOCLASS ProcessInformationClass,<br />
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,<br />
__in ULONG ProcessInformationLength,<br />
__out_opt PULONG ReturnLength<br />
);<br />
<br />
QUERY_INFO_PROCESS ZwQueryInformationProcess;<br />
<br />
NTSTATUS GetProcessImageName(PUNICODE_STRING ProcessImageName)<br />
{<br />
NTSTATUS status;<br />
ULONG returnedLength;<br />
ULONG bufferLength;<br />
PVOID buffer;<br />
PUNICODE_STRING imageName;<br />
<br />
PAGED_CODE();
<br />
if (NULL == ZwQueryInformationProcess) {<br />
<br />
UNICODE_STRING routineName;<br />
<br />
RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess");<br />
<br />
ZwQueryInformationProcess = <br />
(QUERY_INFO_PROCESS) MmGetSystemRoutineAddress(&routineName);<br />
<br />
if (NULL == ZwQueryInformationProcess) {<br />
DbgPrint("Cannot resolve ZwQueryInformationProcess\n");<br />
}<br />
}<br />
status = ZwQueryInformationProcess( NtCurrentProcess(), <br />
ProcessImageFileName,<br />
NULL,
0,
&returnedLength);<br />
<br />
if (STATUS_INFO_LENGTH_MISMATCH != status) {<br />
<br />
return status;<br />
<br />
}<br />
<br />
bufferLength = returnedLength - sizeof(UNICODE_STRING);<br />
<br />
if (ProcessImageName->MaximumLength < bufferLength) {<br />
<br />
ProcessImageName->Length = (USHORT) bufferLength;<br />
<br />
return STATUS_BUFFER_OVERFLOW;<br />
<br />
}<br />
<br />
buffer = ExAllocatePoolWithTag(PagedPool, returnedLength, 'ipgD');<br />
<br />
if (NULL == buffer) {<br />
<br />
return STATUS_INSUFFICIENT_RESOURCES;<br />
<br />
}<br />
<br />
status = ZwQueryInformationProcess( NtCurrentProcess(), <br />
ProcessImageFileName,<br />
buffer,<br />
returnedLength,<br />
&returnedLength);<br />
<br />
if (NT_SUCCESS(status)) {<br />
imageName = (PUNICODE_STRING) buffer;<br />
<br />
RtlCopyUnicodeString(ProcessImageName, imageName);<br />
<br />
}<br />
<br />
ExFreePool(buffer);<br />
<br />
return status;<br />
<br />
}
|
|
|
|
|
The below is log after hooking.
As you see, ProcessHandle was 0x240 when it was created by NtCreateProcessEx.
But, when it was terminated by NtTerminateProcess it was NULL. Why? and How does the kernel terminate a process with a NULL handle?
Can anyone explain?
haerim
========= Log by DBGPRINT ===================
In DriverEntry
Memory for Pool successfully initialized
receiving IOCTL_NTPROCDRV_SET_ADDRNFO ok!
Trying to hook srvices
Setting hook on SSTIndexNtCreateProcess = 0x0000002F
Setting hook on SSTIndexNtCreateThread = 0x00000035
Setting hook on SSTIndexNtTerminateProcess = 0x00000101
Setting hook on pfnLoadLibrary = 0x7C80AE4B
Setting hook on SSTIndexNtCreateProcessEx = 0x00000030
In NtCreateProcessEx
Kernel successfully create NtCreateProcessEx.
----->ProcessHandle = 0x240
Successfully added process handle to Queue
ObjectAttributes = 0x00000000Kernel trying to CreateThread(from User Mode) for ProcessHandle = 0x240
Address of LoadLibraryW = 0x7C80AE4B
---------------Memory allocation OK! BaseAddr = 0x80000
---------------Old EAX Value = 0x0100739d
Kernel sucessfully create new thread.
----->ThreadHandle = 0x1fch for ProcessHandle = 0x240
Called NtTerminateProcess, ProcessHandle=0x00000000
Kernel sucessfully terminate Process.
----->ProcessHandle = 0x00000000
Called NtTerminateProcess, ProcessHandle=0x00000000
ObjectAttributes = 0x00000000
Kernel sucessfully create new thread.
----->ThreadHandle = 0x2d4h for ProcessHandle = 0xffffffff
ObjectAttributes = 0x00000000
Kernel sucessfully create new thread.
----->ThreadHandle = 0x1e0h for ProcessHandle = 0xffffffff
In NtCreateProcessEx
Kernel successfully create NtCreateProcessEx.
----->ProcessHandle = 0x14c
Successfully added process handle to Queue
ObjectAttributes = 0x00000000
Kernel trying to CreateThread(from User Mode) for ProcessHandle = 0x14C
Address of LoadLibraryW = 0x7C80AE4B
---------------Memory allocation OK! BaseAddr = 0x130000
---------------Old EAX Value = 0x004034af
Kernel sucessfully create new thread.
----->ThreadHandle = 0x150h for ProcessHandle = 0x14c
ObjectAttributes = 0x00000000
Kernel sucessfully create new thread.
----->ThreadHandle = 0x470h for ProcessHandle = 0xffffffff
ObjectAttributes = 0x00000000
Kernel sucessfully create new thread.
----->ThreadHandle = 0x470h for ProcessHandle = 0xffffffff
|
|
|
|
|
BOOL WINAPI DllMain( HANDLE hModule, <br />
DWORD ul_reason_for_call, <br />
LPVOID lpReserved<br />
)<br />
{<br />
switch (ul_reason_for_call)<br />
{<br />
case DLL_PROCESS_ATTACH:<br />
MessageBox(NULL,"Before starting process.","Hello",0);<br />
break;<br />
case DLL_PROCESS_DETACH:<br />
MessageBox(NULL,"Before ending.","Hello",0);<br />
break;<br />
}<br />
<br />
return TRUE;<br />
}
When a Notepad process is created there certaily a "Hello" messagebox saying "Before starting process." shows up along with a bell sound. I have to press OK to continue. And, when it is terminated, I expected to see another "Hello" messagebox saying "Before ending." along with a bell sound, too. When I close NotePad.exe, however, no messagebox was shown but only a bell sound.
Why didn't the second messagebox show up but only a bell sound? How did it disappear without me pressing OK button at all?
haerim
|
|
|
|
|
|
You need the NTDDK to be installed on your computer. I'm using MSVS 6.0 for compiling NtProcDrv, and MSVS 7.1 for the rest of the projects.
|
|
|
|
|
I've been playing around with HookInjEx(http://www.codeproject.com/threads/winspy.asp?df=100&forumid=16291&select=1784407&msg=1784407[^]) which worked fine for a single instance of Notepad.exe.
However, when I run two Notepad instances, the injection worked for only one instance and not for the other one.
Is there any nice and clean way to make hooking work for all the instances?
One possible way is to use PsSetCreateProcessNotifyRoutine mentioned in this article.
Please provide a good working example if possible.
haerim
-- modified at 12:37 Friday 1st December, 2006
|
|
|
|
|
|
Hi Andriy,
Thanks for this usefull information. I've been trying it since this morning. The hookdemo.exe is running in the background and I get start and end messages for applications.
However I encountered some problems with some programs.
Excel: Whenever I try to open an Excel document by double-clicking on the file, Excel cannot open the document. It starts with an empty screen.
Visual studio: Try to open a *.cs file by double clicking. It shows process start messagebox. Just after this another messagebox pops up saying that it could not find the file. However I didn't click on the first messagebox coming from the hooking dll and theoretically there is no way that the application continues before I press OK on the first messagebox. How does this happen?
Adobe Acrobat reader: Open a pdf file by double clicking. Acrobat reader gives a memory error on exit.
There seems to be a problem in starting programs with parameters. Do you have any idea?
Thanks in advance
oky
|
|
|
|
|
I haven't had time for exploring the problem.
Try to change MessageBoxes in DLL with some kind of logging. In that case sample code will work fine.
|
|
|
|
|
Awesome article !!
I am trying to figure out how to adapt it to the "API Hooking revealed" from Mr Ivanov ...
and since I am very new to kernel driver programing ... its ... well .. painfull.
I need to be able to know the executable name in order to know if I need to inject a dll in it or not.
I guess this information is to be grabbed from the process handle ... but since all this is in the driver code all my attemps failed.
Could you help me
thxs
|
|
|
|
|
You can simply do it in DLL. Just get process name (in DllMain) and do nothing if it is not your target.
|
|
|
|
|
Thanks for your answer,
Yes I did think about doing it in DLLMain (I did it in fact it works fine)
But this is not an answer to my original question : I need to know the process name before injecting the dll ... otherwhile it means that I will inject the DLL in any process that starts : and this is what i would like avoid.
thanks in advance
Marc
PS: I've previously forgotten to rate you a deserved 5, now its done ,
PPS: didn't get notified of your answer by CP sorry it tooks so much time to post again
|
|
|
|
|
Unfortunately I don't know the answer and I have no time to find it.
|
|
|
|
|
The code below will give you the process name within the NtProcDrv driver. But this will work only on Win XP or later.
I haven't found an answer for Win2K. If you have found, let me know.
haerim
typedef NTSTATUS (*QUERY_INFO_PROCESS) (<br />
__in HANDLE ProcessHandle,<br />
__in PROCESSINFOCLASS ProcessInformationClass,<br />
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,<br />
__in ULONG ProcessInformationLength,<br />
__out_opt PULONG ReturnLength<br />
);<br />
<br />
QUERY_INFO_PROCESS ZwQueryInformationProcess;<br />
<br />
NTSTATUS GetProcessImageName(PUNICODE_STRING ProcessImageName)<br />
{<br />
NTSTATUS status;<br />
ULONG returnedLength;<br />
ULONG bufferLength;<br />
PVOID buffer;<br />
PUNICODE_STRING imageName;<br />
<br />
PAGED_CODE();
<br />
if (NULL == ZwQueryInformationProcess) {<br />
<br />
UNICODE_STRING routineName;<br />
<br />
RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess");<br />
<br />
ZwQueryInformationProcess = <br />
(QUERY_INFO_PROCESS) MmGetSystemRoutineAddress(&routineName);<br />
<br />
if (NULL == ZwQueryInformationProcess) {<br />
DbgPrint("Cannot resolve ZwQueryInformationProcess\n");<br />
}<br />
}<br />
status = ZwQueryInformationProcess( NtCurrentProcess(), <br />
ProcessImageFileName,<br />
NULL,
0,
&returnedLength);<br />
<br />
if (STATUS_INFO_LENGTH_MISMATCH != status) {<br />
<br />
return status;<br />
<br />
}<br />
<br />
bufferLength = returnedLength - sizeof(UNICODE_STRING);<br />
<br />
if (ProcessImageName->MaximumLength < bufferLength) {<br />
<br />
ProcessImageName->Length = (USHORT) bufferLength;<br />
<br />
return STATUS_BUFFER_OVERFLOW;<br />
<br />
}<br />
<br />
buffer = ExAllocatePoolWithTag(PagedPool, returnedLength, 'ipgD');<br />
<br />
if (NULL == buffer) {<br />
<br />
return STATUS_INSUFFICIENT_RESOURCES;<br />
<br />
}<br />
<br />
status = ZwQueryInformationProcess( NtCurrentProcess(), <br />
ProcessImageFileName,<br />
buffer,<br />
returnedLength,<br />
&returnedLength);<br />
<br />
if (NT_SUCCESS(status)) {<br />
imageName = (PUNICODE_STRING) buffer;<br />
<br />
RtlCopyUnicodeString(ProcessImageName, imageName);<br />
<br />
}<br />
<br />
ExFreePool(buffer);<br />
<br />
return status;<br />
<br />
}
|
|
|
|
|