mandag 12. juli 2010

Enkel ressurs for å finne identiteten til ukjent maskinvare.

Hvis du har maskinvare som er blitt installert på datamaskinen men som du ikke kjenner identiteten til, (Feks om du har en maskinvare-enhet som bare vises som ukjent enhet i enhetsbehandling)hva vil være den raskeste måten å finne den nøyaktige identiten til maskinvaren?

Ved å bruke http://www.pcidatabase.com/kan du enkelt søke opp Vendor og Device id'en på maskinvaren for å identifisere den. (Denne informasjonen er blitt brent på en ROM chip på maskinvaren og hentet fra plug and play manageren slik at selv om Windows ikke vet hvilken type maskinvare dette er vil denne informasjonen vises i enhetsbehandling.

Du finner Vender og Device ID'en under egenskapene for maskinvaren i enhetsbehahandling.



Her på bildet er maskinvaren allerede identifisert men du kan enkelt søke etter feks device ID'en 94C1 og få opp hvilken type maskinvare dette er:



Enklere kan det vel ikke bli.

søndag 2. mai 2010

Feilsøking av datamaskin med et mystisk oppstartsproblem.

Kom over en litt fiffig sak der brukeren klagde på at datamaskinen ikke ville slå seg på. Når jeg startet opp datamaskinen fikk jeg den normale BIOS-splashscreenen men ble møtt av dette bildet når Windows ble forsøkt lastet:


Dette ga jo ikke særlig mye å gå på men jeg forsøkte å restarte maskinen og trykke F8 under oppstarten av NTLDR. Dette fungerte bra og jeg fikk opp de vante valgene, dette betydde da at BIOS hadde detektert en gyldig MBR på harddisken hvorpå tilsist NTLDR hadde blitt lastet inn i minnet. En svart skjerm tidlig i oppstarten kan ofte bety hardware-problemer men jeg hadde vertfall indikeringer på at BIOS fant harddisken og fikk lastet de første oppstarsfasene av Windows. Spørsmålet ble da: når stoppet lastingen av Windows opp?

En mulig måte å finne mere info om hva som skjer i oppstarten er å starte windows med /SOS bryteren. Dette gir deg litt mer info over hva som skjer og gir blant annet muligheten til å se driverne som blir lastet inn i oppstarten. (Dette gjøres forsåvidt automatisk når du velger sikkermodus.) Når jeg startet Windows med /SOS bryteren fikk jeg se følgende liste:

Lastet driver \WINDOWS\system32\ntoskrnl.exe
Lastet driver \WINDOWS\system32\hal.dll
Lastet driver \WINDOWS\system32\KDCOM.DLL
Lastet driver \WINDOWS\system32\BOOTVID.dll
Lastet driver ACPI.sys
Lastet driver \WINDOWS\system32\DRIVERS\WMILIB.SYS
Lastet driver pci.sys
Lastet driver isapnp.sys


Noe som egentlig ikke forteller så mye da denne listen bare viser hvilke drivere som ble lastet inn med suksess. Driveren som er problemet blir da med andre ord forsøkt lastet etter isapnp.sys, men hvordan kan finne ut hvilken driver dette er? På systinernals finnes det et program kalt LoadOrder som viser hvilken rekkefølge drivere lastes inn i men dette må kjøres i Windows og på denne maskinen er det ikke mulig å komme inn i Windows. Finnes det da noen måte å finne ut hvilken driver som lastes inn etter isapnp?

Det er faktisk bare tre verdier som avgjør prioriteten til driveren i oppstarten (eller senere) disse verdiene er Start, Tag og Group. For enkelhets skyld har jeg valgt å bruke begrepet tjeneste som en fellesbetegnelse for tjenester/drivere. Under følger en forklaring på hva som menes med disse verdiene og hva de kan brukes til.

Start:
Angir hvilket stadie i oppstarten driveren lastes inn i. Vi har 5 mulige verdier som er: SERVICE_BOOT_START (0) - Lastes inn av osloaderen tidlig i oppstarten
SERVICE_SYSTEM_START (1) - Lastess inn av osloaderen etter at samtlige SERVICE_BOOT_START drivere har blitt lastet.
SERVICE_AUTO_START (2)- Startes av Service Control Manageren (SCM) etter at tjenesteprosessen Services.exe har blitt startet.
SERVICE_DEMAND_START (3) Startes av SCM ved behov.
SERVICE_DISABLED (4) Tjenesten vil aldri lastes.

Tag:
Angir prioritet innenfor en gitt gruppe. En tjeneste som er gitt Tag 1 vil starte før en tjenste gitt Tag 2. Tjenester uten Tag vil starte etter Taggede tjenester.

Group:
Samler tjenester med lignende bruksområder innenfor et gitt gruppenavn. Alle tjenestene innenfor en gitt gruppe må startes før Windows går videre til neste gruppe. Prioriteten til gruppene er gitt gjennom registernøkkelen HKLM\SYSTEM\CurrentControlSet\Control\ServiceGroupOrder\List. Her følger et utdrag av denne listen med de 5 første gruppene:

System Reserved
Boot Bus Extender
System Bus Extender
SCSI miniport
Port


Alle tjenster er å finne innunder HKLM\SYSTEM\CurrentControlSet\Services\. En snedig funksjon i registereditering er at du kan importere register-hi fra andre datamaskiner ved å merke HKLM eller HCU og velge Last inn struktur. Jeg kopierte derfor SYSTEM-hiet fra datamaskinen som opplevde problemet og Lastet da inn dette hiet på min lokale datamaskin for å undersøke hvilke data som var gitt for tjenesten isapnp.sys:



Vi ser da at det er snakk om en BOOT driver under Boot Bus Extender gruppen. Siden alle BOOT driverne ikke har blitt lastet kan vi være sikre på at det dreier seg om en BOOT driver og vi kan se av prioriteringene at den enten må ligge i Boot Bus Extender gruppen eller i System Bus Extender gruppen. Ved å søke i registeret etter disse gruppenavnene kunne man søke opp de driverne som lå i disse gruppene og dermed lage seg en tabell over boot-prioriteringer basert på tagging. Jeg fikk da opp følgende liste i prioritert rekkefølge:

Boot Bus Extendere:
ACPI.sys tag - 1
pci.sys tag - 2
isapnp.sy tag - 3
psiksxvv Ikke tagget.

System Bus Extendere:
pcmcia tag 1
Compbatt.sys Tag 2
pciide.sys tag 3
viaidexp.sys tag 4
Partmgr tag 5
ACPIEC.SYS tag - 6
Mountmgr tag 8
ftdisk.sys tag 9
dmload.sys tag 12
dmio.sys tag 13
Volsnap Ikke tagget.

Vi ser da at ifølge vår liste skulle tjenesten med det merkelige navnet psiksxvv skulle være den neste til å starte opp. La oss ta en nærmere kikk på denne:



Dette gir ikke mye mening og vi kan se flere registerverdier som er bare fyllt med nonsens. Vi kan dermed være sikre på at det dreier seg om en korrupt registernøkkel. For å sjekke at det var denne som skapte problemer satte jeg Start verdien fra 0 til 4 noe som vi husker var SERVICE_DISABLED. Den ville med andre ord ikke bli lastet i oppstarten. Jeg kopierte SYSTEM-hiet tilbake til datamaskinen med problemet og nå startet den opp normalt.

onsdag 26. november 2008

Avbrudd og Unntakshåndtering.

Trap Dispatching:
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.

Windows sin nettverksmodell er bygd opp av følgende hovedkomponenter:

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.

Sikkerheten i Windows XP blir ivaretatt av flere forskjellige komponenter, de viktigste komponentene er:

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.

Objekt-manageren er en del av Windows Executive hvis ansvar står i å lage, slette, beskytte og spore objekter. Hovedmålet til Objekt-manageren er å gi en lik, enhetelig mekanisme for bruk av system ressurser.
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.

Har vært en stund siden det har vært noe skikkelig feilsøkings stoff, men her skal jeg da Internet Explorer hengte seg fullstendig (Mao ingen vinduer ble oppdatert) bestemte jeg meg for å starte Windbg og se hva som forårsaket problemet. Her kan du se hvilken beskjed når jeg første prøvde å koble meg til prosessen med debuggeren:

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!