OpenProcess 無法取得某些process 是權限不夠?還是什麼原因呢? |
答題得分者是:thf
|
dino
一般會員 發表:20 回覆:73 積分:23 註冊:2002-07-29 發送簡訊給我 |
請教各位:
查閱了K.Top 各位先進前輩關於取得process 資訊的寫法,寫了下列的程式, 功能是取得指定的process 的CPU usage(工作管理員CPU這個欄位,沒有的話可從檢視-選擇欄位 選取CPU使用率 ), 問題是一般的process 都可以取得,但是一些例如windows 服務所啟動的process 抓不到(例如:服務 World Wide WebPublishing Service 所create 的dllhost.exe), 用procexp 這個工具去觀察發現 dllhost 是掛在svchost.exe下面,不知道是不是這個原因的關係,還是因為系統權限的關係才無法抓到呢? uses TlHelp32, PsAPI var Form1: TForm1; dtStart, dtCPUPrev: Int64; hProcess: THandle; iCount:Integer; procedure TForm1.Button1Click(Sender: TObject); begin timer1.Enabled := False; Label2.Caption := ''; iCount:=0; hProcess := OpenProcess(PROCESS_QUERY_INFORMATION, true, StrToInt(EdtByPID.Text));//EdtByPID.Text 輸入Process 的PID showmessage(inttostr(hProcess));//這邊得到的都是0 if hProcess > 0 then timer1.Enabled := True; end; procedure TForm1.Timer1Timer(Sender: TObject); var timespan,dtProcess: Int64; begin if (iCount > 0) then begin timespan := DateTimeToInt64(now) - dtStart; if timespan > 0 then begin dtProcess := GetProcessCPU(hProcess) - dtCPUPrev; Label2.Caption := FloatToStr(100 * (dtProcess / timespan)) ' %'; end; end; dtStart := DateTimeToInt64(now); dtCPUPrev := GetProcessCPU(hProcess); Inc(iCount); end; function GetProcessCPU(hP: THandle): Int64; var CreationTime, ExitTime, KernelTime, UserTime: TFileTime; kernel_LARGE, user_LARGE: LARGE_INTEGER; begin Result := 0; if hP > 0 then begin GetProcessTimes(hP, CreationTime, ExitTime, KernelTime, UserTime); kernel_LARGE.LowPart := KernelTime.dwLowDateTime; kernel_LARGE.HighPart := KernelTime.dwHighDateTime; user_LARGE.LowPart := UserTime.dwLowDateTime; user_LARGE.HighPart := UserTime.dwHighDateTime; Result := kernel_LARGE.QuadPart user_LARGE.QuadPart; end; end; function DateTimeToInt64(dt: TDatetime): Int64; var systemtime1: TSystemTime; filetime1: TFileTime; large1: LARGE_INTEGER; begin DatetimeToSystemTime(dt, systemtime1); SystemTimeToFileTime(systemtime1, filetime1); large1.LowPart := filetime1.dwLowDateTime; large1.HighPart := filetime1.dwHighDateTime; Result := large1.QuadPart; end; 編輯記錄
taishyang 重新編輯於 2009-02-20 18:33:40, 註解 歸類成[問題]‧
|
RootKit
資深會員 發表:16 回覆:358 積分:419 註冊:2008-01-02 發送簡訊給我 |
|
dino
一般會員 發表:20 回覆:73 積分:23 註冊:2002-07-29 發送簡訊給我 |
|
thf
一般會員 發表:1 回覆:3 積分:10 註冊:2009-03-02 發送簡訊給我 |
你可能没有明白ROOTKIT兄的意思,其实就是没有DEDUG权限的原因,你可以试试这样,不用改到你原有的代码,只是加上这样一个PROCEDURE
function AdjustProcessPrivilege(Processhandle:Thandle;Token_Name:pchar):boolean; var Token:cardinal; TokenPri:_TOKEN_PRIVILEGES; processDest:int64; i:DWORD; begin Result:=false; if OpenProcessToken(Processhandle,TOKEN_ADJUST_PRIVILEGES,Token) then begin if LookupPrivilegeValue(nil,Token_Name,processDest) then begin TokenPri.PrivilegeCount:=1; TokenPri.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED; TokenPri.Privileges[0].Luid:=processDest; i:=0; if AdjustTokenPrivileges(Token,false,TokenPri,sizeof(TokenPri),nil,i) then Result:=true; end; end; end; 然后在FORM的ONCREATE 中加上这一句: AdjustProcessPrivilege(GetCurrentProcess,'SeDebugPrivilege'); SeDebugPrivilege 就是ROOTKIT提到的DEBUG权限了 提升到这个权限你的进程就相当于SYSTEM用户了(比ADMINISTRATOR还要高级的用户),这样才能查看用户是SYSTEM的进程SVCHOST了 你还可以看看我的另一个主题: http://delphi.ktop.com.tw/board.php?cid=30&fid=72&tid=97469 也是关于这些方面的 ===================引 用 dino 文 章=================== 感謝 RootKit 兄的回覆^^ NtQuerySystemInformation 看起來就蠻難的 sample code應該也不多吧 再努力搜尋資料好了 看來要跟API打交道真的是會'讓人心力交瘁的@@ 謝謝囉 ===================引 用 RootKit 文 章=================== 有可能要 DEBUG 權限吧。 一般是使用 NtQuerySystemInformation 來查詢地 |
dino
一般會員 發表:20 回覆:73 積分:23 註冊:2002-07-29 發送簡訊給我 |
|
dino
一般會員 發表:20 回覆:73 積分:23 註冊:2002-07-29 發送簡訊給我 |
還是有個疑問,使用AdjustProcessPrivilege取得權限之後,所有的Process都可以找到它的使用者名稱嗎?
下列程式碼對於下列Process 使用 OpenProcessToken是 回傳false的 影像名稱 使用者名稱 svchost.exe LOCAL SERVICE svchost.exe NEWWORK SERVICE 程式碼: //列舉所有進程,取得User, Domain procedure TForm1.Button1Click(Sender: TObject); var hProcSnap: THandle; pe32: TProcessEntry32; Domain, User: string; s: string; begin hProcSnap := CreateToolHelp32SnapShot(TH32CS_SNAPALL, 0); if hProcSnap = INVALID_HANDLE_VALUE then Exit; pe32.dwSize := SizeOf(ProcessEntry32); if Process32First(hProcSnap, pe32) = True then while Process32Next(hProcSnap, pe32) = True do begin if GetUserAndDomainFromPID(pe32.th32ProcessID, User, Domain) then //這邊有問題 begin s := Format('%s User: %s ; Domain: %s',[StrPas(pe32.szExeFile), User, Domain]); Listbox1.Items.Add(s); end else Listbox1.Items.Add(StrPas(pe32.szExeFile) ' PID:' IntToStr(pe32.th32ProcessID)); end; CloseHandle(hProcSnap); end; //GetUserAndDomainFromPID 的程式碼 function GetUserAndDomainFromPID(ProcessId: DWORD; var User, Domain: string): Boolean; var hToken: THandle; cbBuf: Cardinal; ptiUser: PTOKEN_USER; snu: SID_NAME_USE; ProcessHandle: THandle; UserSize, DomainSize: DWORD; bSuccess: Boolean; begin Result := False; ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcessId); if ProcessHandle <> 0 then begin if OpenProcessToken(ProcessHandle, TOKEN_QUERY, hToken) then //對於使用者是LOCAL SERVICE 或是 NEWWORK SERVICE的進程,這邊得到false,所以取不到 User, Domain begin bSuccess := GetTokenInformation(hToken, TokenUser, nil, 0, cbBuf); ptiUser := nil; while (not bSuccess) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) do begin ReallocMem(ptiUser, cbBuf); bSuccess := GetTokenInformation(hToken, TokenUser, ptiUser, cbBuf, cbBuf); end; CloseHandle(hToken); if not bSuccess then begin Exit; end; UserSize := 0; DomainSize := 0; LookupAccountSid(nil, ptiUser.User.Sid, nil, UserSize, nil, DomainSize, snu); if (UserSize <> 0) and (DomainSize <> 0) then begin SetLength(User, UserSize); SetLength(Domain, DomainSize); if LookupAccountSid(nil, ptiUser.User.Sid, PChar(User), UserSize, PChar(Domain), DomainSize, snu) then begin Result := True; User := StrPas(PChar(User)); Domain := StrPas(PChar(Domain)); end; end; if bSuccess then begin FreeMem(ptiUser); end; end; CloseHandle(ProcessHandle); end; end; |
thf
一般會員 發表:1 回覆:3 積分:10 註冊:2009-03-02 發送簡訊給我 |
|
dino
一般會員 發表:20 回覆:73 積分:23 註冊:2002-07-29 發送簡訊給我 |
感謝 thf 的鼎力相助,熱心的回答讓我總算找到解決的方法了
運用WTSEnumerateProcesses 搭配 LookupAccountSid 總算把所有的Process的使用者名稱都列出來了 晚點整理一下程式碼貼上來,感恩^^ ===================引 用 thf 文 章=================== 对于 USER 为 NETWORK SERVICE和LOCAL SERVICE的PROCESS用OPENPROCESSTOKEN是不成功的,好象这一点在MSDN上有提到, 不过你可以在网上查一下用WTSEnumerateProcesses 这个FUNC可以得到PROCESS的SID |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |