среда, 31 октября 2018 г.

User account blocking for 100 days is not logged and mailbox not used for another actions (full access/forward mails)

#by me ;)

import-module activedirectory
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn;

$LOGFILE="c:\scripts\aduserblock1.log"
$SMTPSERVER = "mail.domain.local"

function log([string]$txt)
{ add-content $LOGFILE "$(Get-date): $txt" }


function SendEmaiToSD($msgstr){
Send-MailMessage -From powershell@domain.local -To sd@domain.local -Subject "Скрипт блокировки учетных записей в домене domain.loc вызвал ошибку выполнения." -Body $($msgstr) -SmtpServer $SMTPSERVER -Priority High -Encoding UTF8
}

function main{
$mdate = (Get-date).Add(-100d)
$oldusers = get-aduser -Filter {Enabled -eq $true -and msExchMailboxGuid -like "*"} -properties samaccountname, lastlogondate | where{$_.samaccountname -match "^\w{1,2}\.\w+$" -and $_.LastLogonDate -lt $mdate -and $_.LastLogonDate -ne $null} | sort-object lastlogondate | select samaccountname, lastlogondate

foreach($user in $oldusers){
$userIdentities = @()
$usermailbox = get-mailbox -Identity $($user.samaccountname)
if($usermailbox.ForwardingAddress -ne $null){
#write-host detected Forward for $user.samaccountname
continue
}
foreach($userSecurityIdentifier in ($usermailbox | get-mailboxpermission | ?{$_.IsInherited -eq $false -and $_.user -notlike "*NT*AUTH*"}).User.SecurityIdentifier.Value){
if($userSecurityIdentifier -eq $null){
continue
}
$adobject = get-adobject -Filter 'objectSID -like $userSecurityIdentifier -and ObjectClass -eq "user"'
$userIdentities+=$adobject
}
if($userIdentities.Count -gt 0){
#write-host User  $user.samaccountname has another owners for mailbox lastlogondate=$user.lastlogondate
continue
}
log("User account "+$user.samaccountname+" Disabled")
Set-ADUser -Identity $user.samaccountname -Enabled $false
}
}

try{
main
}
catch
{
$ErrorMessage = $_.Exception.Message
SendEmaiToSD($ErrorMessage)
}

вторник, 11 сентября 2018 г.

Crypt. C#
Появилась задача сделать ActiveX компонент для encrypt/decrypt со статическими ключами/солью. Разбор полётов с примерами породил такой сырец:
(внимание гостям, это рабочий варинт. не прилизан, не урезан не обфусцирован, много копи-паст :))
Как есть. Вектор и соль менять.

using System;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;
using System.Security.Cryptography;

namespace AlexCrypt
{
    [ComVisible(true)]
    [Guid("235D87E1-9BFA-47AB-9E97-CF1A2D342054")]
    public interface IAlexCrypt
    {
        string Encrypt(
            string cipherText,
            string passPhrase);
        string Decrypt(
            string cipherText,
            string passPhrase);
    }

    [Guid("162E64E6-99D6-47BB-B52E-1A4205EFF5AF")]
    [ClassInterface(ClassInterfaceType.None)]
    //[ProgId("AlexCrypt")]
    [ComVisible(true)]
    public class AlexCrypt : IAlexCrypt
    {
        public string Encrypt
        (
            string plainText,
            string passPhrase)
        {
            string saltValue = "*4b5FHMwa$h22=Wh";
            string hashAlgorithm = "SHA1";
            int passwordIterations = 2;
            string initVector = "sQY*K&TF8MMcR3=r";
            int keySize = 256;
            string cipherText = "";

            try
            {
                byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
                byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
                byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

                PasswordDeriveBytes password = new PasswordDeriveBytes
                (
                    passPhrase,
                    saltValueBytes,
                    hashAlgorithm,
                    passwordIterations
                );
                byte[] keyBytes = password.GetBytes(keySize / 8);
                RijndaelManaged symmetricKey = new RijndaelManaged();
                symmetricKey.Mode = CipherMode.CBC;
                ICryptoTransform encryptor = symmetricKey.CreateEncryptor
                (
                    keyBytes,
                    initVectorBytes
                );
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream
                (
                    memoryStream,
                    encryptor,
                    CryptoStreamMode.Write
                );

                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                cryptoStream.FlushFinalBlock();
                byte[] cipherTextBytes = memoryStream.ToArray();
                memoryStream.Close();
                cryptoStream.Close();
                cipherText = Convert.ToBase64String(cipherTextBytes);
            }
            catch
            {
                cipherText = "Error";
            }
            return cipherText;
        }

        public string Decrypt
        (
            string cipherText,
            string passPhrase
        )
        {
            string saltValue = "*4b5FHMwa$h22=Wh";
            string hashAlgorithm = "SHA1";
            int passwordIterations = 2;
            string initVector = "sQY*K&TF8MMcR3=r";
            int keySize = 256;
            string plainText = "";
            try
            {
                byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
                byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
                byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
                PasswordDeriveBytes password = new PasswordDeriveBytes
                (
                    passPhrase,
                    saltValueBytes,
                    hashAlgorithm,
                    passwordIterations
                );
                byte[] keyBytes = password.GetBytes(keySize / 8);
                RijndaelManaged symmetricKey = new RijndaelManaged();
                symmetricKey.Mode = CipherMode.CBC;
                ICryptoTransform decryptor = symmetricKey.CreateDecryptor
                (
                    keyBytes,
                    initVectorBytes
                );
                MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
                CryptoStream cryptoStream = new CryptoStream
                (
                    memoryStream,
                    decryptor,
                    CryptoStreamMode.Read
                );
                byte[] plainTextBytes = new byte[cipherTextBytes.Length];
                int decryptedByteCount = cryptoStream.Read
                (
                    plainTextBytes,
                    0,
                    plainTextBytes.Length
                );
                memoryStream.Close();
                cryptoStream.Close();
                plainText = Encoding.UTF8.GetString
                (
                    plainTextBytes,
                    0,
                    decryptedByteCount
                );
            }
            catch
            {   
                plainText = "Error";
            }
            return plainText;
        }
    }
}

Использование функции DsGetDcName
https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsgetdcnamea
C#

//by me :P
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Windows.Forms;

namespace dsgetdc
{
    class Program
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        struct DOMAIN_CONTROLLER_INFO
        {
            [MarshalAs(UnmanagedType.LPTStr)]
            public string DomainControllerName;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string DomainControllerAddress;
            public uint DomainControllerAddressType;
            public Guid DomainGuid;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string DomainName;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string DnsForestName;
            public uint Flags;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string DcSiteName;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string ClientSiteName;
        }

        [DllImport("Netapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern int DsGetDcName
          (
            [MarshalAs(UnmanagedType.LPTStr)]
    string ComputerName,
            [MarshalAs(UnmanagedType.LPTStr)]
    string DomainName,
            [In] int DomainGuid,
            [MarshalAs(UnmanagedType.LPTStr)]
    string SiteName,
            [MarshalAs(UnmanagedType.U4)]
    DSGETDCNAME_FLAGS flags,
            out IntPtr pDOMAIN_CONTROLLER_INFO
          );

        [DllImport("Netapi32.dll", SetLastError = true)]
        static extern int NetApiBufferFree(IntPtr Buffer);

        [Flags]
        public enum DSGETDCNAME_FLAGS : uint
        {
            DS_FORCE_REDISCOVERY = 0x00000001,
            DS_DIRECTORY_SERVICE_REQUIRED = 0x00000010,
            DS_DIRECTORY_SERVICE_PREFERRED = 0x00000020,
            DS_GC_SERVER_REQUIRED = 0x00000040,
            DS_PDC_REQUIRED = 0x00000080,
            DS_BACKGROUND_ONLY = 0x00000100,
            DS_IP_REQUIRED = 0x00000200,
            DS_KDC_REQUIRED = 0x00000400,
            DS_TIMESERV_REQUIRED = 0x00000800,
            DS_WRITABLE_REQUIRED = 0x00001000,
            DS_GOOD_TIMESERV_PREFERRED = 0x00002000,
            DS_AVOID_SELF = 0x00004000,
            DS_ONLY_LDAP_NEEDED = 0x00008000,
            DS_IS_FLAT_NAME = 0x00010000,
            DS_IS_DNS_NAME = 0x00020000,
            DS_RETURN_DNS_NAME = 0x40000000,
            DS_RETURN_FLAT_NAME = 0x80000000,
            DS_TRY_NEXTCLOSEST_SITE = 0x00040000
        }

        private static DOMAIN_CONTROLLER_INFO GetDomainInfo()
        {
            DOMAIN_CONTROLLER_INFO domainInfo;
            const int ERROR_SUCCESS = 0;
            IntPtr pDCI = IntPtr.Zero;
            try
            {
                int val = DsGetDcName("", "", 0, "",
                DSGETDCNAME_FLAGS.DS_DIRECTORY_SERVICE_REQUIRED | DSGETDCNAME_FLAGS.DS_FORCE_REDISCOVERY |
                DSGETDCNAME_FLAGS.DS_RETURN_DNS_NAME | DSGETDCNAME_FLAGS.DS_TRY_NEXTCLOSEST_SITE, out pDCI);
                //check return value for error
                if (ERROR_SUCCESS == val)
                {
                    domainInfo = (DOMAIN_CONTROLLER_INFO)Marshal.PtrToStructure(pDCI, typeof(DOMAIN_CONTROLLER_INFO));
                }
                else
                {
                    throw new Win32Exception(val);
                }
            }
            finally
            {
                NetApiBufferFree(pDCI);
            }
            return domainInfo;
        }
        static void Main(string[] args)
        {
            DOMAIN_CONTROLLER_INFO DomainInfo;
            bool ret = true;
            while (ret)
            {
                DomainInfo = GetDomainInfo();
                string msg = "Using API DsGetDcName function with flags:\r\nDS_DIRECTORY_SERVICE_REQUIRED|DS_FORCE_REDISCOVERY|\r\n";
                msg += "DS_RETURN_DNS_NAME|DS_TRY_NEXTCLOSEST_SITE\r\n";
                msg += "===============================================\r\n\r\n";
                msg += "DnsForestName : " + DomainInfo.DnsForestName + "\r\n";
                msg += "DC-Site: " + DomainInfo.DomainControllerName + "\r\n";
                msg += "Client: " + DomainInfo.ClientSiteName + "\r\n\r\n\t TRY AGAIN?";
                MessageBoxButtons buttons = MessageBoxButtons.YesNo;
                if (System.Windows.Forms.MessageBox.Show(msg, "by me :P, 2018, moscoms", buttons) == DialogResult.No)
                    { ret = false; }
            }
        }
    }
}

понедельник, 10 сентября 2018 г.

In Exchange Management Shell (PS)

Get-GlobalAddressList | update-GlobalAdressList
Get-AddressList | update-AddressList
Get-OfflineAddressBook | Update-OfflineAddressBook

Those 3 commands will help you force the creation of new addressbooks and offline addressbooks

https://social.technet.microsoft.com/Forums/ie/en-US/593f807b-c103-4ceb-892c-9aa42cb79475/forcing-update-of-default-global-address-list?forum=exchangesvradminlegacy

четверг, 6 сентября 2018 г.

https://www.geotrust.eu/en/support/manuals/microsoft/all+windows+servers/export+private+key+or+certificate/


Next run OpenSSL to extract the private key, and the cert file

Export the private key file from the pfx file
openssl pkcs12 -in filename.pfx -nocerts -out key.pem
Export the certificate file from the pfx file
openssl pkcs12 -in filename.pfx -clcerts -nokeys -out cert.pem
Remove the passphrase from the private key
openssl rsa -in key.pem -out server.key

среда, 5 сентября 2018 г.

example prtg query for multiselect


https://myprg-server/sensors.htm?columns=objid,probe,device,name,type,interval,checkbox&filter_type=@sub(WMI)&filter_type=@sub(Windows)&filter_interval=0000000060

/sensors.htm?filter_tags=@tag(bandwidthsensor)
/sensors.htm?filter_tags=@tag(bandwidthsensor,snmptrafficsensor)
/sensors.htm?filter_tags=@tag(%2bbandwidthsensor,%2bsnmptrafficsensor)
/sensors.htm?filter_type=ping
/sensors.htm?filter_type=ping&filter_tags=@tag(myTag)
https://www.paessler.com/manuals/prtg9/libraries.htm

https://www.paessler.com/manuals/prtg9/libraries.htm

понедельник, 27 августа 2018 г.

(copy) https://blogs.msdn.microsoft.com/connector_space/2014/10/01/provision-a-home-directory-for-new-accounts/


##Passes Variables from workflow
#Comment out for Manual testing
Param($SamName,$HomeDir,$DriveLet)
if(-not(Get-Module -name ActiveDirectory))
    {
        Import-Module ActiveDirectory
    }
##Set Variables
$Domain =$(Get-ADDomain).name
$DomainDNS = $(Get-ADDomain).DNSRoot
$Spacer=" "
##Uncomment for Manual Testing
#$SamName = "amarsiglia"
#$homedir = "\\Portal\home\"+$samName
#$DriveLet= "H"
###
if ($homedir)
    {
#Create Home Directory
        mkdir $homedir
#Assign Access Rights
        $account=$Domain+"\"+$SamName
        $rights=[System.Security.AccessControl.FileSystemRights]::FullControl
        $inheritance=[System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit"
        $propagation=[System.Security.AccessControl.PropagationFlags]::None
        $allowdeny=[System.Security.AccessControl.AccessControlType]::Allow
        $dirACE=New-Object System.Security.AccessControl.FileSystemAccessRule ($account,$rights,$inheritance,$propagation,$allowdeny)
        $dirACL=Get-Acl $homedir
        $dirACL.AddAccessRule($dirACE)
        Set-Acl $homedir $dirACL
#Assign AD Attributes
Set-ADUser -Identity $SamName -Replace @{homeDirectory=$homedir;homeDrive=$DriveLet} -Confirm:$false
    }
Return "Success"

четверг, 16 августа 2018 г.

Проект защиты MS Exchange OWA от bruteforce

OWA. Брутфорсят.

Два варианта защиты:
1) установка iis advanced log 
доп инфа https://www.supinfo.com/articles/single/5713-windows-server-2012-create-advanced-logs-on-iis-8
добавляем для сайта owa указанные выше поля. Получаем лог, парсим отлупы, баним по ip  через брэндмауэр на 10 минут. 

2) Ставим nginx как reverspropxy для owa
Рабочее решение тут https://www.linux.org.ru/forum/admin/13670164
Нужный нам кусок для обработки находится в файле "C:\Program Files\Microsoft\Exchange Server\V14\ClientAccess\owa\auth\logon.aspx"

<tr><td><hr></td></tr>
<%
if (Reason == LogonReason.InvalidCredentials) {
%>
<tr id="trInvCrd" class="wrng">
<td><%=LocalizedStrings.GetHtmlEncoded(Strings.IDs.InvalidCredentialsMessage) %></td>
</tr>
<% } %>

Это место дописывает вот эту штуку
Подбираем этот кусок из nginx, каким-то образом. Далее создаем файл для fail2ban, прикручиваем fail2ban.
Вариант не годится - не работает сброс пароля из owa. Механизм сброса пароля неясен (передача шифрованного пароля в AD/LDAP неочевидна из nginx без дополнительного программирования. TMG имеет/имел специальную обработку процедуры сброса пароля LDAP для доменного контроллера)


вторник, 14 августа 2018 г.

Сенсор в prtg для детекта брутфорса аккаунта/ов ActiveDirectory

#by me ;)

#анализ делаем на выборке из 2000 событий из security журнала.
#из этих 2000 отбираем те у кторых ID = 4768 (auth event) и если в поле message есть код отлупа 0x6
#то получаем сколько за минуту пришло подобных отказов. Если их больше чем ТРИ в минуту, то высока вероятность подбора (бывает и 20 в минуту)

$domaincontrollers = ("my-DC01","my-DC02", "my-DC03")
$script = { 
$rawevents = Get-WinEvent -LogName 'Security' -MaxEvents 2000
$events = $rawevents | where{$_.id -eq 4768} | where{$_.message -like '*Код результата:*0x6*'} | sort-object TimeCreated
if($events -eq $null){
 return 0}
$minutes = ($events[-1].TimeCreated - $events[0].TimeCreated).Minutes
return [float]$events.Count/$minutes
}

$maxcount = 0
foreach($domaincontroller in $domaincontrollers){
  $result = [float](Invoke-Command -Computername $($domaincontroller) -ScriptBlock $script)
  if($maxcount -lt $result){
   $maxcount = $result
  }
}

$prtg = '<?xml version="1.0" encoding="Windows-1252" ?> 
<prtg>'

$prtg+="
<result> 
   <channel>Bruteforce AD channel</channel>
   <unit>Custom</unit>
   <customUnit>per minute</customUnit> 
   <float>0</float>
   <value>"+$([int]$maxcount)+"</value> 
   <warning>0</warning>
   <showChart>1</showChart> 
   <showTable>1</showTable>
   <LimitMode>1</LimitMode>
   <LimitMaxError>3</LimitMaxError>
   <LimitErrorMsg>Bruteforce AD account? On average blocks $([int]$maxcount) per minute</LimitErrorMsg>
</result>
</prtg>"

$prtg

четверг, 9 августа 2018 г.

reset all masquerade rules and set only for whitelisted ip
linux, bash

#!/bin/bash
#by me ;)

_input=./whitelist.db
IPT=/sbin/iptables

# Die if file not found
[ ! -f "$_input" ] && { echo "$0: File $_input not found."; exit 1; }

#clear (postrouting)
for i in $(iptables-save -t nat | grep MASQUERADE)
do
 $IPT -t nat -D POSTROUTING 1 > /dev/null 2>&1
done

egrep -v "^#|^$" $_input | while IFS= read -r ip
do
 $IPT -t nat -A POSTROUTING -s $ip -j MASQUERADE
done <"${_input}"

file whitelist.db example
10.0.0.7
10.0.0.8



среда, 1 августа 2018 г.

my powershell joke :)


$a=("|","/","-","\")
$clear = $false
while(1){
 foreach($i in $a){
 write-host -NoNewline "`r$i"
 start-sleep -Milliseconds 100
 if (!$clear){
  $clear = $true
  clear;
  "Erasing files C:*.*"
  }
 }
}

вторник, 3 июля 2018 г.

По шедулеру создаем группу для рассылки

#by me
import-module activedirectory -EA SilentlyContinue
$distrgroup = "(СР) ТАКАЯ ВОТ РАССЫЛКА"
$template = "*ЧАСТЬ НАЗВАНИЯ*"

$groupmembers = Get-ADGroupMember -Identity $($distrgroup)
foreach ($member in $groupmembers){
 if([boolean]((get-aduser $member -properties memberof).memberof -like $($template)) -eq $false){
  Remove-ADGroupMember -Identity $($distrgroup) -Members $member -cf:$false -EA SilentlyContinue
 }
}

$users = get-aduser -filter {enabled -eq $true} -properties memberof | where{$_.memberof -like $($template)}
foreach($user in $users){
trap {continue} Add-ADGroupMember -Identity $($distrgroup) -members $user -EA SilentlyContinue
}

понедельник, 21 мая 2018 г.

ipvsadm + nginx for rdp
nginx conf

worker_processes 2;
error_log /var/log/nginx/error.log;

events {
    worker_connections 16384;
}

stream {

error_log /var/log/nginx/stream_error_rdp.log;
upstream backend{
    server 10.0.0.2:443;
# weight=4 max_fails=1; #fail_timeout=20;
}

server{

    listen 443;
    proxy_pass backend;
}
}

ipvsadm understandable
Set default printer by Powershell (wmi)
Назначить принтер по умолчанию через powershell (wmi)

$Printername = 'Мой домашний Xerox iGen3'
$Printers = Get-WmiObject -Class Win32_Printer
$Printer = $Printers | Where{$_.Name -eq $Printername}
$Printer.SetDefaultPrinter() | out-null

четверг, 17 мая 2018 г.

Get information about virtual machines in Hyper-V (powershell, wmi)

#by alex
filter Import-CimXml 

   $CimXml = [Xml]$_ 
   $CimObj = New-Object -TypeName System.Object 
   foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY[@NAME='Name']")) 
      { 
         $CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE 
      } 
   foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY[@NAME='Data']")) 
      { 
         $CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE 
      } 
   $CimObj 


$vmsresult = @()
$HyperVServers = @("SERVER-VH01","SERVER-VH02","SERVER-VH03")
foreach($HyperVServer in $HyperVServers){
$VMNames = Invoke-Command -computername $HyperVServer {Get-VM  | where {$_.State -eq 'Running'}}
foreach($VMName in $VMNames){
write-host "Work for vm: $($VMName.Name)"
$query = "Select * From Msvm_ComputerSystem Where ElementName='" + $($VMName.Name) + "'"
$Vm = gwmi -computername $HyperVServer -namespace root\virtualization\v2 -query $query
$query = "Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"
$Kvp = gwmi -computername $HyperVServer -namespace root\virtualization\v2 -query $query
$vmdata = $Kvp.GuestIntrinsicExchangeItems | Import-CimXml
$VmObj = New-Object -TypeName System.Object
$VmObj | Add-Member -MemberType NoteProperty -Name "Name" -Value $($VMName.Name)
$VmObj | Add-Member -MemberType NoteProperty -Name "OS" -Value $(($vmdata | ?{$_.Name -eq "OSName"}).Data)
$VmObj | Add-Member -MemberType NoteProperty -Name "IPv4" -Value $(($vmdata | ?{$_.Name -eq "NetworkAddressIPv4"}).Data)
$vmsresult+=$VmObj
}

}

$vmsresult contains VMs

Get same information about virtual machines in PowerCLI :

Connect-VIServer VServer
get-vm * | where {$_.PowerState -eq "PoweredOn"} | Sort | Get-View -Property @("Guest.HostName", "Guest.GuestFullName", "Guest.Ipaddress", "Name") | Select -Property @{N="HostName";E={$_.Guest.HostName}}, @{N="OS";E={$_.Guest.GuestFullName}}, @{N="IPv4";E={$_.Guest.IPaddress}}, @{N="VM Name";E={$_.Name}} | Format-Table -AutoSize



Get same information about hosts in AD by powershell :

$hostsresult = @()
$hosts = get-adcomputer -property * -Filter {Enabled -eq $true} | sort-object name | where {$_.OperatingSystem -like "*Server*"}
foreach($shost in $hosts){
 write-host "Work for $shost"
 $HostObj = New-Object -TypeName System.Object
 $HostObj | Add-Member -MemberType NoteProperty -Name "Name" -Value $($shost.Name)
 $HostObj | Add-Member -MemberType NoteProperty -Name "OS" -Value $($shost.OperatingSystem)
 $ipaddresses = Invoke-Command -ComputerName $shost.name -EA SilentlyContinue -ScriptBlock {(gwmi Win32_NetworkAdapterConfiguration -EA SilentlyContinue | ?{$_.IPAddress}).IPAddress}
 if(-not $ipaddresses){$ipaddresses = "not access winrm"}
 if([string]$ipaddresses.GetType().BaseType -eq "array"){
  $ipaddresses = $ipaddresses -Join ', '
 }
  $HostObj | Add-Member -MemberType NoteProperty -Name "IPv4" -Value $ipaddresses
 $hostsresult+= $HostObj
}

$hostsresult contains hosts
================================================ (another)
$clusterNodes = Get-ClusterNode
ForEach($item in $clusterNodes){
$VMS= Get-VM -ComputerName $item.Name | Where-Object {$_.State –eq 'Running'} 

foreach ($vm in $VMS){
$hdds=Get-VMHardDiskDrive $vm
foreach($hdd in $hdds) {
  $hd = Invoke-Command -computername $item.Name -ScriptBlock {param($hdd); Get-VHD -Path $hdd.Path} -argumentlist $hdd
  $hd | select @{N='VMname'; e={$vm.Name}}, @{N='Mb'; e={$_.FileSize/1Mb}}, @{N='Time'; e={[int]($_.FileSize/1Mb/150/60+30)}}
 }
}

}

среда, 16 мая 2018 г.

IMSVA 9 (8/7) can not send emails to aliases

resolving:


DETAILS
To resolve this issue, do the following in the Database Mail Attribute:

Log in to the IMSVA shell via the Command Line Interface.
When logging in to the IMSVA shell or Command Line Prompt, make sure that you have root privilege.
Run the following command:
# /opt/trend/imss/PostgreSQL/bin/psql imss sa

Or
# cd /opt/trend/imss/PostgreSQL/bin/
# ./psql imss sa

On the "imss=#" prompt, type:
update tb_global_setting set value='proxyAddresses' where name='mail_attr';

To quit, type "\q".
Log on to the IMSVA web console. Disable recipient checking and then save the settings.
Go back to the IMSVA web console to enable recipient checking again and save the settings.
Check and confirm that the issue has been resolved.


понедельник, 14 мая 2018 г.


Получаем инфу по задачам на спулере:
Get spooler jobs powershell:
Get-WMIObject Win32_PerfFormattedData_Spooler_PrintQueue | sort-object -desc jobs, TotalJobsPrinted, JobErrors | Select Name, @{Expression={$_.jobs};Label="CurrentJobs"}, TotalJobsPrinted, JobErrors

Получаем сколько сожрано памяти в МБ деревом процесса spoolsv:
Get memory used in Mb by group spoolsv process:
((get-process spoolsv | Group-Object -Property ProcessName).Group | Measure-Object WorkingSet -Sum).Sum/1Mb

понедельник, 23 апреля 2018 г.

powershell + .net framework examples

Add-Type -AssemblyName 'System.Windows.Forms'
[windows.forms.messagebox]::show('body','title','OkCancel')
[Windows.Forms.Clipboard]::SetText("Hello world!")
[Windows.Forms.Clipboard]::GetText()

Add-Type -AssemblyName 'System.Web'
[Web.HTTPUtility]::UrlEncode('http://google.com')

пятница, 20 апреля 2018 г.

Get local admins  (Local Administrators group list memebers)

function get-localadmins{
  [cmdletbinding()]
  Param(
  [string]$computerName
  )
  $group = get-wmiobject win32_group -ComputerName $computerName -Filter "LocalAccount=True AND SID='S-1-5-32-544'"
  $query = "GroupComponent = `"Win32_Group.Domain='$($group.domain)'`,Name='$($group.name)'`""
  $list = Get-WmiObject win32_groupuser -ComputerName $computerName -Filter $query
  $list | %{$_.PartComponent} | % {$_.substring($_.lastindexof("Domain=") + 7).replace("`",Name=`"","\")}
}

четверг, 19 апреля 2018 г.

Two sites on one http port. apache rewrite

<VirtualHost *:80>
    DocumentRoot "/var/www/html/mysite1/"
    ServerName mysite1.com
    ServerAlias *.mysite1.com
    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^mysite1.com$ [NC]
    RewriteRule ^(.+)$ http://www.mysite1.com/$1 [R=301,L]
    ErrorLog /var/log/httpd/mysite1_error_log
    TransferLog /var/log/httpd/mysite1_access_log
</VirtualHost>

<VirtualHost *:80>
    DocumentRoot "/var/www/html/mysite2/"
    ServerName mysite2.com
    ServerAlias *.mysite2.com
    ErrorLog /var/log/httpd/mysite2_error_log
    TransferLog /var/log/httpd/mysite2_access_log
</VirtualHost>

пятница, 13 апреля 2018 г.

ip ip4 and subnet regexp patterns for python

patternIPv4 = re.compile(r"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$")
patternIPv4Subnet = re.compile(r"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])/(\d|1\d|2\d|3[0-2])$

среда, 11 апреля 2018 г.

powershell script to set permission for remote registry

#set rights for read remote registry
#https://support.microsoft.com/ru-ru/help/314837/how-to-manage-remote-access-to-the-registry
#*netsh firewall set service RemoteAdmin  *required

$login = "username@domain.win"

$path = "SYSTEM\CurrentControlSet\Control\SecurePipeServers\winreg"
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($($path), [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::takeownership)
$acl = $key.GetAccessControl()

$rule = New-Object System.Security.AccessControl.RegistryAccessRule ($($login),"ReadKey","Allow") 
$acl.SetAccessRule($rule)
$key.SetAccessControl($acl)

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/enable-psremoting?view=powershell-5.1

Enable-PSRemoting -SkipNetworkProfileCheck -Force
Set-NetFirewallRule -Name "WINRM-HTTP-In-TCP-PUBLIC" -RemoteAddress Any
=====================================================================

with array of hosts:

$psscript = {
 $login = "mylogin@mydomain.dom"

 $path = "SYSTEM\CurrentControlSet\Control\SecurePipeServers\winreg"
 $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($($path), [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::takeownership)
 $acl = $key.GetAccessControl()

 $rule = New-Object System.Security.AccessControl.RegistryAccessRule ($($login),"ReadKey","Allow") 
 $acl.SetAccessRule($rule)
 $key.SetAccessControl($acl)
}

foreach($pshost in $hostsresult)
{
 $ps = $null
 $ps = New-PSSession -Computername $($pshost.name) -EA SilentlyContinue
 if ($ps -eq $null){
   write-host "Not connected to $($pshost.name)"
   continue
   }
 Invoke-Command -Session $ps -ScriptBlock $psscript
 write-host "$($pshost.name) IS OK"
 Disconnect-PSSession $ps -EA SilentlyContinue | out-null
}



powershell scripts for gpo - info users logons

#by alex
#powershell script for write logon info

$domainname = (Get-WmiObject Win32_ComputerSystem).Domain
$dirtowrite = "\\fileservername\log$"
$log = $dirtowrite + "\-worklog.log" 
$logfile = $dirtowrite + "\-worklog.log"

function log([string]$txt)
{
 add-content $LOGFILE $txt 
}

$clienthostinfo = ""

function mainproc()
{
#if terminal server role installed, get client name too
if((gwmi -namespace root\cimv2\terminalservices -class win32_terminalservicesetting).TerminalServerMode -eq 1){
  Import-Module PSTerminalServices
  $clienthostinfo = "from:"+(Get-TSSession -Filter {$_.Username -like [Environment]::Username} | Select-Object ClientName).ClientName}

 "Logon event at " + $(Get-Date -UFormat "%d-%m-%Y %T") + " for $env:Username on $env:Computername" + " $clienthostinfo" | Out-file -Append -FilePath $("$dirtowrite\$env:Computername-AT-$env:Username@$domainname.log")
}#endof mainproc

try{
 mainproc
 $retcode = 0}
catch{
   $ErrorMessage = $_.Exception.Message
   $invocation = $PSItem.InvocationInfo
   log("Exception detected!`nError message:$ErrorMessage")
   log("invocation:`n$invocation")
   $retcode = -1
}

return $retcode

воскресенье, 8 апреля 2018 г.

zip/unzip with powershell example

[Reflection.Assembly]::LoadWithPartialName( "System.IO.Compression.FileSystem" )
[system.io.compression.zipfile]::CreateFromDirectory("c:\temp", "s:\temp\test.zip")
[system.io.compression.zipfile]::ExtractToDirectory("s:\temp\test.zip","s:\temp")

more about [system.io.compression.zipfile] class:MSDN Developer Network

среда, 4 апреля 2018 г.

powershell script for write info for user by gpo

when user logon, script will associate user and site where user
 initiated logon by ip of user host and set some information about host (write it for AD fields USER.physicalDeliveryOfficeName and USER.info)

use with gpo:
logon script - powershell scenario with parameters "-Nologo -WindowStyle Hidden -Noninteractive -Noprofile -ExecutionPolicy Unrestricted"

script:
#by alex

#script for assotiate user for site by ip

$LOGFILE=$env:Temp+'\ololo-set-physicalDeliveryOfficeName.log'

#в массиве из массивов должно быть минимум 2 элемента, не убирать @("0.0.0.0","0.0.0.0")
$global:networks = @{}
$networks.add('Main',@(@("100.70.0.1","100.70.0.254"),@("100.70.1.1","100.70.1.254")))
$networks.add('Site2',@(@("192.168.3.1","192.168.3.254"),@("0.0.0.0","0.0.0.0")))
$networks.add('Site3',@(@("192.168.99.1","192.168.99.254"),@("192.168.100.1","192.168.100.254")))

$global:sites = @{}
$sites.add('Main','Главный офис компании ООО "ОЛОЛО"')
$sites.add('Site2','Офис в городе Майами')
$sites.add('Site3','Офис в городе Сызрань')

$global:mysitename=''
$global:myips = @((gwmi Win32_NetworkAdapterConfiguration|?{$_.IPAddress})|%{$_.IPAddress -notlike "*::*"})
$global:myip = ''

function log([string]$txt)
{
 add-content $LOGFILE $txt 
}

function getmynetworkname{
global:networks.Keys=$([string]::Join(',',@($global:networks.Keys)))")
  foreach($ip in $global:myips){
   foreach($key in $global:networks.Keys){
     $netbymyip=$ip.split('.')[0]+'.'+$ip.split('.')[1]+'.'+$ip.split('.')[2]
      foreach($arr in $global:networks[$key]){
       $netbyarrip=$arr[0].split('.')[0]+'.'+$arr[0].split('.')[1]+'.'+$arr[0].split('.')[2]
       if($netbyarrip -eq $netbymyip){
        if(([int]$ip.split('.')[3] -ge [int]$arr[0].split('.')[3]) -and ([int]$ip.split('.')[3] -le [int]$arr[1].split('.')[3])){
         $global:myip = $ip
         return $key}
       }
     }
    }
   }#top foreach
 return ""
}

function mainproc
{
 $now = Get-Date -UFormat "%d-%m-%Y %T"
 $retcode = 1
#выход если это терминальный сервер
#exit when terminal session
 if((gwmi -namespace root\cimv2\terminalservices -class win32_terminalservicesetting).TerminalServerMode -eq 1){
  return $retcode 
 }
 $mynetname = getmynetworkname
 if($mynetname -eq ""){
  $message = "Error! No name for network"
  throw $message
  retun -1
 }

 $global:mysitename = $global:sites[$mynetname]
 $searcher = [adsisearcher]"(samaccountname=$env:USERNAME)"
 $user = [adsi]$searcher.FindAll()[0].Properties.adspath[0]
 $objUser = [adsi]("LDAP://"+$env:LOGONSERVER.trim('\')+":389/"+$user.distinguishedName)
 $operatingsysteminfo = Get-WmiObject Win32_OperatingSystem
 $os = (($operatingsysteminfo).Name).Split('|')[0]
 $arch = $operatingsysteminfo.OSArchitecture
 $comp = Get-WmiObject Win32_Computersystem
 $ram = [string]([math]::Round([int64](($comp).TotalPhysicalMemory/1Gb)))+"Gb"
 $CompName = $comp.Name
 $CompManufacturer = 'Unknown'
 $CompModel = 'Unknown'
 if($comp.Manufacturer -ne "System manufacturer"){
 $CompManufacturer = $comp.Manufacturer}
 if($comp.Model -ne "System manufacturer"){
 $CompModel = $comp.Model}
 $objUser.Put("Info","Last logon info:`r`n$now`r`n$CompName`r`n$CompManufacturer   $CompModel`r`nRAM:$ram`r`nOS:$arch $os")
 if($global:mysitename -ne $user.physicalDeliveryOfficeName)
 {
  $objUser.Put("physicalDeliveryOfficeName", $global:mysitename)
  $retcode = 0
 }
 $objUser.SetInfo()
 return $retcode
}#end of mainproc



try{
 $retvalue = mainproc
}
catch{
   $ErrorMessage = $_.Exception.Message
   $invocation = $PSItem.InvocationInfo
   log("Exception detected!`nError message:$ErrorMessage")
   log("invocation:`n$invocation")
   return -1
}
finally{
 if($retvalue -eq 0){
  log("AD attribute physicalDeliveryOfficeName set to $global:mysitename for host $global:myip for user $env:USERNAME at $(Get-Date)")
  }
}
===================================================
another example
$root = [adsi]""
$rootdn = $root.distinguishedName

$userinput = $args[0]
$groupobj = get-group $userinput
$groupdn = $groupobj.DistinguishedName

# Bind to Group object

$group = [adsi]"LDAP://$groupdn"

$group.put("hideDLMembership", "TRUE" )

$group.setinfo()

четверг, 15 февраля 2018 г.

PRTG sensor secrets/examples
example for grace period windows terminal server

poweshell script sensor for prtg:
Get-Content -LiteralPath "C:\scripts\scriptout.txt"

windows sheduler contains everyday task:
powershell -windowstyle minimized -c "powershell -c c:\scripts\grace-period-ts.ps1 > c:\scripts\scriptout.txt"

powershell script for non-domain host:
prepare password:
$pass = "MYP@SSW0RD" | ConvertTo-SecureString -AsPlainText -Force
ConvertFrom-SecureString -SecureString $pass

* Attention, can be reverse unsecured:
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pass)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

copy output for variable $pass for script below
SCRIPT:
$hostname = "ts01"
$prtg = '<?xml version="1.0" encoding="Windows-1252" ?> 
<prtg>'

$username="$hostname\Administrator"
$pass="01000ac0d08c9ddf0115d1118c7a00c04fc297eb01000000af5d5e1acfacf44fb3e6da2b3bb6c12d0000000002000000000003660000c000000010000000ce6f9d71d1da7703458f899c695f4a220000000004800000a000000010000000f26cf27ef25096d4b56c2634b9167fb61800000038f442cef9a1a121ef4238bd21f84b6bf0958f7de57e201914000000aeb56a8714f507a453186e4151614953734b5a35"
$cryptpass=$pass | ConvertTo-SecureString
$cred=New-Object System.Management.Automation.PSCredential -ArgumentList $username, $cryptpass


$gp = [int](Invoke-WmiMethod -Credential $cred -PATH (gwmi -ComputerName $hostname -Credential $cred -namespace root\cimv2\terminalservices -class win32_terminalservicesetting).__PATH -name GetGracePeriodDays).daysleft

$prtg+="
<result> 
   <channel>TS Grace Period Channel</channel>
   <unit>Custom</unit>
   <customUnit>Days</customUnit> 
   <float>0</float>
   <value>"+$gp+"</value> 
   <showChart>1</showChart> 
   <showTable>1</showTable> 
   <Limitmode>1</Limitmode>
   <LimitMinError>14</LimitMinError>
   <LimitErrorMsg>ATTENTION! Grace period less or equal 14 days!($gp)</LimitErrorMsg>
</result>
</prtg>"

$prtg

exit 0


For domain autentication we may use native wmi or winrm
example for winrm:
$s = New-PSSession -Computername $hostname
$gp = Invoke-Command -Session $s -ScriptBlock{[int](Invoke-WmiMethod -PATH (gwmi -namespace root\cimv2\terminalservices -class win32_terminalservicesetting).__PATH -name GetGracePeriodDays).daysleft}
Remove-PSSession $s
etc...