刚刚学习驱动编程,实现一个hook ssdt中对ntopenrocess这个函数的hook,通过进程名判断是否ntopenprocess是否是对一个特定进程(以notepad.exe为例)进行打开操作,如果是,那么就返回null,不是就正常执行
在网上也查了一下,找到2种方法实现这种转换
1.通过PsLookupProcessByProcessId
NTSTATUS status=PsLookupProcessByProcessId((ULONG)pClientId,&EProcess);
LPTSTR ProcessName = (LPTSTR)EProcess + 0x1FC;
strlwr(ProcessName);//转换成小写
if(memcmp(ProcessName,L"notepad.exe",22)==0)
{
pProcessHandle=NULL;
rc=STATUS_ACCESS_DENIED; 
}
编译通过了,但是一start就蓝,调试中发现是在PsLookupProcessByProcessId一直循环
请教一下是为什么?
2.通过ZwQueryInformationProcess函数
这个不知怎么实现,希望高手能给出用这个函数实现由进程句柄得到进程名的源代码
谢了

解决方案 »

  1.   

    ObReferenceObjectByHandle、ObQueryNameString
      

  2.   

    检查一下EProcess + 0x1FC里这个0x1FC这个偏移量是否和你的系统相同
    不要随便拷贝来就用另外,EPROCESS中的进程名好像是16个字节长度的字符串,它通常是文件名的前16个字符检查一下这两个地方,应该问题就在这
      

  3.   

    0x1FC是W2k下面的进程名偏移量,你如果在XP下肯定蓝屏啦还发现一个问题,EPROCESS中的进程名不保证有'\0'结束符。
    你用strlwr(ProcessName);对把整个EPROCESS都搞乱了
      

  4.   

    多谢vocanicy的解答
    我的系统是xp+sp2,那偏移应该是?
    第二个问题应该怎么解决
      

  5.   

    查看到偏移为0x174 (+0x174 ImageFileName    : [16] UChar)
    修改了该处,以及去掉了strlwr(ProcessName);LPTSTR ProcessName = (LPTSTR)EProcess + 0x174; if((memcmp(ProcessName,L"notepad",14)==0)||(memcmp(ProcessName,L"NOTEPAD",14)==0)) 

    pProcessHandle=NULL; 
    rc=STATUS_ACCESS_DENIED;  

    但是还是蓝啊
      

  6.   

    打印出来的是一些字母,但是不是进程名啊
    把代码贴出来,帮忙看看吧
    #include  <ntddk.h>  
    NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId,OUT PEPROCESS * pEProcess);
    #pragma pack(1)
    typedef struct _SystemServiceDescriptorTable
    {
    PVOID ServiceTableBase;
    PULONG ServiceCounterTableBase;
    ULONG NumberOfService;
    ULONG ParamTableBase;
    }SystemServiceDescriptorTable,*pSystemServiceDescritorTable;
    #pragma pack()extern pSystemServiceDescritorTable KeServiceDescriptorTable;
    ULONG RealServiceAddress;void hook();
    void unhook();
    void OnUnload(IN PDRIVER_OBJECT DriverObject);typedef NTSTATUS (_stdcall *NTOPENPROCESS)(OUT PHANDLE pProcessHandle,
       IN ACCESS_MASK DesiredAccess,
       IN POBJECT_ATTRIBUTES pObjectAttributes,
       IN PCLIENT_ID pClientId);NTOPENPROCESS RealNtOpenProcess;NTSTATUS _stdcall MyNtOpenProcess(OUT PHANDLE pProcessHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES pObjectAttributes,
    IN PCLIENT_ID pClientId)
    {
    NTSTATUS rc,status;
    PEPROCESS EProcess;
    pSystem_Processes pSystemInformation=NULL;
    LPTSTR ProcessName;
    rc=RealNtOpenProcess(pProcessHandle,DesiredAccess,
    pObjectAttributes,pClientId);

           
    //判断打开的进程是不是我的进程
    // 主要看看这里
    status=PsLookupProcessByProcessId((ULONG)pClientId,&EProcess);
    ProcessName = (LPTSTR)((ULONG)EProcess + 0x174);
    DbgPrint("\nprocess name is :%s\n",ProcessName); /* if((memcmp(ProcessName,L"notepad",14)==0)||(memcmp(ProcessName,L"NOTEPAD",14)==0))
    {
    pProcessHandle=NULL;
    rc=STATUS_ACCESS_DENIED; 
    }*/ return rc;


    }
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
    PUNICODE_STRING RegistryPath)
    {
    DriverObject->DriverUnload=OnUnload;
    hook();
    return STATUS_SUCCESS;
    }void OnUnload(IN PDRIVER_OBJECT DriverObject)
    {
    unhook();
    }
      

  7.   

    给你推荐一段代码可以运行时确定进程名的偏移量,摘自《Rootkits——Windows内核安全防护》一书不过以下代码只适合于用服务控制管理器加载的驱动程序,并不适合你这里的要求。
    不过你可以参考这个方案,将整个EPROCESS结构的页面都DUMP出来,就知道进程名所在偏移量了。
    // 仅供参考
    ULONG GetLocationOfProcessName()
    {
    ULONG ul_offset;

    PEPROCESS CurrentProc = PsGetCurrentProcess(); for(ul_offset = 0; ul_offset < PAGE_SIZE; ul_offset++)
    {
    if( !strncmp( "System", (PCHAR) CurrentProc + ul_offset,
    strlen("System")))
    {
    return ul_offset;
    }
    }

    return (ULONG) 0;
    }
      

  8.   

    看了你的代码,你这里好像有错误,pClientId是指向进程ID的指针,而你直接当作ID来使用了status=PsLookupProcessByProcessId((ULONG)pClientId,&EProcess); 
    应该是*pClientId才对吧而且你没有对status=PsLookupProcessByProcessId((ULONG)pClientId,&EProcess); 的返回值判断
    因为你前面ID的错误,你这个函数实际上是失败了,应该找不到对应的进程所以EProcess可能指向非法内存地址,你对其操作可能导致蓝屏
      

  9.   

    pClientId就是进程的ID,(写的不好,前面不应该加上P前缀);
    对,为了省事没有判断
    谢谢vocanicy 的热心帮助。
    不过还是没有解决啊。
      

  10.   

    原来就是pClientId的问题
    pClientId结构是:
    typedef struct _CLIENT_ID
    {
         PVOID UniqueProcess;
         PVOID UniqueThread;
    } CLIENT_ID, *PCLIENT_ID;
    第一项才是pid多谢 vocanicy 的帮助结账了可是还有ZwQueryInformationProcess函数 不会
      

  11.   

    经典。!!!vocanicy解释太详细了。感谢!~