Add standalone OCSentinel setup executable builder
Some checks failed
OfficeCom Sentinel Client / build-client (push) Has been cancelled
Some checks failed
OfficeCom Sentinel Client / build-client (push) Has been cancelled
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@ payload/
|
|||||||
*.log
|
*.log
|
||||||
*.zip
|
*.zip
|
||||||
*.sha256
|
*.sha256
|
||||||
|
payload.zip
|
||||||
SetupAttackTracer.exe
|
SetupAttackTracer.exe
|
||||||
decompiled/
|
decompiled/
|
||||||
msi-admin/
|
msi-admin/
|
||||||
|
|||||||
50
build/build-client-installer.ps1
Normal file
50
build/build-client-installer.ps1
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
param(
|
||||||
|
[string]$Configuration = "Release"
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$repoRoot = Split-Path -Parent $PSScriptRoot
|
||||||
|
$artifactsRoot = Join-Path $repoRoot "artifacts"
|
||||||
|
$zipPath = Join-Path $artifactsRoot "OCSentinelClient-win-x64.zip"
|
||||||
|
$bootstrapperRoot = Join-Path $repoRoot "installer\OCSentinelBootstrapper"
|
||||||
|
$payloadPath = Join-Path $bootstrapperRoot "payload.zip"
|
||||||
|
$projectPath = Join-Path $bootstrapperRoot "OCSentinelBootstrapper.csproj"
|
||||||
|
$publishRoot = Join-Path $artifactsRoot "bootstrapper-publish\win-x64"
|
||||||
|
$outputExe = Join-Path $artifactsRoot "OCSentinelSetup.exe"
|
||||||
|
|
||||||
|
if (-not (Test-Path $zipPath)) {
|
||||||
|
& powershell.exe -ExecutionPolicy Bypass -File (Join-Path $repoRoot "build\build-client-package.ps1") -Configuration $Configuration
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "build-client-package.ps1 failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item -Path $zipPath -Destination $payloadPath -Force
|
||||||
|
|
||||||
|
if (Test-Path $publishRoot) {
|
||||||
|
Remove-Item -LiteralPath $publishRoot -Recurse -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path $outputExe) {
|
||||||
|
Remove-Item -LiteralPath $outputExe -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Force -Path $publishRoot | Out-Null
|
||||||
|
|
||||||
|
& dotnet publish $projectPath `
|
||||||
|
-c $Configuration `
|
||||||
|
-r win-x64 `
|
||||||
|
--self-contained true `
|
||||||
|
-p:PublishSingleFile=true `
|
||||||
|
-p:EnableCompressionInSingleFile=true `
|
||||||
|
-p:IncludeNativeLibrariesForSelfExtract=true `
|
||||||
|
-o $publishRoot
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "dotnet publish failed for bootstrapper"
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item -Path (Join-Path $publishRoot "OCSentinelBootstrapper.exe") -Destination $outputExe -Force
|
||||||
|
|
||||||
|
Write-Host "OfficeCom Sentinel setup executable created at $outputExe"
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net10.0-windows</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<UseWindowsForms>false</UseWindowsForms>
|
||||||
|
<AssemblyName>OCSentinelBootstrapper</AssemblyName>
|
||||||
|
<RootNamespace>OCSentinelBootstrapper</RootNamespace>
|
||||||
|
<PublishSingleFile>true</PublishSingleFile>
|
||||||
|
<SelfContained>true</SelfContained>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
|
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
|
||||||
|
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="payload.zip" LogicalName="payload.zip" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
76
installer/OCSentinelBootstrapper/Program.cs
Normal file
76
installer/OCSentinelBootstrapper/Program.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace OCSentinelBootstrapper;
|
||||||
|
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
private static int Main()
|
||||||
|
{
|
||||||
|
string tempRoot = Path.Combine(Path.GetTempPath(), "OCSentinelSetup", Guid.NewGuid().ToString("N"));
|
||||||
|
string zipPath = Path.Combine(tempRoot, "payload.zip");
|
||||||
|
string extractRoot = Path.Combine(tempRoot, "payload");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(tempRoot);
|
||||||
|
Directory.CreateDirectory(extractRoot);
|
||||||
|
|
||||||
|
ExtractEmbeddedPayload(zipPath);
|
||||||
|
ZipFile.ExtractToDirectory(zipPath, extractRoot, overwriteFiles: true);
|
||||||
|
|
||||||
|
string installScript = Path.Combine(extractRoot, "scripts", "install-ocsentinel.ps1");
|
||||||
|
if (!File.Exists(installScript))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("Embedded payload did not contain install-ocsentinel.ps1", installScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
var process = new Process
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "powershell.exe",
|
||||||
|
Arguments = $"-ExecutionPolicy Bypass -File \"{installScript}\"",
|
||||||
|
UseShellExecute = false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
process.Start();
|
||||||
|
process.WaitForExit();
|
||||||
|
return process.ExitCode;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"OCSentinel installer failed: {ex}");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Directory.Exists(tempRoot))
|
||||||
|
{
|
||||||
|
Directory.Delete(tempRoot, recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Best-effort cleanup only.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ExtractEmbeddedPayload(string destinationPath)
|
||||||
|
{
|
||||||
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||||
|
using Stream? resourceStream = assembly.GetManifestResourceStream("payload.zip");
|
||||||
|
if (resourceStream is null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Embedded payload.zip resource was not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
using FileStream output = File.Create(destinationPath);
|
||||||
|
resourceStream.CopyTo(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user