zoukankan      html  css  js  c++  java
  • 有关遍历进程中句柄的方法总结

    此篇文章说是原创有些牵强。就像题目所说的,更多的是对前人方法的总结。写作的初衷倒也不是技术方面的研究,不过是工作的需求罢了。
    方法中涉及到一些函数需要提权,其实我一直以为网上那个标准的提权函数没什么用,直到这次写程序我才知道原来有的时候是真的需要提权的。现附上一份比较好看的提权代码,也方便自己以后使用。
     
    BOOL AdjustProcessPrivilege(HANDLE hProcess, LPCTSTR lpPrivilegeName, DWORD dwPrivilegeAttribute)
    {
     BOOL bRetValue = FALSE;
     HANDLE hProcessToken;
     
     //如果hProcess是NULL,说明调用者想要调整当前进程的权限,使用GetCurrentProcess获得的进程句柄无需关闭
     HANDLE hOpenProcess = (hProcess != NULL) ? hProcess : GetCurrentProcess();
     //打开进程令牌,期望的权限为可以调整权限和查询,得到进程令牌句柄
     if(OpenProcessToken(hOpenProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken) != FALSE)
     {
      LUID stPrivilegeLuid;
      //通过权限名称,查找指定的权限的LUID值
      if(LookupPrivilegeValue(NULL, lpPrivilegeName, &stPrivilegeLuid) != FALSE)
      {
       //设置新的权限
       TOKEN_PRIVILEGES stNewTokenPrivilege;
       stNewTokenPrivilege.PrivilegeCount = 1;
       stNewTokenPrivilege.Privileges[0].Luid = stPrivilegeLuid;
       stNewTokenPrivilege.Privileges[0].Attributes = dwPrivilegeAttribute;
       //调整权限
       if(AdjustTokenPrivileges(hProcessToken, FALSE, &stNewTokenPrivilege, sizeof(stNewTokenPrivilege), NULL, NULL) != FALSE)
       {
        bRetValue = TRUE;
       }
      }
      //关闭进程令牌句柄
      CloseHandle(hProcessToken);
     }
     return bRetValue;
    }


    调用方法如下:
     
    if(AdjustProcessPrivilege((HANDLE)NULL, SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED) == FALSE ||
      AdjustProcessPrivilege((HANDLE)NULL, SE_TAKE_OWNERSHIP_NAME, SE_PRIVILEGE_ENABLED) == FALSE ||
      AdjustProcessPrivilege((HANDLE)NULL, SE_SECURITY_NAME, SE_PRIVILEGE_ENABLED) == FALSE ||
      AdjustProcessPrivilege((HANDLE)NULL, SE_AUDIT_NAME, SE_PRIVILEGE_ENABLED) == FALSE)
     {
      printf(("Adjust process privilege failed!/n"));
     }


    整个提权流程实现起来比较傻瓜化,很符合我的喜好。
    好了,步入正体。开始总结如何遍历一个进程中所打开的句柄。首先,介绍两个结构体。


    typedef struct _SYSTEM_HANDLE
    {
     ULONG  uIdProcess;
     UCHAR  ObjectType;    // OB_TYPE_* (OB_TYPE_TYPE, etc.)
     UCHAR  Flags;         // HANDLE_FLAG_* (HANDLE_FLAG_INHERIT, etc.)
     USHORT  Handle;
     PVOID  pObject;
     ACCESS_MASK GrantedAccess;
    } SYSTEM_HANDLE, *PSYSTEM_HANDLE;
     
    typedef struct _SYSTEM_HANDLE_INFORMATION
    {
     ULONG   uCount;
     SYSTEM_HANDLE aSH[];
    } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;


    这两个结构体定义了系统句柄的信息。接下来,我们看代码:
     
    void MyCloseHandle(DWORD pid)
    {
     //获取进程中的句柄
     PSYSTEM_HANDLE_INFORMATION Info;
     ULONG r;
     CHAR Name[MAX_PATH];
     HANDLE hProcess, hFile;
     hHeap = GetProcessHeap();
     Info = (PSYSTEM_HANDLE_INFORMATION)GetInfoTable(SystemHandleInformation);
     if (Info)
     {
      for (r = 0; r < Info->uCount; r++)
      {
       if (Info->aSH[r].uIdProcess == pid)
       {
        hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, Info->aSH[r].uIdProcess);
        if (hProcess)
        {
         if (DuplicateHandle(hProcess, (HANDLE)Info->aSH[r].Handle, GetCurrentProcess(), &hFile, 0, FALSE, DUPLICATE_SAME_ACCESS))
         {
          GetFileName(hFile, Name);
          if(strstr(Name, "Intel") != NULL)
          {
           printf("PID=%d FileHandle %d FileName=%s ", Info->aSH[r].uIdProcess, Info->aSH[r].Handle, Name);
          }
          
          CloseHandle(hFile);
         }
         CloseHandle(hProcess);
        }
       }
      }
      HeapFree(hHeap, 0, Info);
     }
     printf("Duplicate Finish. ");
    }


    hHeap是一个HANDLE型的全局变量,由于用的地方多并且我比较懒,所以定义成了一个全局变量。最好还是作为局部变量从函数中传递。至于GetInfoTable留到下面再说。SystemHandleInformation则是用来获取系统中句柄信息的一个重要参数。参见结构体:


    typedef enum _SYSTEMINFOCLASS
    {
     SystemBasicInformation,             // 0x002C
     SystemProcessorInformation,         // 0x000C
     SystemPerformanceInformation,       // 0x0138
     SystemTimeInformation,              // 0x0020
     SystemPathInformation,              // not implemented
     SystemProcessInformation,           // 0x00C8+ per process
     SystemCallInformation,              // 0x0018 + (n * 0x0004)
     SystemConfigurationInformation,     // 0x0018
     SystemProcessorCounters,            // 0x0030 per cpu
     SystemGlobalFlag,                   // 0x0004 (fails if size != 4)
     SystemCallTimeInformation,          // not implemented
     SystemModuleInformation,            // 0x0004 + (n * 0x011C)
     SystemLockInformation,              // 0x0004 + (n * 0x0024)
     SystemStackTraceInformation,        // not implemented
     SystemPagedPoolInformation,         // checked build only
     SystemNonPagedPoolInformation,      // checked build only
     SystemHandleInformation,            // 0x0004  + (n * 0x0010)
     SystemObjectTypeInformation,        // 0x0038+ + (n * 0x0030+)
     SystemPageFileInformation,          // 0x0018+ per page file
     SystemVdmInstemulInformation,       // 0x0088
     SystemVdmBopInformation,            // invalid info class
     SystemCacheInformation,             // 0x0024
     SystemPoolTagInformation,           // 0x0004 + (n * 0x001C)
     SystemInterruptInformation,         // 0x0000, or 0x0018 per cpu
     SystemDpcInformation,               // 0x0014
     SystemFullMemoryInformation,        // checked build only
     SystemLoadDriver,                   // 0x0018, set mode only
     SystemUnloadDriver,                 // 0x0004, set mode only
     SystemTimeAdjustmentInformation,    // 0x000C, 0x0008 writeable
     SystemSummaryMemoryInformation,     // checked build only
     SystemNextEventIdInformation,       // checked build only
     SystemEventIdsInformation,          // checked build only
     SystemCrashDumpInformation,         // 0x0004
     SystemExceptionInformation,         // 0x0010
     SystemCrashDumpStateInformation,    // 0x0004
     SystemDebuggerInformation,          // 0x0002
     SystemContextSwitchInformation,     // 0x0030
     SystemRegistryQuotaInformation,     // 0x000C
     SystemAddDriver,                    // 0x0008, set mode only
     SystemPrioritySeparationInformation,// 0x0004, set mode only
     SystemPlugPlayBusInformation,       // not implemented
     SystemDockInformation,              // not implemented
     SystemPowerInfo,             // 0x0060 (XP only!)
     SystemProcessorSpeedInformation,    // 0x000C (XP only!)
     SystemTimeZoneInformation,          // 0x00AC
     SystemLookasideInformation,         // n * 0x0020
     SystemSetTimeSlipEvent,
     SystemCreateSession,    // set mode only
     SystemDeleteSession,    // set mode only
     SystemInvalidInfoClass1,   // invalid info class
     SystemRangeStartInformation,   // 0x0004 (fails if size != 4)
     SystemVerifierInformation,
     SystemAddVerifier,
     SystemSessionProcessesInformation, // checked build only
     MaxSystemInfoClass
    } SYSTEMINFOCLASS, *PSYSTEMINFOCLASS;


    通篇文章用到了很多系统未公开函数和结构体。其实这些东西网上都可以查到,我就不细说了。其实水平太菜,想说清楚也不太容易。
    当找到属于目标进程中的句柄后,通过DuplicateHandle将该句柄再次打开,只不过这次打开为当前进程所用,以备获取该句柄的其它信息。接下来通过GetFileName获得该句柄的名称。当然这个函数也留到后面再说。我们先来看一下GetInfoTable。


     
    PVOID GetInfoTable(IN ULONG ATableType)
    {
     ULONG    mSize = 0x8000;
     PVOID    mPtr;
     NTSTATUS status;
     do
     {
      mPtr = HeapAlloc(hHeap, 0, mSize);
      if (!mPtr) return NULL;
      memset(mPtr, 0, mSize);
      
      HMODULE hNtDLL = LoadLibrary("NTDLL.DLL");
      if ( !hNtDLL )
      {
       return FALSE;
      }
      
      ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtDLL, "ZwQuerySystemInformation");
      if( ZwQuerySystemInformation == NULL)
      {
       return FALSE;
      }
     
      status = ZwQuerySystemInformation(ATableType, mPtr, mSize, NULL);
      
      if (status == STATUS_INFO_LENGTH_MISMATCH)
      {
       HeapFree(hHeap, 0, mPtr);
       mSize = mSize * 2;
      }
     } while (status == STATUS_INFO_LENGTH_MISMATCH);
     if (NT_SUCCESS(status)) return mPtr;
     HeapFree(hHeap, 0, mPtr);
     return NULL;
    }


    这个函数则是利用ZwQuerySystemInformation获取当前系统中的句柄信息。而ZwQuerySystemInformation则是一个未公开函数。


    typedef NTSTATUS (WINAPI *ZWQUERYSYSTEMINFORMATION)(unsigned long, PVOID, ULONG, PULONG);


    NTSTATUS
    ZwQuerySystemInformation(
     IN SYSTEMINFOCLASS SystemInformationClass,
     OUT PVOID SystemInformation,
     IN ULONG SystemInformationLength,
     OUT PULONG ReturnLength OPTIONAL
    );


    然后我们再看GetFileName,看看是如何获取到句柄所对应的文件名称的。


    void GetFileName(HANDLE hFile, PCHAR TheName)
    {
     HANDLE   hThread;
     PNM_INFO Info = (PNM_INFO)HeapAlloc(hHeap, 0, sizeof(NM_INFO));
     Info->hFile = hFile;
     hThread = CreateThread(NULL, 0, GetFileNameThread, Info, 0, NULL);
     if (WaitForSingleObject(hThread, INFINITE) == WAIT_TIMEOUT) TerminateThread(hThread, 0);
     CloseHandle(hThread);
     memset(TheName, 0, MAX_PATH);
     WideCharToMultiByte(CP_ACP, 0, Info->Info.FileName, Info->Info.FileNameLength >> 1, TheName, MAX_PATH, NULL, NULL);
     HeapFree(hHeap, 0, Info);
    }


    其中,PNM_INFO结构体如下:


    typedef struct _FILE_NAME_INFORMATION {
     ULONG  FileNameLength;
     WCHAR  FileName[1];
    } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
    typedef struct _NM_INFO
    {
     HANDLE  hFile;
     FILE_NAME_INFORMATION Info;
     WCHAR Name[MAX_PATH];
    } NM_INFO, *PNM_INFO;


    接下来这里通过创建线程GetFileNameThread来进一步获取句柄信息。
     
    DWORD WINAPI GetFileNameThread(PVOID lpParameter)
    {
     PNM_INFO NmInfo = (PNM_INFO)lpParameter;
     IO_STATUS_BLOCK IoStatus;
     HMODULE hNtDLL = LoadLibrary("NTDLL.DLL");
     if ( !hNtDLL )
     {
      return FALSE;
     }
     ZWQUERYINFORMATIONFILE ZwQueryInformationFile = (ZWQUERYINFORMATIONFILE)GetProcAddress(hNtDLL, "ZwQueryInformationFile");
     if( ZwQueryInformationFile == NULL)
     {
      return FALSE;
     }
     ZwQueryInformationFile(NmInfo->hFile, &IoStatus, &NmInfo->Info, sizeof(NM_INFO) - sizeof(HANDLE), FileNameInformation);
     return 0;
    }


    我们发现,函数中利用到了ZwQueryInformationFile来获取句柄详细信息。而ZwQueryInformationFile则又是一个未公开函数。


    typedef NTSTATUS (WINAPI *ZWQUERYINFORMATIONFILE)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
    FILE_INFORMATION_CLASS);


    NTSTATUS
    ZwQueryInformationFile(
     IN HANDLE  FileHandle,
     OUT PIO_STATUS_BLOCK  IoStatusBlock,
      OUT PVOID  FileInformation,
     IN ULONG  Length,
     IN FILE_INFORMATION_CLASS  FileInformationClass
    );


    而FILE_INFORMATION_CLASS则是一个枚举类型。


    typedef enum _FILE_INFORMATION_CLASS {
     FileDirectoryInformation=1,
     FileFullDirectoryInformation,
     FileBothDirectoryInformation,
     FileBasicInformation,
     FileStandardInformation,
     FileInternalInformation,
     FileEaInformation,
     FileAccessInformation,
     FileNameInformation,
     FileRenameInformation,
     FileLinkInformation,
     FileNamesInformation,
     FileDispositionInformation,
     FilePositionInformation,
     FileFullEaInformation,
     FileModeInformation,
     FileAlignmentInformation,
     FileAllInformation,
     FileAllocationInformation,
     FileEndOfFileInformation,
     FileAlternateNameInformation,
     FileStreamInformation,
     FilePipeInformation,
     FilePipeLocalInformation,
     FilePipeRemoteInformation,
     FileMailslotQueryInformation,
     FileMailslotSetInformation,
     FileCompressionInformation,
     FileCopyOnWriteInformation,
     FileCompletionInformation,
     FileMoveClusterInformation,
     FileQuotaInformation,
     FileReparsePointInformation,
     FileNetworkOpenInformation,
     FileObjectIdInformation,
     FileTrackingInformation,
     FileOleDirectoryInformation,
     FileContentIndexInformation,
     FileInheritContentIndexInformation,
     FileOleInformation,
     FileMaximumInformation
    } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;


    时间有点紧,总结的有些粗略。回头抽出时间来再完善吧。
  • 相关阅读:
    Atitit 经济学常见的流派 古典主义与凯恩斯主义
    Atitit 学习方法 体系化学习方法 Excel 科目,分类,专业 三级分类。。 知识点。。 课程就是每一个知识点的详细化。。 比如经济学 类别 专业 xx概论知识点 3、金
    atiitt it学科体系化 体系树与知识点概念大总结.xlsx
    Atitit 减少财政支出普通人如何蹭政府补贴措施 attilax大总结.docx
    Atitit 信用管理概论 attilax学习心得
    Atitit.月度计划日程表 每月流程表v5
    Atitit 企业6大职能 attilax总结
    Atitit 常见每日流程日程日常工作.docx v8 ver ampm imp 签到 am y 天气情况检查 am y 晨会,每天或者隔天 am 每日计划(项目计划,日计划等。 am
    Atitit 财政赤字解决方案
    Atitit 建设自己的财政体系 attilax总结 1.1. 收入理论 2 1.2. 收入分类 2 1.3. 2 1.4. 非货币收入 2 1.5. 2 1.6. 降低期望 2 1.7.
  • 原文地址:https://www.cnblogs.com/vcerror/p/4289142.html
Copyright © 2011-2022 走看看