onsdag 26. november 2008
Avbrudd og Unntakshåndtering.
Avbrudd (Interrupts) og unntak (Exceptions) er spesielle hendinger i operativsystemet som dirigerer prossoren utenfor den koden den driver på med. En trap eller felle er rett og slett en mekanisme i prosessoren som sørger for å fange en kjørende tråd når et unntak eller avbrudd forekommer og overfører kontrollen til en bestemt plass i operativsystemet. I Windows overføres kontrollen til en såkalt Trap Handler, som er en funksjon som er spesfikk til det unntaket eller avbruddet som forekom. Definisjonen på et avbrudd er en asynkron hendelse (som kan inntreffe til enhver tid) som ikke er relatert til det prosessoren driver på med. Mens et unntak er synkron hendelese som stammer fra kjøringen av den siste instruksjonen på prosessoren.
Både Hardware og software kan generere avbrudd og unntak. Feks kan er et unntak relatert til en databuss et Hardwareproblem, mens et program som prøver å dele på null skyldes programvarefeil. Videre kan en I/O-enhet generere et avbrudd når den trenger service, eller operativsystemet kan generere et programvare-avbrudd (slik som APC og DPC).
Når et hardware avrudd eller unntak blir generert, vil prosessren sørge for å lagre tilstanden som maskinen er i på kernel-stakken slik at tråden kan returnere til det den drev på med straks avbruddet eller unntaket er håndtert. Hvis tråden kjører i User Mode, vil Windows bytte til kernel-stakken for den tråden. Deretter vil Windows generere et Trap Frame på kernel-stakken som inneholder tilstanden til tråden og dens kontekst.
I de fleste tilfeller vil kjernen sørge for å tilby såkalte front-end trap handlere som sørger for å utføre oppgaver relatert til å overføre kontrollen til andre funksjoner som håndterer fellen direkte. Hvis det feks oppstår et enhets-avbrudd så vil kjernen bruke en hardware interrupt trap handler for å øverføre kontrollen til en såkalt Interrupt Service Routine (ISR) som blir levert av enhetsdriveren for enheten.
fredag 21. november 2008
Nettverk i Windows.
Nettverks API:
Gir applikasjoner en måte å kommunisere over et nettverk uavhengig av protokoller. Nettverks API kan bli implementert i User-Mode eller både User og Kernel-Mode, og i noen tilfeller fungerer de som wrappere rundt andre nettverks-API som implementerer en spesifikk programmerings modell eller tilbyr ekstra enheter.
Transport Driver Interface (TDI) klienter:
Er Kernel-mode enhetsdrivere som vanligvis implementerer kernel-mode delen av et nettverks API. TDI-klienter får navnet på grunn av at IRP-pakkene som de sender til protokoll driverne er formatert etter Windows Transport Driver Interface-standarden. Denne standarden spesifiser et felles programmeringsgrensesnitt for kernel-mode drivere.
TDI transports:
Også kjent som transports, NDIS protokoll drivere og protokoll drivere. Er rett og slett protokoll drivere som kjører i kernel-mode. De mottar IRP-pakker fra TDI-klientene og prosesserer den anmodningen spesifisert i pakkene. Denne prosesseringen trenger muligens nettverkskommunikasjon med en nettversknode, som ber TDI-transporteren om å legge med protokollspesifikke headere, (Slik som TCP, UDP og IP) til dataen i IRP-pakken og å kommunisere med adaptere via NDIS-spesifikasjonen.
Network Driver Interface Specification (NDIS) bibloteket:
Fungerer som en slags innkapsling rundt adapter driverne, slik at adaptere driverne ikke behøver å "se" og interaktere med spesfikke detaljer i Windows Kjernen. NDIS bibloteket tilbyr funksjoner som kan brukes av TDI-transports, så vel som ekstra funksjoner til adapter driverne.
NDIS Miniport Drivere:
Er drivere i kernel-mode som er ansvarlig for å bygge et grenesnitt mellom TDI-transportere og spesifikke nettverks adaptere. NDIS miniport driverne er skrevet slik at de innpakket i NDIS-bibloteket. NDIS miniport drivere behandler ikke IRP-pakker, istedet vil de registrere et såkalt call-table grensesnitt til NDIS-biblotket som inneholder pointere til funksjoner som korresponderer med de som NDIS-biblotektet tilbyr TDI-transports. NDIS miniport drivere kommuniserer med nettverks adaptere gjennom funksjoner i NDIS-bibloteket som igjen ender opp i kall til funksjoner i Hardware Abstraction Layer (HAL)
Windows tilbyr flere forskjellige Nettverks API som har hver sine egne unike egenskaper som inkluderer hvilke protokoller det støtter, måten de kommuniserer på og hvilke andre platformer de er kompatible med. La oss nå ta en titt på noen av disse.
Windows Sockets (Winsock)
Er basert på BSD-sockets som er en gammel UNIX-standard for nettverkskommunikasjon fra 80-tallet. Windows sin oppgraderte versjon har en del ekstra egenskaper som BSD sockets ikke har, slik som:
* Støtte for strø-henting (scatter-gather) og asynkron program I/O.
* Quality of Service(QoS) konvensjoner slik at applikasjoner kan negere latenstid og båndbredde krav så lenge det underliggende nettverkset støtter QoS.
* Mulighet for utviding slik at Winsock kan støtte flere protokoller enn de som følger med Windows.
* Støtte for integrerte navneområder i tilegg til de som er definerte av protokoller eller applikasjoner som bruker Winsock. En serverk kan feks gi ut navnet sitt på Active Directory og ved bruke utvidelser for navneområder, kan en klient finne serverens addresse i Active Directory.
* Støtte for beskjeder som kan sendes fra en kilde til flere mottagere samtidig.
Winsock klient-side:
Det første steget en Winsock applikasjon foretar seg er å installere Winsock API-et ved å kalle på initialiserings funksjonen. Deretter vil applikasjonen lage en socket som fungerer som et slags kommunikasjons endepunkt. På Win XP og Server 2003 vil applikasjonen forsøke å få tak i addressen til serveren ved å bruke getaddrinfo. getaddrinfo returnerer en liste over adresser som er assignert serveren og klienten vil deretter prøve hver enkelt av disse addressene til den får kontakt. Når tilkoblingen er opprettet kan klienten sende og motta data data via socketen sin ved å bruke recv og send. En klient som ikke bruker tilkobling spesifiserer den eksterne adresssen ved å bruke funksjonene sendto og recvfrom.
Winsock server-side:
Etter at serveren har installert Winsock-APIet vil den lage en socket og bruke en bind funksjon for å binde denne til en bestemt lokal addresse. Dette kan feks være en TCP/IP addresse eller TCP/IP med IPv6. Det er mao servern som bestemmer hvilken adresstype kommunikasjonen skal foregå over.
Hvis det er konneksjons-basert server vil den bruke funksjonen listen på socketen den har laget og sjekker om noen klienter prøver å koble seg til. Om den mottar noen forespørseler på denne bruker den accept funksjonen for å fullføre forespørselen. Når Serveren har nådd maks antall koblinger vil den slutte å lytte på socketen sin. Etter at accept funksjonen er utført vil serveren lage en ny socket som deretter data sendes over via send og recv.
En konneksjonsløs server vil kunne sende data ved å spesifisere den eksterne addressen for hver operasjon.
Utvidelse av Winsock:
Winsock har støtte for at tredjeparter kan kan legge til henholdsvis såkalte transport service providers og namespace service providers. Transport Service providers kan fungere som et grensesnitt mellom winsock med nye protokoller eller å bruke eksisterende protokoller for å kunne tilby ekstra funksjonalitet slik som feks proxy funksjoner. En Namespace Service provider kan overstyre bestemte navne-oppslags fra Winsocks sin side. Disse tjenestene bruker da Winsock Service Proverider Interface (SPI). Legg for øvrig merke til at dette grensesnitter støtter en funksjon kalt Layered Service Provider (LSP) som kan da faktisk brukes for å settes inn i TCP/IP-stakken til Winsock og endre hele funksjonaliteten til Winsock. Om disse fjernes uriktig kan man evt miste noe eller hele funksjonaliteten til Winsock og Winsock må tilbakestilles. Netshell tilbyr feks slik funksjonalitet.
Implementering av Winsock:
For at en applikasjon skal kunne benytte seg av Winsock trenger den først Winsock API'et som ligger i Ws2_32.dll. Ws2_32.dll vil da gjøre kall til tjenster som kan gjøre navneoppslag og levere beskjeder. Mscwsock.dll fungerer som en Transport Service Provider for protokollene som Microsoft leverer gjennom Winsock. Winsock bruker også såkalte helper-biblotek som tar seg av kommuniseringen med kernel-mode protokolldrivere. Wshtcpip.dll er feks helper-bibloteket til TCP/IP.
Remote Procedure Call (RPC):
RPC er et nettverks-API som muligjør å lage programmer som har noen prosedyrer som kjører lokalt mens andre kjører eksternt.
tirsdag 18. november 2008
Sikkerhet i Windows.
Security Reference Monitor: (SRM)
Er en komponent i Windows executive som er ansvarlig for å: definere data strukturen til såkalte Access Tokens som reprensenterer et sikkerhetskontekst, utføre sikkerhetssjekker på objekter, manipulere privlegier og generere eventuelle sikkerhets-revisjons beskjeder.
Local Security Authority SubSystem: (LSASS)
En prosess i User-mode som er ansvarlig for bla: sikkerhetspolicyen på det lokale systemet(som feks hvilke brukere som kan logge på maskinen, passord policyer, privlegier som blir gitt brukere og grupper og systemets sikkerhets-revisjons innstillinger), bruker autentikasjon, og å sende sikkerhets-revisjons beskjeder til hendelseslisten. LSA-tjenesten som lastes ved Lsasrv.dll er et biblotek som lastes inn i Lsass og som implementerer mesteparten av funksjonalitetn til LSASS.
Lsass policy database:
En database som inneholder det lokale systemets sikkerhetspolicy innstillinger. Databasen er lagret i et seperat register-hi innunder HKLM\SECURITY. Denne databasen inneholder informasjon slik som hvilke domener som kan autentisere pålogginsforsøk, hvem som har tilgang til systemet og hvordan (interaktiv, nettverks, og tjeneste pålogginger), hvem som får hvilke privlegier og hva slags sikkerhets-revidering som blir utført. Lsass policy databasen lagres også såkalte "hemmeligheter" som inkulderer påloggingsinformasjonen som blir brukt for cachede domene pålogginger og Windows Tjeneste-konto pålogginger.
Security Accounts Manager (SAM) tjensten:
Ett sett med sub-rutiner som er ansvarlige for å håndtere databasen som inneholder brukernavnene og gruppene som er definert på den lokale maskinen. SAM tjenesten er implementert innunder Samsrv.dll og er lastet i Lsass-prosessen.
SAM databasen:
En database som på systemer som ikke fungerer som domene-kontrollere inneholder de definerte lokale brukerne og gruppene i tilegg til passord og andre atributter. På maskiner som fungerer som domene-kontrollere lagrer SAM-databasen kun systemets administrator konto for gjenoppretting, dens definisjon og passord.
Databasen blir lagret i et seperat register-hi innunder. HKLM\SAM.
Active Directory:
En katalog-tjenste som inneholder en database som lagrer informasjon om objekter i et domene. Hvor et domene defineres som en samling pc'er og deres assosierte sikkerhetsgrupper som blir håndtert som en eneste enhet. Active Directory lagrer infromasjonen om objektene i domenet inkludert brukere, grupper og pc'er. Passord informasjon og privlegier for domenebrukere og grupper er lagret i Active Directory og denne informasjonen blir da kopiert over til alle domene-kontrollerne i et domene.
Active Directory Serveren er implementert i Ntdsa.dll og lastes av Lsass-prosessen.
Autentiseringspakker:
Inkluderer DLL'er som kjører både i Lsass og i sine egne klient prosesser og som er ansvarlig for å implentere autentiserings-policyen i Windows. En autentiserings DLL er ansvarlig for å undersøke et gitt passord og brukernavn og, hvis de stemmer overens, returnere Lsass informasjon som inneholder brukerens sikkerhets identitet som Lsass kan bruke for å genere en såkalt Access Token.
Logon prosessen: (Winlogon)
En prosess i user mode som er ansvarlig på å fange og svare på SAS (Secure Attention Sequence, mao Ctrl+Alt+Delete) og som håndterer interaktive pålogginger.
Graphical Identification and Authentication: (GINA)
En user-mode dll som lastes av Winlogon og som brukes av Winlogon for å hente brukernavn og passord eller evt smartcard pin kode. Windows kan håndtere forskjellige tredjeparts GINA'er men standard ginaen heter da msgina.dll
Network Logon Service: (Netlogon)
En windows tjeneste (Netlogon.dll) som setter opp en sikker kanal opp mot domene-kontrolleren slik at sikkerhetsforespørsler slik som interaktiv pålogging eller LAN-manger eller NT-LAN-manager autentisering kan bli sendt over denne kanalen.
Kernel Security Device Driver (KSecDD)
Et biblotek som kjører i kernel-mode som inneholder et biblotek med funksjoner som kan brukes for at andre sikkerhetskomponeter som kjører i kernel-mode kan kommunisere med Lsass i user mode. Dette implementeres da via et LPC-grensesnitt.
Tilgangssjekk:
Vi har tidligere snakket om Objekt-Manageren og om hvordan den bruker SRM for å sjekke om en tråd har tilgang til et objekt eller ei. La oss nå se litt nærmere på denne prosessen. Når Objekt-Manageren åpner et eksisterende objekt med et navn vil det først sjekke i sitt eget Namespace for deretter sjekke i sekundære namespace. (Slik som Configuration Managaren sitt register-namespace eller filsystemdriverens filsystem namespace)
Så lenge som objektet ikke befinner seg i dette sekundære namespacet vil da objekt-manageren kalle på funksjonen ObpCreateHandle som lager en oppføring i prosessens HandleTable som deretter vil bli assosiert med objektet. Dog vil funksjonen ExCreateHandle først bli aktiv straks ObpIncrementHandleCount indikerer at tråden har tilgang til objektet. Deretter vil ObpCreateHandle faktisk kalle ExCreateHandle som lager selve Handelen. ObCheckObjektAccess er ansvarlig for å kalle på de nødvendige rutinene for å utføre selve sikkerhetssjekken og returnerer deretter resultatet til ObpIncrementHandleCount.
ObCheckObjectAccess vil videre motta sikkerhetsakkreditivene til tråden som sendte forespørselen, akksesstypen, og sist en pointer til objektet fra ObpIncrementHandleCount. Deretter vil ObCheckObjectAccess låse objektets sikkerhetsatributter slik at ingen andre tråder kan endre sikkerhetskonteksten til objektet. Deretter vil ObCheckObjectAccess kalle på sikkerhetsmetoden beskrevet i typeobjektet. Den vanligste metoden er da default security som innebærer at sikkerhetsinformasjonen er lagret i objekt-headeren.
Security IDentifiers: (SID)
Istedetfor å bruke navn(som ikke er garantert å være unike) for å beskrive enheter som kan utføre handlinger på systemet. så bruker Windows såkalte SID'er. Både Brukere, lokale grupper, domene grupper, lokale PC'er, domener og domene-medlemmer har sine egne SID-verdier.
En SID er da en numerisk verdi av variabel lengde som består av et SID-struktur revisjons nummer, en 48 bits authorirty-identifier verdi, og et varibelt antall av 32bits subautoritære eller RID verdier(Relative Identifier)
Autoritets-nummeret beskriver agenten som gå ut SID'en, typisk Windows Local System eller et domene. Subautorithy verdiene identifiserer kompontenter som agenten som sendte ut SID'en stoler på, mens RID er bare en måte for Windows å garantere unike SID'er
Her kan vi ta en titt på en SID for min Lokale Brukerkonto:
S-1-5-21-144138694-2277693550-1939834215-1007
Alle SID'er er prefixet med S mens vi kan se at revisjonsnr er 1 og Autoritets-nummeret er 5 (Som betyr at SID'en ble gitt ut av Windows Security Authority) mens de 4 neste verdiene er subautoritæreverdier og den siste verdien er altså en RID på 1007.
Brukerkontoer og grupper har tideles en RID som starter på 1000 og øker deretter med 1 etterhvert som nye SID trenges. Mao betyr en RID på 1007 at minimum 8 SID's har blitt gitt ut på dette systemet)
Windows maskiner har også flere innebygde kontoer hvor bla Administrator kontoen bestandig har en RID på 500 mens gjestekontoen har en RID på 501.
Tokens:
SRM bruker et objekt kalt en token(Access Token) som identifiserer sikkerhetskontekstet til en prosess eller tråd. Et sikkerhetskontekst inneholder informasjonen som beskriver privlegiene, kontoene og grupenne som er assosiert med enten prosessen eller tråden.
Under påloggingsprosessen så lager Winlogon en token som representerer brukeren som logger på og fester denne til de første prosessene som startes via Winlogon (feks Userinit.exe) Siden prosesser arver tokens fra prosessen som lagde den vil alle prosesser i en gjeldende sesjon kjøre innunder brukerens token.
Sikkerhetsmekanismene i Windows bygger opp en token av to grunnleggende komponenter. Den ene komponenten består i en token består av brukerens SID og eventuelle gruppe SID. SRM bruker SID'er for å avgjøre om en prosess eller tråd har mulighet til å få den tilgangen den ber om til et sikkret objekt. (Dette betyr ikke nødvendigvis at den får det, men mer om dette senere.)
Det andre komponenten er et såkalt privlege array som er et sett med privlegier som er assosiert med tokenen.
Det finnes i tilegg to typer tokens -primary og impersonation. Primary Tokens identifiserer sikkerhetskontekstet til en prosess. Mens en impresonantion token lar en tråd midlertidlig bruke et annet sikkerhetskontekst.
Security Descriptorer og tilgangskontroll:
Datastrukturen som inneholder informasjonen over sikkerheten til et objektet kalles en "security descriptor" og består av følgende:
Revision Number: Versjonen av SRM modellen som lagde deskriptoren.
Flag: Valgfrie modifiere som definerer oppførselen eller karakterestikken ved deskriptoren. (Feks SE_DACL_PROTECTED som forbyr deskriptoren å arve sikkerhetsinnstillinger fra et annet objekt.)
Owner SID: Eieren's SID
Group SID: SID'en til hovedgruppen for objektet.
Discretionary Access Control List(DACL): Spesifiserer hvem som har hvilken tilgang til et objekt:
System Access Control List(SACL): Spesifiserer hvilke operasjoner av hvilke brukere som vil bli lagret i sikkerhetsoppføringsloggen.
En ACL er bygd opp av en header og enten ingen eller flere Access Control Entries (ACE). I en DACL så inneholder hver ACE en SID, en aksessmaske og et sett med flagg.
Fire typer ACE's kan forekomme i en DACL: Access Allowed, Access Denied, Allowed Object og Denied Object. Access allowed og Access denied forbyr eller tillater akksessrettighetene som er spesifisert i akksessmasken.
Allowed Object og Denied Object er typer som bare brukes innen Active Directory og disse ACE'ene har en GUID (Globally Unique IDentifier)som spesifiserer ar dette gjelder kun for helt spesielle objekter eller subobjekter som bruker denne GUID'en.
Flaggene i ACE'en brukes til å spesifisere hvilke arveegenskaper denne ACE'en har.
En SACL derimot inneholder to typer av ACE'S: System Audit ACE og en System Audit-Object ACE. En System Audit ACE spesifiserer hvilke operasjoner som blir utført på objektet av spesifikke brukere eller grupper som skal overvåkes. Denne informasjonen blir da lagret i Overvåkningsloggen i systemet. Mens System Audit-Object ACE spesifiser en spesiell GUID som spesifiserer hvilke objekter eller subobjekter det dreier seg om. ( På lik linje med DACL Allowed Object og Denied Object)
Hvordan tilgang beregnes:
To algoritmer brukes for å beregne tilgangen til et objekt:
*En for å beregne det maksimale settetet med rettigheter som kan gis til et objekt.
*En for å finne ut om en spesiell rettighet er tilatt til et objekt.
La oss først se på hvordan man kalkulerer seg frem til det maksimale settet med rettigheter:
1.Først sjekkes det om objektet faktisk har en DACL, Hvis objektet ikke har en DACL har alle brukere alle tilganger til objektet.
2.Hvis enheten som gjorde forspørselen har spesifisert Take-ownership (Bli eier av filer og andre objekter) privlegiet i sin token, vil systemet automatisk automatisk gi write-owner rettigheter til eieren av objektet uavhengig av hva som står i DACL.
3.Hvis enheten som gjorde forespøselen eier objektet vil den automatisk få read-control og write-dacl rettigheter til objektet uavhengig av hva som står i DACL.
4.ACE som er merket som Access Denied kommer først og om den som gjorde forespørselen har en identisk SID med den SID'en som er spesifisert i en av Access Denied ACE'ene så blir aksessmasken i ACE'en trukket ifra aksessmasken over tilatte rettigheter.
5.For hver ACE merket Access Allowed som har en SID som tilsvarer SID'en til den som sendte forespørselen vil aksessmasken i ACE'en bli lagt til i aksessmasken over tilatte rettigheter. (Om ikke disse rettighetene ble forbydd fra før)
Når disse 5 trinnene er utført vil da aksessmasken over de tilatte rettighetene bli returnert til den som gjorde forespørselen. Husk at trinnene 2 og 3 vil overstyre eventuelle rettigheter som er spesifisert i DACL. (Mao om en ACE i DACL'en nekter rettigheten read-control vil brukeren allikavel få rettigheten så lenge den eier objektet.)
La oss deretter se på hvordan man kan finne ut om en spesiell rettighet er tillatt for et objekt:
1.Hvis objektet ikke har noen DACL. Så betyr det at objektet ikke er beskyttet og dermed er alle rettigheter automatisk tillatt.
2.Hvis den som gjorde forespørselen har take-ownership privlegiet vil den automatisk få rettigheten write-owner for deretter å inspisere DACL'en. Hvis den ønskede rettigheten faktisk var write-owner er ingen inspeksjon av DACL nødvendig.
3.Hvis den som gjorde forespørselen eier objektet vil den automatisk få rettighetene read-control og write-DACL for deretter å inspisere DACL'en. Hvis en av disse rettighetene var av de ønskede er ingen inspeksjon av DACL nødvendig.
4.Hver ACE i DACL'en blir undersøkt, men de eneste relevante ACE'ene er de som tilfredstiller en av de følgende kravene:
a. En ACE er av typen Access Denied og SID'en i ACE matcher med en aktivert SID eller en deny-only SID i tokenen til den som gjorde forespørselen.
b. En ACE er av typen Access Allowed og SID'en i ACE matcher med en aktivert SID i tokenen til den som gjorde forespørselene og den ikke er merket som deny-only.
c. Andre undersøkelse sjekker for såkalte restriktve SID'er og undersøker om noen av SID'ene i ACE matcher noen av de restriktive SID'ene spesifisert i tokenen.
5.Hvis ACE'en var av typen Access Allowed og rettigetene i aksessmasken tilsvarte de rettigetene som ble forespurt så vil tilgangen bli godkjent. Hvis ACE'en var av typen Access Denied og aksessmasken dens tilsvarte de rettighetene som ble forespurtså vil tilgangen bli avslått.
6.Hvis man har undersøkt alle ACE i en DACL og den forespurte rettigheten ikke ble funnet vil tilgangen bli avslått.
La oss nå bruke Windbg for å titte på en Access Token:
La oss sjekke ut Access Tokenen til LSASS:
0: kd> !process 8a0e7470
PROCESS 8a0e7470 SessionId: none Cid: 0468 Peb: 7ffde000 ParentCid: 0428
DirBase: 0a9600e0 ObjectTable: e1c746e8 HandleCount: 447.
Image: lsass.exe
VadRoot 8a21e078 Vads 143 Clone 0 Private 724. Modified 4805. Locked 0.
DeviceMap e1009200
Token e245d030
ElapsedTime 01:41:54.234
UserTime 00:00:00.578
KernelTime 00:00:00.687
QuotaPoolUsage[PagedPool] 89180
QuotaPoolUsage[NonPagedPool] 10616
Working Set Sizes (now,min,max) (403, 50, 345) (1612KB, 200KB, 1380KB)
PeakWorkingSetSize 1903
VirtualSize 45 Mb
PeakVirtualSize 46 Mb
PageFaultCount 10664
MemoryPriority BACKGROUND
BasePriority 9
CommitCharge 1235
Som vi ser er Access Tokenen lagret på addresse e245d030 la oss se nærmere på denne ved å bruke !token kommandoen fra debuggeren:
0: kd> !token e245d030
_TOKEN e245d030
TS Session ID: 0
User: S-1-5-18
Groups:
00 S-1-5-32-544
Attributes - Default Enabled Owner
01 S-1-1-0
Attributes - Mandatory Default Enabled
02 S-1-5-11
Attributes - Mandatory Default Enabled
Primary Group: S-1-5-18
Privs:
00 0x000000007 SeTcbPrivilege Attributes - Enabled Default
01 0x000000002 SeCreateTokenPrivilege Attributes - Enabled
02 0x000000009 SeTakeOwnershipPrivilege Attributes -
03 0x00000000f SeCreatePagefilePrivilege Attributes - Enabled Default
04 0x000000004 SeLockMemoryPrivilege Attributes - Enabled Default
05 0x000000003 SeAssignPrimaryTokenPrivilege Attributes -
06 0x000000005 SeIncreaseQuotaPrivilege Attributes -
07 0x00000000e SeIncreaseBasePriorityPrivilege Attributes - Enabled Default
08 0x000000010 SeCreatePermanentPrivilege Attributes - Enabled Default
09 0x000000014 SeDebugPrivilege Attributes - Enabled Default
10 0x000000015 SeAuditPrivilege Attributes - Enabled Default
11 0x000000008 SeSecurityPrivilege Attributes -
12 0x000000016 SeSystemEnvironmentPrivilege Attributes -
13 0x000000017 SeChangeNotifyPrivilege Attributes - Enabled Default
14 0x000000011 SeBackupPrivilege Attributes -
15 0x000000012 SeRestorePrivilege Attributes -
16 0x000000013 SeShutdownPrivilege Attributes -
17 0x00000000a SeLoadDriverPrivilege Attributes - Enabled
18 0x00000000d SeProfileSingleProcessPrivilege Attributes - Enabled Default
19 0x00000000c SeSystemtimePrivilege Attributes -
20 0x000000019 SeUndockPrivilege Attributes - Enabled
21 0x00000001c SeManageVolumePrivilege Attributes -
22 0x00000001d SeImpersonatePrivilege Attributes - Enabled Default
23 0x00000001e SeCreateGlobalPrivilege Attributes - Enabled Default
Authentication ID: (0,3e7)
Impersonation Level: Anonymous
TokenType: Primary
Source: *SYSTEM* TokenFlags: 0x89 ( Token in use )
Token ID: dcd3 ParentToken ID: 0
Modified ID: (0, 3c67b)
RestrictedSidCount: 0 RestrictedSids: 00000000
Vi kan se da at hovedgruppen som denne kjører innunder er S-1-5-18 som er da SID'en for Systemkontoen og har da alle mulige tenkelige privlegier.
Vi kan videre titte på security descriptoren for prosess objektet for LSASS, men først må vi finne objekt headeren som har ein ponter til security descriptoren:
0: kd> !object 8a0e7470
Object: 8a0e7470 Type: (8a3b8040) Process
ObjectHeader: 8a0e7458 (old version)
HandleCount: 10 PointerCount: 215
0: kd> dt _object_header 8a0e7458
nt!_OBJECT_HEADER
+0x000 PointerCount : 215
+0x004 HandleCount : 10
+0x004 NextToFree : 0x0000000a
+0x008 Type : 0x8a3b8040 _OBJECT_TYPE
+0x00c NameInfoOffset : 0 ''
+0x00d HandleInfoOffset : 0 ''
+0x00e QuotaInfoOffset : 0 ''
+0x00f Flags : 0x20 ' '
+0x010 ObjectCreateInfo : 0x805628c0 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : 0x805628c0
+0x014 SecurityDescriptor : 0xe1001c3d
+0x018 Body : _QUAD
Security Descriptor pointeren i object headeren bruker de tre laveste bitene som flagg så derfor for å få adgang til selve security descritoren må vi fjerne de tre laveste bitene:
0: kd> !sd 0xe1001c3d & -8
->Revision: 0x1
->Sbz1 : 0x0
->Control : 0x8004
SE_DACL_PRESENT
SE_SELF_RELATIVE
->Owner : S-1-5-32-544
->Group : S-1-5-18
->Dacl :
->Dacl : ->AclRevision: 0x2
->Dacl : ->Sbz1 : 0x0
->Dacl : ->AclSize : 0x44
->Dacl : ->AceCount : 0x2
->Dacl : ->Sbz2 : 0x0
->Dacl : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl : ->Ace[0]: ->AceFlags: 0x0
->Dacl : ->Ace[0]: ->AceSize: 0x14
->Dacl : ->Ace[0]: ->Mask : 0x001f0fff
->Dacl : ->Ace[0]: ->SID: S-1-5-18
->Dacl : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl : ->Ace[1]: ->AceFlags: 0x0
->Dacl : ->Ace[1]: ->AceSize: 0x18
->Dacl : ->Ace[1]: ->Mask : 0x00120410
->Dacl : ->Ace[1]: ->SID: S-1-5-32-544
->Sacl : is NULL
Vi ser da at dette objektet er ein av administrator gruppen (S-1-5-32-544) og dette er en gruppe kontrollert innunder systemkontoen. Vi ser også at den har to ACE oppføringer begge av typen Access Allowed. Maskene kan være litt tungvint å dechiffrere men en kjent maske er ihvertfall 0x001f0fff som betyr fullstendig tilgang-noe som ikke er overraskende siden det gjelder Systemkontoen.
La oss nå teste ut et eksperiment hvor vi lager en mappe og nekter alle rettigheter til denne fra administrator gruppen:
La oss deretter legge til alle rettigheter for denne mappen for brukeren HKB som tilhører gruppen administratorer:
Hva skjer da om vi prøver å gi inn på mappen?
Ved å gå inn på de avanserte rettighetene til mappen kan vi få en oversikt over de aktive ACE'ene for denne mappen og også en forståelse hvorfor dette skjer. Som vi ser blir de forbydende ACE oppføringene prioritert først:
Dog er ikke den beste måten for å undersøke den effektive tilgangen en bruker har til et objekt, den eneste sikre måten å vise dette på er ved å trykke på fanen "Gjeldende Tillatelser" og skrive inn brukernavnet:
Vi kan dog se at denne brukeren faktisk har to rettigheter til dette objektet, nemlig å lese og endre tillatelser. Hvor kommer så disse fra? Når DACL spesifiserte ingen tillatelser? Jo det har seg slik at medlemmer av administratorgruppen er utstyrt med privlegiet take-ownership som vi husker ville automatisk gi slik tilgang, vi kan se en oversikt over privlegiene til forskjellige brukere i den Lokale sikkerhetspolicy manageren:
Dette guiden burde gi en fin innføring i de forskjellige komponentene i sikkerhetssystemet i Windows. Dog er det en del ting som jeg ikke har forklart i detalj men dette kan man finne ut mere om andre plasser - men skulle det være noe som er uklart eller noe er det bare å spørre!
mandag 17. november 2008
Objekt-manageren.
Internt jobber Windows med to hovedtyper av objekter-Executive og Kernel Objects. Executive Objects brukes av komponenter i Windows Executiven(slik som Memory Manageren, PnP manageren, I/O-mangeren osv.) mens Kernel Objects brukes internt i kjernen. Ofte er det slik at et executive objekt er bygd på et Kernel object og dermed inkapsulerer Executive objektet også et Kernel Object. Her følger en liste over de vanligste typene av Executive Objects:
Symbolic link: En mekanisme for å refere til et objektnavn indirekte.
Process: Det virtuelle adresseområdet og kontrolinformasjonen som er nødvendig for et sett av en eller flere tråd-objekter.
Thread: Den kjørbare enheten i en prosess.
Job: En samling prosesser som håndteres som en enhet via Job-objketet.
Section: En region av minnet som er delt mellom flere prosesser.
File: En instans av en åpen fil eller en I/O enhet.
Access Token: Sikkerhets-profilen(SID,brukrettigheter osv) for en prosess eller tråd.
Event: Et objekt med en fast tilstand (Signaled or Not Signaled) som kan brukes til synkronisering eller varsling.
Semaphore: En teller som sørger for at et kun et bestemt antall tråder har tilgang til resursene beskyttet av en Semaphore.
Mutex: En synkroniseringsmekanisme som kan brukes for å serialisere tilgangen til en ressurs.
Timer: En mekanisme for å gi en tråd beskjed når en viss tidsperiode har gått ut.
IoCompletion: En metode for tråder å stille seg i kø og vente på beskjed om fullføring av I/O-operasjoner. (Også kjent som I/O-Completion Port)
Key: En mekanisme for å refere til registeret.
De resterende Executive Objects kan du finne innunder \ObjectTypes i Object manageren.
Objekt-Struktur:
Hvert Objekt består av en Objekt-Header og en Object-body. Objekt-manageren sørger for å styre og lage Objekt-Headeren mens Object-bodyen blir håndtert av den Executive Komponenten som refererte til objektet. Objekt-bodyen inneholder informasjon som er unik for hvert objekt mens Object-Headeren er lik for alle objekter og inneholder grunnleggende informasjon om objektet.
Attributtene som finnes i Object-Headeren:
Object Name: Gjør at at andre prosesser kan bruke objektet ved å refere til navnet på objektet.
Object Directory: Er en struktur for å lagre Objekt-navn.
Security Descriptor: Bestemmer hvem som kan bruke objektet og hva de kan gjøre med det.
Quota Charges: Lister ressurs omkostningene mot en prosess når den åpner en Handle til objektet.
Open handle count: Antall ganger et Handle har blitt åpnet til Objektet.
Open Handles List: Peker mot en liste med prosesser som har åpnet en handle til objektet.
Object Type: Peker mot type-objektet som inneholder attributter som er felles for alle objekter av denne typen.
Reference Count: Antall ganger objektet har blitt referert til. Mao både antall pointere og antall åpne handles som peker til objektet. (Kjernen referer til objekter via pointere istedet for handles.)
Objekt-Handles:
Når en prosess lager eller åpner et objekt via et navn mottar den et handle som reprensenterer tilgangen til objektet. Ved å refere til objektet via en handle øker man ytelsen på objekt-operasjoner siden objekt-mangaren kan finne objektet direkte istedet for å måtte slå det opp via navn hver gang. En handle er en index til et Handle-Table som allokeres når en prosess startes. Et Handle-Table inneholder pointere til alle objektene som en prosess har åpnet handle til.
Objekt-Sikkerhet:
Når du åpner en fil må du spesifisere om du har tenkt å lese eller skrive til filen. Hvis du prøver å skrive til en fil som du har bedd om å lese vil du støte på en feil. På samme måte må du når du lager et objekt eller åpner en handle til det objektet spesifisere hva du har tenkt å gjøre med det. Security Reference Monitoren sørger for å undersøke Security Descriptoren til objektet og undersøker om dette samsvarer med tilgangsspesifikasjonene til prosessen. Om disse samsvarer så sørger Reference Monitoren å lage et set med "Granted Access Rights" som blir lagret i Object Handelen.
Objekt lagring:
Det finnes to typer objekter: midlertidlige og permanente. De fleste objektene er midlertidlige-mao de blir fjernet når de ikke lenger er i bruk mens permanente objekter blir ikke fjernet før de blir eksplisitt bedt om det. Siden de fleste objekter er midlertidlige er det objekt-managerens oppgave å holde dem i minne så lenge de er i bruk og fjerne dem når ingen prosesser bruker dem. Måten Objekt-manageren holder styr på dette er at for hver gang en prosess åpner en handle til et objekt øker den antallet i Open Handle Count i Object-Headeren. Deretter når prosessen da stenger handelen igjen vil da objekt-mangeren sørge for å minke dette antallet. Når Open Handle Count synker til 0 vil da objekt-manageren fjerne objektet fra det globale namespacet. På denne måten kan ingen prosesser åpne et nytt handle til dette objektet.
Siden operativsystemkjernen referer til objekter med pointere istedet for handles må Object-Manageren også holde styr på hvor mange referanser det er blitt gjort til objektet. Dette antallet lagres da i Reference Count telleren og også prosesser som åpner en handle vil telle som en referanse. Når denne telleren tilslutt når 0 er det da ingen som referer til objektet og det kan trygt fjernes fra minnet.
Objekt-Navn:
Enhver ressurs som er representert som et objekt kan få sitt eget unike navn. Ved å gi navn til en ressurs kan objekt-manageren lagre dette i det Globale Namespacet sitt slik at andre prosesser kan åpne en handle til objektet ved å referere til navnet. Prosesser i user mode har da bare tilgang til \BaseNamedObjects og \GLOBAL?? mappene i Object manageren.
Oversikt over Objekt mappene og hvilke typer objekter som lagres der:
\GLOBAL?? : Ms Dos-enhetsnavn
\BaseNamesObjects : Mutexer, events,semaphores,waitable timers og section objects.
\Callback : Callback Objekter
\Device : Enhetsobjekter.
\Driver : Driverobjekter.
\FileSystem : File system driver objekter og enhetsobjekter for å kjenne igjen filsystem.
\KnownDlls : Section navn og bane til såkalte known DLLs (Mao DLL som blir mappet av systemet ved oppstart)
\Nls : Section navn for national language support tabeller.
\Objecttypes : Navn på Typeobjekter.
\RPC Control : Port Objekter til bruk for RPC (Remote Procedure Call)
\Security : Navn på objekter spesifikke for sikkerhets undersystemet.
\Windows : Windows undersystem porter og Windows Station objekter.
Session Namespace:
Hver enkelt Session har et unikt lokalt namespace for den pågående sesjonen. Mappene \DosDevices \Windows og \BaseNamedObjects blir kopiert slik at hver sesjon kan ha unike objekter for disse. Mappene blir da lagret innunder \Sessions\x hvor x er et tall som identifiserer sesjonen mao blir da \BaseNamedObjects for sesjon 3 lagret innunder \Sessions\3\BaseNamedObjects.
Undersøking av Objekter gjennom Windbg og WinObj:
La oss ta utganspunkt i prosessen LSASS:
PROCESS 8a08e458 SessionId: none Cid: 0468 Peb: 7ffde000 ParentCid: 0428
DirBase: 0a9600e0 ObjectTable: e2428388 HandleCount: 446.
Image: lsass.exe
Vi ser at den har totalt 446 åpne handles la oss dumpe ut disse ved å bruke !handle:
0: kd> !handle 0 7 468
Handle table at e2f8b000 with 446 Entries in use
0000: free handle, Entry address e248b000, Next Entry fffffffe
0004: Object: e10085c8 GrantedAccess: 000f0003 Entry: e248b008
Object: e10085c8 Type: (8a3b4ca0) KeyedEvent
ObjectHeader: e10085b0 (old version)
HandleCount: 40 PointerCount: 41
Directory Object: e1003100 Name: CritSecOutOfMemoryEvent
Vi kan da se at det første objektet er av typen KeyedEvent som er et nytt synkroniseringsobjekt som ble introdusert i Windows XP. Dette brukes da når minnet er lavt og en tråd forsøker å bruke en kritisk seksjon i systemet. Denne eventen gjør det da mulig for en tråd å spesifisere en "nøkkel" som den venter på og våkner igjen når en annen tråd i den samme prosessen signalerer eventen med den samme "nøkkelen". På denne måten kan systemet fremdeles bruke critcal sections når minnet er så lavt at man ikke kan allokere et nytt event objekt for den.
Videre spesifisert ser vi at navnet er CritSecOutOfMemoryEvent, Det er totalt 40 åpne handles til denne rundt om i systemet mens det er 41 referanser. La oss kikke nærmere på object-headeren ved å bruke dt kommandoen (display type)
0: kd> dt _object_header e10085b0
nt!_OBJECT_HEADER
+0x000 PointerCount : 41
+0x004 HandleCount : 40
+0x004 NextToFree : 0x00000028
+0x008 Type : 0x8a3b4ca0 _OBJECT_TYPE
+0x00c NameInfoOffset : 0x10 ''
+0x00d HandleInfoOffset : 0 ''
+0x00e QuotaInfoOffset : 0 ''
+0x00f Flags : 0x32 '2'
+0x010 ObjectCreateInfo : 0x00000001 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : 0x00000001
+0x014 SecurityDescriptor : 0xe100b1ff
+0x018 Body : _QUAD
Vi kan videre kikke nærmere på type-objektet som dette objektet hører innunder:
0: kd> dt _object_type 8a3b4ca0
ntdll!_OBJECT_TYPE
+0x000 Mutex : _ERESOURCE
+0x038 TypeList : _LIST_ENTRY [ 0x8a3b4cd8 - 0x8a3b4cd8 ]
+0x040 Name : _UNICODE_STRING "KeyedEvent"
+0x048 DefaultObject : 0x80561e20
+0x04c Index : 0x10
+0x050 TotalNumberOfObjects : 1
+0x054 TotalNumberOfHandles : 0x28
+0x058 HighWaterNumberOfObjects : 1
+0x05c HighWaterNumberOfHandles : 0x29
+0x060 TypeInfo : _OBJECT_TYPE_INITIALIZER
+0x0ac Key : 0x6579654b
+0x0b0 ObjectLocks : [4] _ERESOURCE
Og kan videre kikke videre på hvordan dette initsialliseres:
0: kd> dt _object_type_initializer 8a3b4ca0+60
ntdll!_OBJECT_TYPE_INITIALIZER
+0x000 Length : 0x4c
+0x002 UseDefaultObject : 0x1 ''
+0x003 CaseInsensitive : 0 ''
+0x004 InvalidAttributes : 0
+0x008 GenericMapping : _GENERIC_MAPPING
+0x018 ValidAccessMask : 0x1f0003
+0x01c SecurityRequired : 0 ''
+0x01d MaintainHandleCount : 0 ''
+0x01e MaintainTypeList : 0 ''
+0x020 PoolType : 1 ( PagedPool )
+0x024 DefaultPagedPoolCharge : 0x30
+0x028 DefaultNonPagedPoolCharge : 0
+0x02c DumpProcedure : (null)
+0x030 OpenProcedure : (null)
+0x034 CloseProcedure : (null)
+0x038 DeleteProcedure : (null)
+0x03c ParseProcedure : (null)
+0x040 SecurityProcedure : 0x805f6bbc long nt!SeDefaultObjectMethod+0
+0x044 QueryNameProcedure : (null)
+0x048 OkayToCloseProcedure : (null)
Et annet nyttig program for å undersøke Mappene som Object-manageren lager er WinObj som kan hentes fra Microsoft Sysinternals på denne addressen :
http://technet.microsoft.com/en-us/sysinternals/bb896657.aspx
Her er et bilde av WinObj som viser alle Typeobjektene:
søndag 9. november 2008
Heng i Internet Explorer.
Break-in sent, waiting 30 seconds...
WARNING: Break-in timed out, suspending.
This is usually caused by another thread holding the loader lock
Debuggeren har to måter å huke seg på en prosess - først prøver den å injisere en tråd som brukes til å gjøre et såkalt "break in" i prosessen - hvis denne tråden ikke har svart innen 30 sekunder vil debuggeren supsendere alle trådene og dermed stoppe prosessen på dette viset.
La oss hvilke Krtiske Seksjoner i systemet som er låst via !locks
0:004> !locks
CritSec ntdll!LdrpLoaderLock+0 at 7c97c0d8
LockCount 8
RecursionCount 1
OwningThread d98
EntryCount 74
ContentionCount 74
*** Locked
CritSec urlmon!g_mxsMedia+0 at 44604790
LockCount 0
RecursionCount 1
OwningThread d98
EntryCount 1
ContentionCount 1
*** Locked
Vi ser da et den kritiske at vi har to kritiske seksjoner hvorav den ene blir ventet på hele 8 tråder. ntdll!LdrpLoaderLock+0 er låsen til Dllmain som brukes til å installere og fjerne dll filer. Dllmain skal også informeres om eventuelle nye tråder i prosessen slik at tråder vil registere seg ved Dllmain ved DLL_THREAD_ATTACH.
La oss ta en titt på tråden som injiseres av Windbg:
22 Id: b7c.73c Suspend: 1 Teb: 7ffdc000 Unfrozen
ChildEBP RetAddr Args to Child
0124fc0c 7c90e9c0 7c91901b 00000070 00000000 ntdll!KiFastSystemCallRet
0124fc10 7c91901b 00000070 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc
0124fc98 7c90104b 0197c0d8 7c927357 7c97c0d8 ntdll!RtlpWaitForCriticalSection+0x132
0124fca0 7c927357 7c97c0d8 0124fd2c 00000004 ntdll!RtlEnterCriticalSection+0x46
0124fd18 7c90eac7 0124fd2c 7c900000 00000000 ntdll!_LdrpInitialize+0xf0
00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7
Vi kan se at tråden ikke er ferdig installert enda og venter på at den kritiske seksjonen skal frigjøres. Vi skal se på tråden som eier den krtiske seksjonen men først skal vi bruke !runaway for å se hvilke tråder som har vært mest aktive i prosessen:
0:004> !runaway
User Mode Time
Thread Time
4:d98 0 days 0:00:17.375
20:d84 0 days 0:00:02.562
15:244 0 days 0:00:00.843
0:5dc 0 days 0:00:00.765
18:170 0 days 0:00:00.171
17:e08 0 days 0:00:00.171
14:108 0 days 0:00:00.078
6:e4c 0 days 0:00:00.046
12:c4c 0 days 0:00:00.031
13:d48 0 days 0:00:00.015
22:73c 0 days 0:00:00.000
21:a5c 0 days 0:00:00.000
19:338 0 days 0:00:00.000
16:640 0 days 0:00:00.000
11:350 0 days 0:00:00.000
10:b58 0 days 0:00:00.000
9:a58 0 days 0:00:00.000
8:aec 0 days 0:00:00.000
7:c24 0 days 0:00:00.000
5:dc0 0 days 0:00:00.000
3:990 0 days 0:00:00.000
2:b8c 0 days 0:00:00.000
1:f60 0 days 0:00:00.000
Vi ser at på topp ligger tråden som eier den krtiske seksjonen men på 2, plass ligger en annen tråd som har brukt ganske mye av tiden også - vi skal se på den senere men først skal vi se på tråden som både har brukt mesteparten av tiden til scheduleren og som eier den kritiske seksjonen:
4 Id: b7c.d98 Suspend: 1 Teb: 7ffd8000 Unfrozen
ChildEBP RetAddr Args to Child
0166fe0c 7e41daf6 44577b30 00040572 001931d8 ntdll!KiFastSystemCallRet
0166fe24 44577adc 00000d98 00000000 00000000 USER32!NtUserDestroyWindow+0xc
0166fe40 44551d9f 44604820 00000000 0166fe64 urlmon!DoThreadCleanup+0x117
0166fe50 44551d86 00000001 00000001 00000000 urlmon!DoThreadCleanup+0xf
0166fe64 44551b86 44550000 00000003 00000000 urlmon!TlsDllMain+0x2a
0166fe84 44551a7f 44550000 00000003 00000000 urlmon!DllMain+0x17e
0166fee4 7c9011a7 44550000 00000003 00000000 urlmon!_initterm_e+0x12b
0166ff04 7c919213 445519f1 44550000 00000003 ntdll!LdrpCallInitRoutine+0x14
0166ff7c 7c80c096 0012e490 0012e5b8 0018ea28 ntdll!LdrShutdownThread+0xd7
0166ffb4 7c80b688 00000000 0012e490 0012e5b8 kernel32!ExitThread+0x3e
0166ffec 00000000 447ee424 0018ea28 00000000 kernel32!BaseThreadStart+0x3c
Vi ser at kernel32 har bedt om at tråden stenges og det kaller da inn i urlmon som benytter funksjonene i Dllmain for å rense opp sine objekter i tråden som skal avsluttes. urlmon brukes tilegg som benytter seg av OLE32 så kan det være noe galt med et OLE32 objekt? La oss se på den tråden som brukte nest mest av cpu-tiden i user mode:
20 Id: b7c.d84 Suspend: 1 Teb: 7ff9b000 Unfrozen
ChildEBP RetAddr Args to Child
0d2cf6e4 7c90e9ab 7c8094e2 00000002 0d2cf710 ntdll!KiFastSystemCallRet
0d2cf6e8 7c8094e2 00000002 0d2cf710 00000001 ntdll!ZwWaitForMultipleObjects+0xc
0d2cf784 7e4195f9 00000002 0d2cf7ac 00000000 kernel32!WaitForMultipleObjectsEx+0x12c
0d2cf7e0 77502235 00000001 0d2cf828 000003e8 USER32!RealMsgWaitForMultipleObjectsEx+0x13e
0d2cf808 7750235c 0d2cf828 000003e8 0d2cf838 ole32!CCliModalLoop::BlockFn+0x80
0d2cf830 77516749 ffffffff 0d2cf928 0d2cf860 ole32!ModalLoop+0x5b
0d2cf840 775f1f01 0018ee18 0d2cf928 00000000 ole32!SwitchSTA+0x21
0d2cf860 775f109a 0d2cf928 00209164 0d2cf984 ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+0xd1
0d2cf940 77502409 00209164 0d2cfa54 0d2cfa44 ole32!CRpcChannelBuffer::SendReceive2+0xb9
0d2cf95c 775023b2 0d2cfa54 0d2cfa44 00209164 ole32!CCliModalLoop::SendReceive+0x1e
0d2cf9c8 77500414 00209164 0d2cfa54 0d2cfa44 ole32!CAptRpcChnl::SendReceive+0x6f
0d2cfa1c 77ef3db5 00209164 0d2cfa54 0d2cfa44 ole32!CCtxComChnl::SendReceive+0x113
0d2cfa38 77ef3ead 069a696c 0d2cfa80 0600015b RPCRT4!NdrProxySendReceive+0x43
0d2cfe14 77ef3e42 774d6218 774d92ca 0d2cfe4c RPCRT4!NdrClientCall2+0x1fa
0d2cfe34 77e8a7f3 00000010 00000005 0d2cfe5c RPCRT4!ObjectStublessClient+0x8b
0d2cfe44 77501410 069a696c 00000002 0721fb50 RPCRT4!ObjectStubless+0xf
0d2cfe5c 775013b1 069a696c 0018ee18 00000002 ole32!RemoteReleaseRifRefHelper+0x84
0d2cfe84 77500052 069a696c 0018ee18 00000002 ole32!RemoteReleaseRifRef+0x74
0d2cfedc 774ffe4b 06fbce04 06fbce00 00000000 ole32!CStdMarshal::DisconnectCliIPIDs+0x200
0d2cff04 774fd878 00000002 06fbcea8 06fbce00 ole32!CStdMarshal::Disconnect+0x178
Og vi ser at denne tråden driver og rydder opp i OLE32 objekter og den står og venter på to objekter-la oss se nærmere på disse:
0:004> dd 0d2cf710
0d2cf710 0000088c 00000c40 00000001 00000000
0d2cf720 00000000 00000010 00000000 0000022d
0d2cf730 00000014 00000001 00000000 00000000
0d2cf740 00000010 ff676980 ffffffff 7ff9b000
0d2cf750 7ffde000 7ff9b000 0d2cf78c 0d2cf744
0d2cf760 0d2cf710 0d2cf984 00000002 0d2cf704
0d2cf770 06ac780c 0d2cfe04 7c839aa8 7c8095d8
0d2cf780 00000000 0d2cf7e0 7e4195f9 00000002
dd dumper da atlså arrayet med referasene til de to objektene - la oss titte nærmere på disse:
0:004> !handle 00000c40 7
Handle c40
Type Event
Attributes 0
GrantedAccess 0x1f0003:
Delete,ReadControl,WriteDac,WriteOwner,Synch
QueryState,ModifyState
HandleCount 2
PointerCount 5
Name
0:004> !handle 0000088c 7
Handle 88c
Type Event
Attributes 0
GrantedAccess 0x1f0003:
Delete,ReadControl,WriteDac,WriteOwner,Synch
QueryState,ModifyState
HandleCount 2
PointerCount 4
Name
Vi ser da at det dreier seg om to synkroniseringsobjekter-ved å bruke process explorer fant jeg ut at det ene var signaled mens det andre var såkalt non-signaled og dermed det mest interessante. Handlecount på 2 betyr at en annen struktur fremdeles referer til den la oss se om vi kan finne moduler i minnet som har en referanse til denne addressen:
07f32418 0000088c
07f3241c 0116bc21
07f32420 fffe1800
07f32424 23ffff14
07f32428 fd150003
07f3242c 04035bff SkypeIEPlugin!DllRegisterServer+0x6fef
07f910f8 633a0c16 jscript!MUTX::Enter+0x38
07f910fc 00000010
07f91100 00000000
07f91104 0000088c
SkypeIEplugin hadde også vært refert som de siste funksjonene på stakken:
0d2bdc38 04076aba SkypeIEPlugin!DllRegisterServer+0x47eaa
0d2bdc3c 04076ac2 SkypeIEPlugin!DllRegisterServer+0x47eb2
0d2bdc40 881f6a96
0d2bdc44 00000000
0d2bdc48 00000078
0d2bdc4c 040c3620 SkypeIEPlugin!DllRegisterServer+0x94a10
0d2bdc50 7c90d592 ntdll!ZwClose+0xc
0d2bdc54 00000000
0d2bdc58 00000003
0d2bdc5c 000000a8
0d2bdc60 04062ac4 SkypeIEPlugin!DllRegisterServer+0x33eb4
0d2bdc64 04076af2 SkypeIEPlugin!DllRegisterServer+0x47ee2
0d2bdc68 042627dc
0d2bdc6c 04062bbc SkypeIEPlugin!DllRegisterServer+0x33fac
0d2bdc70 00000003
0d2bdc74 04062bb3 SkypeIEPlugin!DllRegisterServer+0x33fa3
0d2bdc78 881f6a52
0d2bdc7c 00000000
0d2bdc80 040c1130 SkypeIEPlugin!DllRegisterServer+0x92520
0d2bdc84 04260000
0d2bdc88 00000000
0d2bdc8c 00000000
0d2bdc90 0d2bdc78
0d2bdc94 0d2bdcf0
0d2bdc98 0d2bdcf0
0d2bdc9c 00015be0
0d2bdca0 00000015
0d2bdca4 0d2bdc00
0d2bdca8 04062bb3 SkypeIEPlugin!DllRegisterServer+0x33fa3
0d2bdcac 0d2bdcec
0d2bdcb0 7c90ee18 ntdll!_except_handler3
0d2bdcb4 7c910570 ntdll!CheckHeapFillPattern+0x64
0d2bdcb8 ffffffff
0d2bdcbc 7c91056d ntdll!RtlFreeHeap+0x647
0d2bdcc0 04056857 SkypeIEPlugin!DllRegisterServer+0x27c47
0d2bdcc4 04260000
0d2bdcc8 00000000
0d2bdccc 04056876 SkypeIEPlugin!DllRegisterServer+0x27c66
0d2bdcd0 881f6a06
0d2bdcd4 000089be
0d2bdcd8 0d2cf12c
0d2bdcdc 000089be
0d2bdce0 000089be
0d2bdce4 0d2bdcd0
0d2bdce8 0d2bdcd4
0d2bdcec 0d2cf0d8
0d2bdcf0 04055be0 SkypeIEPlugin!DllRegisterServer+0x26fd0
0d2bdcf4 813f07aa
0d2bdcf8 fffffffe
0d2bdcfc 04056876 SkypeIEPlugin!DllRegisterServer+0x27c66
0d2bdd00 03ff2782 SkypeIEPlugin+0x2782
0d2bdd04 04268e10
0d2bdd08 04273780
0d2bdd0c 04001de6 SkypeIEPlugin+0x11de6
Det falt seg derfor naturlig å anta at det var SkypeIEplugin som var problemet og den prøvde sannsynligvis å benytte seg av Dllmain for registere dll filen mens Dllmain sin aksess var låst til en kritisk seksjon som følge av at urlmon prøvde å rydde opp OLE32 objekter brukt av SkypeIEPlugin, siden jeg ikke bruker denne Plugin'en bare fjernet jeg autolastingen av dll'en ved å bruke Autoruns.
Som sagt før, er det noe du lurer på angående dette er det bare å spørre!
torsdag 6. november 2008
I/O-systemet i Windows XP
I/O-Manageren.
I/O-manageren sørger for å definere et rammeverk hvor I/O-forespørslene kan dirigeres til sine respektive drivere som igjen kan håndtere forespørselen. I/O-trafikken blir håndtert pakkevis, og de aller fleste I/O-forespørsler er representert via en IRP (I/O Request Packet)-unntaket ligger altså i fast I/O som da altså ikke bruker IRP-pakker.
IRP-pakker blir generert av I/O-manageren og disse pakkene beskriver da altså en unik I/O operasjon. Deretter vil I/O-manageren gi en peker IRP-pakken til den korrekte driveren slik at den kan lese innholdet i IRP-pakken og utføre operasjonen som er beskrevet i pakken. Når denne operasjonen er ferdigstillt returnerer driveren IRP-pakken til I/O manageren slik at den kan enten fjerne pakken hvis I/O operasjonen er ferdig eller eventuellt sende pakken videre til neste driver for videre prosessering.
Flyten i en typisk I/O forespørsel:
1.Applikasjon i User-Mode kaller på en funksjon i Windows API-et som krever I/O overføring.
2.Denne funksjonen kaller da inn i I/O systemets service API som har funskjoner for forskjellige I/O operasjoner slik som å lese til en fil eller lese fra en fil.
3.Deretter vil I/O manageren finne ut hvilken driver som kan håndtere den forespurte I/O operasjonen og deretter overføre kontrollen til enhetsdrivreren.
4.Enhetsdriveren vil da be HAL om å utføre I/O opp mot maskinvaren hvor på HAL vil lese/skrive til de aktuelle I/O portene og registrene til maskinvaren.
Plug and Play-manageren. (PnP).
Plug and Play i Windows blir håndtert av PnP-manageren som da skal automatisk kjenne igjen maskinvare og kunne tilpasse seg endrende maskinvarekonfigurasjon. For at Plug and Play skal fungere skikkelig krever det at både maskinvare, drivere og operativsystemet er PnP-kompatibelt. PnP i Windows har følgende egenskaper.
- PnP-manageren kjenner automatisk igjen installerte enheter og enumerer dem ved oppstart og vil også kunne detektere fjerning og installering av ny maskinvare mens systemet kjører
- PnP-manageren vil automatisk allokere ressursene som er nødvendig for hver enkelt enhet (Avbrudd, I/O-minne, I/O registere eller buss-spesifikke ressurser.) Siden du kan legge til og fjerne maskinvare mens systemet kjører må også PnP manageren sørge for å kunne dynamisk endre ressurene for å tilfredstille de kravene som maskinvaren stiller.
- PnP-manageren må også kunne laste inn korrekte drivere for den spesifikke enheten ved å sammenlinge spesifikasjonene på enhetene med de definert i driveren og deretter undersøke om driveren har egenskaper for å håndtere maskinvaren. Hvis driveren godkjennes vil PnP-manageren be I/O-mangeren om å laste den.
Power-manageren. Power-manageren håndterer strømtyring for systemet og for maskinvaren. For at dette skal fungere skikkelig må både maskinvare og BIOS samsvare med ACPI (Advanced Configuration and Power Interface)-standarden. Denne standarden spesifiser 6 forskejellige strømtilstander for systemet og 4 for maskinvaren. Systemets tilstander er definert gjennom S0 til S5 hvor S0 er fullstendig på og S5 er fullstendig av. Maskinvaren er definert gjennom D0 til D3 hvor D0 er fullstendig på og D3 er fullstendig av. Tilstandede imellom spesifiser strømsparingstilstander slik som hvile- og dvalemodus. Power manageren sørger for å styre systemet mens driverne sammarbeider med Power-manageren om å styre maskinvaren.
I/O-systemet via Windbg.
Du kan også bruke Windbg for å undersøke nærmere hvordan I/O-systemet oppererer. Du kan feks dumpe ut et trådobjekt og se på IRP-listen dens for å se IRP-pakker som ikke er ferdgistillt.
kd> !irp 822aa318
Irp is active with 1 stacks 1 is current (= 0x822aa388)
No Mdl: System buffer=82010c18: Thread 82284868: Irp stack trace.
cmd flg cl Device File Completion-Context
>[ e, 0] 5 0 82290a50 82302f90 00000000-00000000
\FileSystem\AvgMfx86
Args: 00000238 00000238 53492424 00000000
Vi kan dermed se at driveren som er ansvarlig for å håndtere denne pakken er AvgMfx86 og funksjoner den skal kjøre er definert som operasjon e.
Vi kan sjekke hvilken operasjon dette korresponderer til ved å bruke !drvobj opp mot driveren med en verbosity på 7:
kd> !drvobj AvgMfx86 7
Driver object (8224fbe0) is for:
\FileSystem\AvgMfx86
Driver Extension List: (id , addr)
Device Object list:
82290a50
DriverEntry: f88d1846 avgmfx86
DriverStartIo: 00000000
DriverUnload: f844ef08 fltmgr!FltpMiniFilterDriverUnload
AddDevice: 00000000
Dispatch routines:
[00] IRP_MJ_CREATE f88ce38e avgmfx86+0x38e
[01] IRP_MJ_CREATE_NAMED_PIPE 804fa87e nt!IopInvalidDeviceRequest
[02] IRP_MJ_CLOSE f88ce38e avgmfx86+0x38e
[03] IRP_MJ_READ 804fa87e nt!IopInvalidDeviceRequest
[04] IRP_MJ_WRITE 804fa87e nt!IopInvalidDeviceRequest
[05] IRP_MJ_QUERY_INFORMATION 804fa87e nt!IopInvalidDeviceRequest
[06] IRP_MJ_SET_INFORMATION 804fa87e nt!IopInvalidDeviceRequest
[07] IRP_MJ_QUERY_EA 804fa87e nt!IopInvalidDeviceRequest
[08] IRP_MJ_SET_EA 804fa87e nt!IopInvalidDeviceRequest
[09] IRP_MJ_FLUSH_BUFFERS 804fa87e nt!IopInvalidDeviceRequest
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION 804fa87e nt!IopInvalidDeviceRequest
[0b] IRP_MJ_SET_VOLUME_INFORMATION 804fa87e nt!IopInvalidDeviceRequest
[0c] IRP_MJ_DIRECTORY_CONTROL 804fa87e nt!IopInvalidDeviceRequest
[0d] IRP_MJ_FILE_SYSTEM_CONTROL 804fa87e nt!IopInvalidDeviceRequest
[0e] IRP_MJ_DEVICE_CONTROL f88ce38e avgmfx86+0x38e
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL 804fa87e nt!IopInvalidDeviceRequest
[10] IRP_MJ_SHUTDOWN 804fa87e nt!IopInvalidDeviceRequest
[11] IRP_MJ_LOCK_CONTROL 804fa87e nt!IopInvalidDeviceRequest
[12] IRP_MJ_CLEANUP 804fa87e nt!IopInvalidDeviceRequest
[13] IRP_MJ_CREATE_MAILSLOT 804fa87e nt!IopInvalidDeviceRequest
[14] IRP_MJ_QUERY_SECURITY 804fa87e nt!IopInvalidDeviceRequest
[15] IRP_MJ_SET_SECURITY 804fa87e nt!IopInvalidDeviceRequest
[16] IRP_MJ_POWER 804fa87e nt!IopInvalidDeviceRequest
[17] IRP_MJ_SYSTEM_CONTROL 804fa87e nt!IopInvalidDeviceRequest
[18] IRP_MJ_DEVICE_CHANGE 804fa87e nt!IopInvalidDeviceRequest
[19] IRP_MJ_QUERY_QUOTA 804fa87e nt!IopInvalidDeviceRequest
[1a] IRP_MJ_SET_QUOTA 804fa87e nt!IopInvalidDeviceRequest
[1b] IRP_MJ_PNP 804fa87e nt!IopInvalidDeviceRequest
Vi kan se at operasjonen 0E korresponder til en intern funksjon i driveren. Vi kan også se standard rutinene som I/O-manageren definerer for driveren.
Vi kan også ta en titt på Strømfunksjonalitetene for systemet ved å bruke !pocaps
kd> !pocaps
PopCapabilities @ 0x80560d20
Misc Supported Features: PwrButton SlpButton Lid S3 S4 S5 HiberFile FullWake
Processor Features: Thermal Throttle (MinThrottle = 15%, Scale = 0%)
Disk Features: SpinDown
Battery Features: BatteriesPresent
Battery 0 - Capacity: 0 Granularity: 0
Battery 1 - Capacity: 0 Granularity: 0
Battery 2 - Capacity: 0 Granularity: 0
Wake Caps
Ac OnLine Wake: Sx
Soft Lid Wake: Sx
RTC Wake: S4
Min Device Wake: Sx
Default Wake: Sx
Det er del flere kommandoer som kan brukes, men HTML-genereringen til denne Javacript-teksteditoren er aldeles forferdelig så jeg tror jeg stopper her!
Håper dette var nyttig-om det er noen spørsmål om I/O-systemet eller andre ting med Windows så er det bare å spørre.
mandag 27. oktober 2008
Grunnleggende info om feilsøking med Windbg.
Windbg er en del av Debugging Tools For Windows som kan lastes ned gratis fra denne siden:
http://www.microsoft.com/whdc/devtools/debugging/default.mspx
Windbg kan både brukes til å feilsøke i User Mode og i Kernel Mode delen av systemet. Og har en rekke utvidelser som kan brukes for å gi ekstra informasjon så i hovedsak kan man bruke det til å finne ut absolutt alt som kan være nødvendig for å løse problemet. Dog kan det være vanskelig i starten å få overblikk over alle funksjonene, så jeg skal prøve her å gi en rask innføring av feilsøking med Windgb. Det er 3 hovedgrupper man kan dele feilsøkingen med Windbg inn i:
1.Feilsøking av Windows Programmer.
Du kan enten starte programmet via Ctrl+E og kjøre det via Windbg eller trykke F6 for å hekte Windbg på en allerede kjørende prosess. Dette vil da gjøres i et såkalt "Invasive" modus noe som betyr at du får fullstendig kontroll over programmet men som også betyr at Windbg vil kunne forstyrre normal programoppførsel og også at når du stopper feilsøkingen vil også prosessen avsluttes.
Du har også mulighet for å feilsøke det i "Non-invasive" modus som gir deg litt mindre kontroll men vil minske forstyrellsen Windbg har på prosessen.
2.Feilsøking av Kræsj-dumper.
En kræsjdump er rett og slett et sammendrag av tilstanden til minnet idet noe kræsjet og som har blitt dumpet ut til en fil på harddisken. Windbg kan feilsøke både kræsjdumper tatt fra prosesser eller kræsjdumper fra operativsystemet. Typisk kan du konfiguere hvor mye informasjon du vil ta med- du kan velge mellom en Minidump-som bare dumper ut de mest nødvendige strukturene som kan ha med kræsjet å gjøre, En Kjernedump som dumper ut hele Kjerneminnet eller en fullstendig minnedump som dumper ut absolutt hele minnet.
3.Feilsøking av kjernen.
Dette gjøres ved at debuggeren aktiveres i oppstarten av den maskinen man vil feilsøke, (Kan gjøres i feks Msconfig) og deretter kobler en kabel mellom maskinen som skal feilsøkes og datamaskinen som kjører Windbg. (Enten serie.firewire eller USB 2.0) Deretter kan man koble til maskinen og vente til den går på en feil eller stoppe systemet direkte. Man kan også gjøre såkalt lokal kjernefeilsøking men dette fungerer som regel ikke så godt og gir som regel rimelig begrenset informasjon. Angående kablene som brukes kreves det spesielle debugger-kabler for feilsøking via serie og USB 2.0 tilknyttning mens firewire kan bruke regulære kabler. USB 2.0 debugging støttes bare av Vista og nyere.
Symbolfiler
Før man kan begynne å feilsøke med Windbg er det viktig å oppgi en bane til Symbolfilene. Symbolfiler lages av linkeren som lager .exe eller .dll filer men legges ofte ikke ved siden disse ikke er nødvendig får å kunne kjøre disse filene. Dog er det veldig nyttig å ha symbolfilene når man skal feilsøke da disse kan inneholde nyttig data slik som:
- Globale Variabler
- Lokale Variabler
- Navn på funksjoner
- FPO opptegnelser
Microsoft legger heldigvis ut alle symbolfilene til sine moduler gratis på en symbolserver slik at du fritt laste ned symbolfilene ved behov. Disse inneholder dog bare funksjonnavn og spesifikke globale variabler men er allikavel ekstremt nyttig å konfigurere. Du kan enten konfiguere Symbolbanen ved .sympath kommandoen eller ved å trykke CTRL+S i Windbg. Banen til Microsoft sin symbolserver er: srv*"Symbolbane"*http://msdl.microsoft.com/downloads/symbols hvor "Symbolbane" er banen hvor symbolene blir lastet ned til lokalt til din maskin. Deretter skal symbolene bli lastet inn ved behov straks du kjører .reload. Om du har problemer med å få symbolene til å laste seg inn ordentlig kan du prøve å bruke !sym noisy kommandoen for å undersøke hvordan symbolene lastes.
Husk forøvrig på at en minidump fil ikke inneholder all informasjon om de kjørbare image filene til systemet og det kan være fordelaktig å legge inn banen til microsofts symbolserver også der slik at den kan laste ned image filene automatisk ved behov. Image banen settes ved å trykke CTRL+I eller skrive bruke .exepath kommandoen.
søndag 26. oktober 2008
Oversetting fra virtuell til fysisk adresse på et Windows xp x86 system.
En 32-bits addresse er delt inn i 3 hoveddeler de 10 første bitene benyttes til noe som kalles Page Directory Index som brukes til å finne den rette sidevekslings tabellen som inneholder PTE'en som tilhører den virituelle addressen. PTE står for Page Table Entry som er den strukturen som inneholder den fysiske addressen som den virituelle er mappet til.
Deretter består de neste 10 bitene av addressen av en struktur som kalles Page Table Index som har en peker til selve PTE'en i den aktuelle sidevekslingstabellen.
Tilslutt har man altså 12 gjenstående bit'er som er da avsatt til Byte Index som peker til den aktuelle addressen innenfor den fysiske siden.
Måten Windows leter frem til den fysiske adressen er slik at først letes prosessens Page Directory frem. Noe som skjer hvergang prosessoren gjør et context switch, og lagres typisk i et spesielt prosessor-register. (CR3 på X86) Deretter vil pekeren i Page Directory Index (10 første biter av addressen) vise til hvor den kan finne Page Directory Entry (PDE) som da igjen peker til det aktuelle sidevekslingstabellen. PDE er da en struktur som inneholder et såkalt Page Frame Number (PFN) som skal samsvare med det i sidevekslingstabellen.
Videre brukes da pekeren i Page Table Index (Neste 10 biter) som viser til lokaksjonen til den aktuelle PTE oppføringen. Deretter vil PTE brukes for å finne den fysiske addressen. Hvis PTE'en er gyldig vil den inneholde PFN'en til siden i det fysiske minnet som refererer til den virituelle addressen.
Hvis PTE'en peker til en gyldig side vil da Byte Index (Siste 12 biter) brukes for å finne ut hvor i den aktuelle siden dataen som skal hentes er.
For å forstå litt bedre hvordan denne prosessen fungerer kan det være greit å gå gjennom trinnene manuelt med en kjerne-debugger.
Vi tar da først utgangspunkt i prosessen msnmsgr.exe:
0: kd> !process
PROCESS 89f61270 SessionId: 0 Cid: 0d78 Peb: 7ffdb000 ParentCid: 03e4
DirBase: 0a960460 ObjectTable: e3fbe628 HandleCount: 866.
Image: msnmsgr.exe
Vi ser at Dirbase peker mot den fysiske addressen til Page Directoryen, som vi vet skal operativsystemet installere CR3 registeret med denne addressen slik at prosessoren vet hvor den skal finne Page Directory, la oss dumpe ut CR3 registeret for å sjekke at dette stemmer:
0: kd> r cr3
cr3=0a960460
La oss da ta utgangspunkt i den virtuelle addressen til et Hendeles-objekt i msnmsgr som har addresse 89809a30.
Konvert til bit blir det til 1000100110 0000001001 101000110000 og som vi vet skal de 10 første bitene er Page Directory Index som peker til den spesifikke PDE som har addressen til den spesifikke sidevekslingstabellen.
Page Directoryen ligger da altså på 0a960460 og vi har en Page Directory Index på 226 noe som igjen betyr at PDE ligger på fysisk addresse 0a960686
Vi kan da videre kalkulere oss frem til riktig PTE ved denne formelen:
Sidevekslingstabellbase (0XC0000000 på standard x86 systemer uten PAE)
+ Page Directory Index*størrelsen på en side(4kb på et x86 system)
+ Page Table Index*størrelsen på en PTE (4bytes på et x86 system)
= PTE
La oss kalkulere oss frem til addressen til PTE med denne formelen.
0XC0000000
+ 0X0044C000 (0X226*0X1000*2)
+ 0X00000048 (0X9*4*2)
= 0XC044C048
Som du ser har jeg i tillegg multiplisert resultatene med to, dette er fordi systemet har 2 prosessorer.
Vi kan sjekke om vi har funnet korrekt PTE ved å bruke !pte utvidelesen med en virtuell adresse:
0: kd> !pte 89809a10
VA 89809a10
PDE at 00000000C0602260 PTE at 00000000C044C048
contains 0000000009687963 contains 0000000008A51963
pfn 9687 -G-DA--KWEV pfn 8a51 -G-DA--KWEV
Vi kan videre dumpe ut innholdet av PTE'en: (Fremdeles 4 byte)
0: kd> dd 0C044C048 l1
c044c048 08a51963
PTEen inneholder to strukturer-de første 20 bitene er PFN mens de resterende 12 er avsatt til status flagg. For å finne den fysiske siden i minnet multipliserer vi PFN med størrelsen av en side (fremdeles 4kb) noe som gir oss adressen 08A51000. Dette er da bare basen på siden den fysiske siden. For å finne den eksakte adressen til hvor dataen ligger lagret bruker vi bare Byte indexen i den virtuelle adressen og adderer den med basen på den fysiske siden, noe som da gjør at vi ender opp med den fysiske adressen 08A51A30. La oss dumpe ut dataen som ligger her:
0: kd> !dc 8A51A30
# 8a51a30 aa044a01 00000000 8a288120 8a288120
# 8a51a40 0a060006 20646156 00003750 0000375f
# 8a51a50 89c27188 8979cbc0 8979c590 07100001
# 8a51a60 8a06dcc0 e1b97438 fffffffc 40000000
# 8a51a70 00020006 20646156 8a1169d0 89b30a18
# 8a51a80 0a060002 20646156 00000130 00000132
# 8a51a90 8a2cdc50 00000000 00000000 01400000
# 8a51aa0 8a126c58 e10b5d98 e10b5da8 41000000
La oss sammenligne dette med dataen i den virtuelle adressen:
0: kd> dc 89809a30
89809a30 aa044a01 00000000 8a288120 8a288120
89809a40 0a060006 20646156 00003750 0000375f
89809a50 89c27188 8979cbc0 8979c590 07100001
89809a60 8a06dcc0 e1b97438 fffffffc 40000000
89809a70 00020006 20646156 8a1169d0 89b30a18
89809a80 0a060002 20646156 00000130 00000132
89809a90 8a2cdc50 00000000 00000000 01400000
89809aa0 8a126c58 e10b5d98 e10b5da8 41000000
Vi ser da at dataen er identisk, vi kan med andre ord konkludere med at vi har lykkes i å konvertere en virtuell adresse til en fysisk adresse i minnet. Håper dette var nyttig for å forstå hvordan Windows konverterer minne!
fredag 24. oktober 2008
Windows Xp-maskin med bugcheck 0xA (IRQL not less or equal)
Hentet ut kjerneminnedump fra maskinen og åpnet den i Windbg og dumpet deretter ut stakken:
kd> kv
ChildEBP RetAddr Args to Child
f8959e08 804dbda3 badb0d00 00000000 82266008 nt!KiTrap0E+0x233 (FPO: [0,0] TrapFrame @ f8959e08)
f8959e98 804dc4a8 f8959fc0 0000003e f8959fc0 nt!KiWaitTest+0x30 (FPO: [Non-Fpo])
f8959fa4 804dc378 18d1bda0 00000000 ffdff000 nt!KiTimerListExpire+0x7a (FPO: [Non-Fpo])
f8959fd0 804dbbd4 8055a020 00000000 0000103d nt!KiTimerExpiration+0xaf (FPO: [Non-Fpo])
f8959ff4 804db89e baeead54 00000000 00000000 nt!KiRetireDpcList+0x46 (FPO: [0,0,0])
f8959ff8 baeead54 00000000 00000000 00000000 nt!KiDispatchInterrupt+0x2a (FPO: [Uses EBP] [0,0,1])
WARNING: Frame IP not in any known module. Following frames may be wrong.804db89e 00000000 00000009 bb835675 00000128 0xbaeead54
Nederste stakkramme ser ut til å være ugyldig og referer ikke til noen gyldig instruksjon-men for nå skal vi se på hva som egentlig trigget blåskjermen. Vi ser at feilen er fanget av KiTrap ved f8959e08 la oss endre kontekst ved å sette først .trap f8959e08 og deretter dumpe ut registrene:
kd> .trap f8959e08
ErrCode = 00000000
eax=00000000 ebx=81fd9fe8 ecx=f8959e88 edx=00000000 esi=81fd9fe0 edi=81fda008 eip=804dbda3 esp=f8959e7c ebp=f8959e98 iopl=0 nv up ei pl nz ac pe cycs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010217
nt!KiWaitTest+0x30:804dbda3 6683781601 cmp word ptr [eax+16h],1 ds:0023:00000016=????
Vi kan av dette se at instruksen som feilet var en cmp (compare) instruksjon som hentet en peker fra eax+16. Denne instruksen feiler da fordi at som vi ser er eax registeret nullet ut og dette igjen får oss da til å lese fra minneområde 00000016 som da er et område i minnet som er resverert nullpekere og dermed er et ugyldig område i minnet. Første spørsmål vi har er hva som gjorde at eax ble satt til 0? Vi tar derfor en nærmere titt på instruksjone som ble kjørt innunder KiWaitTest.
kd> uf nt!KiWaitTest+0x30
nt!KiWaitTest:
804dbd7b 8bff mov edi,edi
804dbd7d 55 push ebp
804dbd7e 8bec mov ebp,esp
804dbd80 83ec10 sub esp,10h
804dbd83 53 push ebx
804dbd84 56 push esi
804dbd85 8bf1 mov esi,ecx
804dbd87 837e0400 cmp dword ptr [esi+4],0
804dbd8b 8d4df0 lea ecx,[ebp-10h]
804dbd8e 8d5e08 lea ebx,[esi+8]
804dbd91 8b03 mov eax,dword ptr [ebx]
804dbd93 8955f8 mov dword ptr [ebp-8],edx
804dbd96 894df4 mov dword ptr [ebp-0Ch],ecx
804dbd99 894df0 mov dword ptr [ebp-10h],ecx
804dbd9c 7e5f jle nt!KiWaitTest+0xd7 (804dbdfd)
nt!KiWaitTest+0x27:
804dbd9e 57 push edi
nt!KiWaitTest+0x28:
804dbd9f 3bc3 cmp eax,ebx
804dbda1 744f je nt!KiWaitTest+0xb7 (804dbdf2)
nt!KiWaitTest+0x30:
804dbda3 6683781601 cmp word ptr [eax+16h],1
Vi kan se dermed se at eax registeret blir satt ved instruksjonen:
804dbd91 8b03 mov eax,dword ptr [ebx]
Som henter en dword peker lagret i registeret ebx-hva ligger lagret i ebx?
kd> dd ebx
81fd9fe8 00000000 00000000 18d1af90 00000000
81fd9ff8 f8959fc0 f8959fc0 81fda008 00000000
81fda008 01000013 00000000 00000000 f8370f1a
81fda018 81fd9fe0 00000000 00000000 00000000
81fda028 bad67b5a 81fd7000 820e5ad0 00000000
81fda038 000a0008 00000001 81fda040 81fda040
81fda048 00000000 00000000 00000000 00000000
81fda058 81fda060 00000000 01000013 ffdff980
Som vi kan se er pekerne nullet ut og det er altså slik eax registret har blitt nullet ut.
Jeg slo på pool tagging med gflags for å forsøke å finne ut hvem som eide dette området av minnet og derettet kjøre
!pool opp mot denne addressen.
kd> !pool 81fd9fe8
Pool page 81fd9fe8 region is Nonpaged pool
*81fd7000 : large page allocation, Tag is NALW, size is 0x5000 bytes
Owning component : Unknown (update pooltag.txt)
Som vi kan se har modulen som har allokert dette minneområdet en ukjent minnetag "NALW" og vi kan derfor anta at dette tilhører en tredjepartsmodul. Hvordan finner vi ut hvilken driver som bruker denne tag'en?
Det enkleste er da å bruke programmet strings om kan lastes ned herfra:
http://technet.microsoft.com/en-us/sysinternals/bb897439.aspx
Deretter startet jeg det og kjøte det opp mot den vanligste lokasjonen for systemdrivere (c:\windows\system32\drivers)
kd> lm kv m wlcom51b
start end module name
bad5e000 bad8ac00 wlcom51b (deferred)
Image path: \SystemRoot\system32\DRIVERS\wlcom51b.sys
Image name: wlcom51b.sys
Timestamp: Fri Oct 22 15:59:55 2004 (4179125B)
CheckSum: 00033C12
ImageSize: 0002CC00
Translations: 0000.04b0 0000.04e0 0409.04b0 0409.04e0
Ved oppdatering av denne forsvant problemet, så det ser ut til at det er denne driveren som har gjort stakken korrupt og skrevet over registeret ebx (som lå på stakken.)