public static void SignFile(string filename, CertificateReference certificate) { SignFile(filename, certificate.Certificate); }
private int Startup(IEnumerable<string> args) { var options = args.Switches(); var parameters = args.Parameters(); foreach (var arg in options.Keys) { var argumentParameters = options[arg]; switch (arg) { /* global switches */ case "load-config": // all ready done, but don't get too picky. break; case "nologo": this.Assembly().SetLogo(string.Empty); break; case "help": return Help(); case "certificate-path": _signingCertPath = Path.GetFullPath(argumentParameters.Last()); break; case "password": _signingCertPassword = argumentParameters.Last(); break; case "remember": _remember = true; break; case "sign-only": _strongname = false; break; case "name-only": _sign = false; break; case "verbose": _verbose = true; break; case "company": _company = argumentParameters.Last(); break; case "description": _description = argumentParameters.Last(); break; case "internal-name": _internalName = argumentParameters.Last(); break; case "copyright": _copyright = argumentParameters.Last(); break; case "original-filename": _originalFilename = argumentParameters.Last(); break; case "product-name" : _productName = argumentParameters.Last(); break; case "resign" : _resign = true; break; case "product-version": _productVersion = argumentParameters.Last(); if (_productVersion.VersionStringToUInt64() == 0 || _productVersion.VersionStringToUInt64().UInt64VersiontoString() != _productVersion) { return Fail("--product-version must be in the form ##.##.##.##"); } break; case "file-version": _fileVersion = argumentParameters.Last(); if (_fileVersion.VersionStringToUInt64() == 0 || _fileVersion.VersionStringToUInt64().UInt64VersiontoString() != _fileVersion) { return Fail("--file-version must be in the form ##.##.##.##"); } break; default: return Fail("Unknown parameter [--{0}]", arg); } } Logo(); if( string.IsNullOrEmpty(_signingCertPath) ) { _certificate = CertificateReference.Default; if( _certificate == null ) { return Fail("No default certificate stored in the registry"); } } else if( string.IsNullOrEmpty(_signingCertPassword) ) { _certificate = new CertificateReference(_signingCertPath); } else { _certificate = new CertificateReference(_signingCertPath,_signingCertPassword); } using (new ConsoleColors(ConsoleColor.White, ConsoleColor.Black)) { Console.WriteLine("Loaded certificate with private key {0}", _certificate.Location); } if (_remember) { Verbose("Storing certificate details in the registry."); _certificate.RememberPassword(); CertificateReference.Default = _certificate; } if (parameters.Count() < 1) { return Fail("Missing files to sign/name. \r\n\r\n Use --help for command line help."); } var tasks = new List<Task>(); try { var allFiles = parameters.FindFilesSmarter().ToArray(); List<PeBinary> binaries = new List<PeBinary>(); foreach (var f in allFiles) { Console.WriteLine("Loading File: {0}", f); var filename = f; tasks.Add(Task.Factory.StartNew(() => { // var result = ""; if (CoApp.Toolkit.Crypto.Verifier.HasValidSignature(filename) && !_resign) { using (new ConsoleColors(ConsoleColor.Yellow, ConsoleColor.Black)) { Console.WriteLine("[{0}] already has a valid signature; skipping.", filename); } return; } try { var info = PEInfo.Scan(filename); if (info.IsPEBinary) { var peBinary = PeBinary.Load(filename); lock( binaries) { binaries.Add(peBinary); } if (_company != null) { peBinary.CompanyName = _company; } if (_description != null) { peBinary.FileDescription = _description; } if (_internalName != null) { peBinary.InternalName = _internalName; } if (_copyright != null) { peBinary.LegalCopyright = _copyright; } if (_originalFilename != null) { peBinary.OriginalFilename = _originalFilename; } if (_productName != null) { peBinary.ProductName = _productName; } if (_productVersion != null) { peBinary.ProductVersion = _productVersion; } if (_fileVersion != null) { peBinary.FileVersion = _fileVersion; } if (_strongname) { peBinary.StrongNameKeyCertificate = _certificate; } if (_sign) { peBinary.SigningCertificate = _certificate; } peBinary.Save(); using (new ConsoleColors(ConsoleColor.Green, ConsoleColor.Black)) { Console.WriteLine("Success {0}", filename); } } else { PeBinary.SignFile(filename, _certificate); } } catch (Exception e) { using (new ConsoleColors(ConsoleColor.Red, ConsoleColor.Black)) { Console.WriteLine("Failed {0} : {1}", filename, e.Message); Console.WriteLine(e.StackTrace); } } })); } Console.WriteLine("Tasks: {0}", tasks.ToArray().Count()); Task.Factory.ContinueWhenAll( tasks.ToArray(), (antecedent) => { Console.WriteLine("Loading Done."); }).Wait(); /* tasks.Clear(); foreach (var binary in binaries) { var peBinary = binary; tasks.Add(Task.Factory.StartNew(() => { peBinary.Save(); })); Task.Factory.ContinueWhenAll( tasks.ToArray(), (antecedent) => { Console.WriteLine("Loading Done."); }).Wait(); } * */ } catch (Exception e) { return Fail(e.Message); } return 0; }
/// <summary> /// This puts the strong name into the actual file on disk. The file MUST be delay signed by this point. /// </summary> /// <param name="filename"> </param> /// <param name="?"> </param> public static void ApplyStrongName(string filename, CertificateReference certificate) { filename = filename.GetFullPath(); filename.TryHardToMakeFileWriteable(); if (!File.Exists(filename)) { throw new FileNotFoundException("Can't find file", filename); } // strong name the binary using the private key from the certificate. var wszKeyContainer = Guid.NewGuid().ToString(); var privateKey = (certificate.Certificate.PrivateKey as RSACryptoServiceProvider).ExportCspBlob(true); if (!Mscoree.StrongNameKeyInstall(wszKeyContainer, privateKey, privateKey.Length)) { throw new CoAppException("Unable to create KeyContainer"); } if (!Mscoree.StrongNameSignatureGeneration(filename, wszKeyContainer, IntPtr.Zero, 0, 0, 0)) { throw new CoAppException("Unable Strong name assembly '{0}'.".format(filename)); } Mscoree.StrongNameKeyDelete(wszKeyContainer); }
private int Startup(IEnumerable<string> args) { var options = args.Switches(); var parameters = args.Parameters(); foreach (var arg in options.Keys) { var argumentParameters = options[arg]; switch (arg) { /* global switches */ case "load-config": // all ready done, but don't get too picky. break; case "nologo": this.Assembly().SetLogo(string.Empty); break; case "help": return Help(); case "certificate-path": _signingCertPath = Path.GetFullPath(argumentParameters.Last()); break; case "password": _signingCertPassword = argumentParameters.Last(); break; case "remember": _remember = true; break; case "auto": _auto = true; break; case "sign": _sign = true; break; case "strong-name": _strongname = true; break; case "verbose": _verbose = true; break; case "company": _company = argumentParameters.Last(); break; case "description": _description = argumentParameters.Last(); break; case "internal-name": _internalName = argumentParameters.Last(); break; case "copyright": _copyright = argumentParameters.Last(); break; case "original-filename": _originalFilename = argumentParameters.Last(); break; case "product-name" : _productName = argumentParameters.Last(); break; case "verify" : _verify = true; break; case "reference-assembly" : foreach (var asmRef in argumentParameters) { if( string.IsNullOrEmpty(asmRef)) { return Fail("Missing assembly information for --assembly-reference."); } var parts = asmRef.Split(", ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var assemblyref = new AssemblyReference { Name = parts[0] }; foreach( var part in parts.Skip(1)) { var kp = part.Split("= ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if( kp.Length != 2) { return Fail("Invalid option '{0}' in assembly reference '{1}'.", part, asmRef); } switch( kp[0].ToLower()) { case "version": case "ver": assemblyref.Version = kp[1]; if (assemblyref.Version == 0L) { return Fail("Invalid Version '{0}' in assembly reference '{1}'.", kp[1], asmRef); } break; case "publickeytoken": case "pkt": case "token": if( kp[1].Length != 16) { return Fail("Invalid publicKeyToken '{0}' in assembly reference '{1}'.", kp[1], asmRef); } assemblyref.PublicKeyToken = kp[1]; break; case "processorarchitecture": case "architecture": case "arch": assemblyref.Architecture = kp[1]; if (assemblyref.Architecture == Architecture.Auto || assemblyref.Architecture == Architecture.Unknown) { return Fail("Invalid processorArchitecture '{0}' in assembly reference '{1}'.", kp[1], asmRef); } break; } } if (assemblyref.Version == 0 || assemblyref.Architecture == Architecture.Unknown || string.IsNullOrEmpty(assemblyref.PublicKeyToken)) { return Fail("Invalid assembly reference '{0}' ", asmRef); } assemblyReferences.Add(assemblyref); } break; case "product-version": _productVersion = argumentParameters.Last(); if (_productVersion == 0L ) { return Fail("--product-version must be in the form ##.##.##.##"); } break; case "file-version": _fileVersion = argumentParameters.Last(); if (_fileVersion == 0L ) { return Fail("--file-version must be in the form ##.##.##.##"); } break; case "execution-level": switch( argumentParameters.Last() ) { case "administrator": case "admin": case "requires-admin": case "requiresadmin": case "requiresadministrator": case "requires-administrator": _executionLevel = ExecutionLevel.requireAdministrator; break; case "invoker": case "asinvoker": case "as-invoker": _executionLevel = ExecutionLevel.asInvoker; break; case "highest-available": case "highest": case "highestavailable": _executionLevel = ExecutionLevel.highestAvailable; break; } break; case "dpi-aware" : if (argumentParameters.Last().IsTrue()) { _dpiAware = true; } if (argumentParameters.Last().IsFalse()) { _dpiAware = false; } break; default: return Fail("Unknown parameter [--{0}]", arg); } } Logo(); if( _verify ) { // return Verify(parameters); } if( string.IsNullOrEmpty(_signingCertPath) ) { _certificate = CertificateReference.Default; if( _certificate == null ) { return Fail("No default certificate stored in the registry"); } } else if( string.IsNullOrEmpty(_signingCertPassword) ) { _certificate = new CertificateReference(_signingCertPath); } else { _certificate = new CertificateReference(_signingCertPath,_signingCertPassword); } using (new ConsoleColors(ConsoleColor.White, ConsoleColor.Black)) { Verbose("Loaded certificate with private key {0}", _certificate.Location); } if (_remember) { Verbose("Storing certificate details in the registry."); _certificate.RememberPassword(); CertificateReference.Default = _certificate; } if (parameters.Count() < 1) { return Fail("Missing files to sign/name. \r\n\r\n Use --help for command line help."); } var tasks = new List<Task>(); if( _company != null && _company.Equals("auto", StringComparison.CurrentCultureIgnoreCase) ) { _company = _certificate.CommonName; } var failures = 0; try { var allFiles = parameters.FindFilesSmarter().ToArray(); var origMD5 = new Dictionary<string, string>(); var loading = allFiles.Select(each => Binary.Load(each, BinaryLoadOptions.PEInfo | BinaryLoadOptions.VersionInfo | BinaryLoadOptions.Managed | BinaryLoadOptions.Resources | BinaryLoadOptions.Manifest | BinaryLoadOptions.UnsignedManagedDependencies | BinaryLoadOptions.MD5 ).ContinueWith(antecedent => { lock (allFiles) { if (antecedent.IsFaulted) { Console.WriteLine("Failed to load file '{0}'", each); var e = antecedent.Exception.Flatten().InnerExceptions.First(); Console.WriteLine("{0}--{1}", e.Message, e.StackTrace); return; } try { var binary = antecedent.Result; origMD5.Add(each, binary.MD5); if (binary.IsPEFile) { // do PE file stuff if (_sign) { binary.SigningCertificate = _certificate; } if (binary.IsManaged && _strongname) { binary.StrongNameKeyCertificate = _certificate; } if( !assemblyReferences.IsNullOrEmpty()) { foreach( var asmRef in assemblyReferences ) { binary.Manifest.Value.AddDependency( asmRef.Name , asmRef.Version, asmRef.Architecture, asmRef.PublicKeyToken); } } if (_company != null) { binary.CompanyName = _company; } if (_description != null) { binary.FileDescription = _description; } if (_internalName != null) { binary.InternalName = _internalName; } if (_copyright != null) { binary.LegalCopyright = _copyright; } if (_originalFilename != null) { binary.OriginalFilename = _originalFilename; } if (_productName != null) { binary.ProductName = _productName; } if (_productVersion != 0) { binary.ProductVersion = _productVersion; } if (_fileVersion != 0) { binary.FileVersion = _fileVersion; } if (_dpiAware != null) { binary.Manifest.Value.DpiAware = _dpiAware == true; } if (_executionLevel != ExecutionLevel.none) { binary.Manifest.Value.RequestedExecutionLevel = _executionLevel; } } else { // do stuff for non-pe files // we can try to apply a signature, and that's about it. if (_sign) { binary.SigningCertificate = _certificate; } } binary.Save().Wait(); } catch(Exception e) { while( e.GetType() == typeof(AggregateException)) { e = (e as AggregateException).Flatten().InnerExceptions[0]; } failures += Fail("{0}--{1}", e.Message, e.StackTrace); } } }, TaskContinuationOptions.AttachedToParent)).ToArray(); // Thread.Sleep(1000); // wait for loading. return Task.Factory.ContinueWhenAll(loading, tsks => { Console.WriteLine("Done {0} files", tsks.Length); (from each in Binary.Files select new { Filename = Path.GetFileName(each.Filename), Original_MD5 = origMD5[each.Filename], New_MD5 = each.MD5, // Status = each.Message, }).ToTable().ConsoleOut(); if (failures > 0) { Console.WriteLine("*** Bad News. Failed. *** "); } if (Binary.IsAnythingStillLoading) { Console.WriteLine("\r\n==== Uh, stuff is still in the loading state?! ====\r\n"); } return failures; }).Result; } catch( Exception e ) { Console.WriteLine("{0}--{1}", e.Message,e.StackTrace); return Fail("not good."); } /* try { var binaries = new List<PeBinary>(); var nonBinaries = new List<PEInfo>(); var results = new List<FileResult>(); foreach (var f in allFiles) { Verbose("Inspecting File: {0}", f); var filename = f; // first, load all the binaries // tasks.Add(Task.Factory.StartNew(() => { if (CoApp.Toolkit.Crypto.Verifier.HasValidSignature(filename) && !_resign) { results.Add( new FileResult {FullPath= filename, AlreadySigned = true, OriginalMD5 = filename.GetFileMD5(), Message = "Already Signed (skipped)", Color = ConsoleColor.Yellow}); return; } try { var info = PEInfo.Scan(filename); if (info.IsPEBinary) { var peBinary = PeBinary.Load(filename); lock (binaries) { if (!binaries.Contains(peBinary)) { binaries.Add(peBinary); } foreach (var depBinary in peBinary.UnsignedDependentBinaries.Where(depBinary => !binaries.Contains(depBinary))) { binaries.Add(depBinary); } } } else { if (!nonBinaries.Contains(info)) { nonBinaries.Add(info); } } } catch (Exception e) { results.Add(new FileResult { FullPath = filename, Message = "Failed to load--{0}".format(e.GetType()), Color = ConsoleColor.Red }); } })); } Task.Factory.ContinueWhenAll(tasks.ToArray(), (antecedent) => Verbose("Completed loading files.")).Wait(); tasks.Clear(); // Now, go ahead and modify all the binaries // and sign all the files. foreach( var nBin in nonBinaries ) { var nonBinary = nBin; tasks.Add(Task.Factory.StartNew(() => { var filename = nonBinary.Filename; try { PeBinary.SignFile(filename, _certificate); results.Add( new FileResult { FullPath = filename, OriginalMD5 = nonBinary.MD5, NewMD5 = filename.GetFileMD5(), Message = "Success." }); } catch (DigitalSignFailure exc) { if (exc.Win32Code == 0x800b0003) { results.Add(new FileResult { FullPath = filename, OriginalMD5 = nonBinary.MD5, Message = "Unable to sign unrecognized file", Color = ConsoleColor.Red }); } else { results.Add(new FileResult {FullPath = filename, OriginalMD5 = nonBinary.MD5, Message = exc.Message, Color = ConsoleColor.Red}); } } catch (CoAppException exc) { results.Add(new FileResult { FullPath = filename, OriginalMD5 = nonBinary.MD5, Message = exc.Message, Color = ConsoleColor.Red }); } catch (Exception exc) { results.Add(new FileResult { FullPath = filename, OriginalMD5 = nonBinary.MD5, Message = "Unable to sign unrecognized, non-binary file--{0}".format(exc.GetType()), Color = ConsoleColor.Red}); } })); } binaries.Reverse(); foreach (var bin in binaries) { var peBinary = bin; tasks.Add(Task.Factory.StartNew(() => { var filename = peBinary.Filename; try { if (_strongname) { peBinary.StrongNameKeyCertificate = _certificate; } if (_sign) { peBinary.SigningCertificate = _certificate; } if (_company != null) { peBinary.CompanyName = _company; } if (_description != null) { peBinary.FileDescription = _description; } if (_internalName != null) { peBinary.InternalName = _internalName; } if (_copyright != null) { peBinary.LegalCopyright = _copyright; } if (_originalFilename != null) { peBinary.OriginalFilename = _originalFilename; } if (_productName != null) { peBinary.ProductName = _productName; } if (_productVersion != null) { peBinary.ProductVersion = _productVersion; } if (_fileVersion != null) { peBinary.FileVersion = _fileVersion; } peBinary.Save(_auto); results.Add(new FileResult { FullPath = filename, OriginalMD5 = peBinary.Info.MD5, NewMD5 = filename.GetFileMD5(), Message = "Success" }); } catch (CoAppException exc) { results.Add(new FileResult { FullPath = filename, OriginalMD5 = peBinary.Info.MD5, Message = exc.Message, Color = ConsoleColor.Red }); } catch (Exception exc) { results.Add(new FileResult { FullPath = filename, OriginalMD5 = peBinary.Info.MD5, Message = "Unable to sign PE Binary file--{0}".format(exc.GetType()), Color = ConsoleColor.Red }); } })); } if (tasks.Any()) { // wait for all the work to be done. Task.Factory.ContinueWhenAll(tasks.ToArray(), (antecedent) => { Verbose("Completed Signing Files."); }).Wait(); } var output = results.OrderByDescending(each => each.Color).ToArray(); var outputLines = (from each in output select new { Filename = Path.GetFileName(each.FullPath), Original_MD5 = each.OriginalMD5, New_MD5 = each.NewMD5, Status = each.Message, }).ToTable().ToArray(); Console.WriteLine(outputLines[0]); var footer = outputLines[1]; Console.WriteLine(footer); // trim the header/footer outputLines = outputLines.Skip(2).Reverse().Skip(1).Reverse().ToArray(); for (int i = 0; i < outputLines.Length; i++ ) { using (new ConsoleColors(output[i].Color, ConsoleColor.Black)) { Console.WriteLine(outputLines[i]); } } Console.WriteLine(footer); } catch (Exception e) { return Fail(e.Message); } */ return 0; }