DLL redirection using manifests

后端 未结 3 459
予麋鹿
予麋鹿 2020-11-28 09:04

I need to reliably redirect an applications look up of a specific DLL. Using the app.exe.local approach does not work because local files are ignored if the application has

相关标签:
3条回答
  • 2020-11-28 09:21

    You may be able to work around this by using Detours, wrapping LoadLibrary. Your LoadLibrary wrapper would be able to recognize attempts to load your DLL and rewrite the path appropriately.

    0 讨论(0)
  • 2020-11-28 09:28

    Ok, you need to set it up like this:

    • c:\apppath\testapp.exe - your test apps exe file
    • c:\apppath\testapp.exe.manifest - the - potentially embedded application manifest file
    • c:\apppath\EmptyAssm\EmptyAssm.manifest - A manifest describing your new assembly.
    • c:\apppath\EmptyAssm\empty.dll - the assembly dll
    • c:\apppath\EmptyAssm\empty.dll.2.manifest - the embedded manifest in the dll

    So, you have your test application which contains an application manifest: which contains dependent assembly references for the app - including one you add to your custom dll assembly.

    In the application folder assm subfolder of the app folder you have the assembly-manifest of the "EmptyAssm" assembly, which contains a file node referencing the actual dll, "empty.dll".

    empty.dll embeds its own manifest, containing dependent assembly references on any public or private assemblies it requires.

    This is the important point: the "EmptyAssm" assembly manifest, and the "empty" dll manifests are potentially different. The ("EmptyAssm") assembly's manifest file MUST NOT be embedded, but might share the dll manifest name IF you choose to name your manifest by the name of the dll.

    Now, when the loader loads your EXE, it loads your EXE's manifest and adds it to the activation context. When the EXE's import table is processed, OR you call LoadLibrary, the loader first searches the activation context for an assembly manifest with a matching file node. If it finds a matching assembly, THEN it processess and loads the dll from the assembly location (the folder containing the assemblies .manifest) and it may, at this time, if there is no embedded manifest in the dll AND the dll and manifest have the same name, reuse the same manifest file to setup the dll's activation context.

    IF you want to put the "emptyassm" manifest, and dll, in a different folder to your application folder, AND IF you are targetting Windows Server 2008, or Windows 7, or later, you can add a config file for your app :-

    • c:\apppath\testapp.exe.config - app config file

    The app config file can contain a probing node under the assemblyBinding node (config files look a lot like manifest files), with a privatePath="some relative path". In which case, the relative folder will be searched for assemblies.


    My last response here has example files covering the process of creating an assembly from a dll, and referencing it from an exe :- A way to load DLL from central repository


    Just to clarify: A win32 assembly is (At its simplest) a manifest file describing the assembly, and a dll. They are always, in this model, located in the same folder so the file node of the manifest cannot contain any pathing information at all - only the name of the dll.

    Assemblies can be shared - by giving them a strong version (and some digital signing) and installing them in Windows\WinSxS, or private.

    Windows versions before 5.1 (Win XP) won't search for assemblies at all as this technology was only added in XP. Windows 5.1 thru 6.0 (XP and Vista) will only search for private assemblies in the folder of the object with the active activation context :- If an exe references an assembly, then the folder containing the exe. If code in a dll references an assembly then the dll's folder is searched.

    If you want to store your dll in a private location shared by several apps (For example) you MUST have a requirement of Windows 7 or later :-

    Windows version 6.1 (otherwise known as Windows Server 2008, or Windows 7) and later will, additionally to the module folder, search the path specified as the privatePath element of the probing element in an application configuration file. Application configuration files are always in the same folder as the exe or dll, and are named:

    <exename>.exe.config, or <dllname>.dll.2.config

    (The reason for the .2. is there are potentially lots of manifests and configs embedded as resources, and the loader reserves resources id's 1...15. When searching the disk for a manifest of config file, if the resource id of the embedded resource would have been 1, the id is omitted, but any other number means it becomes part of the file name).

    0 讨论(0)
  • 2020-11-28 09:36

    So it seems its impossible to redirect calls to LoadLibrary with absolute paths using manifests.

    After a lot of playing around with manifests, it seems that once you get past all the bad documentation manifests are actually stupidly simple.

    Basically when the executable is loaded windows collects all the related manifests that are linked using the identity and dependency elements. Then for each file element contained in the manifest files, it adds an entry into the activation context:

    'name attribute of file element' -> 'absolute path of manifest file' + 'name attribute of file element'
    

    Now when a load library call is made, it searches the activation context map for a key that matches the path argument of load library, and then does the loadlibrary with the value for that key.

    So if my application c:\foo\foo.exe has a dependency to the manifest in c:\foo\baa\baa.manifest, and baa.manifest contains a file element <file name="empty.dll"/>, then the activation context will have a mapping: "empty.dll" -> "c:\foo\baa\empty.dll"

    So any calls to LoadLibrary("empty.dll") will be redirected to LoadLibrary("C:\foo\baa\empty.dll").

    However, LoadLibrary("c:\anotherpath\empty.dll") Will not be redirected!

    Now to prove my point of how stupidly simple manifest files and activation contexts are. If the file element of baa.manifest was <file name="c:\anotherpath\empty.dll"/> and you made a LoadLibrary("C:\anotherpath\empty.dll") call, the LoadLibrary call will be redirected to LoadLibrary("C:\foo\baa\C:\anotherpath\empty.dll"), yes, a malformed path...

    The file element does have an undocumented attribute called "loadFrom", which does what it sounds like, and seems like its perfect to solve this problem. Using loadFrom, I was able to redirect an absolute path loadlibrary call, but it seemed to screw up other dependencies in the executable in weird ways. If someone knows more about how "loadFrom" works I would be very interested.

    So how did I solve my problem in the end? By using an incredibly heavy handed approach of DLL Trojaning described at Ethical Hacker. Basically you create a dummy kernel32.dll that redirects all calls to the original kenerl32.dll, except for the LoadLibrary calls, in which you place your own redirection logic. Then in the applications manifest, you place a file element that redirects the kernel32.dll to your dummy. Fun.

    All this describes my experiments on Windows Xp Sp2. For extra fun I'm led to believe manifests behave differently on almost every version of Windows.

    0 讨论(0)
提交回复
热议问题