2014年5月7日星期三

在驱动中获取进程的全路径

#include <ntifs.h>

/*
功能:获取进程的全路径。
优点:进程的名字没有15-16个字符的限制。

此办法早就知道,一直没有实验成功。
今天用DBGVIEW.EXE观察成功,但是没有用WINDBG.EXE调试。

尽管MSDN上这样说:
ZwQueryInformationProcess may be altered or unavailable in future versions of Windows. 
Applications should use the alternate functions listed in this topic.
可是ProcessImageFileName的功能也没有说没有替代的函数。

made by correy
made at 2014.05.06
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com
*/

#define tag  'tset' //test

//2008版本的MSDN,非WDK。
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms687420(v=vs.85).aspx
//上面的一些标注在低版本上的WDK出错。
NTSTATUS /* WINAPI */ ZwQueryInformationProcess(
  __in          HANDLE ProcessHandle,
  __in          PROCESSINFOCLASS ProcessInformationClass,
  __out         PVOID ProcessInformation,
  __in          ULONG ProcessInformationLength,
  __out_opt     PULONG ReturnLength
);

void print_ProcessImageFileName(IN HANDLE PId)
{
    NTSTATUS status = 0;
    PVOID us_ProcessImageFileName = 0;//UNICODE_STRING
    ULONG ProcessInformationLength = 0;
    ULONG ReturnLength = 0;
    PEPROCESS  EProcess = 0;
    HANDLE  Handle = 0;

    /*
    必须转换一下,不然是无效的句柄。
    大概是句柄的类型转换为内核的。
    */
    status = PsLookupProcessByProcessId(PId, &EProcess);
    if (!NT_SUCCESS( status )) 
    {
        KdPrint(("PsLookupProcessByProcessId fail with 0x%x in line %d\n",status, __LINE__));
        return;        
    }
    ObDereferenceObject(EProcess); //微软建议加上。
    status = ObOpenObjectByPointer(EProcess, OBJ_KERNEL_HANDLE, NULL, GENERIC_READ, *PsProcessType, KernelMode, &Handle);//注意要关闭句柄。  
    if (!NT_SUCCESS( status )) 
    {
        KdPrint(("ObOpenObjectByPointer fail with 0x%x in line %d\n",status, __LINE__));
        return;        
    }

    //获取需要的内存。
    status = ZwQueryInformationProcess(Handle, ProcessImageFileName,us_ProcessImageFileName, ProcessInformationLength, &ReturnLength);
    if( !NT_SUCCESS( status ) && status != STATUS_INFO_LENGTH_MISMATCH)
    { 
        KdPrint(("ZwQueryInformationProcess fail with 0x%x in line %d\n",status, __LINE__));
        ZwClose(Handle);
        return;
    }
    ProcessInformationLength = ReturnLength;
    us_ProcessImageFileName = ExAllocatePoolWithTag( NonPagedPool, ReturnLength, tag);
    if (us_ProcessImageFileName == NULL) {
        KdPrint(("ExAllocatePoolWithTag fail with 0x%x\n",status));
        status = STATUS_INSUFFICIENT_RESOURCES;
        ZwClose(Handle);
        return;
    }
    RtlZeroMemory(us_ProcessImageFileName, ReturnLength);

    status = ZwQueryInformationProcess(Handle, ProcessImageFileName,us_ProcessImageFileName, ProcessInformationLength, &ReturnLength);
    if( !NT_SUCCESS( status ) )
    {
        KdPrint(("ZwQueryInformationProcess fail with 0x%x in line %d\n",status, __LINE__));
        ExFreePoolWithTag( us_ProcessImageFileName, tag );
        ZwClose(Handle);
        return;
    }

    KdPrint(("ProcessImageFileName:%wZ\n",us_ProcessImageFileName));//注意:中间有汉字是不会显示的。
    //形如:ProcessImageFileName:\Device\HarddiskVolume1\aa\Dbgvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvview.exe

    ExFreePoolWithTag( us_ProcessImageFileName, tag );
    ZwClose(Handle);
}

VOID ProcessCreateMon ( IN HANDLE hParentId, IN HANDLE PId,IN BOOLEAN bCreate )
{
    if ( bCreate )
    {
        print_ProcessImageFileName(PId);
    }
    else
    {
        DbgPrint( "TERMINATED == PROCESS ID: %d\n", PId);
    }
}

DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;

    status = PsSetCreateProcessNotifyRoutine(ProcessCreateMon, TRUE);
    if (!NT_SUCCESS( status )) 
    {
        DbgPrint( "PsSetCreateProcessNotifyRoutine fail %d\n", status);
        return;
    }
}

DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    BOOLEAN b = 0;

    KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint() 

    DriverObject->DriverUnload = Unload;     

    status = PsSetCreateProcessNotifyRoutine(ProcessCreateMon, FALSE);    
    if (!NT_SUCCESS( status )) 
    {
        DbgPrint( "PsSetCreateProcessNotifyRoutine fail %d\n", status);
        return status;
    }

    return 0;//STATUS_SUCCESS
} 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <ntifs.h>
#include <windef.h>

/*
写作目的:
工作中的一次试验:拦截test.exe的某个操作。可死活拦截不了,郁闷了几天,在同事的探讨中发现了这个问题。
1.eprocees 中:ImageFileName    : [15]  ""
2.运行PsGetProcessImageFileName后,发现:
kd> db rax
fffffa80`1aed78b0  74 65 73 74 2e 65 78 65-70 70 6c 69 63 61 00 02  test.exepplica..
3.其实还有个限制就是不能超过15-16个字符。

这些问题百年不遇,以前用的好好的,今天突然出现这些问题,而且概率性还挺高的。
所以选用别的办法,放弃此函数。
以此纪念。

made by correy
made at 2014.06.17
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com
*/

#define tag  'tset' //test

//2008版本的MSDN,非WDK。
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms687420(v=vs.85).aspx
//上面的一些标注在低版本上的WDK出错。
NTSTATUS /* WINAPI */ ZwQueryInformationProcess(
  __in          HANDLE ProcessHandle,
  __in          PROCESSINFOCLASS ProcessInformationClass,
  __out         PVOID ProcessInformation,
  __in          ULONG ProcessInformationLength,
  __out_opt     PULONG ReturnLength
);


BOOL GetProcessImageFileName(IN HANDLE PId, OUT UNICODE_STRING * file_name )
{
    NTSTATUS status = 0;
    PVOID us_ProcessImageFileName = 0;//UNICODE_STRING
    ULONG ProcessInformationLength = 0;
    ULONG ReturnLength = 0;
    PEPROCESS  EProcess = 0;
    HANDLE  Handle = 0;
    UNICODE_STRING * p = {0};
    UNICODE_STRING temp = {0};
    USHORT i = 0;

    /*
    必须转换一下,不然是无效的句柄。
    大概是句柄的类型转换为内核的。
    */
    status = PsLookupProcessByProcessId(PId, &EProcess);
    if (!NT_SUCCESS( status )) 
    {
        KdPrint(("PsLookupProcessByProcessId fail with 0x%x in line %d\n",status, __LINE__));
        return FALSE ;        
    }
    ObDereferenceObject(EProcess); //微软建议加上。
    status = ObOpenObjectByPointer(EProcess, OBJ_KERNEL_HANDLE, NULL, GENERIC_READ, *PsProcessType, KernelMode, &Handle);//注意要关闭句柄。  
    if (!NT_SUCCESS( status )) 
    {
        KdPrint(("ObOpenObjectByPointer fail with 0x%x in line %d\n",status, __LINE__));
        return FALSE;        
    }

    //获取需要的内存。
    status = ZwQueryInformationProcess(Handle, ProcessImageFileName,us_ProcessImageFileName, ProcessInformationLength, &ReturnLength);
    if( !NT_SUCCESS( status ) && status != STATUS_INFO_LENGTH_MISMATCH)
    { 
        KdPrint(("ZwQueryInformationProcess fail with 0x%x in line %d\n",status, __LINE__));
        ZwClose(Handle);
        return FALSE ;
    }
    ProcessInformationLength = ReturnLength;
    us_ProcessImageFileName = ExAllocatePoolWithTag( NonPagedPool, ReturnLength, tag);
    if (us_ProcessImageFileName == NULL) {
        KdPrint(("ExAllocatePoolWithTag fail with 0x%x\n",status));
        status = STATUS_INSUFFICIENT_RESOURCES;
        ZwClose(Handle);
        return FALSE ;
    }
    RtlZeroMemory(us_ProcessImageFileName, ReturnLength);

    status = ZwQueryInformationProcess(Handle, ProcessImageFileName,us_ProcessImageFileName, ProcessInformationLength, &ReturnLength);
    if( !NT_SUCCESS( status ) )
    {
        KdPrint(("ZwQueryInformationProcess fail with 0x%x in line %d\n",status, __LINE__));
        ExFreePoolWithTag( us_ProcessImageFileName, tag );
        ZwClose(Handle);
        return FALSE ;
    }

    //KdPrint(("ProcessImageFileName:%wZ\n",us_ProcessImageFileName));//注意:中间有汉字是不会显示的。
    //形如:ProcessImageFileName:\Device\HarddiskVolume1\aa\Dbgvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvview.exe
    p = (UNICODE_STRING *)us_ProcessImageFileName;

    //从末尾开始搜索斜杠。
    for (i = p->Length/2 - 1 ; ;i-- )
    {
        if (p->Buffer[i] == L'\\')
        {
            break;
        }
    }

    i++;//跳过斜杠。

    //构造文件名结构,复制用的。
    temp.Length = p->Length - i * 2;
    temp.MaximumLength = p->MaximumLength - i * 2;
    temp.Buffer = &p->Buffer[i];

    //这个内存由调用者释放。
    file_name->Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, tag);
    if (file_name->Buffer == NULL) { 
        DbgPrint("发生错误的文件为:%s, 代码行为:%d\n", __FILE__, __LINE__);
        ExFreePoolWithTag( us_ProcessImageFileName, tag );
        ZwClose(Handle);
        return FALSE ;
    }
    RtlZeroMemory(file_name->Buffer, MAX_PATH);
    RtlInitEmptyUnicodeString(file_name, file_name->Buffer,MAX_PATH);

    RtlCopyUnicodeString(file_name, &temp);
    KdPrint(("ProcessImageFileName:%wZ\n",file_name));

    ExFreePoolWithTag( us_ProcessImageFileName, tag );
    ZwClose(Handle);
    return TRUE ;
}


VOID ProcessCreateMon ( IN HANDLE hParentId, IN HANDLE PId,IN BOOLEAN bCreate )
{
    UNICODE_STRING file_name;
    BOOL B = FALSE ;

    if ( bCreate )
    {
        B = GetProcessImageFileName(PId,  &file_name );
        if (!B)
        {
            DbgPrint( "GetProcessImageFileName fail!\n");
        }
        RtlFreeUnicodeString(&file_name);
    }
    else
    {
        DbgPrint( "TERMINATED == PROCESS ID: %d\n", PId);
    }
}


DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;

    status = PsSetCreateProcessNotifyRoutine(ProcessCreateMon, TRUE);
    if (!NT_SUCCESS( status )) 
    {
        DbgPrint( "PsSetCreateProcessNotifyRoutine fail %d\n", status);
        return;
    }
}


DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    BOOLEAN b = 0;

    KdBreakPoint();

    DriverObject->DriverUnload = Unload;     

    status = PsSetCreateProcessNotifyRoutine(ProcessCreateMon, FALSE);    
    if (!NT_SUCCESS( status )) 
    {
        DbgPrint( "PsSetCreateProcessNotifyRoutine fail %d\n", status);
        return status;
    }

    return 0;//STATUS_SUCCESS
} 

没有评论:

发表评论