• 【旧文章搬运】超级无敌大炉子的LzOpenProcess


    原文发表于百度空间,2008-11-20
    ==========================================================================

    这个东西嘛,思路来自炉子,C版的最早貌似是sudami写的,我也写一个,练练手。
    上次看到有人找资料时找到了我刚开博时的一篇挫文,并且引用到看雪上求助,令我汗颜不已,遂把这个代码加了N多注释,方便自己,也方便某些误打误撞到我这儿找资料的菜菜~

    HANDLE LzOpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle, DWORD dwProcessId)
    {
    NTSTATUS status=0;
    char *pBuf=NULL;
    BOOLEAN wasEnabled;
    DWORD buflen=0x10000,needlen=0;
    DWORD HandleCnt=0;
    HANDLE hRetProcess=0,hOwnerProc,hTmp;
    PSYSTEM_HANDLE_INFORMATION pSysHandleInfo=NULL;
    PROCESS_BASIC_INFORMATION BasePsInfo;
    OBJECT_ATTRIBUTES objatr;
    CLIENT_ID Cid;
    //提升调试权限,否则有些进程,比如服务进程打不开
    RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE,TRUE,FALSE,&wasEnabled);
    InitializeObjectAttributes(&objatr,0,0,0,0);
    //先尝试正常方式打开
    Cid.UniqueProcess=(HANDLE)dwProcessId;
    Cid.UniqueThread=0;
    status=ZwOpenProcess(&hRetProcess,dwDesiredAccess,&objatr,&Cid);//尝试直接打开
    if (NT_SUCCESS(status))
    {
       return hRetProcess;
    }
    //不成功,尝试把PID加1再打开,加2,加3也可以
    //理由:有些HOOK函数中过滤PID时不完善,正确的做法应该是先用掩码忽略低两位之后再比较
    Cid.UniqueProcess=(HANDLE)(dwProcessId+1);
    status=ZwOpenProcess(&hRetProcess,dwDesiredAccess,&objatr,&Cid);//尝试直接打开pid+1
    if (NT_SUCCESS(status))
    {
       return hRetProcess;
    }
    //都不成功,就找别的进程中的Handle,这才是本代码的核心, 这些Handle大部分是在Csrss.exe中
    do 
    {
       //申请查询句柄信息所需的内存
       ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,0,&buflen,MEM_COMMIT,PAGE_READWRITE);
       //查询系统句柄信息,类型为16
       status=ZwQuerySystemInformation(SystemHandleInformation,(PVOID)pBuf,buflen,&needlen);
       if (status==STATUS_SUCCESS)
       {
        break;
       }
       //不成功,则释放内存
       //这里只要一块大内存够放这些内容就行,或者直接申请一块足够大的也可以
       //返回的needlen可以做为参考
       ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,&buflen,MEM_RELEASE);
       //然后把要申请的内存大小乘2,直至成功为止
       buflen*=2;
       pBuf=NULL;
    } while(1);
    //返回的缓冲区内容的第一个DWORD是总的句柄的个数
    HandleCnt=*(DWORD*)pBuf;
    //跳过句柄计数,才是真正的开始
    pSysHandleInfo=(PSYSTEM_HANDLE_INFORMATION)((char*)pBuf+sizeof(DWORD));
    for (DWORD i=0;i<HandleCnt;i++)
    {
       //只验证类型为PROCESS的,值为5
       if (pSysHandleInfo->ObjectTypeNumber==OB_TYPE_PROCESS)
       {
        //打开这个句柄的所有者进程,要复制过来才能查询,否则只能看不能摸~
        Cid.UniqueProcess=(HANDLE)(pSysHandleInfo->ProcessId);
        Cid.UniqueThread=0;
        status=ZwOpenProcess(&hOwnerProc,PROCESS_DUP_HANDLE,&objatr,&Cid);
        if (NT_SUCCESS(status))
        {
         //打开成功,复制句柄到本进程,这里用了PROCESS_ALL_ACCESS以避免权限问题
         status=ZwDuplicateObject(hOwnerProc,
          (HANDLE)(pSysHandleInfo->Handle),
          NtCurrentProcess(),
          &hTmp,
          PROCESS_ALL_ACCESS,
          FALSE,
          0);
         if (NT_SUCCESS(status))
         {
          //复制成功,查询此句柄所对应的进程PID,查询基本信息即可
          status=ZwQueryInformationProcess(hTmp,ProcessBasicInformation,&BasePsInfo,sizeof(PROCESS_BASIC_INFORMATION),NULL);
          if (NT_SUCCESS(status))
          {
           //成功,判断其PID
           if (BasePsInfo.UniqueProcessId==dwProcessId)
           {
            //句柄所有者是我们要的目标进程,再按所需的权限复制过来
            ZwDuplicateObject(hOwnerProc,
             (HANDLE)(pSysHandleInfo->Handle),
             NtCurrentProcess(),
             &hRetProcess,
             dwDesiredAccess,
             FALSE,
             0);
            //关掉为复制而打开的句柄所有者的句柄引用
            ZwClose(hOwnerProc);
            break;
           }
          
          }
    
         }
        }
       }
       pSysHandleInfo++;//指向下一个结构
    }
    if (pBuf)
    {
       ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,&buflen,MEM_RELEASE);
    }
    return hRetProcess;
    }



  • 相关阅读:
    leetcode10 正则表达式匹配 dp
    AS技巧合集「调试技巧篇」
    AS技巧合集「编码技巧篇」
    AS技巧合集「常用技巧篇」
    Android studio:Groovy 与 Gradle 基础【三】
    Android Studio :Android Studio 与 Gradle 深入【二】
    Android studio:从Eclipse迁移到Android Studio【一】
    Anroid Studio入门
    54. Android中adb常用命令及应用常用目录
    53. Android常用工具类
  • 原文地址:https://www.cnblogs.com/achillis/p/10180415.html
Copyright © 2020-2023  润新知