Het oplossen van PE SxS importeert Windows

Ik ben bezig met het schrijven van mijn eigen versie van de Windows Loader (hoewel een zeer eenvoudige versie) en tot dusverre is het redelijk gelukt. Ik ben echter een klein probleempje tegengekomen als het gaat om het recursief doorlopen van de Import-tabel voor de geladen module.

Voor de meeste afhankelijkheden verloopt het goed en kan ik de module eenvoudig recursief laden. Voor sommige afhankelijkheden breekt dit echter gewoon het doelproces. Bij nader onderzoek realiseerde ik me dat dit komt door de zij-aan-zij assemblages van Windows. In wezen was de afhankelijkheid in de geladen PE een andere SxS-versie van de module die werd gebruikt in het doelproces.

In één geval laadde het DLL-bestand waarnaar werd verwezen msvcr90.dll, maar het doelproces gebruikte een eerdere versie van de runtime: msvcr71.dll.

Nu kan de Windows-lader dit prima aan, dus er is duidelijk een "juiste" manier om dit te doen. Ik heb iets gelezen over activeringscontexts, maar ze hebben me niet echt geholpen het probleem te begrijpen.

Het aanroepen van LoadLibrary zelf lost de dll ook niet op naar de juiste versie

LoadLibraryW(L"msvcr90.dll");

Keert eenvoudig terug 0. Weet iemand het

a) Hoe te detecteren of een import een SxS-assembly is

     

b) Hoe de import op te lossen in de juiste SxS-versie voor het proces.

Ik ben echt stom om dit te doen. Ik weet nu het grootste deel van het PE-bestandsformaat uit onderzoek, maar ik ben er vrij zeker van dat de SxS buiten het bereik van de PE-structuur valt.

Als je meer info nodig hebt, reageer dan gewoon. Het uitvoerbare bestand heeft geen extern manifest en het ingesloten manifest specificeert de runtime-versie niet. Het bevat echter wel een kopie van msvcr71.dll in de werkdirectory, als dat iedereen helpt.

Proost.

2
Je ziet alleen de top van de ijsberg die de Titanic tot zinken bracht. U zult ook te maken hebben met manifesten, hetzij ingesloten als een bron of op schijf, uitgeversbeleid, bindende omleidingen, register-vrije COM, dynamische activering via CreateActCtx, aangepaste DLL-zoekpaden ingesteld met SetDllDirectory. De documentatie is waardeloos.
toegevoegd de auteur Hans Passant, de bron
evenals het pad naar het manifest (ik heb het interne manifest geëxtraheerd naar een tijdelijk bestand, CreateActCtx heeft een pad naar het manifest nodig). Vervolgens wordt de activeringscontext gemaakt, wordt de lijst met door nul begrensde modules weergegeven en wordt GetModuleHandle op elke code aangeroepen. Als GetModuleHandle 0 retourneert, gaat het door met het aanroepen van LoadLibrary . Als nog steeds 0 is, wordt de functie afgesloten. Ik weet dat ik het moeilijkste deel overgeslagen heb door simpelweg LoadLibrary te gebruiken in de activeringscontext , maar ik wilde eigenlijk alleen mijn eigen loader gebruiken voor de hoofd-dll, niet de afhankelijkheden.
toegevoegd de auteur Jason Larke, de bron
@HansPassant Ik heb dit voor elkaar gekregen. Je had gelijk omdat het slechts het topje van de ijsberg was haha. Uiteindelijk moest ik een Resource Walker schrijven om het interne manifest van de .dll te vinden (RT_MANIFEST). Vervolgens moest ik een assembly-fragment schrijven waarin alle activeringscontent zaken werden behandeld. Natuurlijk had ik het eenvoudig in C ++ kunnen schrijven en het in een .dll-bestand met statische koppeling (d.w.z. geen SxS) hebben gewikkeld en het vervolgens hebben gebruikt om alle volgende bibliotheken te laden, maar het leek overdreven, dus deed ik het bij de assembly. Kort gezegd geef ik de assembly-functie een null-gescheiden string van benodigde afhankelijkheden ...
toegevoegd de auteur Jason Larke, de bron

1 antwoord

In feite zijn de SxS-afhankelijkheden binnen het bereik van de PE-structuur! Zoals u weet, inventariseren de Import Tables of PE de afhankelijkheden namen , maar niet hun versies. Bij het omgaan met deze afhankelijke tabellen, kijkt de Loader ook naar de Manifest van de PE-afhankelijke afbeeldingen. Als een Manifest één of meerdere bibliotheken documenteert (bijvoorbeeld msvcr90, advapi32, ....), kijkt de loader in de map winsxs om de afhankelijkheid te vinden. Hier een artikel dat geeft een overzicht van deze assembly en hoe deze informatie te verzamelen in C ++.

2
toegevoegd
ja, natuurlijk, roep gewoon GetModuleHandle aan met de naam van de SxS-afhankelijkheid, als deze al is geladen, krijgt u de juiste ingang.
toegevoegd de auteur mox, de bron
Eigenlijk hoeft u de naam van de WinSxs-afhankelijkheid niet zelf te bouwen. Het enige wat u hoeft te doen is om te "testen" met CreateActCtx. Als de lader vindt dat die afhankelijk is, zal deze het juiste pad (bijvoorbeeld x86_microsoft-windows-msvcrt_31bf3856ad364e35_6.1.7601.17744 & zwnj; _none_d33c3413fd4084 & zwnj; d9) voor u hebben gebouwd!
toegevoegd de auteur mox, de bron
Side-by-Side-assemblies (WinSxs) zijn moeilijk te hanteren. Ik had dit probleem tijdens mijn implementatie van PeStudio ( winitor.com )
toegevoegd de auteur mox, de bron
je kunt het! ;-)
toegevoegd de auteur mox, de bron
Het is de taak van de loader (met behulp van WinSxS Manager) om het echte pad van de bibliotheek op te lossen. Zoals vermeld in het artikel, hangt het pad af van de taal, het token voor de openbare sleutel, enz. ... Laat de lader dit voor u oplossen. Gebruik de activeringscontext Api ( msdn. microsoft.com/en-us/library/windows/desktop/… )
toegevoegd de auteur mox, de bron
OK. maar je kunt de activeringscontext api gebruiken! heb je dit geprobeerd?
toegevoegd de auteur mox, de bron
hm, lijkt moeilijk om dit te doen in een externe thread ....
toegevoegd de auteur mox, de bron
Het punt van deze vraag is dat ik mijn eigen lader aan het schrijven ben, dus ik kan niet zomaar naar de Windows-lader stappen om dit voor mij te doen.
toegevoegd de auteur Jason Larke, de bron
Ja, ik heb de versie-indeling verkeerd begrepen. Ik heb uiteindelijk alleen maar een aantal echt hacky rommelige dingen moeten doen, maar het werkt nu: 3
toegevoegd de auteur Jason Larke, de bron
Negatief, het proces zelf heeft al een andere SxS-versie van msvcr geladen. Is er een manier om te controleren of een SxS-afhankelijkheid al is geladen?
toegevoegd de auteur Jason Larke, de bron
Jij zei het. Ik ga gewoon de huidige RT_MANIFEST-bronbestanden (indien aanwezig) ontleden en SxS-referenties vanaf daar oplossen. Als het niet werkt, jammer :)
toegevoegd de auteur Jason Larke, de bron
Vermoedelijk moet de activeringscontext worden opgehaald uit het ladende proces. Aangezien ik dit in C# aan het schrijven ben, en in externe processen laad, denk ik niet dat het een eenvoudige taak zal zijn om thread-local activeringscontexten van een proces op afstand te krijgen:/Ik zou het kunnen doen met wat minder-dan -wenste thread-opschorting en doorverwijzing, maar ik zou liever gewoon de resources voor RT_MANIFEST terugdraaien en sxs-paden vanaf daar oplossen.
toegevoegd de auteur Jason Larke, de bron
Oké, ik dacht dat het eerste ding zou zijn om een ​​lijst te maken van alle mogelijke WinSxS-importen door eerst de RT_MANIFEST-bron te bekijken en alle mogelijke WinSxS-afhankelijkheden daarvan op te lossen. Ik heb echter moeite om te zien hoe de manifestinformatie naar een SxS-directory wordt geconverteerd. Ik weet niet wat de uiteindelijke identifier is in relatie tot het manifest, dat wil zeggen: C: \ Windows \ winsxs \ x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9. & Zwnj; 0.21022.8_none_bcb86 & zwnj; ed6ac711f91 de bcb86ed6ac711f91 bit wordt niet gevonden in het manifest, dus ik weet niet zeker hoe ik dit moet verhelpen: /
toegevoegd de auteur Jason Larke, de bron
Bedankt voor de link, het maakt de dingen een beetje duidelijker. Het enige is, hoe controleer je of een bepaalde importnaam WinSxS is? Ik bedoel, in het manifest is Microsoft.VC90.CRT gekoppeld aan msvcr90.dll , maar hoe is deze link ontstaan? Als ik het manifest voor het eerst lees om WinSxS-compatibele import te identificeren, hoe wijs ik ze dan toe aan een specifieke importnaam?
toegevoegd de auteur Jason Larke, de bron