mirror of
https://github.com/8damon/Blackbird-Platform
synced 2026-06-21 13:41:12 +00:00
902 lines
33 KiB
PowerShell
902 lines
33 KiB
PowerShell
param(
|
|
[switch] $PlanOnly,
|
|
[switch] $Force
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$repoRoot = (& git rev-parse --show-toplevel).Trim()
|
|
if (-not $repoRoot) {
|
|
throw 'This script must be run from inside the Blackbird git repository.'
|
|
}
|
|
|
|
Set-Location $repoRoot
|
|
|
|
$privateOrExternalPaths = @(
|
|
'Blackbird.code-workspace',
|
|
'Client/analysis/Rules/SignatureIntel/signature-rules.json',
|
|
'Client/analysis/Rules/SignatureIntel/default-sigma.yml',
|
|
'Client/analysis/Rules/SignatureIntel/Bundled/',
|
|
'Docs/',
|
|
'docs/',
|
|
'Yara/',
|
|
'Server/',
|
|
'Lib/NetworkServiceLayer/',
|
|
'Kernel/network/',
|
|
'Kernel/core/crashdump.c',
|
|
'Kernel/monitors/bugcheck_monitor.c',
|
|
'Kernel/monitors/bugcheck_monitor.h',
|
|
'UserMode/netsvc/',
|
|
'Usermode/netsvc/',
|
|
'VCXProj/BlackbirdNetSvc.vcxproj',
|
|
'VCXProj/BlackbirdNetSvc.vcxproj.filters'
|
|
)
|
|
|
|
function Convert-ToGitPath {
|
|
param([string] $Path)
|
|
return ($Path -replace '\\', '/').TrimStart('./')
|
|
}
|
|
|
|
function Test-SkippedPath {
|
|
param([string] $Path)
|
|
|
|
$gitPath = Convert-ToGitPath $Path
|
|
foreach ($skipPath in $privateOrExternalPaths) {
|
|
$skip = Convert-ToGitPath $skipPath
|
|
if ($skip.EndsWith('/')) {
|
|
if ($gitPath.StartsWith($skip, [System.StringComparison]::OrdinalIgnoreCase)) {
|
|
return $true
|
|
}
|
|
} elseif ($gitPath.Equals($skip, [System.StringComparison]::OrdinalIgnoreCase)) {
|
|
return $true
|
|
}
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
function Test-TrackedPath {
|
|
param([string] $Path)
|
|
|
|
$gitPath = Convert-ToGitPath $Path
|
|
$tracked = @(& git ls-files -- $Path 2>$null | ForEach-Object { Convert-ToGitPath $_ })
|
|
|
|
if ($gitPath.EndsWith('/')) {
|
|
$prefix = $gitPath
|
|
} else {
|
|
$prefix = "$gitPath/"
|
|
}
|
|
|
|
foreach ($trackedPath in $tracked) {
|
|
if ($trackedPath -ceq $gitPath) {
|
|
return $true
|
|
}
|
|
|
|
if ($trackedPath.StartsWith($prefix, [System.StringComparison]::Ordinal)) {
|
|
return $true
|
|
}
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
function Test-ExactExistingPath {
|
|
param([string] $Path)
|
|
|
|
$requestedGitPath = Convert-ToGitPath $Path
|
|
if ([string]::IsNullOrWhiteSpace($requestedGitPath)) {
|
|
return $false
|
|
}
|
|
|
|
$current = $repoRoot
|
|
foreach ($segment in $requestedGitPath.Split('/')) {
|
|
if ([string]::IsNullOrWhiteSpace($segment)) {
|
|
continue
|
|
}
|
|
|
|
$match = Get-ChildItem -LiteralPath $current -Force -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.Name -ceq $segment } |
|
|
Select-Object -First 1
|
|
|
|
if ($null -eq $match) {
|
|
return $false
|
|
}
|
|
|
|
$current = $match.FullName
|
|
}
|
|
|
|
return $true
|
|
}
|
|
|
|
function Get-StageablePaths {
|
|
param([string[]] $Paths)
|
|
|
|
$stageable = New-Object System.Collections.Generic.List[string]
|
|
foreach ($path in $Paths) {
|
|
if (Test-SkippedPath $path) {
|
|
Write-Warning "Skipping private/external path: $path"
|
|
continue
|
|
}
|
|
|
|
if ((Test-ExactExistingPath $path) -or (Test-TrackedPath $path)) {
|
|
[void] $stageable.Add($path)
|
|
} else {
|
|
Write-Host "Skipping missing path: $path"
|
|
}
|
|
}
|
|
|
|
return $stageable.ToArray()
|
|
}
|
|
|
|
function Test-AnyStagedChanges {
|
|
& git diff --cached --quiet
|
|
return ($LASTEXITCODE -ne 0)
|
|
}
|
|
|
|
function Commit-Group {
|
|
param(
|
|
[string] $Message,
|
|
[string[]] $Paths
|
|
)
|
|
|
|
$stageable = Get-StageablePaths $Paths
|
|
if ($stageable.Count -eq 0) {
|
|
Write-Host "No paths for: $Message"
|
|
return
|
|
}
|
|
|
|
if ($PlanOnly) {
|
|
Write-Host ''
|
|
Write-Host "Would commit: $Message"
|
|
foreach ($path in $stageable) {
|
|
Write-Host " $path"
|
|
}
|
|
return
|
|
}
|
|
|
|
foreach ($path in $stageable) {
|
|
& git add -A -- $path
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "git add failed for commit group '$Message' path '$path'"
|
|
}
|
|
}
|
|
|
|
if (-not (Test-AnyStagedChanges)) {
|
|
Write-Host "No staged changes for: $Message"
|
|
return
|
|
}
|
|
|
|
& git commit -m $Message
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "git commit failed for: $Message"
|
|
}
|
|
}
|
|
|
|
if (-not $PlanOnly) {
|
|
if ((Test-AnyStagedChanges) -and -not $Force) {
|
|
throw 'The git index already has staged changes. Commit or unstage them first, or pass -Force to continue.'
|
|
}
|
|
}
|
|
|
|
$groups = @(
|
|
@{
|
|
Message = 'repo/policy: clarify defensive public scope'
|
|
Paths = @('.gitignore', 'README.md', 'LICENSE')
|
|
},
|
|
@{
|
|
Message = 'build/style: move clang-format into vcxproj configuration'
|
|
Paths = @('.clang-format', 'VCXProj/.clang-format')
|
|
},
|
|
@{
|
|
Message = 'abi: normalize IPC contract header name'
|
|
Paths = @('ABI/Blackbird_ipc.h', 'ABI/blackbird_ipc.h')
|
|
},
|
|
@{
|
|
Message = 'abi: add diagnostics and launch subject contracts'
|
|
Paths = @('ABI/blackbird_ioctl.h', 'ABI/blackbird_ipc.h')
|
|
},
|
|
@{
|
|
Message = 'kernel/callbacks: move OS callback monitors into callbacks tree'
|
|
Paths = @(
|
|
'Kernel/monitors/filesystem_monitor.c',
|
|
'Kernel/monitors/filesystem_monitor.h',
|
|
'Kernel/monitors/handle_monitor.c',
|
|
'Kernel/monitors/handle_monitor.h',
|
|
'Kernel/monitors/image_monitor.c',
|
|
'Kernel/monitors/image_monitor.h',
|
|
'Kernel/monitors/process_monitor.c',
|
|
'Kernel/monitors/process_monitor.h',
|
|
'Kernel/monitors/registry_monitor.c',
|
|
'Kernel/monitors/registry_monitor.h',
|
|
'Kernel/monitors/thread_monitor.c',
|
|
'Kernel/monitors/thread_monitor.h',
|
|
'Kernel/callbacks'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'kernel/core: add optional private feature boundaries'
|
|
Paths = @(
|
|
'Kernel/core/optional_features.h',
|
|
'Kernel/core/optional_feature_stubs.c',
|
|
'Kernel/core/crashdump.h'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'kernel/core: add diagnostics component registry'
|
|
Paths = @('Kernel/core/diagnostics.c', 'Kernel/core/diagnostics.h')
|
|
},
|
|
@{
|
|
Message = 'kernel/core: integrate optional subsystem lifecycle'
|
|
Paths = @(
|
|
'Kernel/core/driver.c',
|
|
'Kernel/core/control/control_common.c',
|
|
'Kernel/core/control/control_dispatch_init.c',
|
|
'Kernel/core/control/control_ioctl_handlers.c',
|
|
'Kernel/core/control/control_private.h',
|
|
'Kernel/core/control/control_uninit_exports.c'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'kernel/core: extend runtime configuration state'
|
|
Paths = @('Kernel/core/runtime_config.c', 'Kernel/core/runtime_config.h', 'Kernel/core/control.h')
|
|
},
|
|
@{
|
|
Message = 'kernel/core: refresh Tempus debug and utility helpers'
|
|
Paths = @(
|
|
'Kernel/core/tempus_debug.c',
|
|
'Kernel/core/tempus_debug.h',
|
|
'Kernel/core/pool_compat.h',
|
|
'Kernel/core/protection_utils.h',
|
|
'Kernel/core/unicode_utils.h'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'kernel/antivirt: add QPC timing compensation'
|
|
Paths = @('Kernel/antivirt/qpc_timing.c', 'Kernel/antivirt/qpc_timing.h', 'Kernel/antivirt/antivirt_ntapi_firmware.c')
|
|
},
|
|
@{
|
|
Message = 'kernel/antivirt: harden registry concealment flow'
|
|
Paths = @('Kernel/antivirt/registry_concealment.c', 'Kernel/antivirt/registry_concealment.h')
|
|
},
|
|
@{
|
|
Message = 'kernel/correlation: extend hollowing analysis state'
|
|
Paths = @('Kernel/correlation/hollowing_engine.c', 'Kernel/correlation/hollowing_engine.h')
|
|
},
|
|
@{
|
|
Message = 'kernel/correlation: refresh intent tracking store'
|
|
Paths = @('Kernel/correlation/intent_store.c', 'Kernel/correlation/intent_store.h')
|
|
},
|
|
@{
|
|
Message = 'kernel/hooks: update NT hook stubs and resolver'
|
|
Paths = @(
|
|
'Kernel/hooks/asm/ntapi_stubs.asm',
|
|
'Kernel/hooks/hook/ntapi_hook.c',
|
|
'Kernel/hooks/hook/ntapi_hook.h',
|
|
'Kernel/hooks/hook/ntapi_hook_ldasm.c',
|
|
'Kernel/hooks/hook/ntapi_hook_ldasm.h',
|
|
'Kernel/hooks/hook/ntapi_hook_resolve.c'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'kernel/ntapi: expand NT monitor coverage'
|
|
Paths = @(
|
|
'Kernel/hooks/monitor/ntapi_monitor.c',
|
|
'Kernel/hooks/monitor/ntapi_monitor.h',
|
|
'Kernel/hooks/monitor/ntapi_monitor_hooks.c',
|
|
'Kernel/hooks/monitor/ntapi_monitor_private.h'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'kernel/monitors: update anti-tamper and APC monitors'
|
|
Paths = @('Kernel/monitors/anti_tamper.c', 'Kernel/monitors/anti_tamper.h', 'Kernel/monitors/apc_monitor.c', 'Kernel/monitors/apc_monitor.h')
|
|
},
|
|
@{
|
|
Message = 'kernel/telemetry: refresh ETW telemetry bridge'
|
|
Paths = @('Kernel/telemetry/etw.c', 'Kernel/telemetry/etw.h')
|
|
},
|
|
@{
|
|
Message = 'kernel/include: add native PEB and TEB declarations'
|
|
Paths = @('Kernel/include')
|
|
},
|
|
@{
|
|
Message = 'controller/core: normalize private headers'
|
|
Paths = @('UserMode/controller/core/Blackbird_controller_private.h', 'UserMode/controller/core/controller_private.h')
|
|
},
|
|
@{
|
|
Message = 'controller/core: refresh controller entrypoint logging'
|
|
Paths = @('UserMode/controller/Blackbird_controller.cpp', 'UserMode/controller/controller.cpp')
|
|
},
|
|
@{
|
|
Message = 'controller/injection: split launch helper modules'
|
|
Paths = @(
|
|
'UserMode/controller/core/injection/Blackbird_controller_injection.cpp',
|
|
'UserMode/controller/core/injection/Blackbird_controller_injection.h',
|
|
'UserMode/controller/core/injection/common.cpp',
|
|
'UserMode/controller/core/injection/environment.cpp',
|
|
'UserMode/controller/core/injection/hook.cpp',
|
|
'UserMode/controller/core/injection/image.cpp',
|
|
'UserMode/controller/core/injection/injection.cpp',
|
|
'UserMode/controller/core/injection/injection.h',
|
|
'UserMode/controller/core/injection/internal.h',
|
|
'UserMode/controller/core/injection/launch.cpp',
|
|
'UserMode/controller/core/injection/token.cpp'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'controller/ipc: split pipe protocol handlers'
|
|
Paths = @(
|
|
'UserMode/controller/core/ipc/Blackbird_controller_ipc.cpp',
|
|
'UserMode/controller/core/ipc/ipc.cpp',
|
|
'UserMode/controller/core/ipc/ipc_hook_support.cpp',
|
|
'UserMode/controller/core/ipc/ipc_internal.h',
|
|
'UserMode/controller/core/ipc/ipc_launch.cpp',
|
|
'UserMode/controller/core/ipc/ipc_proxy.cpp',
|
|
'UserMode/controller/core/ipc/ipc_shared_ring.cpp'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'controller/monitoring: clean ETW and subscription modules'
|
|
Paths = @(
|
|
'UserMode/controller/core/monitoring/Blackbird_controller_etw_monitor.cpp',
|
|
'UserMode/controller/core/monitoring/Blackbird_controller_subscriptions.cpp',
|
|
'UserMode/controller/core/monitoring/etw_monitor.cpp',
|
|
'UserMode/controller/core/monitoring/subscriptions.cpp',
|
|
'UserMode/controller/core/monitoring/ubscriptions.cpp'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'controller/runtime: split service runtime and symbols'
|
|
Paths = @(
|
|
'UserMode/controller/core/runtime/Blackbird_controller_runtime.cpp',
|
|
'UserMode/controller/core/runtime/blackbird_controller_symbol_service.cpp',
|
|
'UserMode/controller/core/runtime/runtime.cpp',
|
|
'UserMode/controller/core/runtime/symbol_service.cpp'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'controller/netsvc: make network service launcher optional'
|
|
Paths = @(
|
|
'UserMode/controller/core/runtime/blackbird_controller_node_runtime.cpp',
|
|
'UserMode/controller/core/runtime/node_runtime.cpp',
|
|
'UserMode/controller/core/runtime/ns'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'controller/correlation: refresh hollowing analysis'
|
|
Paths = @('UserMode/controller/core/correlation/Blackbird_controller_hollowing.cpp', 'UserMode/controller/core/correlation/hollowing.cpp')
|
|
},
|
|
@{
|
|
Message = 'controller/heuristics: refresh event classification'
|
|
Paths = @(
|
|
'UserMode/controller/core/heuristics/Blackbird_controller_heuristics.cpp',
|
|
'UserMode/controller/core/heuristics/heuristics.cpp',
|
|
'UserMode/controller/core/heuristics/heuristics.h'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'usermode/dllhost: add DLL analysis host'
|
|
Paths = @('UserMode/dllhost')
|
|
},
|
|
@{
|
|
Message = 'usermode/include: add native PEB helpers'
|
|
Paths = @('UserMode/include')
|
|
},
|
|
@{
|
|
Message = 'hook/runtime: update SR71 bootstrap and launch gate'
|
|
Paths = @(
|
|
'UserMode/hook/dll.cpp',
|
|
'UserMode/hook/hooks/runtime_bootstrap.cpp',
|
|
'UserMode/hook/hooks/runtime_launch_gate.cpp',
|
|
'UserMode/hook/hooks/runtime_private.h'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'hook/runtime: harden SR71 integrity state'
|
|
Paths = @('UserMode/hook/hooks/runtime.cpp', 'UserMode/hook/hooks/runtime.h', 'UserMode/hook/hooks/runtime_integrity.cpp')
|
|
},
|
|
@{
|
|
Message = 'hook/nt: expand NT hook descriptors'
|
|
Paths = @('UserMode/hook/hooks/nt.cpp', 'UserMode/hook/hooks/nt.h')
|
|
},
|
|
@{
|
|
Message = 'hook/module: update module instrumentation'
|
|
Paths = @('UserMode/hook/hooks/module.cpp', 'UserMode/hook/hooks/module.h')
|
|
},
|
|
@{
|
|
Message = 'hook/ki: update exception dispatcher instrumentation'
|
|
Paths = @('UserMode/hook/hooks/ki.cpp', 'UserMode/hook/hooks/ki.h')
|
|
},
|
|
@{
|
|
Message = 'hook/ws: refresh Winsock telemetry hooks'
|
|
Paths = @('UserMode/hook/hooks/ws.cpp', 'UserMode/hook/hooks/ws.h')
|
|
},
|
|
@{
|
|
Message = 'hook/instrument: update owned range publication'
|
|
Paths = @(
|
|
'UserMode/hook/instrument/bk.cpp',
|
|
'UserMode/hook/instrument/bk.h',
|
|
'UserMode/hook/instrument/stacktrace.cpp',
|
|
'UserMode/hook/instrument/stacktrace.h',
|
|
'UserMode/hook/instrument/unlink.cpp'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'hook/ipc: update hook pipe transport'
|
|
Paths = @('UserMode/hook/ipc/pipe.cpp', 'UserMode/hook/ipc/pipe.h')
|
|
},
|
|
@{
|
|
Message = 'hook/build: refresh SR71 project inputs'
|
|
Paths = @('UserMode/hook/vcxproj/BlackbirdHook.vcxproj')
|
|
},
|
|
@{
|
|
Message = 'sensor: normalize sensor source names'
|
|
Paths = @(
|
|
'UserMode/sensor/Blackbird_etw_printer.c',
|
|
'UserMode/sensor/Blackbird_etw_printer.h',
|
|
'UserMode/sensor/Blackbird_etw_props.c',
|
|
'UserMode/sensor/Blackbird_etw_props.h',
|
|
'UserMode/sensor/Blackbird_etw_symbols.c',
|
|
'UserMode/sensor/Blackbird_etw_symbols.h',
|
|
'UserMode/sensor/Blackbird_event_printer.c',
|
|
'UserMode/sensor/Blackbird_event_printer.h',
|
|
'UserMode/sensor/Blackbird_ioctl_test.c',
|
|
'UserMode/sensor/Blackbird_sensor_core.c',
|
|
'UserMode/sensor/Blackbird_sensor_core.h',
|
|
'UserMode/sensor/Blackbird_symbol_common.c',
|
|
'UserMode/sensor/Blackbird_symbol_common.h',
|
|
'UserMode/sensor/Blackbird_symbol_resolver.c',
|
|
'UserMode/sensor/Blackbird_symbol_resolver.h',
|
|
'UserMode/sensor/Blackbird_test_report_html.c',
|
|
'UserMode/sensor/Blackbird_test_report_html.h',
|
|
'UserMode/sensor/etw_printer.c',
|
|
'UserMode/sensor/etw_printer.h',
|
|
'UserMode/sensor/etw_props.c',
|
|
'UserMode/sensor/etw_props.h',
|
|
'UserMode/sensor/etw_symbols.c',
|
|
'UserMode/sensor/etw_symbols.h',
|
|
'UserMode/sensor/event_printer.c',
|
|
'UserMode/sensor/event_printer.h',
|
|
'UserMode/sensor/ioctl_test.c',
|
|
'UserMode/sensor/sensor_core.c',
|
|
'UserMode/sensor/sensor_core.h',
|
|
'UserMode/sensor/symbol_common.c',
|
|
'UserMode/sensor/symbol_common.h',
|
|
'UserMode/sensor/symbol_resolver.c',
|
|
'UserMode/sensor/symbol_resolver.h',
|
|
'UserMode/sensor/test_report_html.c',
|
|
'UserMode/sensor/test_report_html.h'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'sensor/core: normalize sensor protocol modules'
|
|
Paths = @(
|
|
'UserMode/sensor/core/Blackbird_sensor_core_etw.c',
|
|
'UserMode/sensor/core/Blackbird_sensor_core_internal.h',
|
|
'UserMode/sensor/core/Blackbird_sensor_core_protocol.c',
|
|
'UserMode/sensor/core/sensor_core_etw.c',
|
|
'UserMode/sensor/core/sensor_core_internal.h',
|
|
'UserMode/sensor/core/sensor_core_protocol.c'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'sensor/tests: normalize ioctl test harness'
|
|
Paths = @(
|
|
'UserMode/sensor/tests/Blackbird_ioctl_test_env.c',
|
|
'UserMode/sensor/tests/Blackbird_ioctl_test_etw.c',
|
|
'UserMode/sensor/tests/Blackbird_ioctl_test_intent.c',
|
|
'UserMode/sensor/tests/Blackbird_ioctl_test_internal.h',
|
|
'UserMode/sensor/tests/Blackbird_ioctl_test_ioctl.c',
|
|
'UserMode/sensor/tests/Blackbird_ioctl_test_main.c',
|
|
'UserMode/sensor/tests/Blackbird_ioctl_test_report.c',
|
|
'UserMode/sensor/tests/ioctl_test_env.c',
|
|
'UserMode/sensor/tests/ioctl_test_etw.c',
|
|
'UserMode/sensor/tests/ioctl_test_intent.c',
|
|
'UserMode/sensor/tests/ioctl_test_internal.h',
|
|
'UserMode/sensor/tests/ioctl_test_ioctl.c',
|
|
'UserMode/sensor/tests/ioctl_test_main.c',
|
|
'UserMode/sensor/tests/ioctl_test_report.c'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'sensor/docs: refresh sensor usage notes'
|
|
Paths = @('UserMode/sensor/README.md')
|
|
},
|
|
@{
|
|
Message = 'ui/interop: add backend and native bindings'
|
|
Paths = @(
|
|
'Client/analysis/Interop/BlackbirdNative.Launch.cs',
|
|
'Client/analysis/Interop/BlackbirdNative.cs',
|
|
'Client/analysis/Interop/BkdcNative.cs',
|
|
'Client/analysis/Interop/Kernel32Native.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/models: add disassembly and trust models'
|
|
Paths = @(
|
|
'Client/analysis/Models/BlackbirdBackendModels.cs',
|
|
'Client/analysis/Models/DiagnosticsState.cs',
|
|
'Client/analysis/Models/GraphExplorerItem.cs',
|
|
'Client/analysis/Models/InspectorModels.cs',
|
|
'Client/analysis/Models/LaunchProfile.cs',
|
|
'Client/analysis/Models/MemoryDisassemblyRequestedEventArgs.cs',
|
|
'Client/analysis/Models/PaneHeaderDragEventArgs.cs',
|
|
'Client/analysis/Models/PerformanceSample.cs',
|
|
'Client/analysis/Models/SignatureTrustState.cs',
|
|
'Client/analysis/Models/StackFrameRow.cs',
|
|
'Client/analysis/Models/TelemetryEvent.cs',
|
|
'Client/analysis/Models/ThreadStackSessionModels.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/controls: refresh timeline and performance controls'
|
|
Paths = @(
|
|
'Client/analysis/Controls/BulkObservableCollection.cs',
|
|
'Client/analysis/Controls/PerformanceChartControl.cs',
|
|
'Client/analysis/Controls/SparklinePreviewControl.cs',
|
|
'Client/analysis/Controls/TimeSeriesBuffer.cs',
|
|
'Client/analysis/Controls/TimelineControl.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/services: add launch orchestration service'
|
|
Paths = @(
|
|
'Client/analysis/Services/AnalysisLaunchService.cs',
|
|
'Client/analysis/Services/BlackbirdPreflight.cs',
|
|
'Client/analysis/Services/BlackbirdServiceControl.cs',
|
|
'Client/analysis/Services/LaunchHookOptions.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/services: add runtime configuration service'
|
|
Paths = @(
|
|
'Client/analysis/Services/RuntimeConfigService.cs',
|
|
'Client/analysis/Shell/MainWindow.RuntimeConfig.cs',
|
|
'Client/analysis/Shell/MainWindow.RuntimeConfigApi.cs',
|
|
'Client/analysis/runtimeconfig.template.json'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/services: improve backend session lifecycle'
|
|
Paths = @(
|
|
'Client/analysis/Services/BlackbirdBackendSession.cs',
|
|
'Client/analysis/Services/BlackbirdControlDeviceSession.cs',
|
|
'Client/analysis/Services/BoundedStringPool.cs',
|
|
'Client/analysis/Services/DebugConsoleService.cs',
|
|
'Client/analysis/Services/OutputCapture.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/services: add component and operator identity helpers'
|
|
Paths = @(
|
|
'Client/analysis/Services/ComponentIdentityService.cs',
|
|
'Client/analysis/Services/OperatorIdentityService.cs',
|
|
'Client/analysis/Services/VmRegistrationPackageService.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/capture: refactor archive storage primitives'
|
|
Paths = @(
|
|
'Client/analysis/Services/Capture/CaptureArchiveModels.cs',
|
|
'Client/analysis/Services/Capture/CaptureArchiveStorage.cs',
|
|
'Client/analysis/Services/Capture/Lz4BlockCodec.cs',
|
|
'Client/analysis/Services/Capture/SqliteDatabase.cs',
|
|
'Client/analysis/Services/Capture/SqliteException.cs',
|
|
'Client/analysis/Services/Capture/SqliteNative.cs',
|
|
'Client/analysis/Services/Capture/SqliteStatement.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/capture: add live capture projection engine'
|
|
Paths = @('Client/analysis/Services/Capture/CaptureLiveStoreImpl.cs', 'Client/analysis/Services/Capture/CaptureProjectionEngine.cs')
|
|
},
|
|
@{
|
|
Message = 'ui/services: add broker ETW event mapping'
|
|
Paths = @(
|
|
'Client/analysis/Services/BrokerEtwEventMapper.cs',
|
|
'Client/analysis/Services/ProcessGraphProjectionBuilder.cs',
|
|
'Client/analysis/Services/ProcessIdentityResolver.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/services: update event formatting and compaction'
|
|
Paths = @(
|
|
'Client/analysis/Services/EventDetailFormatting.cs',
|
|
'Client/analysis/Services/EventDetailsParsing.cs',
|
|
'Client/analysis/Services/GroupedEventCompaction.cs',
|
|
'Client/analysis/Services/GroupedEventPaneState.cs',
|
|
'Client/analysis/Services/IntelDetailsProvider.cs',
|
|
'Client/analysis/Services/TelemetryEventStore.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/services: expand performance and stack sampling'
|
|
Paths = @(
|
|
'Client/analysis/Services/PerformanceSampler.cs',
|
|
'Client/analysis/Services/ThreadStackResolver.cs',
|
|
'Client/analysis/Services/VirtualizationProbe.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/signature: expand signature intel analysis'
|
|
Paths = @(
|
|
'Client/analysis/Services/SignatureIntelService.cs',
|
|
'Client/analysis/Services/PackerDetectionService.cs',
|
|
'Client/analysis/Shell/MainWindow.SignatureIntel.cs',
|
|
'Client/analysis/Windows/SignatureIntelRulesWindow.xaml',
|
|
'Client/analysis/Windows/SignatureIntelRulesWindow.xaml.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/session: update session storage and export flow'
|
|
Paths = @(
|
|
'Client/analysis/Services/SessionExportService.cs',
|
|
'Client/analysis/Services/SessionFileStorage.cs',
|
|
'Client/analysis/Shell/MainWindow.CaptureStore.cs',
|
|
'Client/analysis/Shell/MainWindow.SessionStorage.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/shell: rebuild main window backend flow'
|
|
Paths = @(
|
|
'Client/analysis/App.xaml.cs',
|
|
'Client/analysis/AssemblyInfo.cs',
|
|
'Client/analysis/Shell/MainWindow.Backend.cs',
|
|
'Client/analysis/Shell/MainWindow.HooksArm.cs',
|
|
'Client/analysis/Shell/MainWindow.Inspectors.cs',
|
|
'Client/analysis/Shell/MainWindow.IntelDetailsProvider.cs',
|
|
'Client/analysis/Shell/MainWindow.xaml',
|
|
'Client/analysis/Shell/MainWindow.xaml.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/shell: add settings surface'
|
|
Paths = @(
|
|
'Client/analysis/Settings',
|
|
'Client/analysis/Shell/MainWindow.Settings.cs',
|
|
'Client/analysis/Windows/InterfaceSettingsWindow.xaml',
|
|
'Client/analysis/Windows/InterfaceSettingsWindow.xaml.cs',
|
|
'Client/analysis/Windows/LaneSettingsWindow.xaml.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/theme: add light theme and chrome helpers'
|
|
Paths = @(
|
|
'Client/analysis/Themes/DarkTheme.xaml',
|
|
'Client/analysis/Themes/LightTheme.xaml',
|
|
'Client/analysis/Theming/ThemedMessageBox.cs',
|
|
'Client/analysis/Theming/UiPalette.cs',
|
|
'Client/analysis/Theming/WindowChromeBehavior.cs',
|
|
'Client/analysis/Theming/WindowThemeHelper.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/panes: refresh ETW and event panes'
|
|
Paths = @(
|
|
'Client/analysis/Panes/EtwPane.xaml',
|
|
'Client/analysis/Panes/EtwPane.xaml.cs',
|
|
'Client/analysis/Panes/EventsPane.xaml',
|
|
'Client/analysis/Panes/EventsPane.xaml.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/panes: refresh filesystem and heuristics panes'
|
|
Paths = @(
|
|
'Client/analysis/Panes/FilesystemPane.xaml',
|
|
'Client/analysis/Panes/FilesystemPane.xaml.cs',
|
|
'Client/analysis/Panes/HeuristicsPane.xaml',
|
|
'Client/analysis/Panes/HeuristicsPane.xaml.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/panes: replace IPC uplink pane'
|
|
Paths = @('Client/analysis/Panes/IpcUplinkPane.xaml', 'Client/analysis/Panes/IpcUplinkPane.xaml.cs')
|
|
},
|
|
@{
|
|
Message = 'ui/panes: expand performance pane'
|
|
Paths = @('Client/analysis/Panes/PerformancePane.xaml', 'Client/analysis/Panes/PerformancePane.xaml.cs')
|
|
},
|
|
@{
|
|
Message = 'ui/panes: update process and registry panes'
|
|
Paths = @(
|
|
'Client/analysis/Panes/ProcessRelationsPane.xaml',
|
|
'Client/analysis/Panes/ProcessRelationsPane.xaml.cs',
|
|
'Client/analysis/Panes/RegistryPane.xaml',
|
|
'Client/analysis/Panes/RegistryPane.xaml.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/windows: update diagnostics and disassembly views'
|
|
Paths = @(
|
|
'Client/analysis/Windows/DiagnosticsWindow.xaml',
|
|
'Client/analysis/Windows/DiagnosticsWindow.xaml.cs',
|
|
'Client/analysis/Windows/DirectSyscallSuspectWindow.xaml',
|
|
'Client/analysis/Windows/DirectSyscallSuspectWindow.xaml.cs',
|
|
'Client/analysis/Windows/DisassemblyWindow.xaml',
|
|
'Client/analysis/Windows/DisassemblyWindow.xaml.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/windows: update evidence inspector views'
|
|
Paths = @(
|
|
'Client/analysis/Windows/ChildProcessGraphWindow.xaml.cs',
|
|
'Client/analysis/Windows/EventLogWindow.xaml.cs',
|
|
'Client/analysis/Windows/HandleEvidenceWindow.xaml',
|
|
'Client/analysis/Windows/HandleEvidenceWindow.xaml.cs',
|
|
'Client/analysis/Windows/SimpleEventDetailWindow.xaml',
|
|
'Client/analysis/Windows/SimpleEventDetailWindow.xaml.cs',
|
|
'Client/analysis/Windows/TelemetryInspectorWindow.xaml',
|
|
'Client/analysis/Windows/TelemetryInspectorWindow.xaml.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/windows: update thread stack views'
|
|
Paths = @(
|
|
'Client/analysis/Windows/ParallelStacksWindow.xaml',
|
|
'Client/analysis/Windows/ParallelStacksWindow.xaml.cs',
|
|
'Client/analysis/Windows/ThreadStackWindow.xaml',
|
|
'Client/analysis/Windows/ThreadStackWindow.xaml.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/windows: update launch and enrollment flows'
|
|
Paths = @(
|
|
'Client/analysis/Windows/FaultNotificationWindow.cs',
|
|
'Client/analysis/Windows/LaunchParametersWindow.xaml',
|
|
'Client/analysis/Windows/LaunchParametersWindow.xaml.cs',
|
|
'Client/analysis/Windows/LoadingWindow.xaml',
|
|
'Client/analysis/Windows/LoadingWindow.xaml.cs',
|
|
'Client/analysis/Windows/ProcessPickerWindow.xaml',
|
|
'Client/analysis/Windows/ProcessPickerWindow.xaml.cs',
|
|
'Client/analysis/Windows/StartupWelcomeWindow.xaml',
|
|
'Client/analysis/Windows/StartupWelcomeWindow.xaml.cs',
|
|
'Client/analysis/Windows/VmRegistrationWindow.xaml',
|
|
'Client/analysis/Windows/VmRegistrationWindow.xaml.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/windows: refresh floating window hosts'
|
|
Paths = @(
|
|
'Client/analysis/Windows/Floating/EtwFloatWindow.cs',
|
|
'Client/analysis/Windows/Floating/EventsFloatWindow.cs',
|
|
'Client/analysis/Windows/Floating/HeuristicsFloatWindow.cs',
|
|
'Client/analysis/Windows/Floating/MemoryInspectorWindow.cs',
|
|
'Client/analysis/Windows/Floating/PerformanceFloatWindow.cs'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'ui/host: remove legacy operator shell'
|
|
Paths = @('Client/host')
|
|
},
|
|
@{
|
|
Message = 'runner: add headless capture runner'
|
|
Paths = @('Client/runner')
|
|
},
|
|
@{
|
|
Message = 'build/scripts: replace legacy publish scripts'
|
|
Paths = @(
|
|
'Scripts/ci-surface.ps1',
|
|
'Scripts/publish-interfaces.ps1',
|
|
'Scripts/publish.NET.ps1',
|
|
'Scripts/Compile-Win32Resource.ps1'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'build/scripts: add external rule bundle normalizer'
|
|
Paths = @('Scripts/Build-YaraBundle.ps1')
|
|
},
|
|
@{
|
|
Message = 'build/scripts: add VM registration workflow'
|
|
Paths = @('Scripts/Register-BlackbirdVm.ps1')
|
|
},
|
|
@{
|
|
Message = 'build/scripts: update installer optional components'
|
|
Paths = @('Scripts/installer.ps1')
|
|
},
|
|
@{
|
|
Message = 'build/scripts: update remover optional cleanup'
|
|
Paths = @('Scripts/remover.ps1')
|
|
},
|
|
@{
|
|
Message = 'build/scripts: update Tempest invoke packaging'
|
|
Paths = @('Scripts/tempest-invoke.ps1')
|
|
},
|
|
@{
|
|
Message = 'build/solution: add dllhost and runner projects'
|
|
Paths = @(
|
|
'Blackbird.slnx',
|
|
'VCXProj/BlackbirdDllHost.vcxproj',
|
|
'VCXProj/BlackbirdDllHost.vcxproj.filters',
|
|
'VCXProj/BlackbirdRunner.csproj',
|
|
'VCXProj/Blackbird.Runner.manifest',
|
|
'VCXProj/Blackbird.Runner.rc'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'build/kernel: include diagnostics and callback sources'
|
|
Paths = @('VCXProj/Blackbird.vcxproj', 'VCXProj/Blackbird.vcxproj.filters')
|
|
},
|
|
@{
|
|
Message = 'build/controller: update controller project sources'
|
|
Paths = @('VCXProj/BlackbirdController.vcxproj', 'VCXProj/BlackbirdController.vcxproj.filters')
|
|
},
|
|
@{
|
|
Message = 'build/interface: update interface resources'
|
|
Paths = @('VCXProj/BlackbirdInterface.csproj', 'VCXProj/Blackbird.Interface.manifest', 'VCXProj/Blackbird.Interface.rc')
|
|
},
|
|
@{
|
|
Message = 'build/sensor: update sensor and ioctl test projects'
|
|
Paths = @(
|
|
'VCXProj/BlackbirdSensorCore.vcxproj',
|
|
'VCXProj/BlackbirdSensorCore.vcxproj.filters',
|
|
'VCXProj/BlackbirdIoctlTest.vcxproj',
|
|
'VCXProj/BlackbirdIoctlTest.vcxproj.filters'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'build/usermode: refresh shared props and manifests'
|
|
Paths = @(
|
|
'VCXProj/Blackbird.UserMode.Common.props',
|
|
'VCXProj/Blackbird.UserMode.manifest',
|
|
'VCXProj/Blackbird.Version.rc',
|
|
'VCXProj/Directory.Build.props'
|
|
)
|
|
},
|
|
@{
|
|
Message = 'build/operator: retire legacy operator projects'
|
|
Paths = @('VCXProj/BlackbirdOperator.csproj', 'VCXProj/BlackbirdExamples.vcxproj')
|
|
},
|
|
@{
|
|
Message = 'build/scripts: add curated public commit helper'
|
|
Paths = @('Scripts/commit-public-worktree.bat', 'Scripts/Commit-PublicWorktree.ps1')
|
|
}
|
|
)
|
|
|
|
Write-Host "Repository: $repoRoot"
|
|
Write-Host "Commit groups: $($groups.Count)"
|
|
if ($PlanOnly) {
|
|
Write-Host 'Plan-only mode: no git index or commits will be modified.'
|
|
} else {
|
|
Write-Host 'Commit mode: commits will be created locally only. This script never pushes.'
|
|
}
|
|
|
|
foreach ($group in $groups) {
|
|
Commit-Group -Message $group.Message -Paths $group.Paths
|
|
}
|
|
|
|
if ($PlanOnly) {
|
|
exit 0
|
|
}
|
|
|
|
$remaining = & git status --short --untracked-files=all
|
|
$publicRemaining = @()
|
|
foreach ($line in $remaining) {
|
|
$normalized = Convert-ToGitPath $line.Substring([Math]::Min(3, $line.Length))
|
|
$skip = $false
|
|
foreach ($skipPath in $privateOrExternalPaths) {
|
|
$candidate = Convert-ToGitPath $skipPath
|
|
if ($candidate.EndsWith('/')) {
|
|
if ($normalized.StartsWith($candidate, [System.StringComparison]::OrdinalIgnoreCase)) {
|
|
$skip = $true
|
|
break
|
|
}
|
|
} elseif ($normalized.IndexOf($candidate, [System.StringComparison]::OrdinalIgnoreCase) -ge 0) {
|
|
$skip = $true
|
|
break
|
|
}
|
|
}
|
|
|
|
if (-not $skip) {
|
|
$publicRemaining += $line
|
|
}
|
|
}
|
|
|
|
if ($publicRemaining.Count -gt 0) {
|
|
Write-Warning 'Some public-looking changes were not included in the curated commit plan:'
|
|
foreach ($line in $publicRemaining) {
|
|
Write-Warning " $line"
|
|
}
|
|
Write-Warning 'Review these manually before pushing anything.'
|
|
}
|
|
|
|
Write-Host 'Done. Local commits were created; nothing was pushed.'
|