Copy Link
Add to Bookmark
Report
2x05 NT Startup Methods Exposed
...................
...::: 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\<userid> kljucu. <userid> 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 <doc>\<username>\Start Menu\Programs\Startup
direktorijumu. <doc> je string koji sadrzi putanju do Documents and Settings
direktorijuma - najcesce "C:\Documents and Settings". Umesto <username>
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\<username>\Start Menu\Programs\Startup direktorijumu.
Umesto <username> 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.