前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >内核中通过进程PID获取进程的全部路径

内核中通过进程PID获取进程的全部路径

作者头像
IBinary
发布2019-09-29 11:23:11
3.7K0
发布2019-09-29 11:23:11
举报
文章被收录于专栏:逆向技术

目录

一丶简介

我们遇到的Dos路径.如果想转化为NT路径(也就是 C:\xxxx)类似的格式 需要自己实现. 具体原理如下:

二丶原理

1.原理

1.使用** ZwOpenProcess ** 通过进程PID获取HANDLE 2.使用** ZwQueryInformationProcess ** 查询Handle,使用27号(ProcessFileNmae)得到NT路径. 3.使用** ZwOpenFile 打开路径得到Handle 4.使用 ObReferenceObjectByHandle ** 获得 内核对象(FileObject) 5.从FileObject的成员FileName得到其路径 6.使用 RtlVolumeDeviceToDosName 将FileObject设备对象传入.获得Dos路径.也就是盘符 7.拼接路径进行传出

2.代码实现.

代码语言:javascript
复制
typedef NTSTATUS(*PfnZwQueryInformationProcess) (
    __in HANDLE ProcessHandle,
    __in PROCESSINFOCLASS ProcessInformationClass,
    __out_bcount(ProcessInformationLength) PVOID ProcessInformation,
    __in ULONG ProcessInformationLength,
    __out_opt PULONG ReturnLength
    );

PfnZwQueryInformationProcess ZwQueryInformationProcess;

//初始化未公开的导出函数
NTSTATUS InitGloableFunction()
{
    UNICODE_STRING UtrZwQueryInformationProcessName =
        RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");
    ZwQueryInformationProcess =
        (PfnZwQueryInformationProcess)MmGetSystemRoutineAddress(&UtrZwQueryInformationProcessName);
    return STATUS_SUCCESS;
}
NTSTATUS GetDosPathByProcessId(IN ULONG pid,OUT PANSI_STRING pAnsiNtPath)
{
    /*
    1.根据PID获取进程句柄
    2.使用ZwQueryInformationProcess 传入HANDLE 使用27号功能获取路径
    */
    HANDLE hProcess = 0;
    CLIENT_ID cid;
    OBJECT_ATTRIBUTES obj;
    NTSTATUS ntStatus;
    ULONG RetLength = 0;
    PVOID pBuffer = NULL;
    HANDLE hFile;
    IO_STATUS_BLOCK iostu;
    PVOID FileObject = NULL;
    PFILE_OBJECT pMyFileObject = NULL;
    UNICODE_STRING DosName;
    UNICODE_STRING FunllPath;
    
    if (ZwQueryInformationProcess == NULL)
        return STATUS_UNSUCCESSFUL;

    cid.UniqueProcess =(HANDLE)pid;
    cid.UniqueThread = 0;
    InitializeObjectAttributes(&obj, 0, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
    ntStatus = ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &obj, &cid);
    if (!NT_SUCCESS(ntStatus))
        return STATUS_UNSUCCESSFUL;
    //使用27 号功能遍历
    
    ntStatus = ZwQueryInformationProcess(hProcess, ProcessImageFileName, NULL, 0, &RetLength);
    if (STATUS_INFO_LENGTH_MISMATCH != ntStatus)
        return STATUS_UNSUCCESSFUL;

    //申请内存继续获取.
    pBuffer = ExAllocatePoolWithTag(PagedPool, RetLength, 'niBI');
    if (NULL == pBuffer)
        return STATUS_UNSUCCESSFUL;
    //重新调用获取.
    
    ntStatus = ZwQueryInformationProcess(hProcess, ProcessImageFileName, pBuffer, RetLength, &RetLength);
    if (!NT_SUCCESS(ntStatus))
    {
        if (NULL != pBuffer)
        {
            ExFreePoolWithTag(pBuffer, 'niBI');
        }
        return STATUS_UNSUCCESSFUL;
    }
    
    //开始转化路径
    InitializeObjectAttributes(&obj, pBuffer, OBJ_KERNEL_HANDLE, 0, 0);
    ntStatus = ZwOpenFile(
        &hFile,
        GENERIC_READ,
        &obj,
        &iostu,
        FILE_SHARE_READ| FILE_SHARE_WRITE , 
        0);
    if (!NT_SUCCESS(ntStatus))
    {
        if (NULL != pBuffer)
        {
            ExFreePoolWithTag(pBuffer, 'niBI');
        }
        ZwClose(hFile);
        return STATUS_UNSUCCESSFUL;
    }

    //获得文件对象
    ntStatus = ObReferenceObjectByHandle(
        hFile, 
        GENERIC_ALL, 
        *IoFileObjectType, 
        KernelMode,
        &FileObject,
        NULL);
    
    if (!NT_SUCCESS(ntStatus))
    {
        if (NULL != pBuffer)
        {
            ExFreePoolWithTag(pBuffer, 'niBI');
        }
        ntStatus = ObDereferenceObject(FileObject);
        ZwClose(hFile);
        return STATUS_UNSUCCESSFUL;
    }
    pMyFileObject = (PFILE_OBJECT)FileObject;
    if (NULL == pMyFileObject)
    {
        if (NULL != pBuffer)
        {
            ExFreePoolWithTag(pBuffer, 'niBI');
        }
        ntStatus = ObDereferenceObject(FileObject);
        ZwClose(hFile);
        return STATUS_UNSUCCESSFUL;
        
    }
    //通过 RtlVolumeDeviceToDosName 获取Dos路径 也即是C: D: 等盘符
    RtlVolumeDeviceToDosName(pMyFileObject->DeviceObject,&DosName);

    //获得路径直接直接拼接即可.

    FunllPath.MaximumLength = pMyFileObject->FileName.MaximumLength + DosName.MaximumLength;
    FunllPath.Length = pMyFileObject->FileName.Length + DosName.Length;
    FunllPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, FunllPath.MaximumLength, 0);

    //拼接路径
    RtlCopyUnicodeString(&FunllPath, &DosName);//得到C:
    RtlAppendUnicodeStringToString(&FunllPath, &pMyFileObject->FileName);//得到C:\\xxx路径,转为Asii
    RtlUnicodeStringToAnsiString(pAnsiNtPath, &FunllPath,TRUE); //RtlFreeAnsiString  要释放空间.

    
    ExFreePool(FunllPath.Buffer); //因为传出自动为其分配了内存所以这个进行谁放
    if (NULL != pBuffer)
    {
        ExFreePoolWithTag(pBuffer, 'niBI');
    }

    ntStatus = ObDereferenceObject(FileObject);
    ZwClose(hFile);
    return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
{


    
    ANSI_STRING AnsiNtPath;
    pDriverObj->DriverUnload = DriverUnLoad;
    InitGloableFunction();
    KdBreakPoint();
    GetDosPathByProcessId(3356,&AnsiNtPath);
    
    return STATUS_SUCCESS;
}

以下为调试的时候的代码截图. 1.得到FileName

2.使用RtlVolumeDeviceToDosName 得到盘符

3.拼接路径为UNICODE_STRING类型

4.为传入的ANSI_STRING 分配空间转换.得到ANSI_STRING路径.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-08-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一丶简介
    • 二丶原理
      • 1.原理
      • 2.代码实现.
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档