суббота, 27 января 2024 г.

 Направляем траффик из портов в dummy интерфейсы для возможности контроля траффика:

#!/bin/bash

ip link add name config0 type dummy
ip link set config0 up

tc qdisc add dev eth0 handle 1: root prio
tc filter add dev eth0 parent 1: protocol ip u32 match ip sport 8888 0x00ff action mirred egress mirror dev config0

ip link add name config1 type dummy
ip link set config1 up

#tc qdisc add dev eth0 handle 1: root prio 
tc filter add dev eth0 parent 1: protocol ip u32 match ip sport 8889 0x00ff action mirred egress mirror dev config1

ip link add name agro0 type dummy
ip link set agro0 up

#tc qdisc add dev eth0 handle 1: root prio
tc filter add dev eth0 parent 1: protocol ip u32 match ip sport 8890 0x00ff action mirred egress mirror dev agro0

среда, 25 мая 2022 г.

Base64 для систем где его нет (vMware Orchestrator например) (из инета)

var Conv86 = (function () {
    var chars = (
            'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
            'abcdefghijklmnopqrstuvwxyz' +
            '0123456789+/'
        ),
        inver = {}, i;
    for (i = 0; i < chars.length; ++i) {
        inver[chars[i]] = i;
    }
    function base8To6(arr8) {
        var arr6 = [], i,
            e1, e2, e3,
            s1, s2, s3, s4,
            d1, d2, d3;
        for (i = 0; i < arr8.length; i += 3) {
            e1 = (d1 = arr8[i]    ) & 255;
            e2 = (d2 = arr8[i + 1]) & 255;
            e3 = (d3 = arr8[i + 2]) & 255;
            // wwwwwwxx xxxxyyyy yyzzzzzz
            s1 =                     e1 >>> 2 ;
            s2 = ((e1 &  3) << 4) + (e2 >>> 4);
            s3 = ((e2 & 15) << 2) + (e3 >>> 6);
            s4 =   e3 & 63                    ;
            arr6.push(s1, s2);
            if (d3 !== undefined)
                arr6.push(s3, s4);
            else if (d2 !== undefined)
                arr6.push(s3);
        }
        arr6.byteLength = arr8.length;
        return arr6;
    }
    function base6To8(arr6) {
        var arr8 = [], i,
            e1, e2, e3,
            s1, s2, s3, s4,
            d1, d2, d3, d4;
        for (i = 0; i < arr6.length; i += 4) {
            s1 = (d1 = arr6[i]    ) & 63;
            s2 = (d2 = arr6[i + 1]) & 63;
            s3 = (d3 = arr6[i + 2]) & 63;
            s4 = (d4 = arr6[i + 3]) & 63;
            // xxxxxx xxyyyy yyyyzz zzzzzz
            e1 = ( s1       << 2) + (s2 >>> 4);
            e2 = ((s2 & 15) << 4) + (s3 >>> 2);
            e3 = ((s3 &  3) << 6) +  s4       ;
            arr8.push(e1);
            if (d3 !== undefined)
                arr8.push(e2, e3);
            else if (d2 !== undefined )
                arr8.push(e2);
        }
        if (arr6.byteLength !== undefined)
            arr8.length = +arr6.byteLength;
        return arr8;
    }
    function base6To64(arr6) {
        var i, b64 = '';
        for (i = 0; i < arr6.length; ++i) b64 += chars.charAt(arr6[i]);
        /*if (arr6.bytesLength) {
            i = arr6.bytesLength % 3;
            if (i) ++i;
        } else */
        i = b64.length % 4;
        b64 += ['', '==', '==', '='][i];
        return b64;
    }
    function base8To64(arr8) {
        return base6To64(base8To6(arr8));
    }
    function base64To6(b64) {
        var arr6 = [],
            i = b64.length, lenMod = 0;
        while (b64.charAt(--i) === '=')
            ++lenMod;
        for (i = 0; i < b64.length - lenMod; ++i)
            arr6.push(inver[b64.charAt(i)]);
        i = b64.length & 3;
        if (i) i = 4 - i;
        i = i + b64.length;
        arr6.byteLength = 3 * i / 4 - lenMod;
        return arr6;
    }
    function base64To8(b64) {
        return base6To8(base64To6(b64));
    }
    // base16
    function base8To16(arr8) {
        var i, arr16 = [];
        for (i = 0; i < arr8.length; i = i + 2)
            arr16.push((arr8[i] << 8) + arr8[i + 1]);
        return arr16;
    }
    function base16To8(arr16) {
        var i, arr8 = [];
        for (i = 0; i < arr16.length; ++i)
            arr8.push(arr16[i] >>> 8, arr16[i] & 255);
        return arr8;
    }
    function base6To16(arr6) {
        return base8To16(base6To8(arr6));
    }
    function base16To6(arr16) {
        return base8To6(base16To8(arr16));
    }
    function base16To64(arr16) {
        return base8To64(base16To8(arr16));
    }
    function base64To16(b64) {
        return base8To16(base64To8(b64));
    }
    // from UTF8 to X
    function utf8To8(str) {
        var arr8 = [], i;
        for (i = 0; i < str.length; ++i)
            arr8.push(str.charCodeAt(i) & 255);
        return arr8;
    }
    function utf8To6(str) {
        return base8To6(utf8To8(str));
    }
    function utf8To16(str) {
        return base8To16(utf8To8(str));
    }
    function utf8To64(str) {
        return base8To64(utf8To8(str));
    }
    // from X to UTF8
    function utf8From8(arr8) {
        var utf8arr = [];
        for (i = 0; i < arr8.length; ++i)
            utf8arr.push(arr8[i]);
        return String.fromCharCode.apply(String, utf8arr);
    }
    function utf8From6(arr6) {
        return utf8From8(base6To8(arr6));
    }
    function utf8From16(arr16) {
        return utf8From8(base16To8(arr16));
    }
    function utf8From64(b64) {
        return utf8From8(base64To8(b64));
    }
    // from UTF16 to X
    function utf16To16(str) {
        var arr16 = [], i, c;
        for (i = 0; i < str.length; ++i) {
            c = str.charCodeAt(i) & 65535;
            arr16.push(((c & 255) << 8) + (c >>> 8));
        }
        return arr16;
    }
    function utf16To8(str) {
        return base16To8(utf16To16(str));
    }
    function utf16To6(str) {
        return base16To6(utf16To16(str));
    }
    function utf16To64(str) {
        return base16To64(utf16To16(str));
    }
    // from X to UTF16
    function utf16From16(arr16) {
        var utf16arr = [];
        for (i = 0; i < arr16.length; ++i)
            utf16arr.push(((arr16[i] & 255) << 8) + (arr16[i] >>> 8));
        return String.fromCharCode.apply(String, utf16arr);
    }
    function utf16From8(arr8) {
        return utf16From16(base8To16(arr8));
    }
    function utf16From6(arr6) {
        return utf16From16(base6To16(arr6));
    }
    function utf16From64(b64) {
        return utf16From16(base64To16(b64));
    }
    return {
        base6: {
            to8: base6To8,
            to16: base6To16,
            to64: base6To64,
        },
        base8: {
            to6: base8To6,
            to16: base8To16,
            to64: base8To64
        },
        base16: {
            to6: base16To6,
            to8: base16To8,
            to64: base16To64
        },
        base64: {
            to6: base64To6,
            to8: base64To8,
            to16: base64To16
        },
        utf8: {
            to8: utf8To8,
            to6: utf8To6,
            to16: utf8To16,
            to64: utf8To64,
            from8: utf8From8,
            from6: utf8From6,
            from16: utf8From16,
            from64: utf8From64
        },
        utf16: {
            to8: utf16To8,
            to6: utf16To6,
            to16: utf16To16,
            to64: utf16To64,
            from8: utf16From8,
            from6: utf16From6,
            from16: utf16From16,
            from64: utf16From64
        }
    };
}());
 
Conv86.utf16.to64(STRING) соответствует powershell
$decoded64=[System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($i))

среда, 27 апреля 2022 г.

 Перенос CnetOS

source - старая ВМ

dest - новая ВМ


подготовка на sorce:

разрешаем для root вход по ssh (Permit root)


подготовка на dest:

Перенос centOS наживую.

создаём пустую новую ВМ с диском нужного размера

загружаемся в knoppix на этой ВМ

создаём нужные диск/диски

монтируем root в /mnt

делаем перброс данных через tar:

ssh root@source "tar -cf - / --numeric-owner --exclude=/dev/* --exclude=/sys/* --exclude=/proc/* --exclude=/tmp/*" | tar xf - -C /mnt --numeric-owner

после окончания копирования делаем:

mount -o bind /dev /mnt/dev

mount -o bind /sys /mnt/sys

mount -t proc proc /mnt/proc

chroot /mnt


для grub2:

rm -f /boot/initramfs*

для всех файлов vmliuz-XXX.XX.XX пересоздаем initramfs

dracut -f /boot/initramfs-XXX.XX.XX

mv /boot/grub2/grub.cfg *.*.old

grub2-mkconfig /dev/sda -o /boot/grub2/grub.cfg


правим /etc/fstab для монтирования разделов


reboot


всё.


среда, 17 марта 2021 г.

среда, 24 февраля 2021 г.

 Encrypt/Decrypt simple file over ssl

encrypt:
cat my.key | openssl enc -aes-256-cbc -e > my.key.ssl

decrypt:
cat my.key.ssl | openssl enc -aes-256-cbc -d > my.key


пятница, 22 января 2021 г.

incredible find :)
find all not executable files in directory and set executable attribute for any

find /data -type f -name *.exe ! -perm /o+x -exec chmod o+x {} +


+ is not same ;

среда, 13 января 2021 г.

 OMNITRACKER
Отбираем все объекты RFCs у которых было движение статуса из Acceptance в Evaluation и для них устанавливаем в поле AcceptanceDate последнюю дату этого движения.


Set objApp = CreateObject("OtAut.OtApplication")
Set ActiveSession = objApp.MakeSession("localhost",5085,"","")

Set objFolder = ActiveSession.RequestFolders("RFCs")
Set objQuery = objFolder.MakeQuery

Set objHistSearch = objFolder.MakeHistorySearch
objHistSearch.StartDate = DateSerial(1970, 1, 1)
objHistSearch.EndDate = Now
objHistSearch.Field = "State"
objHistSearch.Type = 1 ' otHistSearchModification
objHistSearch.Value1 = "Acceptance"
objHistSearch.Value2 = "Evaluation"


Set objColumn = objQuery.AddColumn("UID")
objColumn.Type = 2 ' otQColTypeUniqueId
objQuery.AddHistorySearch objHistSearch
objQuery.Recursive = True

Set objRS = objQuery.Execute

Set objTransQuery = objFolder.MakeQuery
Set objColumn = objTransQuery.AddColumn("Date")
objColumn.Type = 3 ' otQColTypeStateTransDate
objColumn.Field = "State"
objColumn.StartDateField = "CreationDate"
objColumn.EndDate = Now
objColumn.DefaultDate = Now
objColumn.LastStateTransition = True
objColumn.FromState = "Acceptance"
objColumn.ToState = "Evaluation"
objTransQuery.Recursive = True

For i = 0 To objRs.RowCount - 1
    Set objFilter = objFolder.MakeFilter
    objFilter.SpecialField("UNIQUE_ID") = objRs(i, 0)
    objTransQuery.Filter = objFilter
    Set objTransRS = objTransQuery.Execute
    If objTransRS.RowCount = 1 Then
    Set objRFC = ActiveSession.GetRequestByUniqueId(objRs(i, 0))
    objRFC.Fields("AcceptanceDate").TValue = objTransRS(0, 0)
    objRFC.SaveEx 1023 - 32
    EndIf
Next

четверг, 12 ноября 2020 г.

Connect to foreign exchange ps

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://XXXXXXX
Import-PSSession $Session -DisableNameChecking

среда, 30 сентября 2020 г.

Rebuild Indexes. MS SQL

DECLARE @TableName VARCHAR(255)

DECLARE @sql NVARCHAR(500)

DECLARE @fillfactor INT

SET @fillfactor = 80

DECLARE TableCursor CURSOR FOR

SELECT OBJECT_SCHEMA_NAME([object_id])+'.'+name AS TableName

FROM sys.tables

OPEN TableCursor

FETCH NEXT FROM TableCursor INTO @TableName

WHILE @@FETCH_STATUS = 0

BEGIN

SET @sql = 'ALTER INDEX ALL ON ' + @TableName + ' REBUILD WITH (FILLFACTOR = ' + CONVERT(VARCHAR(3),@fillfactor) + ')'

EXEC (@sql)

FETCH NEXT FROM TableCursor INTO @TableName

END

CLOSE TableCursor

DEALLOCATE TableCursor

GO

четверг, 30 января 2020 г.

transmission-vise.py for Netgear ReadyNas 10400. run's by crontab every 2 hours
how it works:
stop torrent if ratio has been reached or seeders>MAXSEEDERS
start torrent if only my seeding

what's all this:
Netgear ReadyNas 10400 is slow,  but most importantly - hot and noisy at his place, but most of all - if seeding more torrents, it can't share plex because low cpu one core speed.

note:
crontab must run script w/o dots
do like this in /etc/crontab:
/2 *    * * *   root    /root/scripts/transmission-vice_py

#!/usr/bin/python
from os import popen
from sys import exit
import re
import logging

logging.basicConfig(filename='/root/scripts/transmission-vice.log', format='%(asctime)s - %(message)s', level=logging.INFO)

maxratio = 5
maxseeders = 3
unknowndata = 0
tarray = []
rawtorrents=popen('transmission-remote 8181 -l | egrep -v "ID|Sum"').read()

for torrent in rawtorrents.split("\n"):
    if len(torrent)==0:
        break
    spltorrent=torrent.split()
    torrentdict={'ID':spltorrent[0],'Done':spltorrent[1],'ETA':spltorrent[4],
                 'Ratio':spltorrent[7],'Status':spltorrent[8],'Name':' '.join(tuple(spltorrent)[9:])}
    torrentstats=popen('transmission-remote 8181 -t'+torrentdict['ID']+' -it').read()
    stat = re.findall(r"(\d+)\sseeders",torrentstats)
    if len(stat)>0:
        torrentdict['Seeders']=stat[0]
    else:
        torrentdict['Seeders']=unknowndata
    stat = re.findall(r"(\d+)\sleechers",torrentstats)
    if len(stat)>0:
        torrentdict['Leechers']=stat[0]
    else:
        torrentdict['Leechers']=unknowndata
    tarray.append(torrentdict)

for torrent in tarray:
    print("Name:"+torrent["Name"]+" Status:"+torrent["Status"]+" Ratio:"+str(torrent["Ratio"])+" Seeders:"+str(torrent["Seeders"])+" ETA:"+str(torrent["ETA"]))
    peers = popen('transmission-remote 8181 -t'+torrent["ID"]+' -ip' + ' | egrep -v "Address"')
    peerasseeder = False
    for peer in peers:
        if int(float(peer.split()[2])) == 100:
            peerasseeder = True
    if int(torrent["Seeders"])<maxseeders and int(torrent["Leechers"])!=0 and not peerasseeder and float(torrent["Ratio"])<maxratio:
        if torrent["Status"]=="Stopped":
            result=popen('transmission-remote 8181 -t'+torrent["ID"]+' -s').read()
            logging.info("start:"+torrent["Name"]+" Ratio:"+str(torrent["Ratio"])+" Seeders:"+str(torrent["Seeders"]))
    elif  (peerasseeder or int(torrent["Seeders"])>3) and torrent["ETA"]=="Done" and float(torrent["Ratio"])>maxratio:
        if torrent["Status"]=="Idle" or torrent["Status"]=="Seeding":
            result=popen('transmission-remote 8181 -t'+torrent["ID"]+' -S').read()
            logging.info("stop:"+torrent["Name"]+" Ratio:"+str(torrent["Ratio"])+" Seeders:"+str(torrent["Seeders"]))
exit(0)

среда, 31 июля 2019 г.

Скрипт для поиска однофамильцев в AD. powershell
Namesakes detecting in ActiveDirectory, powershell

#by me, 2019

import-module activedirectory

$SMTPSERVER = "exch.domain.local"

function main{
$users = (get-aduser -filter {enabled -eq $true -and EmailAddress -like "*@*"} -properties DisplayName).DisplayName
$doubleDisplayNames = $users | group | where{$_.count -gt 1}
if($doubleDisplayNames.count -gt 0) {
Send-MailMessage -From powershell@domain.local -To achernov@domain.local -Subject "Обнаружены полные однофамильцы в домене domain.local" -Body $($doubleDisplayNames.Name -join "`n") -SmtpServer $SMTPSERVER -Priority High -Encoding UTF8
}
}#end of main

try{
 main
}
catch
{
 $ErrorMessage = $_.Exception.Message
 Send-MailMessage -From powershell@domain.local -To admin@domain.local -Subject "Скрипт поиска однофамильцев в домене domain.loc вызвал ошибку выполнения." -Body $($ErrorMessage) -SmtpServer $SMTPSERVER -Priority High -Encoding UTF8
}

среда, 13 февраля 2019 г.

<#
Скрипт очистки рабочих каталогов 1С пользователей. Скрипт для Terminal Server.
Принцип работы:
Логофит всех пользователей у которых запущен клиент 1С.
Удаляет каталоги формы [guid] из массива, определенного в переменной $global:dirs
Лог работы скрипта в файле с именем из переменной $logfile
Для запуска скрипта файл "C:\Program Files\1cv8\nightrestart" должен существовать
#>

$logfile = "C:\scripts\1C-TS-restartAndRemoveUsersWorkDirs.log"
$path = "C:\Program Files\1cv8\nightrestart"
$test = $false
$global:dirs = ("C:\Users\*\AppData\Local\1C\1Cv82\*","C:\Users\*\AppData\Roaming\1C\1Cv82\*","C:\Users\*\AppData\Local\1C\1Cv8\*","C:\Users\*\AppData\Roaming\1C\1Cv8\*","C:\Users\*\AppData\Roaming\1C\Файлы\")

if (-not(Test-Path $path)) {
    log("Script execution temporarily suspended. File C:\Program Files\1cv8\nightrestart not found.")
    Exit
}

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


function LogoffAll {
# логофим всех пользователей у которых запущен клиент 1C
log("Logoff for all...")
$currentid = (Get-Process -PID $pid).SessionID
$proceses1c = Get-Process | Where-Object{$_.Name -like "1cv8" -or $_.Name -like "1cv8c"}
$sessionids = $proceses1c | select sessionid | Group-Object sessionid | select name
foreach ($sessionid in $sessionids) {if ($sessionid.name -ne "0" -and $sessionid.name -ne $currentid.ToString()) {logoff $sessionid.name}}
}

function RemoveDirs {
    $removedfiles = 0
foreach ($dirname in $global:dirs){
foreach ($dirtoremove in Get-ChildItem $dirname | Where {$_.Name -as [guid]}) {
try {
Remove-Item $dirtoremove -Force -Recurse -cf:$false -ErrorAction Stop -WhatIf:$test
$removedfiles++
}
catch {
log("Error. Can not remove dir " + $dirtoremove)
}
}
}
    return $removedfiles
}

#main section
log("Start...")
LogoffAll
$removeddirs = RemoveDirs
log("Dirs deleted: " + $removeddirs)

среда, 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 для доменного контроллера)