Exemple #1
0
        internal static bool IsDotNetCoreAppHost(string filename, [NotNullWhen(true)] out string?dllFilename)
        {
            // We detect the apphost.exe like so:
            //	- must have an exe extension
            //	- must be a PE file and an EXE (DLL bit cleared)
            //	- must not have .NET metadata
            //	- must have a file with the same name but a dll extension
            //	- this dll file must be a PE file and have .NET metadata

            // .NET Core 1.x: the apphost is a renamed dotnet.exe and it assumes (unless overridden
            // on the command line) that the managed dll is apphostname with a dll extension.
            // .NET Core 2.x-3.x: the relative path of the managed dll is part of the exe, patched
            // by an MSBuild task. Max utf8 string length is 1024 bytes. It's currently not possible
            // to override this path so it should be identical to apphostname with a dll extension,
            // unless someone patched the apphost exe (eg. dnSpy).

            // Windows apphosts have an .exe extension. Don't call Path.ChangeExtension() unless it's guaranteed
            // to have an .exe extension, eg. 'some.file' => 'some.file.dll', not 'some.dll'
            if (filename.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
            {
                dllFilename = Path.ChangeExtension(filename, ".dll");
            }
            else if (!filename.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
            {
                dllFilename = filename + ".dll";
            }
            else
            {
                dllFilename = null;
                return(false);
            }
            if (!File.Exists(dllFilename))
            {
                return(false);
            }
            if (PortableExecutableFileHelpers.IsPE(filename, out bool isExe, out bool hasDotNetMetadata) && (!isExe || hasDotNetMetadata))
            {
                return(false);
            }
            if (!PortableExecutableFileHelpers.IsPE(dllFilename, out _, out hasDotNetMetadata) || !hasDotNetMetadata)
            {
                return(false);
            }

            return(true);
        }
Exemple #2
0
        internal static bool TryGetAppHostEmbeddedDotNetDllPath(string apphostFilename, out bool couldBeAppHost, [NotNullWhen(true)] out string?dotNetDllPath)
        {
            dotNetDllPath  = null;
            couldBeAppHost = false;
            if (!File.Exists(apphostFilename))
            {
                return(false);
            }
            if (PortableExecutableFileHelpers.IsPE(apphostFilename, out _, out var hasDotNetMetadata) && hasDotNetMetadata)
            {
                return(false);
            }
            try {
                var data = ReadBytes(apphostFilename, MaxAppHostExeSize);
                if (GetOffset(data, AppHostExeUnpatchedSignature) >= 0)
                {
                    couldBeAppHost = true;
                    return(false);
                }
                if (GetOffset(data, AppHostExeSignature) < 0)
                {
                    return(false);
                }
                couldBeAppHost = true;
                if (!ExeUtils.TryGetTextSectionInfo(new BinaryReader(new MemoryStream(data)), out _, out _))
                {
                    return(false);
                }

                var basePath = Path.GetDirectoryName(apphostFilename) !;
                foreach (var info in GetAppHostInfos(data))
                {
                    if (!TryGetUtf8StringZ(data, (int)info.RelPathOffset, AppHostInfo.MaxAppHostRelPathLength, out var relPath))
                    {
                        continue;
                    }
                    if (relPath == AppHostExeUnpatched)
                    {
                        continue;
                    }
                    string dotnetFile;
                    try {
                        dotnetFile = Path.Combine(basePath, relPath);
                    }
                    catch (ArgumentException) {
                        continue;
                    }
                    if (!PortableExecutableFileHelpers.IsPE(dotnetFile, out _, out hasDotNetMetadata))
                    {
                        continue;
                    }
                    if (!hasDotNetMetadata)
                    {
                        continue;
                    }
                    dotNetDllPath = dotnetFile;
                    return(true);
                }
            }
            catch (IOException) {
            }
            return(false);
        }