Esempio n. 1
0
        private U Link <T, U>(IEnumerable <StaticLibrary <T> > staticLibraries, Func <byte[], U> UConstructor, Config.OutputType outputType)
            where T : ObjectFile, new()
            where U : IPortableExecutable, new()
        {
            var outputExtension = ".exe";

            switch (outputType)
            {
            case Config.OutputType.EXE:
                CConfig.outputType = Config.OutputType.EXE;
                outputExtension    = ".exe";
                break;

            case Config.OutputType.DLL:
                CConfig.outputType = Config.OutputType.DLL;
                outputExtension    = ".dll";
                break;

            case Config.OutputType.DRIVER:
                CConfig.outputType = Config.OutputType.DRIVER;
                outputExtension    = ".sys";
                break;
            }

            using (new TemporaryContext())
            {
                File.Copy(GoLinkResourcePath, "GoLink.exe");
                File.WriteAllText("input.txt", "");
                var inputFiles = new List <string>();
                foreach (var staticLibrary in staticLibraries)
                {
                    foreach (var objectFile in staticLibrary.ObjectFiles)
                    {
                        var inputFilename = Utils.RandomString(5) + ".obj";
                        inputFiles.Add(inputFilename);
                        File.WriteAllBytes(inputFilename, objectFile.Bytes);
                        File.AppendAllText("input.txt", inputFilename + "\r\n");
                    }
                }
                var outputfilename = "OUTPUT" + outputExtension;
                var linkerOptions  = CConfig.ToString();
                if (linkerOptions.Length > 0)
                {
                    linkerOptions = " " + linkerOptions;
                }
                var linkCommand = "";
                linkCommand += " /fo " + outputfilename;
                linkCommand += linkerOptions;
                linkCommand += " " + "@input.txt";

                // Attempt to link
                // If there are any mising symbols, then try to locate them in ImportStaticLibraryObjects
                // & add them to the linker input list if found and try again until there are no more missing symbols
                var missingSymbols = new List <string>();

                switch (CConfig.ENTRY)
                {
                case "mainCRTStartup":
                case "wmainCRTStartup":
                case "WinMainCRTStartup":
                case "wWinMainCRTStartup":
                case "_DllMainCRTStartup":
                    missingSymbols.Add(CConfig.ENTRY);
                    break;
                }

                for (var i = 0; i < 10; i++)
                {
                    // Find the object file(s) that contain the symbols that are missing
                    foreach (var symbol in missingSymbols)
                    {
                        foreach (var slObject in ImportStaticLibraryObjects)
                        {
                            if (slObject.ExternalSymbols.Contains(symbol))
                            {
                                using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
                                {
                                    string hash = BitConverter.ToString(sha1.ComputeHash(slObject.Bytes)).Replace("-", "");
                                    File.WriteAllBytes($"{hash}.obj", slObject.Bytes);
                                    File.AppendAllText("input.txt", $"{hash}.obj\r\n");
                                }
                                break;
                            }
                        }
                    }

                    missingSymbols.Clear();

                    Process process = new Process();
                    process.StartInfo.FileName               = "GoLink.exe";
                    process.StartInfo.Arguments              = linkCommand;
                    process.StartInfo.UseShellExecute        = false;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.Start();

                    bool isMissingSymbols = false;
                    while (!process.StandardOutput.EndOfStream)
                    {
                        string line = process.StandardOutput.ReadLine().Trim();
                        if (isMissingSymbols)
                        {
                            if (line != "")
                            {
                                missingSymbols.Add(line);
                            }
                        }
                        if (line.Contains("symbols were not defined"))
                        {
                            isMissingSymbols = true;
                        }
                    }

                    if (!isMissingSymbols)
                    {
                        break;
                    }

                    if (ImportStaticLibraryObjects.Count() == 0)
                    {
                        break;
                    }
                }

                var pe = UConstructor(File.ReadAllBytes(outputfilename));
                return(pe);
            }
        }
Esempio n. 2
0
        private U Link <T, U>(IEnumerable <StaticLibrary <T> > staticLibraries, TargetArch targetArch, Func <byte[], U> UConstructor, Config.OutputType outputType)
            where T : ObjectFile, new()
            where U : IPortableExecutable, new()
        {
            switch (targetArch)
            {
            case TargetArch.x86:
                CConfig.MACHINE = Config.Machine.X86;
                break;

            case TargetArch.x64:
                CConfig.MACHINE = Config.Machine.X64;
                break;

            case TargetArch.arm:
            case TargetArch.arm64:
                CConfig.MACHINE = Config.Machine.ARM;
                break;
            }
            var outputExtension = ".exe";

            switch (outputType)
            {
            case Config.OutputType.EXE:
                CConfig.outputType = Config.OutputType.EXE;
                outputExtension    = ".exe";
                break;

            case Config.OutputType.DLL:
                CConfig.outputType = Config.OutputType.DLL;
                outputExtension    = ".dll";
                break;

            case Config.OutputType.DRIVER:
                CConfig.outputType = Config.OutputType.DRIVER;
                outputExtension    = ".sys";
                break;
            }

            using (new TemporaryContext())
            {
                foreach (var staticLibrary in staticLibraries)
                {
                    foreach (var objectFile in staticLibrary.ObjectFiles)
                    {
                        File.WriteAllBytes(Core.Utils.RandomString(10) + ".obj", objectFile.Bytes);
                    }
                }
                var outputfilename = "OUTPUT" + outputExtension;
                var linkerOptions  = CConfig.ToString();
                if (linkerOptions.Length > 0)
                {
                    linkerOptions = " " + linkerOptions;
                }
                var linkCommand = "link.exe";
                linkCommand += " /out:" + outputfilename;
                linkCommand += " /NOLOGO";
                linkCommand += linkerOptions;
                linkCommand += " *.obj";
                var msvcVersion = version.ToString().Replace("v", "").Replace("_", ".");
                var linkBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n" + linkCommand;
                linkBatFile = String.Format(linkBatFile, targetArch.ToString());
                File.WriteAllText("link.bat", linkBatFile);
                var proc = Process.Start("cmd.exe", "/c " + "link.bat");
                proc.WaitForExit();
                var pe = UConstructor(File.ReadAllBytes(outputfilename));
                if (CConfig.MAP)
                {
                    pe.Map = File.ReadAllText("OUTPUT.map");
                }
                return(pe);
            }
        }