................... ...::: phearless zine #2 :::... .....................>---[ NT Startup Methods Exposed ]---<..................... .............................>---[ by reiser ]---<.............................. reiser.p[at]gmail[dot]com com ____________ _ _/ CONTENTS \_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / [1] Introduction [2] Registry 2.1 > Run, RunOnce & RunOnceEx 2.2 > Windows services 2.3 > UserInit path 2.4 > System Shell 2.5 > Load & Run 2.6 > File Associations 2.7 > ActiveX Components 2.8 > Notify 2.9 > AppInit_DLLs 2.10 > Image File Execution [3] Other Methods 3.1 > Startup directory 3.2 > UserInit, string #1602 resource 3.3 > InstallScreenSaver API [4] Appendix 4.1 > Disabling SFP [5] Conclusion \___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ________________ [1] / INTRODUCTION \_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/ Windows je slozen operativni sistem. Zahvaljuci toj osobini, postoji dosta nacina za startup aplikacija prilikom njegovog podizanja, od onih uobicajenih do nekih veoma zanimljivih i neprimetnih. U ovom tekstu cu opisati skoro sve startup nacine koje znam, sa akcentom na one manje poznate. Opisacu i jedan novi nacin, totalno neprimetan, cak i za napredne korisnike. Posebno zato sto jos niko ne zna za njega, osim mene i jos par osoba, bar do objavljivanja ovog zine-a ;) \_______ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ____________ [2] / REGISTRY \_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/ Registry baza, kao vazan deo windowsa, postoji jos od 95-ice. U njoj se cuvaju sistemska podesavanja, informacije o hardveru, kao i podesavanja ostalog software-a. U daljem tekstu, kad navodim putanju do nekog kljuca u registry-u, value ce biti uovkiren [velikim] zagradama. Recimo, HKLM\SOFTWARE\Key1\[some_data] oznacava na some_data value koji se nalazi u HKLM\SOFTWARE\Key1. I jos nesto, u HKEY_USERS se cuvaju postavke za svaki od korisnickih naloga koji postoji na sistemu. HKEY_CURRENT_USER (u daljem tekstu HKCU) je u stvari link ka HKEY_USERS\ kljucu. je ID trenutno ulogovanog korisnika - svaki korisnik ima svoj jedinstven ID. U HKEY_LOCAL_MACHINE (HKLM) se cuvaju podaci koji vaze za sve korisnike. U HKEY_CLASSES_ROOT (HKCR) se nalaze asocijacije fajlova (pogledajte deo 2.6) i jos neke stvari, nebitne za ovaj tekst. ------------------------------ 2.1 > Run, RunOnce & RunOnceEX ------------------------------ Verujem da vecina vas ovo zna, pa se necu preterano zadrzavati na ovome. - HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run Ovde se smestaju skoro sve aplikacije koja treba da se startuju uz sistem. Aplikacije koje naprave ovde kljuc se izvrsavaju kod svih korisnika. - HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run Isti slucaj kao kod gornjeg kljuca, osim sto se aplikacije izvrsavaju samo kod korisnika pod kojim su kreirale ovde kljuc. - HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce Ovde se smesta putanja do aplikacije koja se treba izvrsiti samo jednom, prilikom sledeceg podizanja windows-a. Posle toga, windows brise taj kljuc. Naravno, aplikacija moze opet napraviti isti kljuc, obezbedivsi na taj nacin ponovno startovanje. Key se brise pre izvrsenja aplikacija. Ako se ispred putanje stavi uzvicnik (!), windows ce izbrisati key tek kada aplikacija zavrsi sa radom. U slucaju da u aplikaciji dodje do neke greske koja ce prekinuti njeno izvrsavanje, windows nece obrisati key. Takodje mozete dodati i zvezdicu (*) ispred putanje, sto ce obezbediti pokretanje aplikacije i u safe-modu. Pazite samo da ne napravite dead-loop tako sto ce te kreirati opet isti key u RunOnce kako bi ste obezbedili startup aplikacije prilikom sledeceg podizanja sistema. Windows iscita key iz RunOnce i izvrsi ga, pa predje na sledeci. Ako se key konstano kreira iz vase aplikacije dok windows iscitava RunOnce, nikad se nece izaci iz te petlje. - HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce Isto kao i kod gornjeg RunOnce kljuca, samo sto se aplikacije izvrsavaju samo kod korisnika pod kojim su kreirale ovde kljuc. - HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx Nesto slicno kao i RunOnce, samo sto je struktura key-eva koji se kreiraju malo drugacija. Prvo treba kreirati podkljuc i u njemu jedan REG_SZ ili REG_EXPAND_SZ string koji ce sadrzati putanju do aplikacije koja se treba izvrsiti. Primer: - HKEY_LOCAL_MACHINE - SOFTWARE - Microsoft - Windows - CurrentVersion - RunOnceEx - Some_Key ------> Ime key-a - moze biti bilo sta. key001 = "C:\WINDOWS\notepad.exe" ------> Putanja do aplikacije, tipa REG_SZ ili REG_EXPAND_SZ. Naziv stringa moze biti bilo sta (ovde je key001). ---------------------- 2.2 > Windows Services ---------------------- Servisi su obicne aplikacije koje se mogu startovati prilikom boot-anja sistema. Oni su deo SCM (Service Control Manager) baze. Servise mozemo instalirati na quick'n'dirty nacin, direktnim kreiranjem kljuceva u registry-u ili koriscenjem funkcija namenjenih za to, OpenSCManager, CreateService, StartService itd. Informacije o servisima se cuvaju u registry bazi, putanja HKLM\SYSTEM\CurrentSontrolSet\Services OSNOVNI TIPOVI SERVISA: (u zagradama se nalaze vrednosti ovih flagova u brojkama - u slucaju da servis kreirate direktnim pisanjem po registry-u, Type vrednost treba da sadrzi jedan od ovih brojeva (DWORD)) - SERVICE_KERNEL_DRIVER (1) driver - SERVICE_FILE_SYSTEM_DRIVER (2) file system driver - SERVICE_WIN32_OWN_PROCESS (16) servis koji ne deli svoj proces sa ostalim procesima - SERVICE_WIN32_SHARE_PROCESS (32) servis koji deli svoj proces sa ostalim procesima Ako servis tipa SERVICE_WIN32_OWN_PROCESS ili SERVICE_WIN32_SHARE_PROCESS, mozete kombinovati i flag SERVICE_INTERACTIVE_PROCESS (256). Ovaj flag oznacava da li servis moze da ima GUI ili se izvrsava u pozadini, bez ikakvih prozora, dugmica itd... Ipak, proces koji nema flag SERVICE_INTERACTIVE_PROCESS moze da koristi MessageBox() API za komunikaciju sa korisnikom ili da izvrsi drugi proces koji moze imati GUI. NACINI STARTOVANJA SERVISA: (odgovara Start vrednosti u registry-u (DWORD)) - SERVICE_BOOT_START (0) Servis startuje system loader. Servis mora biti tipa SERVICE_FILE_SYSTEM_DRIVER ili SERVICE_KERNEL_DRIVER. - SERVICE_SYSTEM_START (1) Servis koji startuje IoInitSystem funkcija. Servis mora biti tipa SERVICE_FILE_SYSTEM_DRIVER ili SERVICE_KERNEL_DRIVER. - SERVICE_AUTO_START (2) Servis startuje SCM prilikom podizanja sistema. Odgovara Automatic nacinu startovanja u services.msc. - SERVICE_DEMAND_START (3) Servis se startuje po potrebi, prilikom pozivanja StartService() funkcije. Odgovara Manual nacinu startovanja u services.msc. - SERVICE_DISABLED (4) Servis koji se ne moze startovati. Ima Disabled status u services.msc. NACIN NA KOJI CE WINDOWS REAGOVATI U SLUCAJU DA SERVIS NE MOZE DA SE STARTUJE: (odgovara ErrorControl vrednosti u registry-u (DWORD)) - SERVICE_ERROR_IGNORE (0) Windows belezi gresku, ali nastavlja dalje podizanje sistema - SERVICE_ERROR_NORMAL (1) Windows belezi gresku i prikazuje poruku o gresci, i nastavlja dalje podizanje sistema - SERVICE_ERROR_SEVERE (2) Windows belezi gresku. Ako je sistem startovan u "Last-Known-Good Configuration" rezimu, on nastavlja dalje podizanje. U suprotnom, restartuje racunar. - SERVICE_ERROR_CRITICAL (3) Windows belezi gresku ako je to moguce, i prekida dalje podizanje. Servise mozemo instalirati cak i na udaljenom kompjuteru, koji je, naravno, povezan sa lokalnim kompjuterom. Dovoljno je samo da prvi parametar u OpenSCManager() funkciji pokazuje na ime udaljenog kompjutera na koji zelimo da instaliramo servis. ------------------- 2.3 > Userinit path ------------------- Key HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\[UserInit] sadrzi putanju do userinit.exe fajla. Prilikom bootanja, windows iscita vrednost ovog kljuca i izvrsi komandu koja je tu zapisana. Userinit.exe izvrsava razne operacije prilikom startup-a, startovanje windows-ovog shell-a, uspostavljanje network konekcija, setovanje postavki za trenutnog korisnika (fontovi, boje itd), tako da je neophodan prilikom startovanja sistema. Postoje dva nacina za startup nase aplikacije preko ovog key-a. Mozemo dodati putanju do nase aplikacije u nastavku ovog string-a, tako da on glasi ovako: "userinit.exe C:\nasaaplikacija.exe" Ovako cemo postici da se prilikom podizanja windows-a izvrsi i userinit.exe i nasa aplikacija. Drugi nacin za startovanje nase aplikacije je repliciranje celog stringa: "C:\nasaaplikacija.exe" Na ovaj nacin ce se startovati samo nasa aplikacija. Ona zatim mora izvrsiti userinit.exe kako bi se sistem uspesno podigao. ------------------ 2.4 > System shell ------------------ Na Win9x sistemima putanja do default shell-a (ljuske) je bila zapisana u %systemroot%\system.ini fajlu. Na NT sistemima ova putanja se nalazi u registry-u, HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\[Shell]. U Windows-ima, default shell je explorer.exe. Shell sluzi kao posrednik izmedju korisnika i sistema (start meni, taskbar, desktop...). Situacija je identicna kao i kod UserInit kljuca. Mozemo dodati string na kraju putanje do shell-a ili ga overwrite-ovati i posle iz aplikacije izvrsiti shell. Primer: "explorer.exe C:\nasaaplikacija.exe", ili "C:\nasaaplikacija.exe" Postoji isti key, samo u HKCU. Ako ovde kreirate key, aplikacija se izvrsava samo kod korisnika pod kojim je kreirala taj key. ---------------- 2.5 > Load & Run ---------------- Na Win9x su u %systemroot%\win.ini fajlu postojala dva string-a, load i run. Dodajuci u njihovom nastavku putanju do nekog fajla, on bi se izvrsavao prilikom svakog podizanja sistema. Na NT sistemima ovi stringovi u win.ini fajlu vise ne postoje. Njihovu ulogu su preuzela dva identicna kljuca u HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows, load i run. Prilikom podizanja windows-a, on iscita ova dva key-a i izvrsi komande koje su tu zapisane. Aplikacija treba samo da doda putanju do svog fajla u bilo koji od ova dva key-a. Mozete dodati putanju do aplikacije u nastavku string-a ili overwrite-ovati ceo string. Primer: "c:\windows\notepad.exe c:\nasaaplikacija.exe", ili "c:\nasaaplikacija.exe" Kako se load i run kljucevi nalaze pod HKCU, izvrsavanje vazi samo za trenutnog korisnika. Pod HKLM ovi klucevi ne postoje. ----------------------- 2.6 > File Associations ----------------------- U HKEY_CLASSES_ROOT se nalaze informacije (u daljem tekstu asocijacije) koje odredjuju koja aplikacija je odgovorna za odredjeni tip fajla. Asocijacije su zapisane u obliku podkljuceva, cije ime odgovara ekstenziji koju opisuju. Postoje jos dve lokacije, HKLM\SOFTWARE\Classes i HKCU\SOFTWARE\Classes, gde se takodje nalaze asocijacije. Ako neka asocijacija postoji u HKLM\SOFTWARE\Classes, ona ce automatski biti kreirana u HKCR i obrnuto. U HKCU\SOFTWARE\Classes se nalaze podaci u nesto drugacijem obliku i nebitni su za nas, pa ih u daljem tekstu necemo razmatrati. Posto se u HKCR, odnosno HKLM\SOFTWARE\Classes nalaze i informacije o tome kako se startuju i .exe, .bat, .scr itd... fajlovi, mi mozemo zameniti te informacije nasom, tako da ce se nas program startovati svaki put kad korisnik pokrene neki .exe fajl recimo. Za svaku extenziju postoje dva kljuca. Kljuc 1, koji ima naziv identican kao extenzija, recimo .exe, i kljuc 2, koji sadrzi informacije o tome kako se pokrece fajl sa tom extenzijom. Oba kljuca se nalaze pod HKCR odnosno HKLM\SOFTWARE\Classes. Default vrednost kljuca 1 mora pokazivati na kljuc 2, kako bi windows znao da su povezani. Recimo, default vrednost .exe kljuca je "exefile". U kljucu 2 (posto sam za primer uzeo .exe extenziju, exefile je u stvari kljuc 2) se nalaze podkljucevi shell\open\command. Default vrednost command kljuca sadrzi informaciju o tome kako se fajlovi sa tom extenzijom startuju. Za .exe extenziju je default vrednost "%1" %* (sa navodnicima). Sta ovo znaci ? "%1" je u stvari ime fajla koji hocemo da startujemo, ograniceno navodnicima. %* je skup svih parametara koji se prosledjuju programu koji se startuje. Recimo, ako korisnik pokusa da startuje program koji se nalazi u C:\prog.exe, pozivajuci ga sa parametrima -h -n, windowsu ce biti prosledjena komanda u sledecem obliku: "C:\prog.exe" -h -n E sad, mi mozemo da zamenimo %1 sa putanjom do nase aplikacije, tako da kad korisnik pokusa da startuje neki program, nasa aplikacija ce se startovati umesto njega. Nista lakse, zamenicemo "%1" %* sa "C:\nasaaplikacija.exe" %*. ALI ! Ako ova vrednost ostane u registry-u, nijedan program se nece moci izvrsiti. Zato moramo da prosledimo nasoj aplikaciji putanju do programa zajedno sa parametrima sa kojim je pozvan, i aplikacija ce izvrsiti program koji joj je prosledjen kao parametar. Dakle, umesto: "C:\nasaaplikacija.exe" %* treba da stavimo: "C:\nasaaplikacija.exe" ""%1" %*" Ovako ce se nasa aplikacija izvrsiti svaki put kad korisnik pokusa da izvrsi neki .exe fajl. Putanja do tog fajla + parametri ce biti prosledjeni aplikaciji. Ona samo treba da izvrsi taj program. Ovo je samo jedan od nacina na koji mozete iskoristiti asocijacije za startovanje svoje aplikacije. Mozete recimo i napraviti preusmerenje tako sto ce te kreirati neki svoj kljuc koji ce sadrzati shell\open\command podkljuceve i izmeniti default vrednost kljuca 1, tako da pokazuje na novokreirani kljuc. Na ovaj nacin windows ce citati informacije iz vaseg kljuca. Primer - default vrednost .bat kljuca je "batfile". Menjanjem ove vrednosti na "batfile1", prilikom startovanja bilo kog fajla sa extenzijom .bat, windows ce pokusati da cita informacije iz "batfile1" kljuca. Ovo je i malo teze da se otkrije, zato sto ce vecina korisnika, ako primeti da se nesto cudno desava sa kompjuterom, pogledati standardni, HKCR\batfile\shell\open\command kljuc (u kome ce naravno, sve biti normalno), dok ce nas kljuc (na koji smo redirektovali .bat kljuc) ostati sakriven. Zanimljiva je i ideja prepraviti kljuc koji se odnosi na fajlove sa ekstenzijom .scr (screen saver-i), tako da svaki put kada windows pokusa da izvrsi neki screensaver, izvrsice u stvari nas program. Isto se dogadja i kad se otvori Screen Saver jezicak u Display Properties prozoru ili kad korisnik klikne na dugme Preview. Samo, ako je sistem setovan da radi bez screensaver-a, tj. screensaver je stavljen na [None], ovo pada u vodu. :) ------------------------ 2.7 > ActiveX Components ------------------------ U HKLM\SOFTWARE\Microsoft\Active Setup\Installed Components se nalazi skup kljuceva. Svi ovi kljucevi se procesuiraju prilikom podizanja windows-a. Ako neki kljuc sadrzi StubPath string (REG_SZ ili REG_EXPAND_SZ), windows ce izvrsiti komandu koja je tu zapisana. Recimo, imamo kljuc {44BBA840-CC51-11CF-AAFA-00AA00B6015C} i pod njim string StubPath = "C:\WINDOWS\notepad.exe". Prilikom sledeceg podizanja, windows ce iscitati ovu vrednost i izvrsiti notepad. Dakle, mi samo treba da kreiramo neki slucajno generisan kljuc (moze imati bilo koji naziv, ne mora da ima oblik kao ostali kljucevi, ali korisniku ce biti lakse da ga uoci), i da pod njim kreiramo string sa imenom StubPath, u kome ce biti zapisana putanja do nase aplikacije. Tako cemo obezbediti njeno startovanje prilikom sledeceg podizanja windows-a. Jedna napomena, kad windows startuje nas program, on ce kreirati jos jedan kljuc sa istim nazivom kao nash, samo u HKCU\SOFTWARE\Microsoft\Active Setup\Installed Components. Ako ovaj kljuc postoji prilikom podizanja sistema, windows nece izvrsiti nas program. Zbog toga nasa aplikacija mora da prilikom svakog startovanja proveri da li ovaj key postoji i izbrise ga. ------------ 2.8 > Notify ------------ HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify. Pod ovim kljucem se nalazi skup kljuceva koji se procesuiraju prilikom nekog event-a. Recimo, ako pod Notify kljucem imamo kreiran kljuc "Test1" i pod njim string "Logon", svaki put kad se korisnik uloguje u sistem, windows ce izvrsiti funkciju koja je zapisana pod ovim stringom. Ime DLL-a iz kog se poziva funkcija se nalazi u stringu DLLName. Izbegavajte da navodite putanju do DLL-a ukljucujuci i direktorijume, recimo drivers\mydll.dll. Umesto toga, stavite DLL u %systemroot%\system32 i navedite samo ime DLL-a. Spisak svih event-a koje sam uspeo da nadjem: - Logon Prilikom logon-a korisnika - Logoff Prilikom logoff-a korisnika - Startup Prilikom startupa windows-a - Shutdown Prilikom gasenja windows-a (shutdown, restart) - Lock Prilikom lock-a windows-a. (switch user) - Unlock Prilikom unlock-a windows-a. (izlazenje iz switch user prozora) - PostShell Nisam uspeo da provalim sta je, ima neke veze sa shell-om, odigrava se sigurno prilikom njegovog startovanja - StartShell Prilikom startovanja default shell-a - Reconnect WTF is this ? - Disconnect WTF is this ? - StartScreenSaver Prilikom startovanja screensaver-a (ne prilikom kliktanja na dugme "Preview") - StopScreenSaver Prilikom prekidanja screensaver-a Kad aplikacija kreira kljuceve u Notify, izmene ce delovati posle restarta sistema. ------------------ 2.9 > AppInit_DLLs ------------------ U HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\[AppInit_DLLs] se cuva putanja do dll-ova koji ce se izvrsiti u toku bootanja windows-a. Kako se ovi DLL-ovi ucitavaju veoma rano, samo API funkcije koje su exportovane u kernel32.dll se mogu koristiti u DLL-u. Uglavnom, veoma riskantna metoda, jer vrlo lako moze da se prouzrokuje prekid daljeg podizanja sistema. --------------------------- 2.10 > Image File Execution --------------------------- U kljucu HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options (u daljem tekstu IFEO), se nalazi skup podkljuceva sa imenom nekog executable fajla. Recimo, install.exe, front.exe, wpwin8.exe itd... Ako ovde kreiramo kljuc koji ce se zvati "notepad.exe" i pod njim kreiramo REG_SZ string sa imenom "Debugger", koji ce sadrzati putanju do nekog fajla, recimo "C:\WINDOWS\System32\cmd.exe", svaki put kad korisnik pokrene bilo koji executable koji se zove "notepad.exe", windows ce umesto njega izvrsiti cmd.exe. Putanja do originalnog fajla koji user zeli da izvrsi se prosledjuje programu kao parametar. Ovo mozemo iskoristiti, tako sto cemo napraviti key sa imenom nekog executable fajla koji se cesto izvrsava i u "Debugger" stringu staviti putanju do nase aplikacije. Posle toga, nasa aplikacija treba samo da izvrsi program koji joj je prosledjen kroz parametar. ALI, pre izvrsavanja programa, aplikacija mora da izbrise kljuc koji je kreirala u IFEO, kako ne bi doslo do njenog ponovnog izvrsenja, i posle toga da ga opet kreira. Ovo je veoma dobar nacin za startup aplikacije, malo poznat, i nasa aplikacija se ne mora izvrsiti odmah nakon startup-a windows-a, vec prilikom pokretanja nekog programa koji mi odredimo, recimo Internet Explorer-a. Mozete reimo kreirati kljuceve u IFEO zavisno od liste najcesce pokretanih programa u HKCU\SOFTWARE\Microsoft\Windows\ShellNoRoam\MUICache. \___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ _________________ [3] / OTHER METHODS \_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/ ----------------------- 3.1 > Startup directory ----------------------- Na svim windows-ima postoji ovaj direktorijum. Fajlovi koji se u njemu nalaze ce se izvrsiti prilikom startovanja sistema, nebitno koje su ekstenzije. (windows prvo iscita informacije iz HKCR (pogledajte deo 2.6) i startuje fajl rukovodeci se iscitanim informacijama). Ovaj deo sam podelio na vise manjih celina, zavisno od verzije windows-a. Na XP-u ovaj folder se nalazi u \\Start Menu\Programs\Startup direktorijumu. je string koji sadrzi putanju do Documents and Settings direktorijuma - najcesce "C:\Documents and Settings". Umesto treba da se nalazi naziv nekog od korisnickih naloga ili "All Users". Ako stavite program pod All Users direktorijum, on ce se startovati kod svih korisnika na sistemu. Ukratko, sve sto se nalazi u All Users direktorijumu se odnosi na sve korisnike. Putanja do Documents and Settings direktorijuma za trenutnog korisnika se cuva i u %USERPROFILE% environment promenljivi. Putanja do All Users direktorijuma se cuva u %ALLUSERSPROFILE%. Recimo, ako otkucate u Command Prompt-u "echo %ALLUSERSPROFILE%", ispisace vam se putanja do All Users dir-a. Na NT/2k ovaj folder se nalazi u %systemroot%\profiles\\Start Menu\Programs\Startup direktorijumu. Umesto treba da se nalazi naziv nekog od korisnickih naloga ili "All Users". Uglavnom, isto kao i na XP-u, samo sto je putanja do dir-a promenjena. ------------------------------------- 3.2 > UserInit, string #1602 resource ------------------------------------- Kao sto sam ranije napisao, userinit.exe se pokrece svaki put prilikom podizanja sistema. Evo jedne njegove fje (reversed by sunnis): //////////////////////////////////////////////////////////////////////////////// VOID WINAPI CheckVideoSelection(HINSTANCE hInstance) { UNICODE_STRING DisplayString; HANDLE handle; OBJECT_ATTRIBUTES objectAttributes; WCHAR AdjustDisplayPath[MAX_PATH]; NTSTATUS Status; // // SessionId = 0 je konzolni CSRSS, tj prvi serverski proces // if (NtCurrentPeb()->SessionId == 0) { return; } RtlInitUnicodeString( &DisplayString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\GraphicsDrivers\\DetectDisplay"); InitializeObjectAttributes( &objectAttributes, &DisplayString, OBJ_CASE_INSENSITIVE, NULL, NULL); // // Pokusaj otvaranja prvog kljuca // Status = NtOpenKey( &handle, KEY_ALL_ACCESS, &objectAttributes); if ( !NT_SUCCESS(Status) ) { // // Pokusaj otvaranja drugog kljuca, u slucaju da otvaranje prvog nije uspelo // RtlInitUnicodeString( &DisplayString, L"\\Registry\Machine\\System\\CurrentControlSet\\Control\\GraphicsDrivers\\InvalidDisplay"); InitializeObjectAttributes( &objectAttributes, &DisplayString, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenKey( &handle, KEY_ALL_ACCESS, &objectAttributes); // // Ako ni ovaj kljuc nismo uspeli da otvorimo, rezolucija je vec podesena... Izlazimo // if ( !NT_SUCCESS(Status) ) { return; } } NtClose( handle ); // // 1602 je string resurs "Rundll32 shell32,Control_RunDLL desk.cpl,,3" // LoadStringW( hInstance, 1602, AdjustDisplayPath, sizeof(AdjustDisplayPath)); ExecApplication( AdjustDisplayPath, 0, 1, 0, 1 ); } //////////////////////////////////////////////////////////////////////////////// Kao sto vidimo, ova funkcija pokusava da otvori HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\DetectDisplay key, koristeci native API-je (NtOpenKey). Ako on ne postoji, onda pokusava da otvori HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\InvalidDisplay key. U slucaju da jedan od ova dva key-a postoji, fja poziva LoadStringW() fju i ucitava u promenljivu "String" string resurs #1602. Zatim, pozivajuci ExecApplication() fju izvrsava taj string. ExecApplication() fja se takodje nalazi u userinit.exe fajlu, ali ona nije bitna za nas, pa necu postovati ovde njen source code. Uglavnom, radi nesto slicno kao i ShellExecute() API. Dakle, prilikom svakog startovanja, CheckVideoSelection() fja proverava da li postoje gore navedeni kljucevi, i u slucaju da makar jedan postoji, izvrsice string #1602, koji je uskladisten u userinit.exe kao resurs. Mi mozemo ovo iskoristiti tako sto cemo prepraviti #1602 string i njegovu standardnu vrednost zameniti nasom - putanjom do nase aplikacije. Dakle, kad otvorimo userinit.exe pomocu nekog resource editora i otvorimo string resurse, vidimo ovo: //////////////////////////////////////////////////////////////////////////////// STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US { 1600, "Invalid Display Settings" 1601, "control main.cpl system" 1602, "Rundll32 shell32,Control_RunDLL desk.cpl,,3" 1603, "%s\nThis working directory is invalid: %s\nPlease consult help for more information" 1604, "%s\nThis initial program cannot be started: %s\nPlease consult help for more information" 1605, "An error (%u) occurred while creating user logon.\nThis working directory is invalid: %s\nPlease consult help for more information" 1606, "An error (%u) occurred while creating user logon.\nThis initial program cannot be started: %s\nPlease consult help for more information" 1607, "You are connected to the remote computer. However, an error occured while an initial user program was starting, so you are being logged off. Contact the system administrator for assistance." 1608, "Logon Failed" } //////////////////////////////////////////////////////////////////////////////// Komanda koja je zapisana u stringu #1602 poziva Display Properties dialog, jezicak Settings. Menjajuci ovu komandu, mi mozemo izvrsiti bilo koji fajl. Recimo, umesto "Rundll32 shell32,Control_RunDLL desk.cpl,,3" mozemo staviti putanju do nase aplikacije, "C:\\nasaaplikacija.exe". Backslash-ove moramo pisati kao \\, zato sto u C-u postoje tzv. predefinisani manipulatori koji sluze za operacije sa stringovima, recimo \n za prelazak u novi red itd... Sve sto nasa aplikacija treba da uradi kako bi obezbedila startovanje prilikom sledeceg podizanja sistema, je da zapise putanju do svog fajla u #1602 resurs i da kreira jedan od kljuceva (DetectDisplay ili InvalidDisplay) u HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\. Jedna napomena, kad CheckVideoSelection() fja izvrsi string #1602, ovi kljucevi se automatski brisu, tako da aplikacija mora da ih kreira ponovo, prilikom svakog startovanja. Kljucevi se mogu odmah ponovo kreirati nakon startovanja aplikacije, bez bojazni da ce te napraviti dead-loop. Resurs mozete izmeniti koristeci UpdateResource() fju ili mapirati fajl u memoriju sa CreateFileMapping() & MapViewOfFile() i patchovati ga. Kako CheckVideoSelection() fja otvara kljuceve sa NtOpenKey() fjom (znaci koristi native API), trebalo bi da mozemo slobodno da kreiramo kljuceve sa NtCreateKey() iz nase aplikacije. Koristeci native API fje za kreiranje kljuceva (NtCreateKey), svi standardni registry editori koji kljuceve ne otvaraju koristeci native API fje, nece moci da otvore ovaj kljuc, niti da ga izbrisu. Ja sam kreirao kljuc sa NtCreateKey(), ali userinit.exe nije hteo da ga procesuira i otvori string #1602... Tako da izgleda mora da se koriste win32 api-ji :/ (ako neko uspe sa native API-jima, neka me kontaktira na mail). Primer za koriscenje native API-ja za kreiranje kljuceva, pisan u C-u, mozete naci na www.sysinternals.com (Mark Russinovich). Ako neko zeli Delphi fju koja ovo radi, neka pise na mail. NAPOMENA: Kako ovde menjamo resurs userinit.exe-a, SFP (Windows File Protection) ce reagovati. Pre menjanja resursa ga moramo iskljuciti. Pogledajte deo 4.1 koji govori o iskljucivanju SFP-a. ---------------------------- 3.3 > InstallScreenSaver API ---------------------------- Startup nase aplikacije mozemo obezbediti i tako sto cemo je setovati kao screensaver na sistemu. Dovoljno je da pozovemo InstallScreenSaver API koji je exportovan u desk.cpl fajlu, prosledjujuci joj putanju do naseg programa (program mora da ima ekstenziju .scr). Ovo mozemo uraditi koristeci ShellExecute() API, pozivajuci rundll32.exe. U putanju cemo upisati "rundll32.exe desk.cpl,InstallScreenSaver putanja_do_programa.scr". Posle ovoga, nas program je setovan kao screensaver i ceka na izvrsenje. ;) Jedini problem ovde, je taj sto se posle pozivanja InstallScreenSaver() API-ja pojavi Display Properties prozor - njega treba da ubijemo. Dovoljno je da nadjemo njegov handle i prosledimo mu WM_CLOSE poruku. Primer u Delphi-u: SendMessage(FindWindow(nil, 'Display Properties'), WM_CLOSE, 0, 0); I prilikom pojavljivanja ovog prozora, nas program ce se opet izvrsiti tako da moramo da imamo neku kontrolu broja instanci (preko mutex-a recimo). O ovome je pisao SWaNk u 29a, #7. \___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ____________ [4] / APPENDIX \_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/ ------------------- 4.1 > Disabling SFP ------------------- SFP ili System File Protection proverava digital signature zasticenog fajla koji se nalazi najcesce u %systemroot%\system32 i ako se signature ne poklapa sa microsoft-ovim, SFP ce pokusati da iskopira fajl iz %systemroot%\system32\dllcache direktorijuma u %systemroot%\system32. Ako ni fajl u dllcache diru nema validan digital signature, windows ce zatraziti od korisnika da ubaci originalni CD sa instalacijom windows-a kako bi povratio fajl. Mi treba na neki nacin da onemogucimo prikaz ovog dijaloga, ili iskljucivanjem SFP-a ili ubijanjem dijaloga koji se pojavljuje. 1. NACIN -------- Ovde se nacin na koji mozemo da iskljucimo SFP bitno razlikuje od verzije sistema. Pre svega, treba da promenimo value key-a HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\[SFCDisable] u 0xffffff9d. Zatim, zavisno od sistema, treba da patchujemo fajl (ako neki sistem nije naveden, to znaci da patchovanje nije potrebno): Na Win2k SP1+ treba da u fajlu %systemroot%\system32\SFC.DLL prepravimo dva bajta (tj. dve instrukcije), na offsetu 0x00006211h. Pre prepravljanja, ova dva bajta treba da imaju vrednosti "8B C6". Trebamo ih nop-ovati, tj. prepraviti u "90 90". Na WinXP bez SP-a treba da u fajlu %systemroot%\system32\SFC_OS.DLL prepravimo dva bajta ("8B C6") na offset-u 0x0000E2B8h. Na WinXP SP1 treba da prepravimo dva bajta ("8B C6") na offset-u 0x0000E3BBh. Na WinXP SP2 treba da prepravimo tri bajta ("33 C0 40") na offset-u 0x0000ECE9h. U sva tri slucaja svaki bajt prepravljamo u "90". Prepravljanje mozete izvesti tako sto ce te mapirati fajl u memoriju pomocu MapViewOfFile() fje i patchovati ga. Vodite racuna da patchujete oba fajla, u system32 i system32\dllcache direktorijumima. Najbolje je da patchujete samo jedan, recimo u system32 diru, i da ga onda iskopirate u dllcache. Posle patchovanja i prepravljanja key-a u registry-u, kompjuter se mora restartovati kako bi izmena delovala. Pre restartovanja ce se onaj SFP-ov dijalog za repair fajlova non-stop pojavljivati zbog toga sto smo izmenili SFC.DLL odnosno SFC_OS.DLL. Zato moramo taj dijalog nekako sakriti, tj. zatvarati ga cim ga winlogon.exe kreira. (pogledajte 3. nacin) 2. NACIN -------- Drugi nacin za iskljucivanje SFP-a, koji je nesto laksi od gore navedenog (a i bolji) se sastoji u pozivanju nedokumentovane SfcTerminateWatcherThread procedure, koja se nalazi u SFC.DLL library-u (export #2). Kao sto joj samo ime kaze, ova funkcija ce prekinuti izvrsavanje Watcher Thread-a na 1 minut i SFP ce biti iskljucen za to vreme. Ovu funkciju moze koristiti samo winlogon.exe. Zato mi moramo da pomocu WriteProcessMemory() i CreateRemoteThread() kreiramo remote thread koji ce se izvrsavati iz winlogon-a, a pozivace SfcTerminateWatcherThread proceduru. Nasa aplikacija mora imati i debug privilegije kako bi mogla da koristi WriteProcessMemory() na winlogon.exe-u. Posle dobijanja debug privilegija, treba da alociramo potrebnu kolicinu memorije u winlogon-u i kreiramo remote thread koji pokazuje na funkciju koja ce izvrsiti SfcTerminateWatcherThread proceduru. Pogledajte dodatak, napisao sam kod u Delphi-u koji ovo radi. Takodje vredi pogledati i Ratter-ov tekst o prekidanju Watcher Thread-a (29a, #7). (on je opisao i jos jedan nacin, koji verovatno radi samo na WinXP+ sistemima, pozivanjem SfcFileException fje (export #5), koja se nalazi u SFC_OS.DLL - u dodatku imate source koji gasi SFP i na ovaj nacin) 3. NACIN -------- SFP ne moramo ni iskljucivati. Dovoljno je samo da ubijemo prozor koji winlogon.exe kreira ako primeti da neki fajl nema validan digital signature. Kako prozor ima caption "System File Protection", mi mozemo naci njegov handle koristeci FindWindow() API. Posle toga samo treba da prosledimo WM_NCDESTROY poruku ovom prozoru pomocu SendMessage() API-ja. Primer u Delphi-u: SendMessage(FindWindow(nil, 'Windows File Protection'), WM_NCDESTROY, 0, 0); (nemojte da saljete prozoru WM_CLOSE poruku, zato sto ce se pojaviti ono glupo upozorenje "Are you sure blablatruc ?") \___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ______________ [5] / CONCLUSION \_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/ To bi bilo otprilike sve :) Jos malo pa ce deadline, ostalo je mozda jos par forica koje nisam opisao, ali sta je tu je... Fokusirao sam se samo na NT sisteme, tako da sam neke nacine izostavio (recimo preko wininit.ini, autoexec.bat itd.. na 9x sistemima, zatim preko ICQ-a itd..). Nadam se da ce ovaj mali textic nekome pomoci. Sva pitanja saljite na moj mail ili na ICQ 195866338. Da napishem jos i greetz pa saljem text. cya ;) \___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ greetz goes to: alex, sunnis, deroko, Shatterhand, _bl00dz3r0_, svim likovima sa #ugs, #secure & #vranje, ES forumu gde sam stekao dosta znanja ;p i ostalima koje sam zaboravio da navedem.