public static void RunAssistant() { #if !MONO && !NET35 var file = @".\hr"; var showDialog = !Environment.GetCommandLineArgs().Any(x => x == "-l") && !File.Exists(file); File.Create(file).Close(); if (showDialog) { if (MessageBox.Show(@"It seems this is the first time PHP " + "Vulnerability Hunter has been run on this system. " + "Would you like to use the launcher instead of the command line " + "interface?", "Run Launcher", MessageBoxButtons.YesNo) == DialogResult.Yes) { var guiFile = "phpvh-gui.exe"; if (!File.Exists(guiFile)) { ScannerCli.DisplayError(string.Format("Could not find launcher {0}", guiFile)); Environment.Exit(6); } Process.Start(guiFile); Environment.Exit(0); } } #endif }
static void RunSelfTest() { ServiceLocator.Default.Register(Config); var selfTestExe = PathHelper.GetExecutingPath("PhpVH.SelfTest.exe"); if (!File.Exists(selfTestExe)) { ScannerCli.DisplayCriticalMessageAndExit("Could not find self test EXE {0}.", selfTestExe); } AppDomain.CurrentDomain.ExecuteAssembly(selfTestExe); //ServiceLocator.Default.Resolve<List<TestResult>> }
static void Main(string[] args) { #if !DEBUG try { Main2(args); } catch (System.Exception ex) { ScannerCli.DisplayError(string.Format("\r\nFatal error: {0}\r\n\r\n{1}", ex.Message, ex)); } #else Main2(args); #endif }
public void CreateHandlerFile() { var hookFileText = new StringBuilder("<?php "); foreach (Hook h in this) { hookFileText.AppendLine(h.ReplacementFunction); } if (!Program.Config.HookSuperglobals) { hookFileText.AppendLine(PhpResource.Load("PhpApiOverrides")); hookFileText.AppendLine(PhpResource.Load("SuperGlobalOverride")); } if (Program.Config.DynamicScan) { hookFileText.AppendLine(PhpResource.Load("DynamicProbes")); } if (!Program.Config.CodeCoverageNone) { hookFileText.AppendLine(PhpResource.Load("Annotation")); } hookFileText.Append(" ?>"); var hookFile = Program.Config.WebRoot + "\\" + Hook.HookFileName; try { File.WriteAllText(hookFile, hookFileText.ToString()); } catch (UnauthorizedAccessException) { ScannerCli.DisplayError(string.Format("\r\nError writing hook file to {0}", hookFile)); Environment.Exit(3); } }
private bool CreateBackup(FileInfo file) { var backup = new FileInfo(file.FullName + ".phpvhbackup"); try { if (backup.Exists) { backup.CopyTo(file.FullName, true); } else { file.CopyTo(file.FullName + ".phpvhbackup", true); } } catch (UnauthorizedAccessException ex) { ScannerCli.DisplayError(string.Format("\r\n\r\nError hooking file\r\n{0}\r\n", ex.Message)); return(false); } return(true); }
static void Main2(string[] args) { Cli.UseTrace = true; Trace.AutoFlush = true; Trace.Listeners.Add(new ConsoleTraceListener()); if (!args.Any(x => x == "-l")) { ScannerCli.RunAssistant(); } ScannerCli.DisplayAppInfo(); if (args.Length == 0) { ScannerCli.DisplayInstructions(); Exit(); } Config = ScanConfig.Parse(args); if (Config.TestMode) { RunSelfTest(); return; } var versionTester = new PhpVersionTester(Config); versionTester.CheckVersion(); Cli.WriteLine(); ExeProbe.Copy(); TraceFileName = Config.WebRoot + @"\trace.txt"; foreach (string RelativeAppPath in Config.ApplicationPaths) { string filePath = Config.WebRoot + "\\" + RelativeAppPath.Replace('/', '\\'); if (!Directory.Exists(filePath)) { ScannerCli.DisplayCriticalMessage("Application path {0} not found.", filePath); Exit(); } if (Config.Repair || new DirectoryInfo(filePath) .GetFiles("*.phpvhbackup", SearchOption.AllDirectories) .Any(x => x.Extension.ToLower() == ".phpvhbackup")) { ScannerCli.DisplayPhaseName("Repair"); Cli.WriteLine(); new HookCollection().Unset(new DirectoryInfo(filePath)); if (Config.Repair) { continue; } } _reportWriter = new ReportWriter(RelativeAppPath); Trace.Listeners.Clear(); if (Config.LogConsole) { Trace.Listeners.Add(new TextWriterTraceListener(_reportWriter.ReportPath + "\\scan.log")); } Trace.Listeners.Add(new ConsoleTraceListener()); foreach (var plugin in Config.ScanPlugins) { plugin.Initialize(); } Program.PageFieldTable.Clear(); Cli.WriteLine(); ScannerCli.DisplayAppPath(RelativeAppPath); ////////////////////////////////////////////////////////////////////////// // Static analysis ScannerCli.DisplayPhaseName("Static Analysis"); var sae = new StaticAnalysis.StaticAnalysisEngine(Config); sae.FileScanned += (o, e) => { Cli.WriteLine( "{0} [~{1}~{2}~R~]", e.Item.Filename, e.Item.Alerts.Any() ? ConsoleColor.Red : ConsoleColor.DarkGreen, e.Item.Alerts.Length); e.Item.Alerts.Iter(x => Cli.WriteLine("~Red~Potential Vulnerability: {0}~R~", x.Name)); }; var staticAnalysisAlerts = sae.ScanDirectory(filePath); if (staticAnalysisAlerts.Any()) { _reportWriter.Write("Static analysis", staticAnalysisAlerts.ToXml(), "xml"); } Cli.WriteLine(); Cli.WriteLine(); // End Static analysis ////////////////////////////////////////////////////////////////////////// if (!Config.StaticOnly) { ScanMetrics.Default = new ScanMetrics(); ScanMetrics.Default.Annotator.AnnotationFile = new FileInfo(Config.WebRoot + "\\Annotation.txt"); #region Hooks var hooks2 = new HookCollection(Hook.GetDefaults()); var sqlPlugin = new SqlScanPlugin(null); sqlPlugin.Initialize(); hooks2.AddRange(sqlPlugin.Config.Functions.ToHooks()); #endregion if (Config.HookSuperglobals) { hooks2.AddRange(Hook.GetSuperglobals()); } if (_scan) { ScannerCli.DisplayPhaseName("Form scrape"); var urlDictionary = CreateUrlDictionary(RelativeAppPath, new DirectoryInfo(filePath)); foreach (var page in urlDictionary.Select(x => new { Relative = x.Key, Url = "http://" + Config.Server + x.Key, })) { var data = WebClientHelper.DownloadData(page.Url); var respStr = ASCIIEncoding.ASCII.GetString(data.Data); var forms = FormScraper.GetForms(respStr, page.Url); if (forms.Any()) { foreach (var f in forms) { var action = new Uri(f.Action); if (!action.Host.Contains(Config.Server) || !urlDictionary.ContainsKey(action.LocalPath)) { continue; } var file = urlDictionary[action.LocalPath]; if (!PageFieldTable.ContainsKey(file)) { PageFieldTable.Add(file, new Dictionary <string, List <string> >()); } var superglobal = "$_" + f.Method.ToUpper(); if (!PageFieldTable[file].ContainsKey(superglobal)) { PageFieldTable[file].Add(superglobal, new List <string>()); } var newInputs = f.Inputs .Select(x => x.Name ?? x.Type) .Where(x => x != null && !PageFieldTable[file][superglobal].Contains(x)); PageFieldTable[file][superglobal].AddRange(newInputs); } } ScannerCli.DisplayScrapedUrl(page.Relative, forms); } Trace.WriteLine(""); if (_hook) { ScannerCli.DisplayPhaseName("Dynamic Analysis Initialization"); Cli.WriteLine(); hooks2.Set(new DirectoryInfo(filePath)); hooks2.CreateHandlerFile(); Cli.WriteLine(); Cli.WriteLine(); Program.Config.ScanPlugins .Iter(x => { var annotationTableClone = ScanMetrics.Default.Annotator.AnnotationTable.Clone() as AnnotationTable; annotationTableClone.Plugin = x.ToString(); ScanMetrics.Default.PluginAnnotations.Add(annotationTableClone); }); } ScannerCli.DisplayPhaseName("Dynamic Analysis"); ScanDirectory(new DirectoryInfo(filePath), RelativeAppPath); Console.WriteLine(); } ScannerCli.DisplayPhaseName("Dynamic Analysis Uninitialization"); Cli.WriteLine(); hooks2.DeleteHandlerFile(); File.Delete(TraceFileName); foreach (var plugin in Config.ScanPlugins) { plugin.Uninitialize(); } if (Config.Unhook) { hooks2.Unset(new DirectoryInfo(filePath)); Cli.WriteLine(); Cli.WriteLine(); } } var reportFiles = _reportWriter.WriteFilenames(); #if !MONO && !NET35 if (_reportWriter.ReportFiles.Any() && Config.RunViewer) { var viewerPath = Assembly.GetExecutingAssembly().Location.RemoveAtLastIndexOf('\\', 1) + @"PHPVHReportViewer.exe"; if (File.Exists(viewerPath)) { System.Diagnostics.Process.Start(viewerPath, "\"" + reportFiles + "\""); } else { System.Windows.Forms.MessageBox.Show("Could not locate report viewer executable.", "Error launching report viewer", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); } } #endif } Trace.Listeners.Clear(); Trace.Listeners.Add(new ConsoleTraceListener()); }
static void ScanDirectory(DirectoryInfo AppDirectory, string RelativeAppPath) { var ignoreExtensions = new[] { "png", "jpg", "jpeg", "gif", "ico", "js", "css", }; var urlDictionary = CreateUrlDictionary(RelativeAppPath, AppDirectory); var urlCollections = new[] { urlDictionary.Select(x => x.Key).ToList(), new List <string>() }; var traceTable = new TraceTable(); var report = new StringBuilder(); var coverageReport = new StringBuilder(); var map = new ApplicationMap(); var alerts = new ScanAlertCollection(); int requestCount = 0; MessageDumper messageDumper = null; if (Config.DumpMessages) { messageDumper = new MessageDumper(_reportWriter.ReportPath.FullName); } for (int urlCollectionIndex = 0; urlCollectionIndex < 2; urlCollectionIndex++) { foreach (ScanPluginBase plugin in Config.ScanPlugins) { if (Config.CodeCoverageReport > 0) { ScanMetrics.Default.Annotator.Reset(); ScanMetrics.Default.Annotator.AnnotationTable = ScanMetrics.Default.PluginAnnotations[plugin.ToString()]; } if (!urlCollections[urlCollectionIndex].Any()) { continue; } ScannerCli.DisplayScanPlugin(plugin); foreach (var remotePath in urlCollections[urlCollectionIndex]) { ScannerCli.DisplayResourcePath(remotePath); IEnumerable <IEnumerable <TracedFunctionCall> > calls = null; if (urlCollectionIndex == 0) { var key = urlDictionary[remotePath]; if (Program.PageFieldTable.ContainsKey(key)) { calls = Program.PageFieldTable[key] .Select(x => x.Value.Select(y => new TracedFunctionCall() { Name = x.Key, ParameterValues = new List <string>() { y } })); } } for (int i = 0; i < plugin.ModeCount; i++) { foreach (var useStaticAnalysisInputs in new[] { false, true }) { var trace = new FileTrace(); if (useStaticAnalysisInputs && calls != null) { if (!calls.Any(x => x.Any())) { continue; } foreach (var c in calls) { trace.Calls.AddRange(c); } } bool discoveredVars = true; while (discoveredVars) { var traceFile = new FileInfo(TraceFileName); IOHelper.TryAction(traceFile.Delete); var client = new TcpClient() { ReceiveTimeout = Config.Timeout, SendTimeout = Config.Timeout }; while (!client.Connected) { try { client.Connect(Config.Server, Config.Port); } catch (SocketException ex) { ScannerCli.DisplayError(ex.Message); Thread.Sleep(5000); } } client.LingerState = new LingerOption(true, 0); HttpResponse resp = null; string req, respString = ""; using (var stream = client.GetStream()) { req = plugin.BuildRequest(i, remotePath, trace); if (Config.DumpMessages) { messageDumper.Dump(req, requestCount, MessageType.Request); } var stopwatch = new Stopwatch(); stopwatch.Start(); stream.WriteString(req); try { var sgs = trace.Calls .Superglobals() .Select(x => new { x.Name, Value = x.ParameterValues.Count > 0 ? x.ParameterValues[0] : null }) .Distinct(); var discoveredVarCount = sgs.Count(); var reader = new HttpResponseReader(stream); resp = reader.Read(); stopwatch.Stop(); respString = resp.CompleteResponse; ScannerCli.DisplayResponse( resp, i, discoveredVarCount, stopwatch.ElapsedMilliseconds, resp.CompleteResponse.Length); } catch (SocketException) { ScannerCli.DisplayResponseError(respString); } catch (IOException) { ScannerCli.DisplayResponseError(respString); } } if (urlCollectionIndex == 0 && resp != null) { var abs = "http://" + Config.Server + remotePath; var urls = new UriScraper() { Regex = new Regex(@"[/.]" + Config.Server + @"($|/)", RegexOptions.IgnoreCase | RegexOptions.Compiled), } .Parse(resp.Body, abs) .Select(x => new Uri(x).LocalPath); foreach (var url in urls) { if (!ignoreExtensions.Any(x => url.ToLower().EndsWith("." + x)) && !urlCollections[0].Contains(url) && !urlCollections[1].Contains(url)) { urlCollections[1].Add(url); ScannerCli.DisplayDiscoveredUrl(url); } } } client.Close(); if (Config.DumpMessages) { messageDumper.Dump(respString, requestCount, MessageType.Response); } requestCount++; traceFile = new FileInfo(TraceFileName); FileTrace newTrace = null; IOHelper.TryAction(() => { if (traceFile.Exists) { using (var reader = traceFile.OpenText()) newTrace = FileTrace.Parse(reader); } }); if (newTrace == null) { newTrace = new FileTrace(); } newTrace.Request = req; newTrace.Response = respString; newTrace.File = remotePath; var alert = plugin.ScanTrace(newTrace); if (alert != null) { if (Config.BeepOnAlert) { Console.Beep(); } ScannerCli.DisplayAlert(alert); alerts.Add(alert); report.Append(alert.ToString()); } discoveredVars = false; foreach (TracedFunctionCall c in newTrace.Calls .Superglobals() .Where(x => x.ParameterValues.Any())) { var oldCalls = trace.Calls.Where(x => x.Name == c.Name && x.ParameterValues.SequenceEqual(c.ParameterValues)); if (!oldCalls.Any()) { discoveredVars = true; break; } } var orphanedInputs = trace.Calls .Superglobals() .Where(x => !newTrace.Calls .Any(y => x.Name == y.Name && x.ParameterValues .SequenceEqual(y.ParameterValues))) .ToArray(); newTrace.Calls.AddRange(orphanedInputs); trace = newTrace; } var superglobals = trace.Calls.Superglobals(); map.AddTrace(trace); if (Config.DiscoveryReport) { if (!traceTable.ContainsKey(plugin)) { traceTable.Add(plugin, new Dictionary <int, Dictionary <string, FileTrace> >()); } if (!traceTable[plugin].ContainsKey(i)) { traceTable[plugin].Add(i, new Dictionary <string, FileTrace>()); } if (!traceTable[plugin][i].ContainsKey(trace.File)) { traceTable[plugin][i].Add(trace.File, trace); } else { traceTable[plugin][i][trace.File] = trace; } } } } } if (Config.CodeCoverageReport > 0 && urlCollectionIndex == 0) { Cli.WriteLine("Calculating code coverage..."); CodeCoverageTable coverage = null; IOHelper.TryAction(() => { var calculator = new CodeCoverageCalculator( ScanMetrics.Default.Annotator.AnnotationFile, ScanMetrics.Default.PluginAnnotations[plugin.ToString()]); coverage = calculator.CalculateCoverage(); }); coverage.Plugin = plugin.ToString(); coverageReport.AppendLine(coverage.ToString() + "\r\n"); } Cli.WriteLine(); } } _reportWriter.Write("Vulnerability Report", report.ToString()); _reportWriter.Write("Input Map Report", map.ToXml(), "xml"); if (alerts.Any()) { _reportWriter.Write("Vulnerability Report", alerts.ToXml(), "pxml"); } if (Config.DiscoveryReport) { _reportWriter.Write("Scan Overview Report", DiscoveryReport.Create(traceTable)); } if (Config.CodeCoverageReport > 0) { _reportWriter.Write("Code Coverage Report", coverageReport.ToString()); var annotationXml = ScanMetrics.Default.PluginAnnotations.ToXml(); var annotationFile = _reportWriter.Write( "Annotation", annotationXml, "axml"); Cli.WriteLine(); var commenter = new CoverageCommenter(ScanMetrics.Default.PluginAnnotations); commenter.LoadTable(annotationFile); commenter.WriteCommentedFiles(_reportWriter.ReportPath.FullName); _reportWriter.ReportFiles.Add( new ReportFile( "Coverage Comments", Path.Combine("Code Coverage", "index.html"))); } }
public void CheckVersion() { try { WriteProbe(); var resp = RequestProbe(); var isVersion = false; if (resp != null) { isVersion = Regex.IsMatch(resp, @"^[0-9.]+$"); } if (isVersion) { Cli.WriteLine("PHP version ~Cyan~{0}~R~ detected", resp); if (_knownVersions.Contains(resp)) { Cli.WriteLine("~Green~Known PHP version~R~"); } else { Cli.WriteLine("~Yellow~Unknown PHP version; PhpVH may not work properly on untested versions~R~"); } } else if (resp == null) { if (ThrowOnFail) { throw new InvalidOperationException("No response from server"); } else { ScannerCli.DisplayCriticalMessageAndExit("~Red~No response from server; exiting~R~"); } } else { var maxRespLen = 60; if (resp.Length > maxRespLen) { resp = resp.Remove(maxRespLen); } if (ThrowOnFail) { throw new InvalidOperationException(string.Format("PHP version check failed~R~\r\nProbe response: {0}", resp)); } ScannerCli.DisplayCriticalMessageAndExit( "~Red~PHP version check failed~R~\r\nProbe response: {0}\r\nThis error generally occurs when the webroot is not properly configured.", maxRespLen); } } finally { DeleteProbe(); } }
public static ScanConfig Create(string[] args) { var config = new ScanConfig(); int argIndex = 0; for (int i = 0; i < args.Length; i++) { if (args[i] == "-s") { config.Server = args[i + 1]; i++; foreach (var a in config.ScanPlugins) { a.Server = config.Server; } } else if (args[i] == "-static") { config.StaticOnly = true; } else if (args[i] == "-t") { int timeout = 0; if (args.Length == i + 1 || !int.TryParse(args[i + 1], out timeout)) { ScannerCli.DisplayCriticalMessageAndExit("Error parsing timeout"); } i++; config.Timeout = timeout; } else if (args[i] == "-p") { int port; if (!int.TryParse(args[i + 1], out port)) { ScannerCli.DisplayCriticalMessageAndExit("Error parsing port"); } i++; config.Port = port; } else if (args[i] == "-l") { config.LauncherUsed = true; } else if (args[i] == "-n") { config.Unhook = false; } else if (args[i] == "-v") { config.RunViewer = true; } else if (args[i] == "-d") { config.DiscoveryReport = true; } else if (args[i] == "-c") { config.CodeCoverageReport = 1; } else if (args[i] == "-c2") { config.CodeCoverageReport = 2; } else if (args[i] == "-dump") { config.DumpMessages = true; } else if (args[i] == "-b") { config.BeepOnAlert = true; } else if (args[i] == "-log") { config.LogConsole = true; } else if (args[i] == "-test") { config.TestMode = true; } else if (args[i] == "-r") { config.Repair = true; } //else if (args[i] == "-h") // config.HookSuperglobals = true; else if (args[i] == "-l") { // Nothing } else if (args[i] == "-m") { var modes = args[i + 1]; i++; foreach (var c in modes) { ScanPluginBase scan = null; switch (c.ToString().ToLower()[0]) { case 'c': scan = new CommandScanPlugin(config.Server); break; case 'l': try { scan = new LocalFileInclusionScanPlugin(config.Server); } catch (UnauthorizedAccessException) { ScannerCli.DisplayCriticalMessageAndExit("Error writing LFI test file. Ensure that " + "PHP Vulnerability Hunter has administrative privileges."); } break; case 'f': scan = new FileScanPlugin(config.Server); break; case 'p': scan = new ArbitraryPhpScanPlugin(config.Server); break; case 's': scan = new SqlScanPlugin(config.Server); break; case 'd': scan = new DynamicScanPlugin(config.Server); break; case 'x': scan = new XssScanPlugin(config.Server); break; case 'i': scan = new FullPathDisclosureScanPlugin(config.Server); break; case 'r': scan = new OpenRedirectScanPlugin(config.Server); break; } if (scan == null) { ScannerCli.DisplayCriticalMessageAndExit("Invalid scan mode: " + c); } config.ScanPlugins.Add(scan); } } else { switch (argIndex) { case 0: config.WebRoot = args[i]; if (!Directory.Exists(config.WebRoot)) { ScannerCli.DisplayError(string.Format("Could not find directory {0}", config.WebRoot)); Environment.Exit(5); } break; case 1: if (args[i] == "*") { var dir = new DirectoryInfo(config.WebRoot); config.ApplicationPaths = dir.GetDirectories() .Select(x => x.Name) .ToArray(); } else { config.ApplicationPaths = args[i].Split(','); } break; } argIndex++; } } if (argIndex != 2) { ScannerCli.DisplayCriticalMessageAndExit("Invalid argument count"); } // Validate user input if (!Directory.Exists(config.WebRoot)) { ScannerCli.DisplayCriticalMessageAndExit("Web root {0} not found.", config.WebRoot); } if (config.ScanPlugins.Count == 0 && !config.Repair) { LocalFileInclusionScanPlugin lfi = null; try { lfi = new LocalFileInclusionScanPlugin(config.Server); } catch (UnauthorizedAccessException) { ScannerCli.DisplayCriticalMessageAndExit("Error writing LFI test file. Ensure that " + "PHP Vulnerability Hunter has administrative privileges."); } config._ScanPlugins = new List <ScanPluginBase>() { new CommandScanPlugin(config.Server), new FileScanPlugin(config.Server), lfi, new ArbitraryPhpScanPlugin(config.Server), new DynamicScanPlugin(config.Server), new SqlScanPlugin(config.Server), new XssScanPlugin(config.Server), new OpenRedirectScanPlugin(config.Server), new FullPathDisclosureScanPlugin(config.Server), }; } return(config); }
public void Set(DirectoryInfo Directory) { IEnumerable <FileInfo> files = null; try { files = Directory .GetFiles("*", SearchOption.AllDirectories) .Where(x => x.Extension.ToLower() == ".php" || x.Extension.ToLower() == ".inc"); } catch (UnauthorizedAccessException) { var error = string.Format("\r\nError enumerating files in {0}", Directory.FullName); ScannerCli.DisplayError(error); return; } var progressBar = new CliProgressBar(files.Count()); progressBar.Write(); files.AsyncIter(f => { if (!CreateBackup(f)) { return; } string php = File.ReadAllText(f.FullName); PhpToken[] tokens = null; Action getTokens = () => tokens = PhpParser.StripWhitespaceAndComments(new PhpLexer(php) .GetTokens() .ToArray()); getTokens(); lock (Program.PageFieldTable) { if (!Program.PageFieldTable.ContainsKey(f.FullName)) { Program.PageFieldTable.Add(f.FullName, new Dictionary <string, List <string> >()); } var superglobals = StaticAnalyzer.FindSuperglobalFields(tokens); foreach (var superglobal in superglobals) { if (!Program.PageFieldTable[f.FullName].ContainsKey(superglobal.Key)) { Program.PageFieldTable[f.FullName].Add(superglobal.Key, new List <string>()); } var newValues = superglobal.Value .Where(x => !Program.PageFieldTable[f.FullName][superglobal.Key].Contains(x)); Program.PageFieldTable[f.FullName][superglobal.Key].AddRange(newValues); } } lock (Program.FileIncludeTable) Program.FileIncludeTable.Add(f.FullName, PhpParser.GetIncludedFiles(tokens)); var functions = PhpParser.GetGlobalFunctionCalls(tokens); if (Program.Config.CodeCoverageReport > 0) { php = ScanMetrics.Default.Annotator.AnnotateCode(f.FullName, php, tokens); } if (!Program.Config.HookSuperglobals) { php = PreloadHelper.Patch(php); } foreach (Hook h in this) { h.Set(ref php); } getTokens(); string include = "require_once('" + Program.Config.WebRoot.Replace('\\', '/') + "/" + Hook.HookFileName + "');"; if (tokens.Length >= 2 && tokens[1].TokenType == PhpTokenType.namespaceKeyword) { var eos = tokens.FirstOrDefault(x => x.TokenType == PhpTokenType.EndOfStatement); php = php.Insert(eos.Index + 1, "\r\n" + include + "\r\n"); } else { php = "<?php " + include + " ?>" + php; } try { File.WriteAllText(f.FullName, php); } catch (UnauthorizedAccessException ex) { ScannerCli.DisplayError(string.Format("\r\n\r\nError hooking file\r\n{0}\r\n", ex.Message)); return; } progressBar.Value++; progressBar.Write(); }); }