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

转载地址: 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;
 
}

 

转载于:https://www.cnblogs.com/Lthis/p/4491442.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值