Scripts/slumberjack-alpha.ps1

Param(
    [switch]$DownloadOnly,
    [string]$EventCollector=$env:COMPUTERNAME,
    [ipaddress]$ElasticHost='127.0.0.1'
)

$Start = Get-Location
$DownloadFolder = 'Slumberjack'

function CheckIf-DomainAdmin {
    $UserId = [Security.Principal.WindowsIdentity]::GetCurrent()
    $AdminId = [Security.Principal.WindowsBuiltInRole]::Administrator
    $CurrentUser = New-Object Security.Principal.WindowsPrincipal($UserId)
    $RunningAsAdmin = $CurrentUser.IsInRole($AdminId)
    if (-not $RunningAsAdmin) { 
        Write-Output "`n[x] This script requires administrator privileges.`n"
        Abort
    }
}

function CheckIf-DomainController {
    $ProductType = (Get-WmiObject -Class Win32_OperatingSystem).ProductType
    if ($ProductType -ne 2) {
        Write-Output "`n[x] This script must be executed on a Domain Controller.`n"
        Abort
    }
}

function Download-Software {
    $Sysmon = 'sysmon.exe', 'sysmon64.exe', 'Eula.txt'
    $SysmonConfig = 'sysmonconfig-export.xml'
    $Winlogbeat = 'winlogbeat.exe', 'winlogbeat.yml'
    $Slumberjack = 'Install-Sysmon.ps1', 'sysmonsubscription.xml', 'Install-Winlogbeat.ps1'
    $Software = $Sysmon + $SysmonConfig + $Winlogbeat + $Slumberjack
    $CurrentDirectory = Get-ChildItem $pwd -Recurse
    $Found = @()
    $Missing = @()
    $Download = @{}

    if (-not (Test-Path $DownloadFolder)) { 
        New-Item -ItemType Directory $DownloadFolder | Out-Null
    }

    $Software | ForEach-Object {
        $File = $_
        if ($CurrentDirectory.Name -contains $File) {
            $Found += $CurrentDirectory | Where-Object { $_.Name -eq $File }
        } else {
            $Missing += $File
        }
    }

    $Found | ForEach-Object {
        if ($_.Directory.Name -notlike $DownloadFolder) {
            Copy-Item $_.FullName -Destination ".\$DownloadFolder"
        }
    }

    $Missing | ForEach-Object {
        if (($Sysmon -contains $_) -and ($Download.Keys -notcontains 'Sysmon')) { 
            $Download.Add('Sysmon','https://download.sysinternals.com/files/Sysmon.zip') 
        }
    
        elseif (($SysmonConfig -contains $_) -and ($Download.Keys -notcontains 'Sysmon-config')) { 
            $Download.Add('Sysmon-config','https://github.com/SwiftOnSecurity/sysmon-config/archive/master.zip') 
        }

        elseif (($Winlogbeat -contains $_) -and ($Download.Keys -notcontains 'Winlogbeat')) { 
            $Download.Add('Winlogbeat','https://artifacts.elastic.co/downloads/beats/winlogbeat/winlogbeat-6.2.4-windows-x86_64.zip ') 
        }

        elseif (($Slumberjack -contains$_) -and ($Download.Keys -notcontains 'SlumberjackFiles')){ 
            $Download.Add('SlumberjackFiles','https://github.com/cyberphor/Slumberjack/archive/master.zip')     
        }
    }

    $Download.GetEnumerator() | 
    ForEach-Object {
        $ZipFile = '.\' + $_.Key + '.zip'
        Invoke-WebRequest -Uri $_.Value -OutFile $ZipFile
        Unblock-File $ZipFile
        Expand-Archive $ZipFile
        Remove-Item -Recurse $ZipFile
    }

    Get-ChildItem $pwd -Recurse | 
    ForEach-Object {
        if ($_.Name -in $Missing) {
            Copy-Item $_.Fullname -Destination $DownloadFolder
        }
    }
     
    '.\Sysmon','.\Sysmon-config','.\Winlogbeat','.\SlumberjackFiles' | 
    ForEach-Object { if (Test-Path $_) { Remove-Item -Recurse $_ } }
}

function Deploy-Sysmon {
    $Policy = 'Deploy-Sysmon'
    $Script = 'Install-Sysmon.ps1'
    $Comment = 'Uses a "Startup" script to install and configure the "Sysmon" service.'
    $Files = @(
        ".\$DownloadFolder\$Script", 
        ".\$DownloadFolder\Eula.txt",
        ".\$DownloadFolder\Sysmon.exe", 
        ".\$DownloadFolder\Sysmon64.exe",
        ".\$DownloadFolder\sysmonconfig-export.xml"
    )

    if (Test-Path ".\$DownloadFolder\$Script") {
        New-GPO -Name $Policy -Comment $Comment

        $Domain = (Get-WmiObject -Class Win32_ComputerSystem).Domain
        $Sysvol = "$env:SystemRoot\SYSVOL\sysvol\$Domain\Policies"
        $Guid = (Get-GPO -Name $Policy).Id.Guid
        $Gpo = "$Sysvol\{$Guid}"
        $MachineFolder = "$Gpo\Machine"
        $ScriptsFolder = "$Gpo\Machine\Scripts"
        $StartupScriptsFolder = "$ScriptsFolder\Startup"

        New-Item -ItemType Directory -Name 'Scripts' -Path $MachineFolder
        New-Item -ItemType Directory -Name 'Startup' -Path $ScriptsFolder
        Copy-Item $Files -Destination $StartupScriptsFolder

        $PsscriptsFile = "$ScriptsFolder\psscripts.ini"
        '','[Startup]',"0CmdLine=$Script",'0Parameters=' | Out-File -Encoding unicode $PsscriptsFile 
        $PsscriptsFile = Get-Item $PsscriptsFile
        $PsscriptsFile.Attributes = 'Hidden'

        $GptFile = "$Gpo\GPT.ini"
        $OldVersion = '0'
        $NewVersion = '2'
        (Get-Content -Path $GptFile) -replace $OldVersion, $NewVersion | Set-Content -Path $GptFile

        $SearchAdsi = New-Object DirectoryServices.DirectorySearcher
        $SearchAdsi.Filter = "(&(objectCategory=groupPolicyContainer)(Name={$Guid}))"
        $GpoInAd = $SearchAdsi.FindAll().Item(0)
        $GpoInAd = $GpoInAd.GetDirectoryEntry()
        $GuidPairForClientAndMmcSnapIn = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}]'
        $GpoInAd.Properties['gpcmachineextensionnames'].Value = $GuidPairForClientAndMmcSnapIn
        $GpoInAd.Properties['versionNumber'].Value = $NewVersion
        $GpoInAd.CommitChanges()

        $Ou = (Get-ADDomain -Current LocalComputer).DistinguishedName
        New-GPLink -Name $Policy -Target $Ou
    }
}

function Enable-WinRM {
    $Policy = 'Enable-WinRM'
    $Comment = 'Enables and configures the "Windows Remote Management (WinRM)" service.'
    New-GPO $Policy -Comment $Comment

    $Key = 'HKLM\Software\Policies\Microsoft\Windows\WinRM\Service'
    $ValueName = 'AllowAutoConfig'
    $Value = 1
    $Type = 'Dword'
    Set-GPRegistryValue -Name $Policy -Key $Key -ValueName $ValueName -Value $Value -Type $Type

    $ValueName = 'IPv4Filter'
    $Value = '*'
    $Type = 'String'
    Set-GPRegistryValue -Name $Policy -Key $Key -ValueName $ValueName -Value $Value -Type $Type

    $ValueName = 'IPv6Filter'
    $Value = '*'
    $Type = 'String'
    Set-GPRegistryValue -Name $Policy -Key $Key -ValueName $ValueName -Value $Value -Type $Type

    $fwrule = 'v2.10|Action=Allow|Active=TRUE|Dir=In|Protocol=6|LPort=5985|'
    'App=System|Name=@FirewallAPI.dll,-30253|Desc=@FirewallAPI.dll'
    $fwrule += ',-30256|EmbedCtxt=@FirewallAPI.dll,-30252'
    $Key = 'HKLM\Software\Policies\Microsoft\WindowsFirewall\FirewallRules'    
    $ValueName = 'WINRM-HTTP-In-TCP'
    $Value = $fwrule
    $Type = 'String'
    Set-GPRegistryValue -Name $Policy -Key $Key -ValueName $ValueName -Value $Value -Type $Type

    $Key = 'HKLM\SYSTEM\CurrentControlSet\Services\WinRM'    
    $ValueName = 'Start'
    $Value = 2
    $Type = 'Dword'
    Set-GPRegistryValue -Name $Policy -Key $Key -ValueName $ValueName -Value $Value -Type $Type

    $Ou = (Get-ADDomain -Current LocalComputer).DistinguishedName
    New-GPLink -Name $Policy -Target $Ou
}

function Configure-WEF {
    $Policy = 'Configure-WEF'
    $Comment = 'Configures "Windows Event Forwarding."'
    New-GPO -Name $Policy -Comment $Comment

    $Key = 'HKLM\Software\Policies\Microsoft\Windows\EventLog\EventForwarding\SubscriptionManager'
    $Server = ([System.Net.Dns]::GetHostByName(($EventCollector))).Hostname
    $Value = 'Server=http://' + $Server + ':5985/wsman/SubscriptionManager/WEC,Refresh=10'
    $Type = 'String'
    Set-GPRegistryValue -Name $Policy -Key $Key -Value $Value -Type $Type

    $Ou = (Get-ADDomain -Current LocalComputer).DistinguishedName
    New-GPLink -Name $Policy -Target $Ou
}

function Deploy-EventCollectors {
    $GroupName = 'Event Collectors'
    $GroupScope = 'Global'
    $GroupCategory = 'Security'
    $Description = 'Members of this group collect Sysmon logs and share them via Winlogbeat.'

    if (-not (Get-ADGroup -Filter {Name -eq $GroupName})) {
        New-ADGroup -Name $GroupName `
            -SamAccountName $GroupName `
            -DisplayName $GroupName `
            -GroupScope $GroupScope `
            -GroupCategory $GroupCategory `
            -Description $Description
    }
    
    if (-not (Get-ADGroup -Filter {Name -eq $GroupName -and Member -like $EventCollector})) {
        $Member = $EventCollector + '$'
        Add-ADGroupMember $GroupName -Members $Member
    }

    $Policy = 'Deploy-EventCollectors'
    $Script = 'Install-Winlogbeat.ps1'
    $Comment = 'Enables the "Windows Event Collection" service and installs "Winlogbeat."'
    $Files = @(
        ".\$DownloadFolder\$Script";
        ".\$DownloadFolder\winlogbeat.yml";
        ".\$DownloadFolder\winlogbeat.exe";
        ".\$DownloadFolder\sysmonsubscription.xml"
    ) 

    $ConfigFile = "$DownloadFolder\winlogbeat.yml"

    if (Test-Path $ConfigFile) {
        $Config = Get-Content $ConfigFile

        $Config = $Config.Replace('winlogbeat.event_logs:',"winlogbeat.event_logs:`n -name: ForwardedEvents")
        $Config = $Config.Replace('- name: Application','#- name: Application')
        $Config = $Config.Replace('ignore_older: 72h','#ignore_older: 72h')
        $Config = $Config.Replace('- name: Security','#- name: Security')
        $Config = $Config.Replace('- name: System','#- name: System')
        $Config = $Config.Replace('setup.template.settings:','#setup.template.settings:')
        $Config = $Config.Replace('index.number_of_shards: 3','#index.number_of_shards: 3')
        $Config = $Config.Replace('setup.kibana:','#setup.kibana:')
        $Config = $Config.Replace('output.elasticsearch:','#output.elasticsearch:')
        $Config = $Config.Replace('hosts: ["localhost:9200"]','#hosts: ["localhost:9200"]')
        $Config = $Config.Replace('#output.logstash:','output.logstash:')
        $Config = $Config.Replace('#hosts: ["localhost:5044"]','hosts: ["' + $ElasticHost + ':5044"]')

        $Config | Out-File ".\foo.yml"
    }

    if (Test-Path ".\$DownloadFolder\$Script") {
        New-GPO -Name $Policy -Comment $Comment

        $Domain = (Get-WmiObject -Class Win32_ComputerSystem).Domain
        $Sysvol = "$env:SystemRoot\SYSVOL\sysvol\$Domain\Policies"
        $Guid = (Get-GPO -Name $Policy).Id.Guid
        $Gpo = "$Sysvol\{$Guid}"
        $MachineFolder = "$Gpo\Machine"
        $ScriptsFolder = "$Gpo\Machine\Scripts"
        $StartupScriptsFolder = "$ScriptsFolder\Startup"

        New-Item -ItemType Directory -Name 'Scripts' -Path $MachineFolder
        New-Item -ItemType Directory -Name 'Startup' -Path $ScriptsFolder
        Copy-Item $Files -Destination $StartupScriptsFolder

        $PsscriptsFile = "$ScriptsFolder\psscripts.ini"
        '','[Startup]',"0CmdLine=$Script",'0Parameters=' | Out-File -Encoding unicode $PsscriptsFile 
        $PsscriptsFile = Get-Item $PsscriptsFile
        $PsscriptsFile.Attributes = 'Hidden'

        $GptFile = "$Gpo\GPT.ini"
        $OldVersion = '0'
        $NewVersion = '2'
        (Get-Content -Path $GptFile) -replace $OldVersion, $NewVersion | Set-Content -Path $GptFile

        $SearchAdsi = New-Object DirectoryServices.DirectorySearcher
        $SearchAdsi.Filter = "(&(objectCategory=groupPolicyContainer)(Name={$Guid}))"
        $GpoInAd = $SearchAdsi.FindAll().Item(0)
        $GpoInAd = $GpoInAd.GetDirectoryEntry()
        $GuidPairForClientAndMmcSnapIn = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}]'
        $GpoInAd.Properties['gpcmachineextensionnames'].Value = $GuidPairForClientAndMmcSnapIn
        $GpoInAd.Properties['versionNumber'].Value = $NewVersion
        $GpoInAd.CommitChanges()

        $GroupName = 'Event Collectors'
        Set-GPPermissions -Name $Policy -Replace -PermissionLevel GpoRead -TargetName 'Authenticated Users' -TargetType Group
        Set-GPPermissions -Name $Policy -PermissionLevel GpoApply -TargetName $GroupName -TargetType Group

        $Ou = (Get-ADDomain -Current LocalComputer).DistinguishedName
        New-GPLink -Name $Policy -Target $Ou
    }
}

function Abort {
    Set-Location $Start
    break
}

Clear-Host

if ($DownloadOnly) { Download-Software } 
else {
    CheckIf-DomainAdmin
    CheckIf-DomainController
    Download-Software
    Deploy-Sysmon
    Enable-WinRM
    Configre-WEF
    Deploy-EventCollectors
}

Abort