private ThreatInformation FeatureExtractFile(string filePath, bool forPrediction = false)
        {
            var peFile = new PeNet.PeFile(filePath);

            var information = new ThreatInformation
            {
                NumberImports   = peFile.ImageResourceDirectory.NumberOfIdEntries,
                DataSizeInBytes = peFile.ImageSectionHeaders.FirstOrDefault()?.SizeOfRawData ?? 0.0f
            };

            foreach (var name in Enum.GetNames(typeof(ThreatTypes)))
            {
                if (!filePath.Contains(name))
                {
                    continue;
                }

                information.Classification = name;
            }

            if (!string.IsNullOrEmpty(information.Classification) || forPrediction)
            {
                return(information);
            }

            Console.WriteLine($"{filePath} was not named properly");

            return(null);
        }
Пример #2
0
        private bool CheckExeCodeSize(string exeo, string exep)
        {
            var peoHeaderE = new PeNet.PeFile(exeo);
            var peoHeaderO = new PeNet.PeFile(exep);

            return(peoHeaderE.ImageSectionHeaders[0].SizeOfRawData == peoHeaderO.ImageSectionHeaders[0].SizeOfRawData);
        }
Пример #3
0
        public static List <string> GetDllCharacteristics(string Path)
        {
            List <string> output = new List <string>();

            if (NeedsSignature(Path))
            {
                try
                {
                    // This line throws the exceptions below.
                    var    peHeader1       = new PeNet.PeFile(Path);
                    ushort characteristics = peHeader1.ImageNtHeaders.OptionalHeader.DllCharacteristics;
                    foreach (DLLCHARACTERISTICS characteristic in Enum.GetValues(typeof(DLLCHARACTERISTICS)))
                    {
                        if (((ushort)characteristic & characteristics) == (ushort)characteristic)
                        {
                            output.Add(characteristic.ToString());
                        }
                    }
                }
                catch (IndexOutOfRangeException)
                {
                    Log.Verbose("Failed to get PE Headers for {0} (IndexOutOfRangeException)", Path);
                }
                catch (ArgumentNullException)
                {
                    Log.Verbose("Failed to get PE Headers for {0} (ArgumentNullException)", Path);
                }
                catch (Exception e)
                {
                    Log.Debug(e, "Failed to get DLL Characteristics for path: {0}", Path);
                }
            }

            return(output);
        }
        protected internal static List <DLLCHARACTERISTICS> GetDllCharacteristics(string Path)
        {
            if (NeedsSignature(Path))
            {
                try
                {
                    List <DLLCHARACTERISTICS> l = new List <DLLCHARACTERISTICS>();
                    var    peHeader1            = new PeNet.PeFile(Path);
                    ushort characteristics      = peHeader1.ImageNtHeaders.OptionalHeader.DllCharacteristics;
                    foreach (DLLCHARACTERISTICS characteristic in Enum.GetValues(typeof(DLLCHARACTERISTICS)))
                    {
                        if (((ushort)characteristic & characteristics) == (ushort)characteristic)
                        {
                            l.Add(characteristic);
                        }
                    }
                    return(l);
                }
                // Catches a case where the line establising the PeFile fails with Index outside bounds of the array.
                catch (IndexOutOfRangeException)
                {
                    Log.Verbose("Failed to get PE headers for {0}", Path);
                }
                catch (Exception e)
                {
                    Log.Debug("{0}:{1}", e.GetType().ToString(), e.Message);
                    Log.Debug(e.StackTrace);
                }
            }

            return(new List <DLLCHARACTERISTICS>());
        }
Пример #5
0
        public void ExportedFunctions_WithForwardedFunctions_ParsedFordwardedFunctions()
        {
            var peFile         = new PeNet.PeFile(@"Binaries/win_test.dll");
            var forwardExports = peFile.ExportedFunctions.Where(e => e.HasForwad).ToList();

            Assert.Equal(180, forwardExports.Count);
            Assert.Equal("NTDLL.RtlEnterCriticalSection", forwardExports.First(e => e.Name == "EnterCriticalSection").ForwardName);
        }
Пример #6
0
        public static bool GetImageArchitecture(string filepath)
        {
            var file = new PeNet.PeFile(filepath);

            if (file.HasValidComDescriptor)
            {
                throw new BadImageFormatException(".NET assembly is not supported.");
            }

            return(file.Is32Bit);
        }
Пример #7
0
        static void Main(string[] args)
        {
            var file = new PeNet.PeFile(@"C:\Local Virus Copies\7c1dba942ca01313b5f4fbcf085d92ce65d1c0c69587fa64207c040179bf23fc");

            Console.WriteLine($"IsValidPeFile: {file.IsValidPeFile.ToString()}");
            Console.WriteLine($"HasValidExceptionDir.: {file.HasValidExceptionDir.ToString()}");
            Console.WriteLine($"HasValidExportDir.: {file.HasValidExportDir.ToString()}");
            Console.WriteLine($"HasValidImportDir.: {file.HasValidImportDir.ToString()}");
            Console.WriteLine($"HasValidResourceDir.: {file.HasValidResourceDir.ToString()}");
            Console.WriteLine($"HasValidSecurityDir.: {file.HasValidSecurityDir.ToString()}");
            Console.ReadKey();
        }
Пример #8
0
 /// <summary>
 /// Tries to parse the PE file. If no exceptions are thrown, true
 /// </summary>
 /// <param name="file"></param>
 /// <returns>True if the file could be parsed as a PE file, else false.</returns>
 public static bool IsValidPEFile(string file)
 {
     PeNet.PeFile pe = null;
     try
     {
         pe = new PeNet.PeFile(file);
     }
     catch
     {
         return(false);
     }
     return(pe.IsValidPeFile);
 }
Пример #9
0
        private CodeByte Disamexe(string fileexe)
        {
            progressBar1.Maximum = 100;
            CodeByte codeByte = new CodeByte();

            int exampleCodeBitness;
            var peHeader = new PeNet.PeFile(fileexe);

            if (peHeader.Is64Bit)
            {
                exampleCodeBitness = 64;
            }
            else
            {
                exampleCodeBitness = 32;
            }

            FileStream   input  = new FileStream(fileexe, FileMode.Open, FileAccess.Read);
            BinaryReader reader = new BinaryReader(input);

            reader.ReadBytes((int)peHeader.ImageSectionHeaders[0].PointerToRawData);
            byte[] buffer = reader.ReadBytes((int)peHeader.ImageSectionHeaders[0].SizeOfRawData);
            input.Close();

            ulong exampleCodeRIP = peHeader.ImageNtHeaders.OptionalHeader.ImageBase + peHeader.ImageSectionHeaders[0].VirtualAddress;
            var   codeBytes      = buffer;
            var   codeReader     = new ByteArrayCodeReader(codeBytes);
            var   decoder        = Iced.Intel.Decoder.Create(exampleCodeBitness, codeReader);

            decoder.IP = exampleCodeRIP;
            ulong endRip       = decoder.IP + (uint)codeBytes.Length;
            var   instructions = new InstructionList();

            while (decoder.IP < endRip)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
                if (decoder.IP % PROGRESS_MODULO == 0)
                {
                    progressBar1.Value = (int)(decoder.IP * 100 / endRip);
                }
            }
            codeByte.instructions = instructions;
            codeByte.hexcode      = buffer;
            codeByte.CodeRIP      = exampleCodeRIP;

            return(codeByte);
        }
Пример #10
0
 public static Signature?GetSignatureStatus(string Path)
 {
     if (!NeedsSignature(Path))
     {
         return(null);
     }
     try
     {
         var peHeader         = new PeNet.PeFile(Path);
         var authenticodeInfo = new AuthenticodeInfo(peHeader);
         var sig = new Signature(authenticodeInfo);
         return(sig);
     }
     catch (Exception)
     {
     }
     return(null);
 }
        public static List <string> GetDllCharacteristics(string Path)
        {
            List <string> output = new List <string>();

            if (NeedsSignature(Path))
            {
                try
                {
                    // This line throws the exceptions below.
                    using var peHeader1 = new PeNet.PeFile(Path);
                    var dllCharacteristics = peHeader1.ImageNtHeaders?.OptionalHeader.DllCharacteristics;
                    if (dllCharacteristics is DllCharacteristicsType chars)
                    {
                        ushort characteristics = (ushort)chars;
                        foreach (DLLCHARACTERISTICS?characteristic in Enum.GetValues(typeof(DLLCHARACTERISTICS)))
                        {
                            if (characteristic is DLLCHARACTERISTICS c)
                            {
                                if (((ushort)c & characteristics) == (ushort)c)
                                {
                                    output.Add(c.ToString());
                                }
                            }
                        }
                    }
                }
                catch (Exception e) when(
                    e is IndexOutOfRangeException ||
                    e is ArgumentNullException ||
                    e is System.IO.IOException ||
                    e is ArgumentException ||
                    e is UnauthorizedAccessException ||
                    e is NullReferenceException)
                {
                    Log.Verbose($"Failed to get PE Headers for {Path} {e.GetType().ToString()}");
                }
                catch (Exception e)
                {
                    Log.Debug(e, $"Failed to get PE Headers for {Path}");
                }
            }

            return(output);
        }
 public static Signature?GetSignatureStatus(string Path)
 {
     if (!NeedsSignature(Path))
     {
         return(null);
     }
     try
     {
         using var peHeader = new PeNet.PeFile(Path);
         if (peHeader.Authenticode is AuthenticodeInfo ai)
         {
             var sig = new Signature(ai);
             return(sig);
         }
     }
     catch (Exception e)
     {
         Log.Debug(e, "Thrown in GetSignatureStatus");
     }
     return(null);
 }
        public FileClassificationResponseItem(byte[] fileBytes)
        {
            SHA1Sum     = fileBytes.ToSHA1();
            Confidence  = 0.0;
            IsMalicious = false;
            FileSize    = fileBytes.Length;

            try
            {
                var peFile = new PeNet.PeFile(fileBytes);

                Is64Bit = peFile.Is64Bit ? TRUE : FALSE;

                try
                {
                    NumImports = peFile.ImageImportDescriptors.Length;
                }
                catch
                {
                    NumImports = 0.0f;
                }

                NumImportFunctions = peFile.ImportedFunctions.Length;

                if (peFile.ExportedFunctions != null)
                {
                    NumExportFunctions = peFile.ExportedFunctions.Length;
                }

                IsSigned = peFile.IsSigned ? TRUE : FALSE;

                Strings = fileBytes.ToStringsExtraction();
            }
            catch (Exception)
            {
                ErrorMessage = $"Invalid file ({SHA1Sum}) - only PE files are supported";
            }
        }
Пример #14
0
        public static int ParseConfig(ref DSConfig config, ref DSFileInfo fi)
        {
            D.Print("Entering ParseConfig()");
            string file = new string(config.file).Replace("\0", "");

            // Checks if file exists
            if (File.Exists(file) == false)
            {
                return(Constants.DONUT_ERROR_INVALID_PARAMETER);
            }

            // Validate URL
            if (config.inst_type == Constants.DONUT_INSTANCE_URL)
            {
                // Make sure it's a validate URL (check this don't know exactly how it's checking)
                D.Print("Validating URL");
                if (Uri.IsWellFormedUriString(String(config.url), UriKind.Absolute) == false)
                {
                    return(Constants.DONUT_ERROR_INVALID_URL);
                }

                // If URL doesn't have trailing slash, add one
                //if (config.url(config.url.Length - 1) != "/")
                //{
                //    config.url += "/";
                //}
            }

            // Validate Arch
            D.Print("Checking for Arch Mismatch");
            if (config.arch != Constants.DONUT_ARCH_ANY &&
                config.arch != Constants.DONUT_ARCH_X86 &&
                config.arch != Constants.DONUT_ARCH_X84 &&
                config.arch != Constants.DONUT_ARCH_X64)
            {
                return(Constants.DONUT_ERROR_INVALID_ARCH);
            }

            // Validate AMSI/WDLP Bypass Option
            D.Print("Validating Bypass Option");
            if (config.bypass != Constants.DONUT_BYPASS_SKIP &&
                config.bypass != Constants.DONUT_BYPASS_ABORT &&
                config.bypass != Constants.DONUT_BYPASS_CONTINUE)
            {
                return(Constants.DONUT_ERROR_BYPASS_INVALID);
            }

            // Get File Info
            var ret = ParseInputFile(file, ref fi);

            if (ret != Constants.DONUT_ERROR_SUCCESS)
            {
                return(ret);
            }

            // Set Module Type
            config.mod_type = fi.type;
            if (config.mod_type == Constants.DONUT_MODULE_DLL || config.mod_type == Constants.DONUT_MODULE_EXE)
            {
                // Check for Arch mismatch
                if ((config.arch == Constants.DONUT_ARCH_X86 && fi.arch == Constants.DONUT_ARCH_X64) ||
                    (config.arch == Constants.DONUT_ARCH_X64 && fi.arch == Constants.DONUT_ARCH_X86))
                {
                    return(Constants.DONUT_ERROR_ARCH_MISMATCH);
                }

                // Check existence of DLL function specified
                if (config.mod_type == Constants.DONUT_MODULE_DLL && config.method != null)
                {
                    try
                    {
                        var  exported = new PeNet.PeFile(file).ExportedFunctions;
                        bool found    = false;
                        foreach (var func in exported)
                        {
                            if (func.Name == String(config.method))
                            {
                                found = true;
                            }
                        }
                        if (found == false)
                        {
                            return(Constants.DONUT_ERROR_DLL_FUNCTION);
                        }
                    }
                    catch
                    {
                        return(Constants.DONUT_ERROR_DLL_FUNCTION);
                    }
                }

                // If unmanaged DLL with params, need function
                if (config.mod_type == Constants.DONUT_MODULE_DLL && config.param != null)
                {
                    if (config.method == null)
                    {
                        return(Constants.DONUT_ERROR_DLL_PARAM);
                    }
                }
            }

            // If .NET DLL make sure Method and Class provided
            if (config.mod_type == Constants.DONUT_MODULE_NET_DLL)
            {
                if (config.cls == null || config.method == null)
                {
                    return(Constants.DONUT_ERROR_NET_PARAMS);
                }
            }
            return(Constants.DONUT_ERROR_SUCCESS);
        }
Пример #15
0
        public static int ParseInputFile(string file, ref DSFileInfo fi)
        {
            D.Print("Entering ParseInputFile()");
            PeNet.PeFile PE;

            var extension = Path.GetExtension(file);

            D.Print($"File extension is: {extension}");
            // If supplied file is a directory
            if (extension == null)
            {
                return(Constants.DONUT_ERROR_FILE_INVALID);
            }

            // Parse extension
            if (extension == ".vbs")
            {
                fi.type = Constants.DONUT_MODULE_VBS;
                fi.arch = Constants.DONUT_ARCH_ANY;
            }
            else if (extension == ".js")
            {
                fi.type = Constants.DONUT_MODULE_JS;
                fi.arch = Constants.DONUT_ARCH_ANY;
            }
            else if (extension == ".xsl")
            {
                fi.type = Constants.DONUT_MODULE_XSL;
                fi.arch = Constants.DONUT_ARCH_ANY;
            }
            else if (extension == ".exe")
            {
                fi.type = Constants.DONUT_MODULE_EXE;
                fi.arch = Constants.DONUT_ARCH_ANY;
            }
            else if (extension == ".dll")
            {
                fi.type = Constants.DONUT_MODULE_DLL;
                fi.arch = Constants.DONUT_ARCH_ANY;
            }
            else
            {
                return(Constants.DONUT_ERROR_FILE_INVALID);
            }

            // Do PE parsing for .dll and .exe
            if (fi.type == Constants.DONUT_MODULE_DLL || fi.type == Constants.DONUT_MODULE_EXE)
            {
                D.Print("Parsing PE file");
                try
                {
                    PE = new PeNet.PeFile(file);
                    if (PE.ImageDosHeader == null)
                    {
                        return(Constants.DONUT_ERROR_FILE_INVALID);
                    }
                    if (PE.ImageNtHeaders == null)
                    {
                        return(Constants.DONUT_ERROR_FILE_INVALID);
                    }
                }
                catch
                {
                    return(Constants.DONUT_ERROR_FILE_INVALID);
                }

                // Check and Reset Arch
                if (PE.Is32Bit == true)
                {
                    fi.arch = Constants.DONUT_ARCH_X86;
                }
                else
                {
                    fi.arch = Constants.DONUT_ARCH_X64;
                }

                // Check .NET and Reset Type
                if (PE.HasValidComDescriptor == true)
                {
                    D.Print("COM Descriptor found, .NET selected");
                    if (PE.IsDLL == true)
                    {
                        fi.type = Constants.DONUT_MODULE_NET_DLL;
                    }
                    else
                    {
                        fi.type = Constants.DONUT_MODULE_NET_EXE;
                    }

                    Copy(fi.ver, PE.MetaDataHdr.Version);
                    D.Print($"Runtime found in Metadata Header: {String(fi.ver)}");
                }
                else if (PE.ImageRelocationDirectory.Length == 0)
                {
                    //Think this should be ok?
                    return(Constants.DONUT_ERROR_NORELOC);
                }
            }
            return(Constants.DONUT_ERROR_SUCCESS);
        }
Пример #16
0
        static void Main(string[] args)
        {
            //Cheesy way to generate a temp filename for our original DLL
            var tempName = Path.GetFileNameWithoutExtension(Path.GetTempFileName());

            var orgDllPath = @"";

            var payloadPath = @"shellcode.bin";

            var pragmaBuilder = "";

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i].ToLower().Equals("--dll") || args[i].ToLower().Equals("-dll"))
                {
                    if (i + 1 < args.Length)
                    {
                        orgDllPath = Path.GetFullPath(args[i + 1]);
                    }
                }


                if (args[i].ToLower().Equals("--payload") || args[i].ToLower().Equals("-payload"))
                {
                    if (i + 1 < args.Length)
                    {
                        //Needed to filter filename input from powershell
                        payloadPath = Path.GetFileName(args[i + 1]);
                    }
                }
            }

            if (string.IsNullOrWhiteSpace(orgDllPath) || !File.Exists(orgDllPath))
            {
                Console.WriteLine($"[!] Cannot locate DLL path, does it exists?");
                Environment.Exit(0);
            }

            if (string.IsNullOrWhiteSpace(payloadPath))
            {
                Console.WriteLine($"[!] shellcode filname/path is empty, bad input!");
                Environment.Exit(0);
            }


            //Create an output directory to export stuff too
            string outPath = Directory.CreateDirectory("output_" + Path.GetFileNameWithoutExtension(orgDllPath)).FullName;

            Console.WriteLine($"[+] Reading exports from {orgDllPath}...");

            //Read PeHeaders -> Exported Functions from provided DLL
            PeNet.PeFile dllPeHeaders = new PeNet.PeFile(orgDllPath);

            //Build up our linker redirects
            foreach (var exportedFunc in dllPeHeaders.ExportedFunctions)
            {
                pragmaBuilder += $"#pragma comment(linker, \"/export:{exportedFunc.Name}={tempName}.{exportedFunc.Name},@{exportedFunc.Ordinal}\")\n";
            }
            Console.WriteLine($"[+] Redirected {dllPeHeaders.ExportedFunctions.Count()} function calls from { Path.GetFileName(orgDllPath)} to {tempName}.dll");

            //Replace data in our template
            dllTemplate = dllTemplate.Replace("PRAGMA_COMMENTS", pragmaBuilder);
            dllTemplate = dllTemplate.Replace("PAYLOAD_PATH", payloadPath);

            Console.WriteLine($"[+] Exporting DLL C source to {outPath + @"\" + Path.GetFileNameWithoutExtension(orgDllPath)}_pragma.c");

            File.WriteAllText($@"{outPath + @"\" + Path.GetFileNameWithoutExtension(orgDllPath)}_pragma.c", dllTemplate);
            File.WriteAllBytes(outPath + @"\" + tempName + ".dll", File.ReadAllBytes(orgDllPath));
        }
Пример #17
0
        public void IsDriver_GivenAPeFile_ReturnsDriverOrNot(string file, bool isDriver)
        {
            var peFile = new PeNet.PeFile(file);

            Assert.Equal(isDriver, peFile.IsDriver);
        }
Пример #18
0
        public static System.Diagnostics.Process?StartLocalTrace(int bitWidth, ProcessLaunchSettings settings, PeNet.PeFile? targetPE = null, long testID = -1)
        {
            if (!File.Exists(GlobalConfig.GetSettingPath(CONSTANTS.PathKey.PinPath)))
            {
                GlobalConfig.InstallNewPin();
                if (!File.Exists(GlobalConfig.GetSettingPath(CONSTANTS.PathKey.PinPath)))
                {
                    Logging.RecordError($"Pin.exe path is not correctly configured (Settings->Files->Pin Executable)");
                    return(null);
                }
            }


            string pintool = bitWidth is 32 ? GlobalConfig.GetSettingPath(CONSTANTS.PathKey.PinToolPath32) :
                             GlobalConfig.GetSettingPath(CONSTANTS.PathKey.PinToolPath64);

            if (File.Exists(pintool) is false)
            {
                Logging.RecordError("Valid pintool not found - installing");
                GlobalConfig.InstallNewTools();
                pintool = bitWidth is 32 ? GlobalConfig.GetSettingPath(CONSTANTS.PathKey.PinToolPath32) :
                          GlobalConfig.GetSettingPath(CONSTANTS.PathKey.PinToolPath64);
            }

            if (!File.Exists(pintool))
            {
                if (pintool is null)
                {
                    Logging.RecordError($"Pintool path was not set");
                }
                else
                {
                    Logging.RecordError($"Pintool {pintool} path was not found");
                }
                return(null);
            }

            if (!File.Exists(settings.BinaryPath))
            {
                Logging.RecordError($"Target binary not available: {settings.BinaryPath}");
                return(null);
            }

            try
            {
                if (targetPE is null)
                {
                    targetPE = new PeNet.PeFile(settings.BinaryPath);
                    if (targetPE is null)
                    {
                        Logging.RecordError($"Unable to parse PE file: {settings.BinaryPath}");
                        return(null);
                    }
                }
            }
            catch (Exception e)
            {
                Logging.RecordException($"Unable to parse PE file: {settings.BinaryPath} - {e.Message}", e);
                return(null);
            }


            if (targetPE.IsDll)
            {
                return(StartLocalDLLTrace(pintool, settings, testID));
            }
            else if (targetPE.IsExe) //'isexe' is true even for DLLs, so isdll has to be first
            {
                return(StartLocalEXETrace(pintool, settings, testID: testID));
            }

            Logging.RecordError("Unable to trace non-EXE/DLL file");
            return(null);
        }
Пример #19
0
        public PhpDiagDialog(IServiceProvider provider, ServerManager server)
            : base(provider)
        {
            InitializeComponent();

            var knownPhpVersions = new Dictionary <string, PhpVersion>
            {
                { "5.6", new PhpVersion("5.6", new DateTime(2018, 12, 31), new Version(11, 0)) },
                { "7.0", new PhpVersion("7.0", new DateTime(2018, 12, 3), new Version(14, 0)) },
                { "7.1", new PhpVersion("7.1", new DateTime(2019, 12, 1), new Version(14, 0)) },
                { "7.2", new PhpVersion("7.2", new DateTime(2020, 11, 30), new Version(14, 11)) }
            };

            var container = new CompositeDisposable();

            FormClosed += (sender, args) => container.Dispose();

            container.Add(
                Observable.FromEventPattern <EventArgs>(btnGenerate, "Click")
                .ObserveOn(System.Threading.SynchronizationContext.Current)
                .Subscribe(evt =>
            {
                txtResult.Clear();
                try
                {
                    Warn("IMPORTANT: This report might contain confidential information. Mask such before sharing to others.");
                    Warn("-----");
                    Debug($"System Time: {DateTime.Now}");
                    Debug($"Processor Architecture: {Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")}");
                    Debug($"OS: {Environment.OSVersion}");
                    Debug($"Server Type: {server.Mode.AsString(EnumFormat.Description)}");
                    Debug(string.Empty);

                    var modules = new ModulesFeature((Module)provider);
                    modules.Load();
                    Debug($"Scan {modules.Items.Count} installed module(s).");
                    if (modules.Items.All(item => item.Name != "FastCgiModule"))
                    {
                        Error($"FastCGI module is not installed as part of IIS. Please refer to https://docs.microsoft.com/en-us/iis/application-frameworks/scenario-build-a-php-website-on-iis/configuring-step-1-install-iis-and-php#13-download-and-install-php-manually for more details.");
                        return;
                    }
                    else
                    {
                        Debug("FastCGI module is installed.");
                    }

                    Debug(string.Empty);
                    var handlers = new HandlersFeature((Module)provider);
                    handlers.Load();
                    var foundPhpHandler = new List <HandlersItem>();
                    Debug($"Scan {handlers.Items.Count} registered handler(s).");
                    foreach (var item in handlers.Items)
                    {
                        if (item.Modules == "FastCgiModule")
                        {
                            Debug($"* Found FastCGI handler as {{ Name: {item.Name}, Path: {item.Path}, State: {item.GetState(handlers.AccessPolicy)}, Handler: {item.TypeString}, Entry Type: {item.Flag} }}.");
                            foundPhpHandler.Add(item);
                        }
                    }

                    if (foundPhpHandler.Count == 0)
                    {
                        Error($"No FastCGI handler is registered for this web site.");
                        Error($" * To run PHP on IIS, please refer to https://docs.microsoft.com/en-us/iis/application-frameworks/scenario-build-a-php-website-on-iis/configuring-step-1-install-iis-and-php#13-download-and-install-php-manually for more details.");
                        Error($" * To run Python on IIS, please refer to https://pypi.org/project/wfastcgi/ or use HttpPlatformHandler https://docs.microsoft.com/en-us/iis/extensions/httpplatformhandler/httpplatformhandler-configuration-reference.");
                        return;
                    }

                    Debug(string.Empty);
                    var fastCgiFeature = new FastCgiFeature((Module)provider);
                    fastCgiFeature.Load();
                    Debug($"Scan {fastCgiFeature.Items.Count} registered FastCGI application(s).");
                    var foundPhp = new List <FastCgiItem>();
                    foreach (var item in fastCgiFeature.Items)
                    {
                        var combination = string.IsNullOrWhiteSpace(item.Arguments) ? item.Path : item.Path + '|' + item.Arguments;
                        foreach (var handler in foundPhpHandler)
                        {
                            if (string.Equals(combination, handler.ScriptProcessor, StringComparison.OrdinalIgnoreCase))
                            {
                                Debug($"* Found FastCGI application registered as {{ Full path: {item.Path}, Arguments: {item.Arguments} }}.");
                                foundPhp.Add(item);
                                break;
                            }
                        }
                    }

                    if (foundPhp.Count == 0)
                    {
                        Error($"No suitable FastCGI appilcation is registered on this server.");
                        Error($" * To run PHP on IIS, please refer to https://docs.microsoft.com/en-us/iis/application-frameworks/scenario-build-a-php-website-on-iis/configuring-step-1-install-iis-and-php#13-download-and-install-php-manually for more details.");
                        Error($" * To run Python on IIS, please refer to https://pypi.org/project/wfastcgi/ or use HttpPlatformHandler https://docs.microsoft.com/en-us/iis/extensions/httpplatformhandler/httpplatformhandler-configuration-reference.");
                        return;
                    }

                    Debug(Environment.NewLine);
                    Debug($"Verify web stack installation versions.");
                    foreach (var item in foundPhp)
                    {
                        var path = item.Path;
                        if (path.TrimEnd('"').EndsWith("php-cgi.exe", StringComparison.OrdinalIgnoreCase))
                        {
                            // PHP
                            var info    = FileVersionInfo.GetVersionInfo(path);
                            var version = $"{info.FileMajorPart}.{info.FileMinorPart}";
                            if (knownPhpVersions.ContainsKey(version))
                            {
                                var matched = knownPhpVersions[version];
                                if (matched.ExpiringDate <= DateTime.Now)
                                {
                                    Error($"* PHP {info.FileVersion} ({path}) is unknown or obsolete. Please refer to http://php.net/supported-versions.php for more details.");
                                }
                                else if (matched.ExpiringDate > DateTime.Now && (matched.ExpiringDate - DateTime.Now).TotalDays < 180)
                                {
                                    Warn($"* PHP {version} ({path}) will soon be obsolete. Please refer to http://php.net/supported-versions.php for more details.");
                                }
                                else
                                {
                                    Debug($"* PHP {version} ({path}) is supported.");
                                }

                                var x86     = new PeNet.PeFile(path).Is32Bit;
                                var cppFile = Path.Combine(
                                    Environment.GetFolderPath(x86 ? Environment.SpecialFolder.SystemX86 : Environment.SpecialFolder.System),
                                    $"msvcp{matched.CppVersion.Major}0.dll");
                                if (File.Exists(cppFile))
                                {
                                    var cpp = FileVersionInfo.GetVersionInfo(cppFile);
                                    if (cpp.FileMinorPart >= matched.CppVersion.Minor)
                                    {
                                        Debug($"  Visual C++ runtime is detected (expected: {matched.CppVersion}, detected: {cpp.FileVersion}).");
                                    }
                                    else
                                    {
                                        Error($"  Visual C++ runtime {matched.CppVersion} is not detected. Please install it following the tips on https://windows.php.net/download/.");
                                    }
                                }
                                else
                                {
                                    Error($"  Visual C++ {matched.CppVersion} runtime is not detected. Please install it following the tips on https://windows.php.net/download/.");
                                }
                            }
                            else
                            {
                                Error($"* PHP {info.FileVersion} ({path}) is unknown or obsolete. Please refer to http://php.net/supported-versions.php for more details.");
                            }
                        }
                        else if (path.TrimEnd('"').EndsWith("python.exe", StringComparison.OrdinalIgnoreCase))
                        {
                            // Python
                        }
                    }

                    Debug(string.Empty);
                    var systemPath = Environment.GetEnvironmentVariable("Path");
                    Debug($"Windows Path environment variable: {systemPath}.");
                    Debug(string.Empty);
                    string[] paths = systemPath.Split(new char[1] {
                        Path.PathSeparator
                    });
                    foreach (var item in foundPhp)
                    {
                        var path = item.Path;
                        if (path.TrimEnd('"').EndsWith("php-cgi.exe", StringComparison.OrdinalIgnoreCase))
                        {
                            var rootFolder = Path.GetDirectoryName(path);
                            Debug($"[{rootFolder}]");
                            if (!Directory.Exists(rootFolder))
                            {
                                Error("Invalid root folder is found. Skip.");
                                continue;
                            }

                            var config = Path.Combine(rootFolder, "php.ini");
                            if (File.Exists(config))
                            {
                                Info($"Found PHP config file {config}.");
                                var parser = new ConcatenateDuplicatedKeysIniDataParser();
                                parser.Configuration.ConcatenateSeparator = " ";
                                var data            = parser.Parse(File.ReadAllText(config));
                                var extensionFolder = data["PHP"]["extension_dir"];
                                if (extensionFolder == null)
                                {
                                    extensionFolder = "ext";
                                }

                                var fullPath = Path.Combine(rootFolder, extensionFolder);
                                Info($"PHP loadable extension folder: {fullPath}");
                                var extesionNames = data["PHP"]["extension"];
                                if (extesionNames == null)
                                {
                                    Info("No extension to verify.");
                                }
                                else
                                {
                                    var extensions = extesionNames.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                                    Info($"Found {extensions.Length} extension(s) to verify.");
                                    var noError = true;
                                    foreach (var name in extensions)
                                    {
                                        var fileName = Path.Combine(fullPath, $"php_{name}.dll");
                                        if (!File.Exists(fileName))
                                        {
                                            Error($"* Extension {name} is listed, but on disk the file cannot be found {fileName}");
                                            noError = false;
                                        }
                                    }

                                    if (noError)
                                    {
                                        Info("All extension(s) listed can be found on disk.");
                                    }
                                }
                            }
                            else
                            {
                                Warn($"Cannot find PHP config file {config}. Default settings are used.");
                            }

                            var matched = false;
                            foreach (var system in paths)
                            {
                                if (string.Equals(rootFolder, system, StringComparison.OrdinalIgnoreCase))
                                {
                                    matched = true;
                                    break;
                                }
                            }

                            if (matched)
                            {
                                Debug($"PHP installation has been added to Windows Path environment variable.");
                            }
                            else
                            {
                                Error($"PHP installation is not yet added to Windows Path environment variable. Please refer to https://docs.microsoft.com/en-us/iis/application-frameworks/scenario-build-a-php-website-on-iis/configuring-step-1-install-iis-and-php#13-download-and-install-php-manually for more details.");
                                Warn($"Restart Jexus Manager and rerun PHP Diagnostics after changing Windows Path environment variable.");
                            }

                            Debug(string.Empty);

                            // TODO: verify other configuration in php.info.
                        }
                        else if (path.TrimEnd('"').EndsWith("python.exe", StringComparison.OrdinalIgnoreCase))
                        {
                        }
                    }
                }
                catch (Exception ex)
                {
                    Debug(ex.ToString());
                    Rollbar.RollbarLocator.RollbarInstance.Error(ex);
                }
            }));

            container.Add(
                Observable.FromEventPattern <EventArgs>(btnSave, "Click")
                .ObserveOn(System.Threading.SynchronizationContext.Current)
                .Subscribe(evt =>
            {
                var fileName = DialogHelper.ShowSaveFileDialog(null, "Text Files|*.txt|All Files|*.*");
                if (string.IsNullOrEmpty(fileName))
                {
                    return;
                }

                File.WriteAllText(fileName, txtResult.Text);
            }));

            container.Add(
                Observable.FromEventPattern <EventArgs>(btnVerify, "Click")
                .ObserveOn(System.Threading.SynchronizationContext.Current)
                .Subscribe(evt =>
            {
                txtResult.Clear();
            }));
        }
Пример #20
0
        public static MonoLibraryOffsets GetOffsets(string gameExecutableFilePath, bool force = true)
        {
            if (gameExecutableFilePath == null)
            {
                throw new ArgumentNullException("gameExecutableFilePath parameter cannot be null");
            }

            string unityVersion;

            if (gameExecutableFilePath.EndsWith(".exe"))
            {
                var peHeader = new PeNet.PeFile(gameExecutableFilePath);
                unityVersion = peHeader.Resources.VsVersionInfo.StringFileInfo.StringTable[0].FileVersion;

                // Taken from here https://stackoverflow.com/questions/1001404/check-if-unmanaged-dll-is-32-bit-or-64-bit;
                // See http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
                // Offset to PE header is always at 0x3C.
                // The PE header starts with "PE\0\0" =  0x50 0x45 0x00 0x00,
                // followed by a 2-byte machine type field (see the document above for the enum).
                FileStream   fs = new FileStream(gameExecutableFilePath, FileMode.Open, FileAccess.Read);
                BinaryReader br = new BinaryReader(fs);
                fs.Seek(0x3c, SeekOrigin.Begin);
                int peOffset = br.ReadInt32();
                fs.Seek(peOffset, SeekOrigin.Begin);
                uint peHead = br.ReadUInt32();

                // "PE\0\0", little-endian
                if (peHead != 0x00004550)
                {
                    throw new Exception("Can't find PE header");
                }

                int machineType = br.ReadUInt16();
                br.Close();
                fs.Close();

                Console.WriteLine($"Game executable file closed, unity version = {unityVersion}.");

                switch (machineType)
                {
                case 0x8664:     // IMAGE_FILE_MACHINE_AMD64
                    return(GetOffsets(unityVersion, true, BinaryFormat.PE, force));

                case 0x14c:     // IMAGE_FILE_MACHINE_I386
                    return(GetOffsets(unityVersion, false, BinaryFormat.PE, force));
                }
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                FileInfo gameExecutableFile       = new FileInfo(gameExecutableFilePath);
                string   infoPlist                = File.ReadAllText(gameExecutableFile.Directory.Parent.FullName + "/Info.plist");
                string   unityVersionField        = "Unity Player version ";
                int      indexOfUnityVersionField = infoPlist.IndexOf(unityVersionField);
                unityVersion = infoPlist.Substring(indexOfUnityVersionField + unityVersionField.Length).Split(' ')[0];

                // Start the child process.
                Process p = new Process();

                // Redirect the output stream of the child process.
                p.StartInfo.UseShellExecute        = false;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.FileName  = "file";
                p.StartInfo.Arguments = gameExecutableFile.FullName;
                p.Start();

                // Do not wait for the child process to exit before
                // reading to the end of its redirected stream.
                // p.WaitForExit();
                // Read the output stream first and then wait.
                string output = p.StandardOutput.ReadToEnd();
                p.WaitForExit();
                return(GetOffsets(unityVersion, output.EndsWith("x86_64\n"), BinaryFormat.MachO, force));
            }

            throw new NotSupportedException("Platform not supported");
        }