Cum de a determina în mod sigur că programul se execută ca un serviciu

Cum de a determina în mod sigur că programul se execută ca un serviciu?

Am fost undeva în exemplul meu, dar trage numele de utilizator cu care rulează serviciul, și o compară cu numele sub care procesul se execută. Întâmplător - cum ar fi serviciul noi. Dar același utilizator nu înseamnă că procesul nostru - servicii. Serviciul poate fi rulat în numele unui alt uchetki, astfel încât această metodă este eliminată. Cum de a determina care procesul se execută managerul de serviciu și nu altcineva?








> Cum de a determina care procesul se execută managerul de serviciu,
> # XA0, și nu altcineva

Crezi că dacă mă duc în consola de administrare și serviciul se execută, acesta va rula în numele meu?


> Serviciul poate fi rulat în numele unui alt uchetki asa
> Această metodă elimină
Nu este foarte bună dreptate pune-l. Mă voi corecta:

Procesul poate fi rulat cu același nume, care rulează serviciul, și apoi o reconciliere a numelor a da un rezultat incorect.


> Crezi că dacă mă duc în consola de administrare și
> Serviciul rulează, acesta va rula în numele meu?

Setările de serviciu pot fi atribuite la orice uchetku utilizat pentru a executa serviciul. Deși sub vizitator pentru a rula. Și nu va fi același lucru, va fi de așteptat să complet diferit de comportament al programului decât în ​​cazul în care oaspetele o dată el începe programul. Aici e chestia.

Dacă nu-i amestecat, atunci când executați „ca un serviciu de“ program de construcții devine. parametrii (sau în afara spec. call-back „și tic nervos? complet uitate).
Și astfel întrebarea nu este clar: programul în cazul în care serviciul - rulează în întregime într-un anumit fel.

PS
mâna nu este în cazul în care să se uite rapid, dar sper că nu te mint


> Deci, ce? Zapuskatsya va fi în orice caz managery serviciu

Nu inteleg :) Utilizatorul poate, de exemplu, în Windows Explorer și executați exe pentru a lua cu un serviciu. Și nu este ceva care ar trebui să fie)

Ce totul: a scrie serviciu, care ar trebui să funcționeze strict sub uchetki atribuite lui. Dar ai nevoie pentru a depana, astfel că el ar putea rula și ca un serviciu și ca un program normal, un pic de reglare cu logica internă. Mai târziu, când se apropie de final, va trebui să interzică lansarea unui alt serviciu, cu excepția.

> Ești în serviciul este necesar să se determine în a cărei uchetki se execută, dar nu pentru a determina în cazul în care serviciul se execută.
și cum apoi cu opțiunea în cazul în care este rulat ca un program? uchetki nu figura, deoarece poate fi pornit de oricine, singura opțiune este de a găsi pe cineva pentru a partaja (de la) programul este pornit.
și anume „În cazul în care serviciul se execută“ doar determină dacă un serviciu sau un program.

vorbim despre utilizarea în comun și ramificare respectiv de cod, în funcție de modul în care programul va începe ca un serviciu sau ca un program.
de exemplu, putem vedea scktsrvr.exe (acolo sursa) în Delphi, aceasta este o metodă de determinare a acestora (ceea ce el nu determină întotdeauna dreapta).
> A fost undeva exemplul meu
acolo sigur.

PAH clătite. Ei bine, împărțiți conceptul de servicii și aplicații. destul de confuz. )

typedef struct _SYSTEM_PROCESS_INFORMATION # XA0; # XA0; ulong NextEntryOffset;
# XA0; NumberOfThreads ulong; # XA0;
# XA0; # XA0; BYTE Reserved1 [48];
# XA0; # XA0; PVOID Reserved2 [3];
# XA0; # XA0; MÂNER UniqueProcessId;
# XA0; # XA0; PVOID Reserved3;
# XA0; # XA0; ulong HandleCount;
# XA0; # XA0; BYTE Reserved4 [4];
# XA0; # XA0; PVOID Reserved5 [11];
# XA0; # XA0; size_t PeakPagefileUsage;
# XA0; # XA0; size_t PrivatePageCount;
# XA0; # XA0; LARGE_INTEGER Reserved6 [6];
> SYSTEM_PROCESS_INFORMATION;

Apoi, nu este nimic de puzzle. Doar termina depanare.

Mânerul trebuie să aibă drepturile de acces PROCESS_QUERY_INFORMATION și PROCESS_VM_READ

În general, avem un cod. critici interesați

Funcția GetProcessParentID: Cardinal;
var
# XA0; ProcEntry: TProcessEntry32;
# XA0; hSnapshot: THandle;
# XA0; CurrID: Cardinal;
# XA0; Succes: Boolean;
începe
# XA0; Rezultat: = 0;
# XA0; hSnapshot: = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
# XA0; dacă (hSnapshot <> INVALID_HANDLE_VALUE) atunci
# XA0; # XA0; încercați
# XA0; # XA0; # XA0; ProcEntry.dwSize: = sizeof (ProcEntry);
# XA0; # XA0; # XA0; succes: = Process32First (hSnapshot, ProcEntry);
# XA0; # XA0; # XA0, în cazul în care de succes, atunci
# XA0; # XA0; # XA0; începe
# XA0; # XA0; # XA0; # XA0; CurrID: = GetCurrentProcessId;
# XA0; # XA0; # XA0; # XA0; SetLastError (ERROR_SUCCESS);
# XA0; # XA0; # XA0; # XA0, în timp ce de succes face
# XA0; # XA0; # XA0; # XA0; # XA0; dacă (ProcEntry.th32ProcessID = CurrID) atunci
# XA0; # XA0; # XA0; # XA0; # XA0; începe
# XA0; # XA0; # XA0; # XA0; # XA0; # XA0; Rezultat: = ProcEntry.th32ParentProcessID;






# XA0; # XA0; # XA0; # XA0; # XA0; # XA0; Break;
# XA0; # XA0; # XA0; # XA0; # XA0; end
# XA0; # XA0; # XA0; # XA0; # XA0; altcineva
# XA0; # XA0; # XA0; # XA0; # XA0; # XA0; succes: = Process32Next (hSnapshot, ProcEntry);
# XA0; # XA0; # XA0; end;
# XA0; # XA0; # XA0; Win32Check (GetLastError);
# XA0; # XA0; în sfârșit
# XA0; # XA0; # XA0; CloseHandle (hSnapshot);
# XA0; # XA0; end
# XA0; altcineva
# XA0; # XA0; Win32Check (GetLastError);
se încheie;

Funcția GetProcessParentName: string;
var
# XA0; ProcEntry: TProcessEntry32;
# XA0; hSnapshot: THandle;
# XA0; Succes: Boolean;
# XA0; ParentPID: Cardinal;
începe
# XA0; Rezultat: = "";
# XA0; hSnapshot: = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
# XA0; dacă (hSnapshot <> INVALID_HANDLE_VALUE) atunci
# XA0; # XA0; încercați
# XA0; # XA0; # XA0; ProcEntry.dwSize: = sizeof (ProcEntry);
# XA0; # XA0; # XA0; succes: = Process32First (hSnapshot, ProcEntry);
# XA0; # XA0; # XA0, în cazul în care de succes, atunci
# XA0; # XA0; # XA0; începe
# XA0; # XA0; # XA0; # XA0; ParentPID: = GetProcessParentID;
# XA0; # XA0; # XA0; # XA0; SetLastError (ERROR_SUCCESS);
# XA0; # XA0; # XA0; # XA0, în timp ce de succes face
# XA0; # XA0; # XA0; # XA0; # XA0; dacă (ProcEntry.th32ProcessID = ParentPID) atunci
# XA0; # XA0; # XA0; # XA0; # XA0; începe
# XA0; # XA0; # XA0; # XA0; # XA0; # XA0; Rezultat: = ProcEntry.szExeFile;
# XA0; # XA0; # XA0; # XA0; # XA0; # XA0; Break;
# XA0; # XA0; # XA0; # XA0; # XA0; end
# XA0; # XA0; # XA0; # XA0; # XA0; altcineva
# XA0; # XA0; # XA0; # XA0; # XA0; # XA0; succes: = Process32Next (hSnapshot, ProcEntry);
# XA0; # XA0; # XA0; end;
# XA0; # XA0; # XA0; Win32Check (GetLastError);
# XA0; # XA0; în sfârșit
# XA0; # XA0; # XA0; CloseHandle (hSnapshot);
# XA0; # XA0; end
# XA0; altcineva
# XA0; # XA0; Win32Check (GetLastError);
se încheie;

# XA0; # XA0; # XA0; CloseServiceHandle (Svc);
# XA0; # XA0; end;
# XA0; # XA0; CloseServiceHandle (Mgr);
# XA0; end;
se încheie;

Procedura Win32Check (errorcode: Cardinal);
începe
# XA0; dacă (errorcode <> ERROR_SUCCESS) atunci
# XA0; # XA0; ridica Win32Exception.Create (SysErrorMessage (errorCode));
se încheie;

Puteți încerca să transmită cheia de pornire linie.
Este, dacă nu învață să lucreze cu servicii și manager de servicii

> În general, avem un cod. critici interesați
Veți plăti pentru rând? atunci totul este bine, foarte bine. dar, în general, nu există Rouse_ oferă opțiuni mai compact, intuitiv că nu costă nimic pentru a modifica.
Dar, în acest caz

Funcția ParentProcName: string;
const
# XA0; ProcessBasicInformation = 0;
var
# XA0; Info: PROCESS_BASIC_INFORMATION;
# XA0; dwProcessHandle: dword;
# XA0; ProcessName: string;
# XA0; Hndl: THandle;
începe
# XA0; Rezultat: = "noname";
# XA0; dwProcessHandle: = GetCurrentProcess;
# XA0; dacă NtQueryInformationProcess (dwProcessHandle, ProcessBasicInformation, @Info, sizeof (Info), nil) = NO_ERROR
# XA0; # XA0, apoi începe
# XA0; # XA0; # XA0; Hndl: = OpenProcess (PROCESS_QUERY_INFORMATION sau PROCESS_VM_READ, False, Info.uInheritedFromUniqueProcessId);
# XA0; # XA0; # XA0; dacă Hndl <> 0 atunci
# XA0; # XA0; # XA0; # XA0; încercați
# XA0; # XA0; # XA0; # XA0; # XA0; setlength (ProcessName, MAX_PATH);
# XA0; # XA0; # XA0; # XA0; # XA0; dacă GetModuleBaseNameA (Hndl, 0, PChar (ProcessName), MAX_PATH)> 0
# XA0; # XA0; # XA0; # XA0; # XA0; # XA0; apoi Rezultat: = PChar (ProcessName);
# XA0; # XA0; # XA0; # XA0; în sfârșit
# XA0; # XA0; # XA0; # XA0; # XA0; CloseHandle (Hndl);
# XA0; # XA0; # XA0; # XA0; end;
# XA0; # XA0; end;
se încheie;

acesta înlocuiește cele două treimi din codul.

> De ce roditelstkie procesele Suka - nu este clar pentru mine.
în cazul în care nu numai pentru depanare în cazul în care programul este scris ca exemplul dat de mine mai devreme programul de Borland.


> Run - se înregistrează de call-back și toate. și
> Nu poate fi nimic altceva decât un serviciu, prin definiție,

Poate :) serviciu - este același proces, și nu este diferit de procedeul convențional, cu excepția faptului că a început și controlat de către managerul de sistem.


> Acesta înlocuiește cele două treimi din codul

Deci, este adevărat, dar, în plus față de avertismentele roșii despre NtQueryInformationProcess, există un alt punct, care, de asemenea am menționat:

Mânerul trebuie să aibă drepturile de acces PROCESS_QUERY_INFORMATION și PROCESS_VM_READ

Acest lucru și GetModuleFileNameEx # XA0 referă de asemenea la GetModuleBaseName. Uită-te la MSDN, dacă nu crezi. Și serviciul, amintiți-vă, nu este obligată să aibă aceste drepturi, deoarece acesta poate fi rulat de către orice utilizator.

> Mânerul trebuie să aibă drepturile de acces PROCESS_QUERY_INFORMATION și PROCESS_VM_READ
de aceea ei sunt aici și sunt solicitate
Hndl: = OpenProcess (PROCESS_QUERY_INFORMATION sau PROCESS_VM_READ Fals, Info.uInheritedFromUniqueProcessId.)
deoarece mânerul ar trebui să le aibă.

și cu NtQueryInformationProcess. se solicită Infa proces propriu, este ridicol, dacă dreptul de a nu este chiar citit. acest lucru nu poate fi.

toate drepturile pentru a citi informație, IMHO, există chiar și un oaspete. verificați prin începerea serviciului său de către utilizatorii cu privilegii de oaspeți. în versiuni ale acestui cod, fără / cu el.
ci pe modul în care drepturile de proces snepshot la citirea lor de informații nu are nevoie? el este, de asemenea, citit.

> Deoarece poate fi rulat de către orice utilizator.
chiar și atunci logica nu se poate. Serviciul în sine pentru serviciile sale ar trebui să fie ceva ce drepturi. și ei sunt, IMHO, mai mult decât este necesar pentru a citi numele modulului.


> De aceea, ei sunt aici și sunt solicitate
Și este din cauza drepturilor limitate juzverej OpenProcess returnează Acces refuzat atunci când încearcă să deschidă procesul părinte.


> Se solicită Infa proces propriu
De ce am proprii? Am nevoie de un părinte. PID I a lua părinte, dar numele de fișier părinte - numai prin ToolHelp, care lucrează dintr-un uchetki limitat.


> Verificați pornind serviciul său de către utilizatorii cu privilegii de oaspeți
O am de la început și au făcut :) Cu toate acestea, nu un oaspete, dar sub uchetki special, care constă dintr-un grup de utilizatori. Dreptul la funcțiile Nt / ZwHHH nu a fost testat, dar pe GetModuleFileNameEx și GetModuleBaseName declanșat imediat. După un instantaneu al tuturor sa dovedit fără discuție.

Apropo, eu lucrez aici, de asemenea, cu drepturile. Sa dovedit că nepravilno.BuildExplicitAccessWithName a declarat și GetSecurityInfo a anunțat în mod incorect la Borland mai multe funcții. Și lângă BuildExplicitAccessWithName încă am văzut caracteristicile pe care un postfixat W sunt parametrii PAnsiChar.


> Sa constatat că Borland a anunțat mai multe funcții în mod corespunzător.
> BuildExplicitAccessWithName și GetSecurityInfo incorect
> A anunțat. Și lângă BuildExplicitAccessWithName încă văzută
> Function, care cu postfixat W sunt parametri PAnsiChar.
>

Și soarele există pete.

Nu puțini, dar multe, și sunt corectate sau lent sau nu.