• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 26  文章 - 6  trackbacks - 0
            <2009年11月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            朋友

            • cqh
            • 大學室友...

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             

            1、何為內核對象
                  每個內核對象都只是一個內存塊,它由操作系統內核分配,并只能由操作系統內核訪問。這個內存塊是一個數據結構,其成員維護著于對象相關的信息。少數成員(安全描述符何使用計數等)是所有對象都有的,但其他大多數成員都是不同類型的對象特有的。
                  e.g. 訪問令牌(access token)對象、事件對象、文件對象、文件映射對象、I/O完成端口對象、作業對象、郵件槽(mailsolt)對象、互斥量(mutex)對象、管道(pipe)對象等
                  *可利用Sysintenals的WinObj(http://technet.microsoft.com/zh-cn/sysinternals/bb896657.aspx)工具查看內核對象類型的列表。
            1.1、使用計數
                  使用計數事所有內核對象類型都有的一個數據成員。初次創建對象事,其使用計數被設為1。如果另
            一進程獲得對現有內核對象的訪問后,使用計數會遞增。進程終止運行后,操作系統內核將自動遞減進程仍然打開的所有內核對象的使用計數。一旦對象的使用計數變為0,操作系統內核就會銷毀該對象。
            1.2、內核對象的安全性
                  內核對象可以用一個安全描述(security descriptor, SD)符來保護。它描述了誰擁有對象;哪些組和用戶被允許訪問或使用此對象;哪些組何用戶被拒絕訪問此對象。
                  用于創建內核對象的所有函數幾乎都有指向一個SECURITY_ATTRIBUTES結構的指針
                                  typedef struct _SECURITY_ATTRIBUTES { 
                                      DWORD  nLength;                         //Specifies the size, in bytes, of this structure,一般為sizeof(此結構變量)
                                      LPVOID nLength;                         //Specifies the size, in bytes, of this structure,一般為sizeof(此結構變量)
                                      LPVOID nLength;                         //Specifies the size, in bytes, of this structure,一般為sizeof(此結構變量)
                                      LPVOID nLength;                         //Specifies the size, in bytes, of this structure,一般為sizeof(此結構變量)
                                      LPVOID nLength;                         //Specifies the size, in bytes, of this structure,一般為sizeof(此結構變量)
                                      LPVOID nLength;                         //Specifies the size, in bytes, of this structure,一般為sizeof(此結構變量)
                                      LPVOID nLength;                         //Specifies the size, in bytes, of this structure,一般為sizeof(此結構變量)
                                      LPVOID nLength;                         //Specifies the size, in bytes, of this structure,一般為sizeof(此結構變量)
                                      LPVOID lpSecurityDescriptor;       //和安全性有關的成員
                                      BOOL   lpSecurityDescriptor;       //和安全性有關的成員
                                      BOOL   lpSecurityDescriptor;       //和安全性有關的成員
                                      BOOL   lpSecurityDescriptor;       //和安全性有關的成員
                                      BOOL   lpSecurityDescriptor;       //和安全性有關的成員
                                      BOOL   lpSecurityDescriptor;       //和安全性有關的成員
                                      BOOL   lpSecurityDescriptor;       //和安全性有關的成員
                                      BOOL   bInheritHandle
                                 } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES;    

            2、進程內核對象句柄表
                     進程的句柄表結構

            索引

            指向內核對象內存塊的指針

            訪問掩碼(包含標志位的一個DWORD

            標志

            1

            0x?????????

            0x?????????

            0x?????????

            2

            0x?????????

            0x?????????

            0x?????????

            2.1、創建一個內核對象
                  用于創建內核對象的任何函數都會返回一個與進程相關的句柄,這個句柄可由同一個進程中運行的所有線程使用。由于句柄值實際事作為進程句柄表的索引來使用的,索引這些句柄是與當前這個進程相關的,無法供其他進程使用。
                   調用函數來創建一個內核對象時,如果調用失敗,多數返回的句柄值是0(NULL),但有幾個函數會返回-1(也就是在Winbase.h中定義的INVALID_HANDLE_VALUE)。檢查它們的返回值是,務必相當仔細。
            2.2、關閉內核對象
               無論以什么方式創建內核對象,我們都要調用CloseHandle向系統表明我們已經結束使用對象。
                     BOOL CloseHandle(
                             HANDLE
            hObject   // handle to object
                      );            
               在內部,該函數首先檢查主調進程的句柄表,驗證“傳給函數的句柄值”標識的是“進程確實有權訪問的一個對象”。
               1)如果句柄是有效的,系統就將獲得內核對象的數據結構的地址,并將結構中的“使用計數”成員遞減,如果使用計數變成0,內核對象將被銷毀,并從內存中去除。
               2)如果句柄是無效的,
                     如果進程是正常運行的,CloseHandle將返回FALSE,而GetLastError返回ERROR_INVALID_HANDLE。
                     如果進程正在被調試,那么系統將拋出0xC0000008異常(“指定了無效的句柄”)。
            hObject   // handle to object
                      );            
               在內部,該函數首先檢查主調進程的句柄表,驗證“傳給函數的句柄值”標識的是“進程確實有權訪問的一個對象”。
               1)如果句柄是有效的,系統就將獲得內核對象的數據結構的地址,并將結構中的“使用計數”成員遞減,如果使用計數變成0,內核對象將被銷毀,并從內存中去除。
               2)如果句柄是無效的,
                     如果進程是正常運行的,CloseHandle將返回FALSE,而GetLastError返回ERROR_INVALID_HANDLE。
                     如果進程正在被調試,那么系統將拋出0xC0000008異常(“指定了無效的句柄”)。
               *檢測內核對象泄露
                   用Windows任務管理器,選擇(查看)->(選擇列),然后選擇顯示(句柄數)。便可在進程出監視任何一個應用程序的內核對象數了。
                    使用Sysinternals提供的Process Explorer工具(http://technet.microsoft.com/zh-cn/sysinternals/bb896653.aspx),選擇(View)->(Select Columns),選擇(Handle),選中所有列標題。 在頂部選擇想要檢查的進程,按F5來獲得一份最新的內核對象列表。 然后啟動應用程序并開始指向一個待查的工作流。完成之后,再次按F5。在此期間生成的每個內核對象都顯示為綠色

            3、跨進程邊界共享內核對象
                  內核對象的句柄是與每一個進程相關的,是為確保健壯性(可靠性)和安全性。
            3.1、使用對象句柄繼承
               只有在進程之間有一個父-子關系的時候,才可以使用對象句柄繼承。   
               首先,父進程必須向系統指出它希望這個對象的句柄是可繼承的。
                        e.g.

                SECURITY_ATTRIBUTES sa;
                sa.nLength 
            = siezof(sa);
                sa.lpSecurityDescriptor 
            = NULL;
                sa.bInheritHandle 
            = TRUE;        //Make the returned handle inheritable

                HANDLE hMutex 
            = CreateMutex(&sa, FALSE, NULL);
               然后,由父進程生成子進程,通過CreateProcess函數完成    
            BOOL CreateProcess(
              LPCTSTR lpApplicationName,
              LPTSTR lpCommandLine,
              LPSECURITY_ATTRIBUTES lpProcessAttributes,
              LPSECURITY_ATTRIBUTES lpThreadAttributes,
              BOOL bInheritHandles,            
            //通常情況下設為FALSE(表明我們不希望子進程繼承父進程句柄表中的“可繼承句柄”)
                                                                  
            //如果傳遞TRUE,子進程就會繼承父進程的“可繼承句柄”的值。
                                                                            
            //(系統會遍歷符進程的句柄表,對它的每一個記錄項進行檢查,凡是包含一個
                                                                           
            //有效的“可繼承句柄”的項,都會被完整地復制到子進程的句柄表)
              DWORD dwCreationFlags,
              LPVOID lpEnvironment,
              LPCTSTR lpCurrentDirectory,
              LPSTARTUPINFO lpStartupInfo,
              LPPROCESS_INFORMATION lpProcessInformation
            );
                    除了復制句柄表的記錄項,系統還會遞增內核對象的使用計數,引擎兩個進程現在都在使用這個對象。
            3.2改變句柄的標志
                 1)父進程想控制哪些子進程能繼承內核對象句柄。可以調用SetHandleInformation函數來改變內核對象句柄的繼承標志。
            BOOL SetHandleInformation(
              HANDLE hObject,        
            //有效句柄標志
              DWORD dwMask,            //想要更改那個或哪些標志
              DWORD dwFlags            //希望把標志設為什么
            );
               每個句柄都關聯了兩個標志:
            #define HANDLE_FLAG_INHERIT                                       0x00000001
            #define HANDLE_FLAG_PROTECT_FROM_CLOSE        0x00000002
               如果想打開一個內核對象句柄的繼承標志
            SetHandleInformation(hObj, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
               如果想關閉這個標志
            SetHandleInformation(hObj, HANDLE_FLAG_INHERIT, 0);
               如果告訴系統不允許關閉句柄
            SetHandleInformation(hObj,,HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE);
            CloseHandle(hObj);    
            //會引發異常
               2)使用GetHandleInformation函數返回句柄標志
            BOOL GetHandleInformation(
              HANDLE hObject,
              LPDWORD lpdwFlags
            );
               e.g.檢查句柄是否可繼承
            DWORD dwFlags;
            GetHandleInformation(hObj, 
            &dwFlags);
            BOOL fHandleIsInheritable 
            = (0 != (dwFlags & HANDLE_FLAG_INHERIT));
            3.3為對象命名
            HANDLE CreateMutex(
              LPSECURITY_ATTRIBUTES lpMutexAttributes,
              BOOL bInitialOwner,
              LPCTSTR lpName
            );

            HANDLE CreateEvent(
              LPSECURITY_ATTRIBUTES lpEventAttributes,
              BOOL bManualReset,
              BOOL bInitialState,
              LPCTSTR lpName
            );

            HANDLE CreateEvent(
              LPSECURITY_ATTRIBUTES lpEventAttributes,
              BOOL bManualReset,
              BOOL bInitialState,
              LPCTSTR lpName
            );
               所有這些函數的最后一個參數都是pszName。傳入NULL,相當于向系統表明我們要創建一個未命名的(即匿名)內核對象。
               要根據對象名稱來共享一個對象,我們必須為此對象指定一個名稱。傳入一個“以0為終止的名稱字符串”的地址。
            //進程A
            HANDLE hMutexProcessA = CreateMutex(NULL, FALSE, TEXT("JeffMutex"));

            //進程B
            HANDLE hMutexProcessB = CreateMutex(NULL, FALSE, TEXT("JeffMutex"));
                  當進程B調用CreateMutex時,系統會查看是否存在一個名為 "JeffMutex "("JeffMutex "的對象是一個互斥量對象)的內核對象。如果存在,接著檢查對象的類型,和調用者是否擁有該對象的完全訪問權限。 如果答案是肯定的,系統就會在進程B的句柄表中查找一個空白記錄項,并將其初始化為指向現有的內核對象;否則,返回NULL(失敗)。
                   也可以調用Open*函數:
            posted on 2009-11-26 11:06 longshen 閱讀(962) 評論(0)  編輯 收藏 引用 所屬分類: VC++
            久久久久国产一级毛片高清板| 人妻无码αv中文字幕久久| 久久电影网一区| 91精品国产色综久久| 亚洲国产成人久久综合一区77| 精品国产青草久久久久福利| 久久成人国产精品| 久久福利资源国产精品999| 国产麻豆精品久久一二三| 久久亚洲AV无码西西人体| 久久久久久亚洲精品成人| 欧美久久久久久午夜精品| 久久久久人妻精品一区二区三区 | 国产精品99久久99久久久| 久久中文字幕视频、最近更新| 国内精品久久久久伊人av| 香蕉久久夜色精品国产尤物| 久久福利青草精品资源站免费| 国产A三级久久精品| 日本高清无卡码一区二区久久 | 久久久久久国产精品免费免费| 人妻无码αv中文字幕久久琪琪布| 理论片午午伦夜理片久久| 久久99国产精品99久久| 浪潮AV色综合久久天堂| 久久亚洲熟女cc98cm| 欧美国产成人久久精品| 久久久久亚洲av成人无码电影| 青青热久久综合网伊人| 72种姿势欧美久久久久大黄蕉| 亚洲综合精品香蕉久久网| 久久人人爽人人爽人人片AV东京热 | 久久久久国产一级毛片高清版| 久久综合给合久久狠狠狠97色69| 亚洲人成无码久久电影网站| 内射无码专区久久亚洲| 久久午夜综合久久| 久久久久久国产a免费观看黄色大片 | 色天使久久综合网天天| 久久综合九色综合网站| 亚洲精品乱码久久久久久久久久久久 |