【转】[内核/驱动]驱动中获取进程全路径和注册表全路径

转载地址: http://blog.sina.com.cn/s/blog_60a1a51d0100e78g.html

2008.07.05
    经过这几天的努力,注册表保护驱动已经基本稳定。很多人都在网上问如何获取访问注册表的进程全路径和被访问的注册表的全路径,下面就将部分代码贴出来。

//驱动中获取被访问注册表的全路径
BOOLEAN GetRegFullPath(HANDLE KeyHandle,
       PUNICODE_STRING pRegFullPath)
{
    POBJECT pKey = NULL;
    BOOLEAN bSucc = TRUE;

    //由句柄得到对象指针
    pKey = GetPointer(KeyHandle);
    if (NULL == pKey)
    {
        bSucc = FALSE;
        goto BeforeLeave;
    }

    //减少引用计数
    ReleasePointer(pKey);

    ULONG uActualLen = 0;
    __try
    {
        //查询注册表项(注意这里是项)全路径
        if(!NT_SUCCESS(ObQueryNameString(pKey,
            (OBJECT_NAME_INFORMATION*)pRegFullPath,
            MAXPATHLEN,
            &uActualLen)))
        {
            bSucc = FALSE;
            goto BeforeLeave;
        }
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        KdPrint(("GetRegFullPath ObQueryNameString Exception!"));
        bSucc = FALSE;
        goto BeforeLeave;
    }

    BeforeLeave:
        return bSucc;
}

//由句柄得到对象指针
POBJECT GetPointer(HANDLE KeyOrHandle)
{
    POBJECT pKey = NULL;

    if(!KeyOrHandle)
    {
        return NULL;
    }

    // Make sure that we‘re not going to access
    // the kernel handle table from a non-system process
    //
    if((LONG)(ULONG_PTR) KeyOrHandle < 0 &&
        ExGetPreviousMode() != KernelMode)
    {
        return NULL;
    }

    if(!NT_SUCCESS(ObReferenceObjectByHandle(KeyOrHandle,
        0,
        NULL,
        KernelMode,
        &pKey,
        NULL)))
    {
        KdPrint(("Error %x getting key pointer\n"));
        pKey = NULL;
    } 

    return pKey;
}

//减少引用计数
VOID ReleasePointer(POBJECT object)
{
    if(object) ObDereferenceObject(object);
}

//使用方法
……
PUNICODE_STRING pRegFullPath = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool,
    MAXPATHLEN * sizeof(WCHAR) + 2 * sizeof(ULONG),
    ‘abcd‘);
GetRegFullPath(pRegFullPath );
KdPrint(("%wZ", pRegFullPath ));
ExFreePoolWithTag(pRegFullPath, ‘abcd‘);
……
//至于为什么要这样申请内存,下面这个链接给出了解释:
http://hi.baidu.com/1ian9yu/blog/item/a41cbadd73576adf8c102931.html

//驱动中获取访问注册表的进程全路径
有好几种方法:有一篇博文写的很清楚,下面是链接:http://hi.baidu.com/30571/blog/item/a718e52252e2304cac34de7d.html
下面给出我试过的两种方法:
第一种:EPROCESS->PEB->ProcessParameters->ImagePathName
要想很好地理解下面的代码,建议在WinDbg下使用命令 dt _EPROCESS(更详细的命令请查help)等查看相关结构,自己算一下面代码中的偏移量。这段代码在Windows 2000 / Windows XP 下都可以使用,缺点在上面那个链接里面写的很清楚。
PWCHAR GetProcessFullPath()
{
    if(KeGetCurrentIrql() != PASSIVE_LEVEL)
    {
        return NULL;
    }

    //返回的是PEPROCESS类型
    //dwAddress是EPROCESS的地址
    DWORD dwAddress = (DWORD)PsGetCurrentProcess();
    if(dwAddress == 0 || dwAddress == 0xFFFFFFFF)
    {
        return NULL;
    }
    //dwAddress是EPROCESS中PEB*成员的地址
    dwAddress += 0x1B0;
    //dwAddress是PEB*
    if((dwAddress = *(DWORD*)dwAddress) == 0)
    {
        return 0;
    }
    //dwAddress是PEB中的ProcessParameters(PRTL_USER_PROCESS_PARAMETERS类型)的地址
    dwAddress += 0x10;
    //dwAddress是ProcessParameters(PRTL_USER_PROCESS_PARAMETERS类型)
    if((dwAddress = *(DWORD*)dwAddress) == 0)
    {
        return 0;
    }
    //dwAddress是ImagePathName(UNICODE_STRING)的地址
    dwAddress += 0x3C;
    //dwAddress是ImagePathName(UNICODE_STRING)
    if((dwAddress = *(DWORD*)dwAddress) == 0)
    {
        return 0;
    }

    return (PWCHAR)dwAddress;
}

第二种:
自己写了一段测试代码,比较乱哈,但这种方法确实是可行的,不过貌似只能在Windows XP上使用。
DWORD GetCurrentProcessFullPath(WCHAR *pImageName)
{
    KIRQL CurIRQL;
    NTSTATUS QueryStatus;
    ULONG returnedLength;
    PVOID buffer = NULL;
    UNICODE_STRING ImageName;
    DWORD dwRet = 0;
    NTSTATUS CreateStatus;
    HANDLE FileHandle = NULL;
    OBJECT_ATTRIBUTES ObjAttrib;
    IO_STATUS_BLOCK IoStatusBlock;
    PFILE_OBJECT pFileObj;
    NTSTATUS ReferenceStatus;
    NTSTATUS DeviceToDosStatus;
    WCHAR wcVolume;
    WCHAR wszDeviceNameTemp[10] = L"\\??\\X:";
    WCHAR wszDeviceName[10] = {0};
    UNICODE_STRING DeviceName;
    OBJECT_ATTRIBUTES ob;
    HANDLE LinkHandle;
    ULONG rt;
    UNICODE_STRING VolumeName;
    WCHAR BufferVolume[32] = L"";
    UNICODE_STRING FullPath;
    WCHAR BufferPath[MAXPATHLEN] = L"";

    PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process

    CurIRQL = KeGetCurrentIrql();
        if (PASSIVE_LEVEL != CurIRQL)
    {
        dwRet = 1;
        goto BeforeLeave;
    }

    __try
    {
        if (!MmIsAddressValid(pImageName))
        {
            dwRet = 1;
            goto BeforeLeave;
        }
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        dwRet = 1;
        goto BeforeLeave;
    }

    if (NULL == ZwQueryInformationProcess)
    {
        //获取ZwQueryInformationProcess函数的地址
        UNICODE_STRING routineName;
        RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess");
        ZwQueryInformationProcess = (ZWQUERYINFORMATIONPROCESS)MmGetSystemRoutineAddress(&routineName);
        if (NULL == ZwQueryInformationProcess)
        {
            dwRet = 1;
            goto BeforeLeave;
        }
    }

    //获取保存进程路径需要的buffer长度
    QueryStatus = ZwQueryInformationProcess(NtCurrentProcess(),
        ProcessImageFileName,
        NULL,
        0,
        &returnedLength);

    if (STATUS_INFO_LENGTH_MISMATCH != QueryStatus)
    {
        dwRet = 1;
        goto BeforeLeave;
    }

    buffer = ExAllocatePoolWithTag(NonPagedPool,
        returnedLength,
        ‘ipgD‘);

    if (NULL == buffer)
    {
        dwRet = 1;
        goto BeforeLeave;
    }

    __try
    {
        QueryStatus = ZwQueryInformationProcess(NtCurrentProcess(),
            ProcessImageFileName,
            buffer,
            returnedLength,
            &returnedLength);

        if (!NT_SUCCESS(QueryStatus))
        {
            dwRet = 1;
            goto BeforeLeave;
        }

        InitializeObjectAttributes(&ObjAttrib,
            (PUNICODE_STRING)buffer,
            OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
            NULL,
            NULL);

        CreateStatus = ZwCreateFile(&FileHandle,
            GENERIC_READ,
            &ObjAttrib,
            &IoStatusBlock,
            NULL,
            FILE_ATTRIBUTE_NORMAL,
            0,
            FILE_OPEN,
            FILE_SYNCHRONOUS_IO_NONALERT,
            NULL,
            0);

        if (!NT_SUCCESS(CreateStatus) || !FileHandle)
        {
            dwRet = 1;
            goto BeforeLeave;
        }

        ReferenceStatus = ObReferenceObjectByHandle(FileHandle,
            FILE_READ_DATA,
            NULL,
            KernelMode,
            &pFileObj,
            NULL);

        if (!NT_SUCCESS(ReferenceStatus))
        {
            dwRet = 1;
            goto BeforeLeave;
        }

        ObDereferenceObject(pFileObj);
        for (wcVolume = L‘A‘; wcVolume <= L‘Z‘; wcVolume++)
        {
            wszDeviceNameTemp[4] = wcVolume;
            DeviceName.Buffer = wszDeviceNameTemp;
            DeviceName.Length = (USHORT)(wcslen(wszDeviceNameTemp) * sizeof(WCHAR));
            DeviceName.MaximumLength = (USHORT)sizeof(wszDeviceNameTemp);
            //KdPrint(("Symbolelic Name %wZ", &DeviceName));
            InitializeObjectAttributes(&ob,
                &DeviceName,
                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                NULL,
                NULL);

            VolumeName.Buffer = BufferVolume;
            VolumeName.Length = 0;
            VolumeName.MaximumLength = MAXPATHLEN;
            ZwOpenSymbolicLinkObject(&LinkHandle, GENERIC_READ, &ob);
            ZwQuerySymbolicLinkObject(LinkHandle, &VolumeName, &rt);

            //KdPrint(("Volume Name %wZ", &VolumeName));

            if (LinkHandle)
            {
                ZwClose(LinkHandle);
            }

            memset(BufferPath, 0, sizeof(BufferPath));
            RtlInitEmptyUnicodeString(&FullPath, BufferPath, MAXPATHLEN);
            RtlCopyUnicodeString(&FullPath, &VolumeName);
            RtlAppendUnicodeStringToString(&FullPath, &(pFileObj->FileName));
            //KdPrint(("%wZ", &FullPath));
            if (0 == RtlCompareUnicodeString(&FullPath, (PUNICODE_STRING)buffer, TRUE))
            {
                pImageName[0] = wcVolume;
                pImageName[1] = L‘:‘;
                pImageName[2] = L‘\0‘;
                wcsncat(pImageName, pFileObj->FileName.Buffer, pFileObj->FileName.Length);
                break;
            }
        }

        //不知道什么原因,IoVolumeDeviceToDosName这个函数可能导致系统死锁
        //所以没有使用这个函数
        dwRet = 0;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        //KdPrint(("Symbolelic EXCEPTION %wZ"));
        dwRet = 1;
    }
BeforeLeave:
    if (buffer)
    {
        ExFreePoolWithTag(buffer,  ‘ipgD‘);
    }

    if (FileHandle)
    {
        ZwClose(FileHandle);
    }

    return dwRet;

}
时间: 2024-08-05 07:03:17

【转】[内核/驱动]驱动中获取进程全路径和注册表全路径的相关文章

java代码中获取进程process id(转)

另一方面,线程ID=进程ID+内部线程对象ID并不成立,    参考: blog.csdn.net/heyetina/article/details/6633901     如何在java代码中获取进程process id, 实现方法如下所示:    参考: rednaxelafx.iteye.com/blog/716918 http://www.cnblogs.com/mumuxinfei/p/3678854.html

synaptics驱动,插入USB鼠标禁用触控板注册表

Title:synaptics驱动,插入USB鼠标禁用触控板注册表 --2010-11-01 22:21 记得以前用过一个synaptics的驱动,自带有插入USB鼠标禁用触控板的选项的,有些没有自带. 今天下了个最新的触控板驱动,再去找了个注册表数据,可以用禁用触控板的功能了.以下是代码. -------------------------------------------------------------------------------------------------------

C#中获取Excel文件的第一个表名

//    2.以数据库方式打开并输入数据//      此方式将xls文件所在目录看作数据库,其中的xls文件看作数据库表,表名即文件名(不加扩展名).//      函数importExcelToDataSet(string FilePath,string sheet)功能:从xls中读出数据到DataSet中,并返回DataSet对象. private DataSet importExcelToDataSet(string FilePath/*即文件目录的路径*/, string shee

cmd中删除、添加、修改注册表命令

转自:http://www.jb51.net/article/30586.htm regedit的运行参数 REGEDIT [/L:system] [/R:user] filename1 REGEDIT [/L:system] [/R:user] /C filename2 REGEDIT [/L:system] [/R:user] /E filename3 [regpath] /L:system Specifies the location of the SYSTEM.DAT file. /R:

驱动层 完成获取进程网络流量模块(总结)

xp平台下是使用TDI,win 7平台采用的是WFP的模式 WFP框架下思路 获取进程ID  获取进程的上传数据大小和下载数据大小,然后存储到链表中 链表中节点结构体如下: typedef struct tagFlowInfoItem { /**  链表结构 */ LIST_ENTRY  m_listEntry; /**  进程ID */ HANDLE  m_processID; /** 已上传流量,BYTE为单位 */ UINT64 m_uploadFlow; /** 已下载流量,BYTE为单

C#操作注册表全攻略

相信每个人对注册表并不陌生,在运行里面输入“regedit”就可以打开注册表编辑器了.这东西对Windows系统来说可是比较重要的,也是病 毒常常会光顾的地方,比如病毒和恶意软件常常会在注册表的启动项里面写入自己的启动键值来达到自启动的目的,有些病毒还会修改注册表里面来映像劫持杀毒软 件,这是破坏系统的第一步.同时,大多软件(软件的序列号和信息)和硬件信息.系统信息.安全模式等等设置都保存在这里,因此系统的健康在很大程度上要依 赖注册表的健康.       作为编程开发人员,我们有必要了解注册表

如何在脚本中获取进程ID(PID)

我想要知道运行中脚本子shell的进程id.我该如何在shell脚本中得到PID. 当我在执行shell脚本时,它会启动一个叫子shell的进程.作为主shell的子进程,子shell将shell脚本中的命令作为批处理运行(因此称为"批处理进程"). 在某些情况下,你也许想要知道运行中的子shell的PID.这个PID信息可以在不同的情况下使用.比如,你可以使用shell脚本的PID在/tmp下创建一个唯一的临时文件.有时侯脚本需要检测所有运行的进程,它可以从进程列表中排除自身的子sh

Windows Minifilter驱动 - 获取进程ID, 进程名字和线程ID (5)

在minifilter里面可能有好几种获取调用进程id,名字和线程的办法.我这里有一种: 使用 PsSetCreateProcessNotifyRoutine 和 PsSetLoadImageNotifyRoutine 这是两个API,我们可以借助它们获取进程信息.具体看:http://msdn.microsoft.com/en-us/library/windows/hardware/ff559951(v=vs.85).aspx PsSetLoadImageNotifyRoutine 可以使用这

Windows Phone 8.1 驱动开发——注册表read/write

在做Windows Phone驱动开发时,时常需要和注册表打交道,因此,作为手机驱动开发人员,有必要了解一下注册表相关的知识.本人目前对注册表也不怎么了解,也只是大概的知道在Windows Phone下,驱动的inf文件并不像桌面Windows那样提供驱动自动安装程序,在Windows Phone下,inf文件最终会被解析成注册表信息并添加到注册表中.我们驱动往往将一些硬件参数保存在注册表中,因此在软件编程时,自然就会涉及到注册表的读写更新操作. 本人目前在做触摸屏驱动时,就涉及到了注册表的读写