穿透Session隔離的進(jìn)程間通訊

本文主要介紹了不同session之間的進(jìn)程通信暇屋。應(yīng)用場(chǎng)景如下:

SessionID為0的windows服務(wù)S需要檢測(cè)和控制SessionID為1或2(取決于該進(jìn)程的用戶)的UI程序的多個(gè)實(shí)例(P1 柏蘑,P2厅缺,P3……)的運(yùn)行狀態(tài)迎瞧。

1.遇到的第一個(gè)問題是捂龄,需要在服務(wù)S中檢測(cè)指定進(jìn)程P_i的運(yùn)行狀態(tài)躏哩。在該進(jìn)程為多實(shí)例運(yùn)行的狀態(tài)下奏候,區(qū)分不同的實(shí)例可以根據(jù)進(jìn)程ID和進(jìn)程的窗口名稱來進(jìn)行區(qū)分岩瘦。服務(wù)S接收到檢測(cè)窗口名稱為“WindowText_i”的進(jìn)程的運(yùn)行狀態(tài)未巫,而服務(wù)不能調(diào)用窗口相關(guān)的API來獲得進(jìn)程的窗口,只能遍歷到每個(gè)進(jìn)程的進(jìn)程ID担钮,因此無法將窗口名稱和進(jìn)程ID對(duì)應(yīng)起來橱赠。

解決方案:進(jìn)程P_i啟動(dòng)時(shí)創(chuàng)建一個(gè)共享內(nèi)存,該共享內(nèi)存的名稱的唯一性標(biāo)志為該進(jìn)程P_i的進(jìn)程ID箫津,然后進(jìn)程P_i向這塊共享內(nèi)存中寫入自己的窗口名稱;服務(wù)S需要檢測(cè)進(jìn)程P_i的狀態(tài)時(shí)狭姨,先枚舉所有的進(jìn)程ID,然后根據(jù)進(jìn)程ID查找共享內(nèi)存苏遥,如果找到饼拍,說明該進(jìn)程是自己需要的檢測(cè)的進(jìn)程,然后讀取共享內(nèi)存里的數(shù)據(jù)田炭,可以獲得該進(jìn)程的窗口名稱“WindowText_i”师抄,達(dá)到將窗口名稱和進(jìn)程ID對(duì)應(yīng)起來的目的。

共享內(nèi)存名稱示例:

'''

strMemName.Format(_T("Global\\ShareMemory_%d"),GetCurrentProcessId());

'''

前面加入的“global\\”是為了創(chuàng)建全局的共享內(nèi)存教硫,不同session區(qū)域的進(jìn)程只能夠找到自己所屬session區(qū)域的共享內(nèi)存和全局共享內(nèi)存叨吮。服務(wù)和進(jìn)程P_i屬于不同的session區(qū)域辆布,因此必須要加上全局標(biāo)識(shí)。

創(chuàng)建共享內(nèi)存的語句:

// 創(chuàng)建共享文件句柄

g_hMapFile = CreateFileMapping(

NULL,? // 物理文件句柄

&sa,? // 默認(rèn)安全級(jí)別

PAGE_EXECUTE_READWRITE,? // 可讀可寫

0,? // 高位文件大小

SHRE_MEMORY_BUF_SIZE,? // 低位文件大小

strMemName? // 共享內(nèi)存名稱

);

創(chuàng)建共享文件句柄的第二個(gè)參數(shù)為安全級(jí)別茶鉴,創(chuàng)建一般的共享內(nèi)存時(shí)锋玲,可以將這個(gè)參數(shù)設(shè)置為NULL,表示使用默認(rèn)的安全級(jí)別涵叮。但是在創(chuàng)建一個(gè)可以被服務(wù)獲取到的全局共享內(nèi)存時(shí)惭蹂,需要指定一個(gè)更加廣泛的的安全描述符,增加一個(gè)新的訪問控制項(xiàng)目(ACE)給你的ASP進(jìn)程的擁有者割粮,保證服務(wù)能夠獲取到該共享內(nèi)存盾碗。默認(rèn)的訪問控制列表(ACL)只包含創(chuàng)建者和管理員組。

SECURITY_ATTRIBUTES sa = { sizeof(sa) };

SECURITY_DESCRIPTOR sd;

InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);

SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);

sa.lpSecurityDescriptor = &sd;

創(chuàng)建全局的共享內(nèi)存之前舀瓢,最好再創(chuàng)建一個(gè)全局的互斥量廷雅,保證共享內(nèi)存不會(huì)被多個(gè)進(jìn)程同時(shí)訪問,增加安全性氢伟“窠危互斥量的命名模式與共享內(nèi)存一致,但是名字不能相同(相同的名字朵锣,創(chuàng)建時(shí)會(huì)失斆巍),創(chuàng)建互斥量時(shí)的安全描述符诚些,可以與共享內(nèi)存使用同一個(gè)飞傀。

共享內(nèi)存和互斥量的資源釋放都要在進(jìn)程P_i中實(shí)現(xiàn)。

2.遇到的第二個(gè)問題是诬烹,當(dāng)由服務(wù)S啟動(dòng)某個(gè)進(jìn)程P_i時(shí)砸烦,如果服務(wù)S使用的API為CreateProcesss,那么啟動(dòng)后的進(jìn)程P_i是看不到界面的绞吁,因?yàn)镃reateProcess創(chuàng)建的子進(jìn)程與父進(jìn)程的sessionID相同幢痘。如果想要?jiǎng)?chuàng)建有界面的進(jìn)程P_i,需要調(diào)用另一個(gè)API函數(shù):CreateProcessAsUser家破。調(diào)用過程如下:

BOOL WINAPI CreateProcessAsUser(

? _In_opt_? ? HANDLE? ? ? ? ? ? ? ? hToken,

? _In_opt_? ? LPCTSTR? ? ? ? ? ? ? lpApplicationName,

? _Inout_opt_ LPTSTR? ? ? ? ? ? ? ? lpCommandLine,

? _In_opt_? ? LPSECURITY_ATTRIBUTES lpProcessAttributes,

? _In_opt_? ? LPSECURITY_ATTRIBUTES lpThreadAttributes,

? _In_? ? ? ? BOOL? ? ? ? ? ? ? ? ? bInheritHandles,

? _In_? ? ? ? DWORD? ? ? ? ? ? ? ? dwCreationFlags,

? _In_opt_? ? LPVOID? ? ? ? ? ? ? ? lpEnvironment,

? _In_opt_? ? LPCTSTR? ? ? ? ? ? ? lpCurrentDirectory,

? _In_? ? ? ? LPSTARTUPINFO? ? ? ? lpStartupInfo,

? _Out_? ? ? LPPROCESS_INFORMATION lpProcessInformation

);

第一個(gè)參數(shù) hToken是用戶認(rèn)證令牌的句柄颜说,一般而言可以通過遍歷進(jìn)程,然后獲得資源管理器(explorer.exe)的用戶令牌來得到當(dāng)前用戶的用戶認(rèn)證令牌:

HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,pe32.th32ProcessID);

bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken);

其中汰聋,hProcess 為資源管理器(explorer.exe)的進(jìn)程句柄门粪。

但是在本例中,使用當(dāng)前登錄用戶的認(rèn)證令牌創(chuàng)建的進(jìn)程P_i是沒有權(quán)限創(chuàng)建全局共享內(nèi)存的烹困,因?yàn)橹挥芯哂泄芾韱T權(quán)限的用戶才可以創(chuàng)建全局共享內(nèi)存玄妈。普通進(jìn)程可以選擇右鍵管理員權(quán)限并單擊確認(rèn)按鈕啟動(dòng)程序來獲得管理員權(quán)限,但是本例中的進(jìn)程通過服務(wù)啟動(dòng),而服務(wù)通過網(wǎng)絡(luò)接收遠(yuǎn)程計(jì)算機(jī)的控制拟蜻,不可能在啟動(dòng)進(jìn)程P_i時(shí)再點(diǎn)擊確認(rèn)按鈕绎签。因此需要使用另一種方式為進(jìn)程P_i獲得管理員權(quán)限。以下代碼添加到服務(wù)中瞭郑。

第一辜御,需要獲得服務(wù)所屬用戶(system)的令牌hPToken:

OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS,&hPToken);

第二,復(fù)制該令牌屈张,得到新的令牌hUserTokenDup

DuplicateTokenEx(hPToken,TOKEN_ALL_ACCESS,NULL,SecurityAnonymous, TokenPrimary,&hUserTokenDup);

第三,設(shè)置新的令牌hUserTokenDup的令牌信息?

dwConsoleSessionId = WTSGetActiveConsoleSessionId();//獲取當(dāng)前用戶的會(huì)話ID袱巨,如果不是遠(yuǎn)程桌面登錄的情況下阁谆,只執(zhí)行這一步就可以了

SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)&dwConsoleSessionId,sizeof(DWOR));

當(dāng)操作系統(tǒng)上登錄了多個(gè)用戶的時(shí)候,WTSGetActiveConsoleSessionId()獲得的sessionid可能與當(dāng)前遠(yuǎn)程桌面用戶的不一致愉老,如果使用這個(gè)會(huì)話ID來設(shè)置令牌信息场绿,遠(yuǎn)程用戶無法看到啟動(dòng)后的進(jìn)程P_i的界面,因此需要獲得當(dāng)前資源管理器(explorer.exe)用戶的會(huì)話ID:ProcessIdToSessionId(pe32.th32ProcessID, &dwSessionID);然后比較兩個(gè)會(huì)話ID嫉入。

第四焰盗,為了保證進(jìn)程P_I具有創(chuàng)建全局共享內(nèi)存的權(quán)限,需要賦予令牌這個(gè)權(quán)限:

LookupPrivilegeValue(NULL,SE_CREATE_GLOBAL_NAME/*SE_DEBUG_NAME*/,&luid)咒林;//查找創(chuàng)建全局變量的權(quán)限

tp.PrivilegeCount = 1;

tp.Privileges[0].Luid = luid;? ?

tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //權(quán)限使能為啟用

AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,NULL);

第五熬拒,創(chuàng)建進(jìn)程環(huán)境塊,保證環(huán)境塊是在用戶桌面的環(huán)境下

HANDLE hToken;

WTSQueryUserToken(dwConsoleSessionId, &hToken);

if(!CreateEnvironmentBlock(&pEnv,hToken,FALSE))

{

dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;

}

第六垫竞,創(chuàng)建進(jìn)程

CreateProcessAsUser(hUserTokenDup,NULL,lpCmdLine,NULL,NULL,FALSE, dwCreationFlags,pEnv,NULL,&si,&pi)澎粟;

第七,釋放資源

關(guān)閉前面所有的句柄欢瞪,并釋放環(huán)境:DestroyEnvironmentBlock(pEnv)活烙。

3.遇到的第三個(gè)問題,由服務(wù)創(chuàng)建的進(jìn)程P_i可以創(chuàng)建全局共享內(nèi)存遣鼓,但是進(jìn)程P_i有很多中啟動(dòng)方式啸盏,其他方式啟動(dòng)的進(jìn)程P_i不具有管理員權(quán)限,且用戶一般為當(dāng)前登錄用戶骑祟。這時(shí)候可以為該用戶添加一個(gè)創(chuàng)建全局變量的權(quán)限回懦。創(chuàng)建過程如圖所示。

按照序號(hào)1 - 6的順序曾我,依次點(diǎn)擊粉怕,然后在彈出的對(duì)話框中輸入需要添加的用戶名(以u(píng)ser為例),即可為該用戶添加創(chuàng)建全局對(duì)象的權(quán)限抒巢,完成后如序號(hào)7所示贫贝。

添加完成后,使用普通用戶也可以雙擊啟動(dòng)進(jìn)程P_i,并由進(jìn)程P_i創(chuàng)建全局共享內(nèi)存稚晚。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末崇堵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子客燕,更是在濱河造成了極大的恐慌鸳劳,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件也搓,死亡現(xiàn)場(chǎng)離奇詭異赏廓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)傍妒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門幔摸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人颤练,你說我怎么就攤上這事既忆。” “怎么了嗦玖?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵患雇,是天一觀的道長。 經(jīng)常有香客問我宇挫,道長苛吱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任捞稿,我火速辦了婚禮又谋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘娱局。我一直安慰自己彰亥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布衰齐。 她就那樣靜靜地躺著任斋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪耻涛。 梳的紋絲不亂的頭發(fā)上废酷,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音抹缕,去河邊找鬼澈蟆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卓研,可吹牛的內(nèi)容都是我干的趴俘。 我是一名探鬼主播昧港,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼通贞,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼竹揍!你這毒婦竟也來了蓝丙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤疲憋,失蹤者是張志新(化名)和其女友劉穎凿渊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缚柳,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡埃脏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秋忙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剂癌。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖翰绊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情旁壮,我是刑警寧澤监嗜,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站抡谐,受9級(jí)特大地震影響裁奇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜麦撵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一刽肠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧免胃,春花似錦音五、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扼雏,卻和暖如春坚嗜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诗充。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國打工苍蔬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝴蜓。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓碟绑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜈敢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349