2013年1月18日星期五

PsLookupProcessByProcessId.C

/*
本文就暂时命名为PsLookupProcessByProcessId.C吧!
pid与进程名互换,很简单的问题,不削一顾,可到用的时候才知道重要。
网上很多,那是别人的。
还是自己的感觉好,完全懂,还一个修改。
made by correy
made at 2013.01.18
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com

If the call to PsLookupProcessByProcessId is successful, PsLookupProcessByProcessID increases the reference count on the object returned in the Process parameter. 
Consequently, when a driver has completed using the Process parameter, the driver must call ObDereferenceObject to dereference the Process parameter received from the PsLookupProcessByProcessID routine. 
*/

#include <ntddk.h>
#include <ntifs.h> 

extern UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process); //c++ 才需要"C"

DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{

}

HANDLE GetPidFromProcessName(char * ProcessName)
{
    PEPROCESS Process;
    int h;
    CHAR * pName;
    STRING s1,s2;
    for (h = 0; h < 10000; h += 4) //由于PEPROCESS结构不公开,不采用遍历的办法,反而更通用。
    {
        if (PsLookupProcessByProcessId((HANDLE)h, & Process) != STATUS_INVALID_PARAMETER)
        {
            pName = (CHAR*)PsGetProcessImageFileName(Process);//未公开函数。也有替换的办法。
            RtlInitString(&s1, pName);
            RtlInitString(&s2, ProcessName);
            if (RtlEqualString(&s1, &s2, 1))
            {
                DbgPrint("pid == %08d\n",h);
                return (HANDLE)h;
            }
        }
    }
    return (HANDLE)-1;
}

char * GetProcessNameFromPid(HANDLE pid)
{
    PEPROCESS Process;
    if (PsLookupProcessByProcessId(pid, & Process) == STATUS_INVALID_PARAMETER)
    {
        return "pid不存在";
    }
    DbgPrint("ProcessName is %s\n",PsGetProcessImageFileName(Process));
    return (CHAR*)PsGetProcessImageFileName(Process);//未公开函数。也有替换的办法。
}

DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    HANDLE h;
    char * ProcessName;
    //KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
    DriverObject->DriverUnload = Unload;
   
    h = GetPidFromProcessName("explorer.exe");
    ProcessName = GetProcessNameFromPid(h);
    return 0;
}

//////////////////////////////////////////////////////////////////////////////
//改进版,排除了死进程。有一些垃圾的东西。
/*
本文就暂时命名为PsLookupProcessByProcessId.C吧!
pid与进程名互换,很简单的问题,不削一顾,可到用的时候才知道重要。
网上很多,那是别人的。
还是自己的感觉好,完全懂,还可以修改。
made by correy
made at 2013.01.24
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/

#include <ntddk.h>
#include <ntifs.h>  

typedef struct _SYSTEM_THREAD_INFORMATION {
    LARGE_INTEGER KernelTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER CreateTime;
    ULONG WaitTime;
    PVOID StartAddress;
    CLIENT_ID ClientId;
    KPRIORITY Priority;
    KPRIORITY BasePriority;
    ULONG ContextSwitchCount;
    LONG State;
    LONG WaitReason;
} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;

typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG NextEntryDelta;
    ULONG ThreadCount;
    ULONG Reserved1[6];
    LARGE_INTEGER CreateTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER KernelTime;
    UNICODE_STRING ProcessName;
    KPRIORITY BasePriority;
    ULONG ProcessId;
    ULONG InheritedFromProcessId;
    ULONG HandleCount;
    ULONG Reserved2[2];
    VM_COUNTERS VmCounters;
    IO_COUNTERS IoCounters;
    SYSTEM_THREAD_INFORMATION Threads[1];
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;

extern UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process); //c++ 才需要"C"
extern int PsGetProcessExitStatus(PEPROCESS Process);

extern NTSTATUS ZwQuerySystemInformation( int SystemInformationClass,
                          PVOID SystemInformation,
                          ULONG SystemInformationLength,
                          PULONG ReturnLength OPTIONAL);

DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{

}

//HANDLE GetPidFromProcessName(char * ProcessName)
//int IsActiveProcess(int h)
//{//枚举进程
//    NTSTATUS ntStatus;
//    ULONG cbBuffer = 0x8000;
//    PVOID pBuffer = NULL;
//    PSYSTEM_PROCESS_INFORMATION pInfo;
//    UNICODE_STRING us1,us2;
//
//    do {
//        pBuffer = ExAllocatePoolWithTag(NonPagedPool, cbBuffer,'tag');  
//        if (pBuffer == NULL)  {
//            return 0;
//        }
//
//        ntStatus = ZwQuerySystemInformation(5, pBuffer, cbBuffer, NULL);
//        if (ntStatus == STATUS_INFO_LENGTH_MISMATCH)  {
//            ExFreePoolWithTag(pBuffer,'tag');
//            cbBuffer *= 2;
//        } else if (!NT_SUCCESS(ntStatus)) {
//            ExFreePoolWithTag(pBuffer,'tag');
//            return 0;
//        }
//    } while(ntStatus == STATUS_INFO_LENGTH_MISMATCH);
//
//    pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
//    while(TRUE)
//    {
//        /*LPWSTR pszProcessName = pInfo->ProcessName.Buffer;
//        if (pszProcessName == NULL) {
//            pszProcessName = L"NULL";
//        }*/
//
//        DbgPrint("pid == %08d;pname:%wZ\n", pInfo->ProcessId,pInfo->ProcessName.Buffer);
//
//        RtlInitUnicodeString(&us1, pInfo->ProcessName.Buffer);
//        RtlInitUnicodeString(&us2, L"explorer.exe"); ///wgclient.exe
//
//        if (RtlEqualUnicodeString(&us1, &us2, 1))   {
//            ExFreePoolWithTag(pBuffer,'tag');
//            return h;
//        }
//
//        /*if (pInfo->ProcessId == h)   {
//            ExFreePoolWithTag(pBuffer,'tag');
//            return h;
//        }*/
//
//        if (pInfo->NextEntryDelta == 0) {
//            break;
//        }
//        pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo)+pInfo->NextEntryDelta);   
//    }
//
//    ExFreePoolWithTag(pBuffer,'tag');
//}

//用ZwQueryInformationProcess ProcessBasicInformation->ExitStatus的办法没有能实现,
//不用eprocess的exittime和判断ObjectTable是否为0 ,
//更不用ZwQuerySystemInformation的5号功能枚举。
//也没有使用peb的办法。
int IsActiveProcess(int h)
{
    PEPROCESS Process;
    int ExitCode;

    if (PsLookupProcessByProcessId((HANDLE)h, & Process) != STATUS_INVALID_PARAMETER)
    {
        __try
        {
            ExitCode = PsGetProcessExitStatus(Process);
            if (ExitCode == 259) //这个观察所得。
            {
                return 1;
            }
            else //等于1就是退出了。
            {
                return 0;
            }
        }
        __except (1)
        {
            //这时候大多是Process是错误的。
        }
    }

    return 0;
}

HANDLE GetPidFromProcessName(char * ProcessName)
{
    PEPROCESS Process;
    int h;
    CHAR * pName;
    STRING s1,s2;
    KIRQL  OldIrql;

    KeRaiseIrql(APC_LEVEL, &OldIrql);

    for (h = 0; h < 10000; h += 4) //由于PEPROCESS结构不公开,不采用遍历的办法,反而更通用。
    {
        if (PsLookupProcessByProcessId((HANDLE)h, & Process) != STATUS_INVALID_PARAMETER)
        {
            pName = (CHAR*)PsGetProcessImageFileName(Process);//未公开函数。也有替换的办法。

            //如果pName不可以访问,请退出,不然蓝屏。 解决办法是下面加异常处理

            //KeRaiseIrql(APC_LEVEL, &OldIrql);

            __try
            {
                if (!MmIsAddressValid(pName))
                {
                    continue;
                }

                RtlInitString(&s1, pName);
                RtlInitString(&s2, ProcessName);
            }
            __except (1)
            {
                //KeLowerIrql(OldIrql);
                continue;
            }

            //KeLowerIrql(OldIrql);

            //ObDereferenceObject(Process);//加这一行蓝屏。

            if (RtlEqualString(&s1, &s2, 1))
            {
                DbgPrint("pid == %08d\n",h);
                //KeLowerIrql(OldIrql);

                //放置在这里会运行的快一点。放到上一个if语句,运行的很慢。
                //排除已经退出的进程。
                if (IsActiveProcess(h)) 
                {
                    KeLowerIrql(OldIrql);
                    return (HANDLE)h;
                }
            }

            s1.MaximumLength = 0;//释放,避免以后还运行。
            s2.MaximumLength = 0;
        }
    }

    KeLowerIrql(OldIrql);
    return (HANDLE)-1;
}

char * GetProcessNameFromPid1(HANDLE pid)
{
    PEPROCESS Process;

    if (PsLookupProcessByProcessId(pid, & Process) == STATUS_INVALID_PARAMETER)
    {
        return "pid不存在";
    }

    DbgPrint("ProcessName is %s\n",PsGetProcessImageFileName(Process));

    return (CHAR*)PsGetProcessImageFileName(Process);//未公开函数。也有替换的办法。
}

DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    HANDLE h;
    char * ProcessName;
    int b = 0;
    LARGE_INTEGER   interval;

    KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint() 
    DriverObject->DriverUnload = Unload; 

    for (;;)  //主要是测试用的。
    {
        if (b)
        {
            break;
        }

        h = GetPidFromProcessName("explorer.exe");
        ProcessName = GetProcessNameFromPid1(h);
        
        interval.QuadPart = (1 * (((-10) * 1000) * 1000)); //暂停5秒钟。
        KeDelayExecutionThread(KernelMode, FALSE, &interval);//这3行是新添加的.
    }

    return 0;
} 
还有一个种微软公开,但过时的办法:ZwQuerySystemInformation和ZwQueryInformationProcess

没有评论:

发表评论