讀Windows核心編程-3-核心對象

來源:互聯網
上載者:User

(3)核心對象

何為核心對象

核心對象是Windows作業系統核心分配和訪問的對象,每個核心對象對應於一個記憶體塊,該記憶體塊只能由核心分配,訪問和釋放。該記憶體塊是一個資料結構,維護著與對象相關的資訊。少數成員是所有核心對象所共有的,如:安全性描述元和使用計數,其他多數成員則是每種核心對象所特有的。

核心對象有很多種,如:存取權杖,事件,檔案,檔案對應,作業,互斥體,管道,進程,線程,訊號量,可等待計時器以及線程池工廠等。可使用一些工具來觀察,如:WinObj,Process Explorer等。

    核心對象在應用程式中只能通過Windows的一組函數Create*/Open*/CloseHandle以及相應的核心物件控點(*Handle)來訪問,核心物件控點(32位Windows進程中控制代碼為32位,64位進程中,控制代碼也變成64位)是一個不透明值,其具體意義也可能與Windows不同版本的具體實現相關,不過能夠確定的是:

  1. 控制代碼是進程相關的,一個進程的控制代碼傳給其他進程是沒有意義的;
  2. 控制代碼可以在同一進程中的所有線程使用;
  3. 控制代碼包含了進程控制代碼表的索引值,所以通過控制代碼就能找到對應的核心對象所在的地址。

使用計數

核心對象的所有這是核心,而非進程,而且進程操作核心對象的唯一手段就是用控制代碼作為參數來調用相應的Windows API(Create*/Open*/CloseHandle)。Windows作業系統可由此來實現對核心對象的使用計數,就是說同一個核心對象,Windows作業系統知道有多少進程在引用它。只有當引用計數變為0的時候,核心對象才被銷毀,因此,一個核心對象的生命週期有可能比建立它的進程生命週期要長。

核心對象安全性

核心對象都使用一個安全性描述元來保護,安全性描述元定義了誰擁有對象,哪些組和使用者被允許訪問和使用此對象,哪些被拒絕。該安全資訊用參數SECURITY_ATTRIBUTES來指定,如果傳NULL給這個參數,則表示使用預設的安全性(具體包括哪些安全資訊,取決於當前進程的安全性權杖security token)。

除了核心對象,進程還可能使用一些其他對象,如菜單,視窗,滑鼠,筆刷和字型,這些屬於使用者物件或GDI對象,而非核心對象。一個簡單的方法來判斷是否是核心對象,就看其Create*方法有沒有指定安全資訊的參數。

進程的核心物件控點

進程的核心物件控點都包含了進程控制代碼表的索引值,而進程的控制代碼表是在進程初始化的時候系統為其分配的;實際上將控制代碼值除以4(或者右移2位,以忽略Windows內部使用的最後兩位)就能得到實際的控制代碼表索引值。一個可能的控制代碼表結構如:


每個控制代碼包含一個索引值,能夠只想該表中的一條記錄,而該控制代碼表中每一條記錄都是一個資料結構,這個資料結構包含了:

  1. 一個核心對象的指標;
  2. 一個存取遮罩(access mask);
  3. 一些標誌位,如可繼承性等。

建立核心對象

調用Create*函數來建立核心對象,如下面的列表所示,建立失敗時,有的函數會返回NULL(這就是為神馬第一個有效控制代碼值為4的原因),有的則會返回INVALID_HANDLE_VALUE(這個值是-1);但是GetLastError()都會返回ERROR_INVALID_HANDLE。

CreateProcess/CreateThread/CreateFile/CreateFileMapping/CreateMutex/CreateSemaphore

關閉核心對象

關閉核心對象,無論是哪種類型,如何建立的,都使用CloseHandle;如果關閉失敗,CloseHandle將返回FALSE。

調用CloseHandle後,將導致進程控制代碼表中相應的記錄被清空,並且將相應核心對象引用計數減1,如果計數變成0則銷毀該核心對象。

如果進程忘記調用CloseHandle,那就要等到進程退出時,系統才會為進程關閉所有使用到的內物件控點。事實上,進程終止時,系統會確保所有的資源都得到釋放,包括核心對象,資源,GDI對象以及記憶體塊。(使用Windows工作管理員或Process Explorer可以驗證這一點)。

跨進程共用核心對象

由於核心對象是儲存在進程核心地址空間中的,所以可以跨進程共用核心對象。系統中所有的進程都共用核心地址空間:對32位系統,這是0x80000000~0xFFFFFFFF之間的記憶體,對64位系統,這是0x00000400 00000000~0xFFFFFFFF FFFFFFFF之間的空間。

共用核心對象的三種方式:

  1. 使用物件控點繼承
    1. 進程建立子進程或孫進程時候可以使用控制代碼繼承
    2. 被繼承的控制代碼必須設定bInheritHandle=TRUE
    3. 父進程建立子進程的時候必須設定bInheritHandles=TRUE
    4. 上述條件都滿足時,子進程會複製父進程中可繼承(bInheritHandle=TRUE)的控制代碼,且相應的控制代碼值和索引,以及可繼承性都與父進程相同。

 

  1. 使用命名物件
    1. 使用Create*建立核心對象時,可以給對象命名以使之能夠跨進程使用,其他進程只要用相同的名字來調用Create*/Open*;
    2. 命名物件的問題時沒有一個機制來驗證該名字是否已經存在,因此需要直接調用Open*,或者在Create*後,調用GetLastError看其是否返回ERROR_ALREADY_EXIST,以判斷是否真的建立新的對象,還是只是開啟了現有的核心對象;
    3. Create*/Open*取回現有核心對象時,系統都會根據名字尋找現有的核心對象,並驗證調用進程是否有相應的核心訪問(讀寫)許可權,但仍存在安全性問題,例如,惡意程式可以使用跟某些高許可權進程相同的核心對象名字;
    4. 專有命名空間可以部分解決安全性和重名問題;相關API:CreatePrivateNameSpace/ClosePrivateNameSpace。

 

  1. 複製物件控點
    1. DuplicateHandle可以將進程相關的物件控點複製到另一個進程中,複製後的控制代碼和目標進程相關;
    2. 複製後的控制代碼由於和目標進程相關(就是說該控制代碼在目標進程的控制代碼表中),因此只能在目標進程中關閉該控制代碼。

 

樣本:

DWORD currentProcessId=GetCurrentProcessId();

    HANDLE hMutexInSource=CreateMutex(NULL, FALSE, _T("MyTestMutex"));

    STARTUPINFO si = { sizeof(si) };

    si.dwFlags = STARTF_USESHOWWINDOW;

    si.wShowWindow = TRUE;

    PROCESS_INFORMATION pi={};

    HANDLE hMutextInTarget=NULL;

    TCHAR cmdline[] =TEXT("c://program files//internet explorer//iexplore.exe http://www.baidu.com/");

 

    if(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)){

        HANDLE hSourceProcess = GetCurrentProcess();

 

        tcout<<"before duplicate handle"<<endl;

        //display_process_handles(pi.dwProcessId);

        if(!DuplicateHandle(hSourceProcess,hMutexInSource,pi.hProcess,&hMutextInTarget,0,FALSE,DUPLICATE_SAME_ACCESS)){

            display_last_error();

        }

        else{

            tcout<<"after duplicate handle"<<endl;

            //display_process_handles(pi.dwProcessId);

        }

 

        setlocale(LC_ALL, "chs");

        _tprintf(_T(" 新進程的進程ID號:%d\n"), pi.dwProcessId);

        _tprintf(_T(" 新進程的主線程ID號:%d\r\n"), pi.dwThreadId);

 

        CloseHandle(pi.hProcess);

    }

    else{

        display_last_error();

    }

    CloseHandle(hMutexInSource);

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.