8.09.2023

Powershell ve UserAgent tanımlayıcısı

Örneğin şu şekilde Powershell'den yapılan bir web sorgusu

PS> Invoke-WebRequest -Uri "https://whatmyuseragent.com"

aynen bir web tarayıcının göndereceği gibi sunucuya, UserAgent String olarak bilinen tarayıcı bilgisi gönderir. Powershell için bu şuna benzer bir dizedir:

Mozilla/5.0 (Windows NT; Windows NT 10.0; tr-TR) WindowsPowerShell/5.1.22621.1778

Powershell 5.0 ve Türkçe Windows 10/11 bilgisayardan bağlantıyı gösteriyor. Bunu özelleştirebiliriz. Microsoft.PowerShell.Commands.PSUserAgent sınıfını kullanarak şu tarayıcıları taklit etmek mümkün:

PS> iwr -UserAgent ([Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer) -Uri "https://whatmyuseragent.com"

Bu gibi bir komut, şu sayfadaki tabloya göre Interet Explorer 9.0 bilgisi gönderir. Sınıfın içindeki seçenekler biraz eski:

ChromeUseragent string for Chrome (7.0).
FireFoxUseragent string for Firefox (4.0).
InternetExplorerUseragent string for InternetExplorer (9.0).
OperaUseragent string for Opera (9.0).
SafariUseragent string for Safari (5.0).

Bunun dışında elbette elle seçilmiş değerler de kullanılabilir.

PS> iwr -useragent "merhaba" -uri "https://whatmyuseragent.com"


18.08.2023

Powershell yürütme işleci

Execute operator'ün Türkçesi. Şu sayfadan basit bir örnek:

PS> $mysb = {$b = 456 ; Echo $b }

PS> & $mysb

456

Benden bir örnek:

PS> $myip = {(iwr "http://whatismyip.akamai.com").Content}

PS> $myip

Yine ss64.com'dan bir örnek daha; Script Block'un içinde param koyarak bir fonksiyon gibi kullanabiliriz:

PS> $alert = { param ($message) "$message" } 

PS> & $alert -message "Merhaba"

Merhaba


17.08.2023

Powershell veri biçimlendirme

Türkçe yerel ayarları olan bir bilgisayarda Powershell kullanırken ondalık sayıları yazarken ondalık ayraç nokta "." ama ekrana bastırırken virgüldür ","

$veri = 1222333.456789 # ondalık sayı

"{0:f}"  -f $veri # 1222333,57
"{0:f3}" -f $veri # 1222333,568
"{0:e}"  -f $veri # 1,222334e+006
"{0:E}"  -f $veri # 1,222334E+006
"{0:n}"  -f $veri # 1.222.333,57

$veri = 1299.99 # para birimi

"{0:c}" -f $veri # ₺1.299,99

$veri = 1234 # tamsayı

"{0:n}"    -f $veri # 1.234,00
"{0:d8}"   -f $veri # 00001234 (sola sıfır ekler)
"{0,8:n0}" -f $veri # ___1.234 (sayıdan önce 3 boşluk olur)

$veri = 255 # 16'lık düzen

"{0:x}"  -f $veri # ff
"{0:X4}" -f $veri # 00FF

#veri = 0.25 # yüzde

"{0:p}"  -f $veri # %25,00
"{0:p1}" -f $veri # %25,0
"{0:p0}" -f $veri # %25

# veri = Get-Date # tarih

"{0:d}"  -f $veri # 17.08.2023
"{0:D}"  -f $veri # 17 Ağustos 2023 Perşembe
"{0:f}"  -f $veri # 17 Ağustos 2023 Perşembe 15:17
"{0:F}"  -f $veri # 17 Ağustos 2023 Perşembe 15:17:41
"{0:g}"  -f $veri # 17.08.2023 15:17
"{0:g}"  -f $veri #
17.08.2023 15:17:42
"{0:r}"  -f $veri # Thu, 17 Aug 2023 15:17:41 GMT
"{0:o}"  -f $veri # 2023-08-17T15:17:41.0556971+03:00
"{0:yy-MM-dd}"  -f $veri # 23-08-17

Burada

d: kısa tarih
D: uzun tarih
f: uzun tarih, kısa saat
F: uzun tarih, uzun saat
t: kısa saat
T: uzun saat
g: kısa genel tarih biçimi
G: uzun genel tarih biçimi
yy: yılın son 2 hanesi (23 gibi)
yyyy: tam yıl biçimi (2023 gibi)
M: İçinde bulunulan ay, mümkünse tek haneli sayı
MM: İçinde bulunulan ay, çift haneli (tek ise önüne sıfır ekler)
MMM: İçinde bulunulan ay, 3 karakterli kısaltma
MMMM: İçinde bulunulan ay, tam adı
d : Ayın günü, tek haneli
dd: Ayın günü, çift haneli
hh: Saat, 12 saatlik düzende
HH: Saat, 24 saatlik düzende
mm: Dakika
ss: Saniye 

Tarih için ayrıca Get-Date ile -Format parametresi de benzer iş görür.

PS> Get-Date -Format "yyyy-MM-dd HH:mm:ss"

2023-08-17 15:17:41

Get-Date'in bir de -UFormat parametresi var:

Get-Date -UFormat %V # yılın haftasını verir (1-52)

10'luk düzende bir sayıyı 16'lık düzende görmek için yukarıdaki gibi

PS> "{0:x}" -f 252   # fc

kullanılabilir. Ama daha genel olarak bir sayıyı herhangi bir düzende yazmak için

PS> [Convert]::ToString(252,2)
11111100

kullanılabilir.

16'lık düzendeki bir sayıyı girmek için başına 0x koymak yeterli:

0xfc    # onluk düzende 252'ye karşılık gelir

Veya ikilik düzendeki bir sayıyı girmek için başına 0b koymak gerek:

0b11111100    # bu da 252

Veya şu şekilde dönüştürmek de işimize yarayabilir:

[Convert]::ToInt32("11111100",2)
252

Bir dosyanın içeriğini hex olarak görmek için

PS> $icerik = cat '.\file.txt' -Encoding Byte -Raw
PS> [System.BitConverter]::ToString($icerik).Replace("-","") 

Daha kolay bir yol, belki, Format-Hex kullanmak:

PS> Format-Hex -Path '.\file.txt'

Tek satırda/cümlede birden fazla veri biçimlendirme:

PS> $veri1=1199; $veri2=5231; $veri3=3199.99
PS> "ilk sayımız {0:d8}, sonraki {1:e2} ve nihayet {2:f4}" -f $veri1, $veri2, $veri3
ilk sayımız 00001199, sonrajş 5,23e+003, ve nihayet 3199,9900

Şu sayfadan güzel birkaç örnek:

PS> "|{0,-10}| |{1,10}|" -f "hello", "world"
|hello     ||     world|

PS> "{0:###-##-##}" -f 1234567
123-45-67

Sonuna 3 haneli tamsayılar eklenmiş Name001, Name002,... gibi 100 isim üretmek:

PS> 1..100 | % { 'Name{0:d3}' -f $_ }

Bir karakterin 16'lık düzendeki karşılığı

PS> '0x' + "{0:x}" -f [int][char]'A'
0x41



3.08.2023

Windows'da dosya ve klasörlerin son değiştirme zamanlarını değiştirmek

NTFS dosya sistemi her dosya ve klasör için 3 farklı zaman bilgisi saklar; oluşturma, son değiştirme ve erişim.

PS> dir file1.txt | select Name, CreationTime, LastWriteTime, LastAccessTime

Name      CreationTime        LastWriteTime       LastAccessTime
----      ------------        -------------       --------------
file1.txt 2023-07-31 08:01:00 2023-08-01 14:05:00 2023-08-03 11:55:48

Bu tarihlerden herhangi birini değiştirmek için şöyle bir kullanım yeterli:

PS> (dir file1.txt).CreationTime=("1999-12-31 23:59:00")
PS> (dir file1.txt).LastWriteTime=("1999-12-31 23:59:00")
PS> (dir file1.txt).LastAccessTime=("1999-12-31 23:59:00")

Hatta bir klasördeki tüm dosyaların zamanlarını değitirmek için

$files =  Get-ChildItem -force | Where-Object {! $_.PSIsContainer}
foreach($object in $files)
{
     $object.CreationTime=("10 November 2016 12:00:00")
}

önerilmiş.

31.07.2023

Linux'ta güncellemeleri otomatik denetlemeyi iptal etmek

Genellikle linux bilgisayarlarda ilk yaptığım, açılışta güncellemeleri kontrol etmek olur. Ama ben bunu yaparken zamanlanmış görevlerden biri de aynı işlemi yapıyor olur. Bu durumda önce devam eden görevin bitmesini beklemem gerekir. Ben kullandığım bilgisayarlarda otomatik güncelleme denetlemesini faydalı bulmadığım için devre dışı bırakmak istiyorum. Fedora GNOME için bu:

sudo systemctl disable dnf-makecache.timer
sudo systemctl disable dnf-makecache.service
sudo systemctl disable packagekit

komutlarıyla mümkün. Ubuntu GNOME için ise bunlara ek olarak

sudo systemctl disable apt-daily.timer
sudo systemctl disable apt-daily-upgrade.timer
sudo systemctl disable apt-daily.service
sudo systemctl disable apt-daily-upgrade.service

yapılması ve /etc/apt/apt.conf.d/20auto-upgrades dosyasının ilk satırındaki

APT::Periodic::Update-Package-Lists "1";

satırının sonundaki 1'in 0 yapılarak şu hale getirilmesi gerekiyor:

APT::Periodic::Update-Package-Lists "0";

systemctl disable işlemine ek olarak systemctl stop işlemleri de mevcut oturum için gerekli olabilir. Seçimlik.

Fedora XFCE için ise dnfdragora'nın her açılışta sistem tepsisinde görünmesini ve bildirimler vermesini engellemek için /etc/xdg/autostart konumundaki ilgili dosyanın etkisiz hale getirilmesi (silinerek, başka yere taşınarak veya dosyanın düzenlenmesi aracılığıyla) gerekiyor.

17.07.2023

LVM - LV genişletme

Bir RockyLinux sunucum vardı. Varsayılan kurulumda disk bölümlendirmesini bırakarak gitmenin cezasını 1 TB'lık bir diskte 900 GB home bölümü ve 70 GB'lık bir root bölümü oluşturması şeklinde ödedim. Root doldu. Home'u küçültüp, root'a yer açmak gerek. Ama bütün Redhat, CentOS ve RockyLinux kurulumlarında varsayılan dosya sistemi XFS olduğu için ve XFS de küçültme işlemini desteklemediği için bu disk bölümünü silip tekrar oluşturmak zorundayım. Bu amaçla sanal makineyi ISO disk kalıbı ile açmak (ilk ekranda "Troubleshooting", sonra "Rescue a Rocky Linux system", sonrasında da 3'e basarak "Skip to shell" diyerek) bir seçenek. Ama LVM ve XFS üzerinde çalışırken diski unmount etmemize gerek yok. /home disk bölümü içine erişen bir uygulama yoksa (ya da onu geçici olarak durdurabiliyorsak) sunucuyu root ile açıp işlemlerimize devam edebiliriz.

Başlamadan önce sunucumuzda xfsdump ve xfsprogs paketlerinin yüklü olduğunu doğrulamak gerek:

# dnf list installed xfsdump xfsprogs

Her şeyin durumunu görebilmek için mevcut volume gruop (VG) yapısını listeleyerek başlayalım:

# vgs

VG        #PV        #LV        #SN    VSize        VFree
rl        1            3          0    <1022.41G    0

Bundan sonra da mantıksal bölümleri (logical volume, LV) inceleyelim:

# lvs
LV      VG    LSize
home    rl    948.46g
root    rl     70.00g
swap    rl     <3.95g

İlk iş, home'un yedeğini almak. Bunun için xfs araçlarından xfsdump ve xfsrestore'u kullanabiliriz. Bu aşamada /home mount edilmiş olmalı.

# mkdir /backup

# xfsdump -l 0 -f /backup/home_backup.dump /home

Sonrasında .dump dosyasının durumunu kontrol etmek için

# ls -lh

# xfsdump -I

# xfsrestore -t -f /backup/home_backup.dump

kullanılabilir. Bu aşamada artık /dev/rl/home'u silip yeniden oluşturabiliriz. Silmeden önce unmount etmeliyiz.

# umount /home

Eğer /home bağlantı noktasının meşgul olduğuna dair bir hata ile karşılaşırsak lsof /home ile bakabilir, PID'leri kontrol ettikten sonra kill -9 <PID> ile sonlandırıp tekrar unmount etmeyi deneyebiliriz.

Şimdi home mantıksal bölümünü silebiliriz:

# lvremove /dev/rl/home

home'u sildikten sonra VG içinde boş yer açılmış olmalı:

# vgs
VG    #PV    #LV    #SN    VSize        VFree
rl    1        2      0    1022.41g    948.46g

#LV bir azaldı, VFree alanı da sildiğimiz mantıksal bölüm boyutunca arttı. Şimdi tekrar, daha küçük bir home mantıksal birimi oluşturalım. 20G yeter de artar bile.

# lvcreate -L 20G -n home rl

Bu komut sonunda

WARNING: xfs signature detected on /dev/rl/home at offset 0 Wipe it? [y/n]:

gibi bir uyarı verdi. Oluşturduğumuz yerde eski bir xfs bölümü kalıntısı bulmuş. Bu bilgiyi kullanabileceğim bir yer bulamadım. Sanıyorum veri kurtarma teknikleri ile yanlışlıkla silinmiş bir mantıksal bölümü geri getirmek için. Bizim amacımız bu değil; y'ye basarak işleme devam edebiliriz. Sonrasında sırasıyla yeni oluşturulan bölümü biçimlendirip, mount edip, yedekten geri yükleyeceğiz:

# mkfs.xfs /dev/rl/home

# mount /dev/rl/home /home

# xfsrestore -f /backup/home_backup.dump /home

Bu sayede çok ilginç bir şey daha öğrendim; eğer bir sunucu için /home klasörü ve içindekiler, bir kişisel bilgisayarın /home klasörüne kıyasla daha vazgeçilebilir ise veya yedeklemeyi unuttuysak /home klasörümüzü ve diğer birkaç varsayılan dosyayı yaratmak için şurada bahsedildiği gibi aşağıdaki komutu kullanabiliriz:

# mkhomedir_helper kullanici_adi

Nihayet /dev/rl/root mantıksal birimini genişletebiliriz. Önce mevcut VG'deki boş yeri kontrol edelim:

# vgs

VG    #PV    #LV    #SN    VSize        VFree
rl    1        3      0    1022.41g    928.46g

Evet, 928 GB yer hala mevcut. root mantıksal birimini VG içindeki tüm boş alanı kapsayacak şekilde (-l +100%FREE) genişletelim:

# lvextend -l +100%FREE /dev/rl/root

LV'nin genişlediğini doğrulayalım:

# vgs

VG    #PV    #LV    #SN    VSize        VFree
rl    1        3      0    1022.41g        0

ve

# lvs 

LV      VG    LSize
home    rl     20.00g
root    rl    998.46g
swap    rl     <3.95g

LV genişledi, ama içindeki xfs dosya sisteminin boyutu hala eski boyutlarında:

#df -hT

Filesystem           Type  Size   Used    Avail  Use%    Mounted on
/dev/mapper/rl-root  xfs   70G    50G    20G     72%     /
/dev/mapper/rl-home  xfs   20G    176M   20G      1%     /home
/dev/sda1            vfat  599M    7.0M  592M     2%     /boot/efi
/dev/sda2            xfs  1014M   316M   699M    32%     /boot


Sıra root mantıksal biriminin içindeki xfs dosya sistemini genişletmeye geldi:

# xfs_growfs /dev/rl/root

Nihayet o da genişledi

# df -hT

Filesystem           Type    Size    Used   Avail  Use%   Mounted on
/dev/mapper/rl-root  xfs     999G    57G    942G    72%   /

Eğer herşey tamamsa /backup/home_backup.dump'ı silebiliriz.

10.07.2023

chrony

Yerel ağda çevrimdışı çalışan linux çalışan bir makinede zaman eşitleme sorunu olduğunu farkettim. Yerel ağımızdaki tüm Windows bilgisayalarlar, zaman eşitlemesi için etki alanı sunucumuzu kullanıyorlar. Ama linux makine için bu yapılandırma atlanmış.

Önce timedatectl ile mevcut zaman eşitlemesi yapılandırmasını kontrol ettim:

# timedatectl

               Local time: Pzt 2023-07-10 08:38:03 +03
           Universal time: Pzt 2023-07-10 05:38:03 UTC
                 RTC time: Pzt 2023-07-10 05:38:03
                Time zone: Europe/Istanbul (+03, +0300)
System clock synchronized: no
              NTP service: active
          RTC in local TZ: no

Zaman dilimi bilgisi doğru ve NTP eşitlemesi etkin gözüküyor. Zaman eşitleme alt bileşeni olarak ntpd, systemd-timesyncd veya chronyd kullanılıyor olabilir. systemctl status ile var olan hizmetlere baktım, sadece chronyd'nin aktif olduğunu gördüm. chrony'nin yapılandırma dosyası /etc/chronyd.conf'u açtıım

# vim /etc/chronyd.conf

Tek yaptığım ilk satırda pool direktifinin yanında yer alan eski NTP sunucusu 2.fedora.pool.ntp.org'u kaldırıp yerine yerel ağdaki sunucumun IP adresini girdim. Aslında pool kullanıldığı için yanına da ekleyebilirdim ama cihaz çoğunlukla çevrimdışı çalışacağından gerek görmedim. Daha sonra chronyd hizmetini yeniden başlattım:

# systemctl restart chronyd.service

chrony yerine ntp kurulu olsaydı onun yapılandırma dosyası da /etc/ntp.conf olacaktı. systemd-timesyncd için de yapılandırma dosyası /etc/systemd/systemd-timesyncd.conf olurdu.

Hizmetin tekrar başlatılması sonucunda zaman eşitlemesi yapılacak. Ben tcpdump ile durumu takip etmek istedim:

# tcpdump udp port 123 -i eth0

Buna alternatif olarak chronyc komut dosyası ile durumu takip edebilirim:

# chronyc sources

# chronyc tracking

---

[1] https://www.redhat.com/sysadmin/chrony-time-services-linux

[2] https://www.golinuxcloud.com/configure-chrony-ntp-server-client-force-sync/

2.07.2023

Manjaro'da açılışta donma sorunu

Sorun birkaç kez tekrarlayınca sistem kayıtlarını incelemek istedim. Sondan bir önceki (-b -1)  boot'taki hataları ve daha önemli mesajları (-p 3) görmek için

$ journalctl -b -1 -p 3

kullandım. Şöyle birkaç satır gördüm:

Haz 25 20:32:49 manjaro kernel: iwlwifi 0000:02:00.0: pci_enable_msi failed - -22
Haz 25 20:32:49 manjaro kernel: BUG: kernel NULL pointer dereference, address: 0000000000000000
Haz 25 20:32:49 manjaro kernel: #PF: supervisor read access in kernel mode
Haz 25 20:32:49 manjaro kernel: #PF: error_code(0x0000) - not-present page

Sonra kırmızı ile işaretlediğim "supervisor read access in kernel mode" satırını tüm kayıtlarda arattım:

$ journalctl | grep 'supervisor read access in kernel mode' 

Bu hatalar acaba her seferinde bir donma ile sonuçlanan ve güç düğmesine basılı tutarak sistemi zorla kapattığım durumlara mı sebep oluyordu, yoksa bazı durumlarda sistem normal açılmış olabilir miydi? Bunu bulmak için şu yazdımdaki yöntemi kullanarak normal kapanmayan durumları listeledim: 

$ last -Fxn52 shutdown reboot

Son iki komudun çıktılarındaki tarihlerin arasındaki korelasyon bu hatanın sonucunda bilgisayarın donduğunu gösteriyordu. journal kayıtlarımın el verdiği (yakın bir dönemde eski kayıtları bir miktar temizlemiştim) ölçüde bunun manjaro 6.1 LTS çekirdek sürümüyle ilgili olabileceğini gördüm. %100 diyemesem de sanki 6.1 sürümü öncesinde yaşamadığım bir olaydı. Bir denemek için 6.1 LTS sürümü kaldırmaya karar verdim. Önce bilgisayarı bir kez yeniden başlatıp daha önceki (5.15 LTS) bir çekirdek sürümü ile açtım. Daha sonra da şu komutla 6.1'i kaldırdım: 

$ sudo mhwd-kernel --remove linux61

Bir süre kullanıp göreceğim. Bu arada Manjaro Forum'da ([1],[2]) bu hatanın 2021'den bu yana karşılaşılabilen bir hata olduğu, ve 5.10 LTS'de bile olduğunu gördüm. Şu anda 5.15 LTS sürümümü deniyorum, birkaç gün içinde olay tekrarlarsa başka çekirdekler denemem gerekebilir.

2023-09-01: 5.15 çekirdek sürümüne geçtikten sonra bugüne kadar benzer bir sorunla karşılaşmadım. Bir sonraki LTS çekirdek sürümne kadar 5.15'te kalacağım.

---

[1] https://forum.manjaro.org/t/system-freezes-bug-kernel-null-pointer-dereference/81207/2 

[2] https://forum.manjaro.org/t/linux-5-13-acpi-call-bug-kernel-null-pointer-dereference/74307 

26.06.2023

port durumu inceleme

Tüm ICMP trafiği açık olsa bile ping'in yeterli olmadığı durumlar vardır.

Uzak sunucuda çalışan bir hizmetin açık portunun cevap verip vermediğini inceleme ihtiyacı olur; 80 numaralı HTTP portuna erişebiliyor muyum, NTP sunucusunun 123 UDP portu dinlemede mi gibi.

Powershell dünyasında kısmen TCP için

PS> Test-NetConnection -ComputerName uzakpc -Port 80

gibi bir yöntem var. Yine TCP için Sysinternals'ın psping'i kullanılabilir:

PS> psping uzakpc:80

Ama UDP için benzer bir araç bilmiyordum. Linux'ta netcat (nc) için şöyle bir kullanım buldum:

$ nc -z -u -v time.windows.com 123

Connection to time.windows.com 123 port [udp/ntp] succeeded!

burada

-z : zero IO (sadece bağlantı durumunu bildir, gereksiz veri alışverişi yapma)

-u : UDP kullan

-v : verbose (ayrıntılı çıktı göster)

Windows'da ise gerek WSL gerekse nmap ile gelen nc klonu ncat ile de benzer kullanım mümkün. UDP için

PS> ncat -vuz time.windows.com 123

Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Connected to 40.119.148.38:123.
Ncat: UDP packet sent successfully
Ncat: 1 bytes sent, 0 bytes received in 2.04 seconds.

veya TCP için

PS> ncat -vt uzakpc 80

Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Connected to xx.xx.xx.xx:80.

ncat, TCP için -z (zero IO) parametresini kabul etmedi, protokolün doğası gereği. Yukarıdaki komuttan sonra bağlantı açık kalır, web snuucu GET, POST gibi komutlardan birini bekler. Örneğin Ctrl+C ile çıkmadan aşağıdaki gibi bir komut yazılarak varsayılan açılış sayfası istenebilir:

GET / HTTP/1.1

Benzer ihtiyacı olan powershell severler, kendi cmdlet'lerini de yapmışlar [1].

Bu arada 123/udp portuna bağlanabiliyor olmak, çalışan bir NTP hizmeti olduğu anlamına gelmez, sadece ilgili sunucunun NTP portuna bağlanabildiğimizi gösterir. Aynı şekilde 80/tcp portuna bağlanmak web sunucunun tam olarak istediğimiz şekilde çalıştığını göstermez, sadece bu portunu dinleyen bir hizmetin aktif olduğunu gösterir.

---

[1] https://cloudbrothers.info/en/test-udp-connection-powershell/

23.06.2023

Karanlık tema

Blog'un görseline uzun zamandır gereken önemi veremediğimin farkındaydım. Nihayet o gün bugünmüş. Karanlık temamın güzel olduğunu düşünüyorum. "Nihayet, gecenin bir vakti blog yazarken beyaz ışığa bakmayacağım" demek isterdim, ama düzenleme sayfasının teması değişmiyormuş. Olsun, bu da bir şey.

16.06.2023

pktmon

Linux sistemlerde mümkündü, ama Windows'da olduğunu yeni öğrendim. Uzaktaki bir sistemin yakalanan paketleri kaydetmesini (Wireshark veya tcpdump gibi) nasıl sağlayabilirim?

Şu videoda belirtildiği gibi pktmon kullanarak:

pktmon start --capture

ile başlanan yakalama işlemi, mevcut klasördeki pktmon.etl dosyasına kaydediliyor. Bu dosyayı açmak için bir sürü yöntem vardır eminim, ama Wireshark ile açmak için önce bu dosyayı pcapng formatına dönüştürmek gerek. Bunu da

pktmon etl2pcap pktmon.etl

diyerek yapabiliyoruz. Bundan sonrası Wireshark işleri. Filtreler ekleme için şu ve bu sayfalar faydalı olabilir. Örneğin --capture ile yakalamaya başlamadan önce hedefimizi daraltmak ve yakalanan dosyayı küçültmek için şu şekilde filtreler eklenebilir:

pktmon filter add -i 1.1.1.1 -t icmp

Bu satır ile 1.1.1.1 adresine giden ve bu adresten gelen ICMP paketleri yakalanır.

pktmon filter add -p 53

Yukarıdaki satır da sadece 53 portu (DNS) trafiğini yakalar.

9.06.2023

ssh-rsa algorithm is disabled

Linux sunucularda oturum açmak için kullandığım görece "yeni" bir rsa anahtarım vardı. Yeni kurulum yaptığım bir sunucuya da bu anahtarı aktarıp ssh ile oturum açmaya çalıştığımda kabul etmedi, loglarda

sshd[xxxxx]: main: sshd: ssh-rsa algorithm is disabled

gibi bir satır gördüm. Niye acaba ssh-rsa devre dışı bırakılmış olabilir diye bir arama yapmak yerine bunu ChatGPT'ye sormak istedim:

Özetle ssh-rsa, SHA1 hash işlevlerini kullandığı için, SHA1'in ise artık güvensiz kabul edildiğinden [1] dolayı, devre dışı geliyormuş. Bu konuda ilginç görüşler [2] de var ama camia güvensiz diyorsa güvensizdir.

SHA1'in güvensiz kabul edildiğini biliyordum, ama RSA'nın SHA1 kullandığını bilmiyordum. Son 1 yılda kurulmuş bir sunucu (Debian) üzerinde oluşturduğum ssh anahtarımın da ssh-rsa olduğunu öğrenince şaşırdım.

İki seçeneğim var; ya sunucuda (güvenlik uyarılarını göz ardı ederek) ssh-rsa desteğini etkinleştireceğim, ya da ssh anahtarımı sha512 desteği olacak şekilde yenileyeceğim. İlk yöntemi denemek istemesem de serverfault.com'da ve redhat.com'da şu şekilde bir yöntem belirtilmiş:

# update-crypto-policies --set DEFAULT:SHA1

Ayrıca stackexchange.com'da da bir yöntem buldum, ama RockyLinux'ta işe yaramadı.

Gelelim önerilen yönteme. ssh-keygen'in sha512 kullanmasını söyleyen bir parametre yok. Ama çeşitli kaynaklardan [3,4] bulduğum yöntem ssh-keygen'e -t ile anahtar tipini ecdsa olarak belirtmek ve bit uzunluğunu 521 (evet, ilginç) seçmek.

$  ssh-keygen -t ecdsa -b 521

man ssh-keygen'de parametreler hakkında şu bilgiler var:

-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa
             Specifies the type of key to create.  The possible values are “dsa”, “ecdsa”, “ecdsa-sk”, “ed25519”, “ed25519-sk”, or “rsa”.

-b bits
             Specifies the number of bits in the key to create.  For RSA keys, the minimum size is 1024 bits and the default is 3072 bits.  Gener‐
             ally, 3072 bits is considered sufficient.  DSA keys must be exactly 1024 bits as specified by FIPS 186-2.  For ECDSA keys, the -b
             flag determines the key length by selecting from one of three elliptic curve sizes: 256, 384 or 521 bits.  Attempting to use bit
             lengths other than these three values for ECDSA keys will fail.  ECDSA-SK, Ed25519 and Ed25519-SK keys have a fixed length and the -b
             flag will be ignored.

Bir genel anahtarın içine bakarak ne tür bir algoritma kullandığını görebiliriz:

$ cat id_ecdsa.pub

ecdsa-sha2-nistp521  ...

---

[1] https://www.computerworld.com/article/3173616/the-sha1-hash-function-is-now-completely-unsafe.html

[2] https://www.quora.com/Does-SHA-1s-insecurity-have-any-effect-on-Git

[3] https://cloud.ibm.com/docs/hp-virtual-servers?topic=hp-virtual-servers-generate_ssh 

[4] https://www.ssh.com/academy/ssh/keygen#choosing-an-algorithm-and-key-size

 

8.06.2023

pacman.log

Uzun bir süredir Manjaro kurulu olan bir bilgisayarım var. Diskini değiştirdim, diskte yer azaldı, temizlik yaptım, ama pacman.log dosyasını hiç temizlemedim. 4 seneden fazla bir zamandır kullanıyormuşum:

$ head -5 /var/log/pacman.log

İlk satırdaki tarih ilk güncelleme yaptığım tarih.

5 farklı sürüm LTS çekirdek kurmuşum:

$ grep -E 'installed linux[[:digit:]]{2,3}[[:blank:]]' /var/log/pacman.log | wc -l

5

grep komutuna özgü [[:digit:]] ve [[:blank:]] zırvaları ile uğraşmamak için

$ grep -E 'installed linux[0-9]{2,3} ' /var/log/pacman.log | wc -l

de kullanabiliriz. Ama + ve * gibi nicelik belirten operatörler için yine -en azından grep kullanırken- [[:digit:]] ve [[:blank:]] gibi işleçlere ihtiyaç var.

Bütün çekirdek güncellemeleri bu kadar değil. Güncellemeler 248 kez olmuş:

$ grep -E 'upgraded linux[[:digit:]]{2,3}[[:blank:]]' /var/log/pacman.log | wc -l

248

80 kez pacman ile kurulum yapmışım:

$ grep "Running 'pacman -S " /var/log/pacman.log | grep -v "pacman -S -" | wc -l

80

Kaç kez "büyük" sistem güncellemesi yaptığımı bulamadım. Ama sanıyorum her güncelleme öncesinde manjaro-keyring yükseltiliyor. Buradan belki şu komut ile bir yerlere varsabilir miyiz

$ grep "upgraded manjaro-keyring" /var/log/pacman.log

Ayrıca pacman.log'larından şunları da öğrendim. Eğer pacman -Syu yapıyorsam loglarda

[PACMAN] Running 'pacman -Syu'

satırı geçiyor. Eğer pamac update yapıyorsam loglarda

[PAMAC] synchronizing package lists

geçiyor. Eğer grafik arayüzden octopi kullanıyorsam da loglarda

[PACMAN] Running '/usr/bin/pacman -S --noconfirm

geçiyor. Bunların sonucunda pacman.log dosyam 3,5 MB civarında.

2.06.2023

Uzaktan winget kurulumu

Etki alanındaki makinelerde bile winget varsayılan olarak kurulu gelmiyor, şu an için. Kurmak için şu adresten kurulum paketini indirmek gerek.Uzaktan kurulum yapacağım için Microsoft Store'dan indirmek bir seçenek değil.

Kurulum paketimizin adı Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle gibi birşey olacak. Bunu hedef makinemizin D:\ sürücüsünün köküne koyduğumuzu varsayalım. Daha sonra bir uzak powershell bağlantısı gerçekleştirmemiz lazım.

PS> etsn uzakpc

Bu aşamadan sonra varsayılan olarak uzaktaki PC'nin C:\Users\<kullaniciadi>\Documents gibi bir konumunda oturumumuz başlayacak. Önce

[uzakpc] C:\Users\metin\Documents\> cd D:

gibi bir komutla kurulum dosyamızın olduğu konuma geçiş yaptım. Daha sonra da Add-AppxPackage ile kurulumu başlattım.

[uzakpc] D:\Add-AppxPackage -Path .\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle

Bu komut hiçbir mesaj göstermeden tamamlandı. Sonrasında

[uzakpc] D:\> winget list

ile algılanan paketleri sorgulamak istediğimde önce anlaşılmaz birkaç bozuk satırdan sonra şöyle bir  hata verdi:

The `msstore` source requires that you view the following agreements before using.
Terms of Transaction: https://aka.ms/microsoft-store-terms-of-transaction
The source requires the current machine's 2-letter geographic region to be sent to the backend service to function properly (ex. "US").

Do you agree to all the source agreements terms?
[Y] Yes  [N] No: An unexpected error occurred while executing the command:
0x8a150042 : Error reading input in prompt

Ama Y veya N'ye basmama izin vermeden çıktı. Uzaktan bu prompt sorununu nasıl halledebilirim diye winget'in parametrelerine bakarken

 --disable-interactivity   Disable interactive prompts

parametresini farkettim. winget'i bu parametre ile çalıştırmayı denediğimde de asıl sorun ortaya çıktı:

[uzakpc] D:\winget list --disable-interactivity

The `msstore` source requires that you view the following agreements before using.
Terms of Transaction: https://aka.ms/microsoft-store-terms-of-transaction
The source requires the current machine's 2-letter geographic region to be sent to the backend service to function properly (ex. "US").

One or more of the source agreements were not agreed to. Operation cancelled. Please accept the source agreements or remove the corresponding sources.
 

Bu konu ile yaptığım aramada da şu sayfada winget'in yardımında (/? ile ulaşılan) listelenmeyen iki parametersini buldum:

--accept-package-agreements

--accept-source-agreements

Benim durumumda bu sanki "source agreements" ile ilgili görünüyordu. Bu sebeple ikinci paremetre ile şansımı denedim:

[uzakpc] D:\> winget list --accept-source-agreements

ve sonuca ulaştım.

2023-09-01 Ek: Şu videoda indirmeden doğrudan kurmayı seçmiş. Bir ara denemek lazım:

PS> Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe

30.05.2023

Scheduled Tasks vs Scheduled Jobs

Bir süredir gördüğüm ama farklarını bilmediğim iki farklı tip cmdlet seti arasındaki farkları, okuduğum eski ama çok güzel bir yazı aracılığıyla öğrendim; Powershell camiasına uzun yıllar "Microsoft Scripting Guy" lakabıyla değerli katkılarda bulunmuş Ed Wilson'ın yazılarından biri ile.

Powershell'de zamanlanmış görevler oluşturmak istersek karşımızda ScheduledTasks ve ScheduledJobs adında iki farklı kavram oluyor. Task ve Job kelimeleri Türkçe'de "görev"e karşılık geliyor. Bu sebeple anlatırken İngilizceleri üzerinden anlatacağım.

Windows ile birlikte gelen Görev Zamanlayıcısı arayüzü, Task olarak gruplanan görevlerin zamanlanması için bir araç. Geniş bir kullanım yelpazesi var. ps1 uzantılı powershell dosyaları da çalıştırılabilir, exe uzantılı çalıştırılabilir programlar da çalıştırılabilir.

Jobs ise Powershell'e özgü bir kavram. Terminal kavramında arkaplan görevleri vardır. Çalışması uzun zaman alacak komutları arka planda çalıştırmak isteyebiliriz. Bu zaman diliminde diğer komutun işlemini bitirmesini beklemeden başka işlemler de yapabiliriz. Bu sırada arkaplanda çalışan Job'ları takip edilebilir, bittiğinde sonuçları ve çıktılarını gözlemleyebiliriz. Hatta bazı cmdlet'lerin -AsJob parametersi vardır; çalışmayı arkaplanda yürütmek için. Scheduled Jobs ise bu tip arkaplan görevlerinin bir uzantısı gibi.

PS> $j = Invoke-Command -ComputerName localhost, Server01, Server02 -Command {Get-Date} -AsJob

Bu komutla sunucular üzerinde Get-Date komutunu yürütme işlemi arkaplanda yürütülür. Daha sonra

PS> $j

Id Name   PSJobTypeName State      HasMoreData   Location
-- ----   ------------- -----      -----------   --------
3  Job3   RemotingJob   Failed     False         localhost,Server...

komutu ile görevin durumu görüntülenebilir. Hatta 3 farklı sunucu bize çıktı ürettiği için bu arkaplan görevinin ayrıntıları için

PS> Get-Job -IncludeChildJobs

Id  Name   PSJobTypeName State      HasMoreData   Location    Command
--  ----   ------------- -----      -----------   --------    -------
3   Job3   RemotingJob   Failed     False         localhost,Server...
4   Job4                 Completed  True          localhost   Get-Date
5   Job5                 Failed     False         Server01    Get-Date
6   Job6                 Completed  True          Server02    Get-Date

yazılarak alt görevler listelenebilir. Daha sonra her birinin çıktılarını görmek için

PS> Receive-Job -Name Job6 -Keep | Format-Table ComputerName,
>> DateTime -AutoSize
ComputerName DateTime
------------ --------
Server02     Thursday, March 13, 2008 4:16:03 PM

yazılabilir. ScheduledJobs aslında, bu arkaplan görevlerinin otomasyonu için ScheduledTask atlyapısı ile birlikte Poweshell için oluşturulmuş bir modül. Jobs ile ilgili modülün adı PSScheduledJob. Bu modülün içindeki cmdlet'lere bakmak için

PS> gcm -m PSScheduledJob

yazabiliriz. Oluşturulan Scheduled Jobs nesnelerine dosya sistemi üzerinden C:\Users\<kullaniciadi>\AppData\Local\Microsoft\Windows\PowerShell\ScheduledJobs klasöründen erişebiliriz.

Zamanlanmış görevleri Powershell'den yönetmek için geliştirilen modül ise ScheduledTasks. Bu modül ile birlikte gelen cmdlet'lere de bakalım:

PS> gcm -m ScheduledTasks

Jobs sadece Poweshell komutları veya ps1 uzantılı dosyaları çalıştırmak üzere tasarlanmış. Tasks için böyle bir kısıtlama söz konusu değil. taskschd.msc ile eriştiğimizi MMC snap-in'i ile hem Task'ları hem de Job'ları yönetebiliriz. Ama bu snap in ile sadece Task oluşturabiliriz. Powershell ile oluşturulmuş Job'lara ise taskschd.msc içinden Görev Zamanlayıcı Kitaplığı>Microsoft>Windows>Powershell yolundan ulaşabiliriz.

Bir örnek olması açısından Powershell yardım kitaplığını güncelleyecek bir Job yaratalım. Bunu her oturum açtığımızda, 30 dakikalık rastgele gecikme sonrasında çalışacak şekilde ayarlayalım. İlk iş önce bir zamanlayıcı (trigger) yaratmak:

PS> $t = New-JobTrigger -AtLogon -RandomDelay 00:30:00

Sonra da zamanlayıcı kullanarak yeni bir Job kaydedelim.

PS> Register-ScheduledJob -Name "YardimGuncelle" -Trigger $t -ScriptBlock {Update-Help -Force}

Bu Job'ın dosya sisteminde ve tasksch.msc'deki görünümleri aşağıdaki gibi oldu.

 


 Benzer bir şekilde bir de Task oluşturalım. Yine zamanlayıcıdan başlayalım.

PS> $t1 = New-ScheduledTaskTrigger -AtLogon -RandomDelay 00:30:00

Task'lar sadece powershell komut veya betikleri olmadıkları için eylem nesnesi oluşturmalıyız.

PS> $a1 = New-ScheduledTaskAction -Execute powershell.exe -Argument "-ExecutionPolicy RemoteSigned -Command 'Update-Help -Force'"

Nihayet bu iki nesneyi de birleştirip bir Task olarak kaydedelim.

PS> Register-ScheduledTask -TaskName "YardimGuncelle2" -Trigger $t1 -Action $a1

Mevcut Job'ları veya Task'ları sorgulamak için ise sırasıyla

PS> Get-ScheduledJob

ve

PS> Get-ScheduledTask

cmdlet'leri kullanılabilir.

İki modül arasında işlevsellik farkları var. Örneğin Job'lar için kaçırılan görevlerin tekrar çalıştırılması gibi bir seçenek yok, Task'lar için var. Bunu sağlayan da New-ScheduledTaskSettingsSet cmdlet'inin -StartWhenAvailable parametresi.

24.05.2023

Windows 10 ve üstü sistemlerde açık kalma süresi (uptime) belirleme

Bir süredir hayatımızda hızlı başlatma var.

Varsayılan olarak açık geliyor, sürekli eklenen yeni bileşenlerin Windows'un açılışını daha da yavaşlatmaması için bulunan bir çözüm. Ama bunun sonucunda da bir bilgisayara eski yöntemlerle ne kadardır açık diye baktığımızda beklenmedik uzun süreler görebiliyoruz. Bilgisayar aslında kapat komutuyla eskiden olduğu gibi kapanmıyor, uyku moduna alınıyor.

Buraya kadar giriş kısmıydı. Gelişmeye geçelim. Bir bilgisayarın ne kadar süredir açık olduğunu sorgulamak için genelde WMI (veya CIM) sorgusu ile Win32_OperatingSystem sınıfından LastBootUpTime değeri okunur. Örneğin:

PS> Get-CimInstance -ClassName Win32_OperatingSystem | Select LastBootUpTime

gibi. Bu, en son açılış zamanını verirdi, eskiden. Bunu şu andaki saat-tarih bilgisinden çıkararak ne kadar süredir açık olduğu bilgisine ulaşırdık.

Her ne kadar bilgisayarın gerçek "açık kalma süresi" bu olsa da yine de kullanıcının başlat menüsünden kapatma ve sonrasında güç düğmesine basarak bilgisayarı açma alışkanlığına göre açılış ve kapanış geçmişi öğrenmek istersek şu yazımda belirttiğim sistem olaylarından Kernel-General, 1 olayını dikkate alabiliriz. Ancak bu olay açılış haricinde de oluşabiliyor. Bunu ayırt etmek için de Reason=2 koşuluna dikkat etmek gerek.

Yani:

PS> Get-WinEvent -ComputerName uzakpc -FilterHashtable @{Logname="System";Id=1;ProviderName="*Kernel-General"} | where {$_.properties[3].Value -eq 2} | Select-Object -First 1

gibi bir sorgu ile bu olayı tespit edip buradan TimeCreated alanı ile en son açılış anını belirliyorum. Ayrıntılar sekmesinde görüntülenen verilerden Reason, properties[3]'e den gekliyor (sıfır endeksli). Hızlı başlatma durumunda işletim sisteminin kapanmasına karşılık gelen olay da Kernel-Power 107 olayı. Bu iki olay olay kayıtlarında arka arkaya geliyor.

Bu arada herhangi bir makinede hızlı açılış/başlatma (fast boot) etkin mi değil mi diye bakmak için

PS> (gp "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Power")."HiberbootEnabled"

Bu komut 1 dönüyorsa hızlı başlatma etkindir, 0 (sıfır) dönüyorsa değildir.

22.05.2023

Outlook adres defteri indirme hatası

Yeni oluşturulan hesaplar Outlook adres defterinde görüntülenmiyorsa Gönder/Al sekmesinden Gönder/Al Gruplarından "Adres defterini indir.." seçilir. Ama burada da aşağıdaki gibi bir 0x8004010f hatası alıyorsak Exchange sunucu tarafında bazı kontroller yapmak gerekir.

Yüksek olasılıkla Exchange sunucuda bir varsayılan adres defterimiz vardır. GlobalWebDistributionEnabled ve WebDistributionEnabled özelliklerini kontrol edelim:

PS> Get-OfflineAddressBook | fl Name,GlobalWebDistributionEnabled,WebDistributionEnable

Benim sunucumda bu

Name                         : Default Offline Address Book (Ex2013)
GlobalWebDistributionEnabled : False
WebDistributionEnable        : True

olarak döndü. Bu durumda burada ve şurada söylendiği gibi bu dağıtılabilirlik özelliklerini etkinleştirmek gerek:

PS> Get-OfflineAddressBook | Set-OfflineAddressBook GlobalWebDistributionEnabled $true

Benim durumumda sadece GlobalWebDistributionEnabled devredışı olduğu için onu etkinleştirdim.

21.05.2023

Poweshell ile download edilecek içeriğin boyutunu indirmeden önce öğrenmek

Varsayalım ki uzak web sunucu üzerinde bir içeriğimiz var:

https://live.sysinternals.com/files/SysinternalsSuite.zip

İndirmeden önce boyutunu öğrenmek isityoruz.

Şu yöntem kullanılabilir:

(iwr -uri "https://live.sysinternals.com/files/SysinternalsSuite.zip" -Method Head).Headers.'Content-Length'

18.05.2023

Çalışan bir süreç hizmete mi ait?

Get-Process ile çalışan süreçleri listeleyebiliy, süreç bazında ayrıntılara erişebiliyoruz. Peki bu süreçlerden herhangi biri halen çalışmakta olan bir hizmete mi ait? Get-Process'in döndüğü verilerin içinde bu ilişkiyi görebileceğimiz bir alan yok. Ama eski adı WMI (Windows Management Instrumentation)  veya yeni adı CIM (Common Information Model) olan yöntemle mümkün. Örneğin Get-CIMInstance ile Get-Service'ten daha fazla veriye erişmek mümkün:

Get-CIMInstance Win32_Service

Çalışan her hizmete ait sürecin adı ve süreç kimliği (process ID) gibi veriler görülebilir. Örneğin uzaktaki sunucuda gördüğüm lsass süreci, 820 kimliği ile çalışıyor. Peki bu süreç herhangi bir hizmetle ilişkili midir?

Elimde hem süreç adı hem de süreç kimliği varken iki farklı sorgu yapabilirim:

Get-CIMInstance Win32_Service | Where-Object ProcessId -eq 820

ya da aliasları kullanarak (biraz da format-table ile çıkışı düzenleyerek)

gcim Win32_Service | where Name -eq "lsass" | ft DisplayName, Name, ProcessId, State, Status, ExitCode -AutoSize

DisplayName                      Name     ProcessId State   Status ExitCode
-----------                      ----     --------- -----   ------ --------
Kerberos Key Distribution Center Kdc            820 Running OK            0
CNG Key Isolation                KeyIso         820 Running OK            0
Netlogon                         Netlogon       820 Running OK            0
Active Directory Domain Services NTDS           820 Running OK            0
Security Accounts Manager        SamSs          820 Running OK            0

Sonuçta bu sürece bağlı birden fazla hizmetimizin olduğunu gördük.

16.05.2023

Windows kimlik bilgileri

Windows 10 ve üzeri bilgisayarlarda başlat menüsüne "Kimlik bilgileri yöneticisi" yazınca ya da komut satırından control keymgr.dll yazarak ulaşılan alan, Windows'un şifre hatırlama mekanizması ile kaydedilen kullanıcı adı ve parolaların saklandığı mekanizma. Şu yazımda da belirttiğim gibi bu mekanizma bazen sorun tespitini zor hale getirebiliyor. Bir profildeki kimlik bilgilerini listeyebilir miyim diye bakarken cmdkey'e ve vaultcmd'ye rastgeldim.

cmdkey /list

veya

vaultcmd /list

Ama bunları uzaktaki bir bilgisayarda çalıştırdığımda uzak terminale bağlanırken kullandığım kullanıcı hesabına ait kayıtlar listelendi.

Acil durumlarda kullanmak üzere daha pratik ama daha vahşi bir yöntem olarak credential store tamamen silinebilir:

C:\Users\<user>\AppData\Roaming\Microsoft\Credentials
C:\Users\<user>\AppData\Local\Microsoft\Credentials


4648 güvenlik olay kayıtları ve VaultSvc

Etki alanı sunucusu güvenlik olay kayıtlarında 4771 oluştuğunda istemci tarafında da 4625 görmek normaldir. Ancak son zamanlarda farkettim ki birçok 4771 olayına karşılık gelen bir 4625 yok. Bunun sebebini araştırmak için sunucu tarafında aldığım bir 4771 olayının saatini kullanarak istemci tarafındaki olayları inceledim.

$sunucu4771 = Get-WinEvent -Computer DC -FilterHashTable @{LogName="Security";Id=4771} | Where-Object {$_.properties[0].Value -eq "kullanici.adi"} | Select-Object -First 1 -Properties TimeCreated, @{Name="Client";Expression={$_.properties[6].Value.split(":")[1]}}

Bu sorgu sonucunda $sunucu4771 değişkeninde en son 4771 olayının zamanı (TimeCreated) ve bu olayı oluşturan istemci IP adresi (Client) olmalı. Bu verilerle istemciyi sorgulayalım:

$istemci = Get-WinEvent -Computername $sunucu4771.client -FilterHashTable @{LogName="Security";StartTime=$sunucu4771.TimeCreated.AddSeconds(-2);EndTime=$sunucu4771.TimeCreated.AddSeconds(2)}

Burada da 4771 olayından 2 saniye önce ve 2 saniye sonrası zaman aralığında istemci tarafında oluşan güvenlik olay kayıtlarını listeledim. Gördüm ki bu sorguda 4648 olay kayıtları tutulmuş. Peki nedir bu 4648 diye ayrıntılarına baktığımda farkettim ki 4648, Windows Credential Store'a kaydedilmiş parolaların kullanılmasıyla oluşmuş olaylar. Benim durumumda şöyle oluyor; kullanıcının şifresinin süresi dolduktan sonra Outlook kullanıcının parolasını kabul etmiyor ve "parola kutusu" çıkıyor. Kullanıcı da sorgulamadan şifresini yazıp tamama basıyor. Ama yazılan şifre zaten süresi dolmuş şifre olduğundan parola kutusu tekrar çıkıyor. Bu aşamada kullanıcılar genellikle "parolayı kaydet, bana bi daha sorma" yoluna gidiyor. Ama kaydedilen şifre süresi geçmiş şifre oluyor.

Windows Credential Store, VaultSvc hizmeti ile çalışıyor. Bu hizmet mi devre dışı bırakılmalı, bilemedim.

10.05.2023

Zamanlanmış Görevler

Windows'da zamanlanmış görevler (scheduled tasks) veya yeni adıyla görev zamanlayıcısı (task scheduler) olarak bilinen bir çalışma yapısı var. Periyodik olarak veya belli bir olay olduğunda (ör. oturum açma) uygulanması gereken bir görev varsa bu yapıyı kullanıyoruz.

Bu şekilde belli bir zamanda çalıştırlmak üzere oluşturduğumuz nesnelere görev,  bu görevleri periyodik veya belli olaylar olduğunda çalıştırma mekanizmasına tetikleyiciler, görevlerin amacı olarak çalıştırılacak uygulamalara da etkinlik diyoruz.

Temel olarak çok basit bir çalışma yapısı var, ama her seçenek her durumda işe yaramıyor. Örneğin her 15 dakikada bir çalıştırılmasını istediğimiz görev sadece iki durumda 15 dakikada bir çalıştırılıyor:

- Bir kez çalışacak şekilde ayarlanan ve sonrasında yenileme belirtilen durumlar,

- Belli bir periyotta (günlük, aylık vs) çalışacak şekilde ayarlanan ve sonrasında yenileme belirtilen durumlar.

Ne kaldı? Bir olay olduktan sonra (oturum açma/kapama, bilgisayar açılışı, bir olay günlüğü kaydı olduğunda vs.) çalıştırılmak üzere ayarlanan görevler sonrasında yenileme belirtilmiş olsa da yenilenmiyor.

Ayrıca yukarıda görüldüğü gibi en altta bir "Gizli" kutucuğu var. Çalıştırılan görev normal şartlarda bir pencere açıyorsa bu pencerenin gizli olmasını istediğimiz durumlarda işaretleniyor. Benim çalıştırdığım görev bir Powershell betiğiydi. Bunu da her çalıştırmada görüntülemek istememiyordum. Ama bu "Gizli" kutucuğunu işaretlememe rağmen her seferinde bu pencere görüntüleniyordu. Buna çözüm olarak görevin yukarıda seçildiği gibi "Yalnızca kullanıcı oturum açtığında çalıştır" seçeneği seçilerek değil, "Kullanıcı oturum açmışsa da açmamışsa da çalıştır" seçeneği ile oluşturulmasını önerilmiş. Bu bazı durumlarda işe yarayabilir ama benim için kullanıcının oturum açmadığı durumlarda bir anlamı yoktu. Bu durumda işimize yarayabilecek bir çözüm de superuser.com'da buldum. Görev etkinliğine powershell.exe (ve ilgili script'i) değil de bir .vbs dosyasını göstererek içerği şu şekilde belirlemek önerilmiş (hepsi tek satırda):

WScript.CreateObject("WScript.Shell")
.Run "powershell -ExecutionPolicy Bypass -WindowsStyle Hidden -File C:\\Path\\To\\MyScript.ps1', 0,true


5.05.2023

Olay günlüğündeki en eski olay

Ara sıra da olsa bir bilgisayardaki olay günlüklerinin içindeki en eski olayı görmek istiyorum; çoğunlukla sistem ve güvenlik günlüğündeki. Get-WinEvent cmdlet'inin -Oldest paremetresi, olayları en eskiden başlayarak en yeniye göre sıralıyor. En eskiyi görmek için -MaxEvents ile birleştirilebilir.

PS> Get-WinEvent -LogName Security -Oldest -MaxEvents 1

Uzak bir bilgisayar üzerindeki en eski 4624 olay kaydını görmek istersek

PS> Get-WinEvent -Computername uzakpc -FilterhashTable @{LogName="Security";Id=4624} -Oldest -MaxEvents 1


3.05.2023

Powerhell ile uzaktan bağlanan kim

Bir etki alanımız olduğunu ve bu etki alanı içinde powershell remoting'i etkinleştirdiğimizi düşünelim. Bu etki alanına dahil olan bilgisayarların herhangi birinde uzaktan komut çalıştırdığımızda işlem, Powershell Web Services süreci wsmprovhost.exe aracılığıyla çalışır. Herhangi bir makineye kimin bağlı olduğunu görmek için

PS> ps wsmprovhost* -IncludeUsername

kullanabiliriz.

26.04.2023

Powershell'de çıkışa satır numarası eklemek

Domain'de bir grubun üyelerini listelemek için şöyle bir komut kullanıyorum:

PS> Get-ADGroupMember -Identity "Grup Adi"

Bunun sonucunda kullanıcı nesneleri listelenir. Nesne ile bütün verilere ihtiyacım yok, sadece isimler yeterli. Bu durumda select-object ile sadece Name alanı süzülebilir:

PS> Get-ADGroupMember -Identity "Grup Adi" | select name

Gelen listeye bir de kullanıcıların grup bilgisini eklemek istiyorum. Benim durumumda bu bilgi Organizational Unit adında var.

PS> Get-ADGroupMember -Identity "Grup Adi" | select Name,@{N="Bolum";E={$_.DistinguishedName.split(",")[1].Split("=")[1]}}

Nihayet, bir de bu listeyi 1'den başlayıp her satırda artan şekilde satır numaralarıyla görüntülemek istiyorum. Bunun için bir $satir değişkeni yaratıp şu şekilde sürece ilave ettim:

PS> $satir=0;  Get-ADGroupMember -Identity "Grup Adi" | select Name,@{N="Bolum";E={$_.DistinguishedName.split(",")[1].Split("=")[1]}} | % {$satir++;"$satir `t$($_.Name)`t$($_.Bolum)}

Daha kolay bir örnek üzeriden satır numaraları konusunu tekrarlayayım. Bir metin dosyasına satır numaraları eklemek için

PS> $satir=0; gc dosya.txt | % {$satir++;"$satir`t$_"}


24.04.2023

Powershell ile ekran çözünürlüğünü değiştirmek

Maalesef Powershell ile varsayılan olarak çözüürlüğü değiştirecek bir cmdlet gelmiyor. Ama Powershell-Gallery'de güzel bir modül var. Kurmak için terminali yönetici yetkileriyle açtıktan sonra

PS> Install-Module DisplaySettings

kullanmak ve sonrasında kaynağa güvendiğimizi belirtmek gerek. Bu adımlardan sonra

PS> Set-DisplayResolution -Width 1440 -Height 900

ile çözünürlüğü ayarlamak mümkün. Var olan çözünürlüğü öğrenmek için ise

PS> Get-DisplayResolution

var. Modüldeki yegane iki cmdlet bunlar. Modül bugün itibarı ile 0.0.2 sürümde.

Server Core için böyle bir modül var ama PSGallery'deki modülün Microsoft ile bir ilişkisini göremedim.

10.04.2023

Powershell'de tür dönüşümü (casting)

Birçok programlama ortamında tür dönüşümü eşittir işaretinin sağında yapılır. Ama powershell'de bu iş eşittirin solunda da yapılıyor. Bunun sebebiyle ilgili bulduğum çok güzel bir açıklamayı[1] paylaşmak istiyorum.

Varsayalım bir xml dosyamız var, diskte kayıtlı (dosya.xml). Bu xml dosyamızı okuyup bir değişkene atmak istiyoruz. Ama değişkenimizin de xml tipinde bir değişken olmasını istiyoruz. Diğer programlama ortamlarından alışık olduğumuz durum şu olabilir:

PS> $x = [xml]Get-Content -Path dosya.xml

Bu yanlış bir ifade olurdu. [xml] tür dönüşümü yapmak istediğimiz veri, dosya.xml dosyası okunduktan sonra Get-Content cmdlet'inin döndüğü tüm veri olduğundan burada bir parantez kullanmalıyız. Yani;

PS> $x = [xml](Get-Content -Path dosya.xml)

Bu şekilde x değişkenine atanan verinin xml türünde olması sağlanabilir. Ama powershell'de bu iş şu şekilde yapılıyor:

PS> [xml]$x = Get-Content -Path dosya.xml

Bu şekilde x değişkenimizin türü xml olarak oluşturulmuş. Sonrasında bu değişkene yapılacak atamaların da otomatik xml'e dönüştürülmesi sağlanmış.

---

[1] https://stackoverflow.com/questions/11685265/casting-in-powershell-weird-syntax

7.04.2023

Olay günlüğü (eventlog) boyutlarını değiştirme

Get-WinEvent ile güvenlik olay kayıtlarını incelerken bazen hiç kayıt dönmüyor. Bunun sebebi de varsayılan olarak 20 MB olarak ayarlanan güvenlik olay günlüğünün bir süre sonra eski olayları siliyor olması. Yerel bilgisayarda mevcut durumu kontrol etmek için

PS> Get-Evenlog -List

kullanabiliriz. Güvenlik olay günlüğü (security) için bunu yönetici yetkileriyle açılmış bir pencereden çalıştırmamız gerek. Uygulama ve sistem için buna gerek yok. Bu komutun ürettiği çıktıda Max(K) sütununa bakarak istediğimiz olay günlüğünün azami boyutunu öğrenebiliriz. Bunu Get-WinEvent ile de yapabiliriz. Örneğin uzak bir bilgisayarın uygulama, sistem ve güvenlik olay kayıtlarını (yetkilerimiz dahilinde) incelemek için

PS> Get-WinEvent -Computername uzakpc -Listlog Application, System, Security

Yerel bilgisayarda olay herhangi bir günlüğüne ayrılmış alanı değiştirmek için

PS> Limit-Eventlog -LogName Security -MaximumSize 128MB

kullanabiliriz. Yeni boyutun 64KB'ın katları olması gerektiği söylenmiş. Bunu sağlamak için en iyi yöntem MB birimlerini kullanarak 1MB'ın katlarını belirtmek olabilir.

Limit-Eventlog cmdlet'inin -Computer parametresi ile ya da Invoke-Command kullanarak bu işlemi uzak bilgisayarlarda da uygulayabiliriz.

Sadece yerel bilgisayarda çalışan Get-LogProperties cmdlet'ini uzak bilgisayarda kullanmak için Invoke-Command ile birlikte çalıştırabiliriz. Hatta alias'larla birlikte şöyle bir çıktı üretir:

PS> icm -cn uzakpc {Get-LogProperties Security}

PSComputerName : uzakpc
RunspaceId     : <...>
Name           : Security
Enabled        : True
Type           : Admin
Retention      : False
AutoBackup     : False
MaxLogSize     : 524288000


26.03.2023

Powershell'in dahili fonksiyonları

Powershell'de New-Item cmdlet'ini yeni dosya oluşturmak veya yeni klasör oluşturmak için kullanabiliriz. Bu farkı belirtmek için -ItemType var. Dökümantasyona göre varsayılan bir değeri yok:


Ama garip bir şekilde özellikle belirtmezsek dosya sistemi modunda "dosya" oluşturuyor. Bu varsayılan değer demek değil mi?

Neyse, bu cmdlet'in "ni" alias'ı da var. Gerek tam cmdlet adı, gerek alias'ı ni ile klasör oluşturmak için -ItemType'a Directory değerini vermek yeterli. Hatta ItemType parametresinin yukarıdaki resimde görüldüğü gibi Type alias'ı da var.

PS> New-Item -ItemType Directory -Name YeniKlasor

PS> ni -type directory YeniKlasor

Ama ilginç bir şekilde mkdir veya md komutları da Powershell'de çalışıyor. Önceleri bunları New-Item alias'ları olduğunu sanmıştım ama öyle değilmiş (olsaydı alias için varsayılan parametre değeri nasıl değiltirilir, merak ederdim). Get-Command ile baktığımda şöyle bir sonuç aldım:

PS> Get-Command mkdir

CommandType     Name                      Version    Source
-----------     ----                      -------    ------
Function        mkdir

Meğer mkdir bir Powershell dahili (built-in) komutuymuş. md ise mkdir için bir alias'mış. Diğer dahili komutlar şunlar:

cd..
cd\
ImportSystemModules
pause
help
prompt
Clear-Host
TabExpansion2
Get-Verb
oss

Bunların hepsi için Get-Command ile baktığımızda CommandType sütununda Function yazıyor. Örneğin Write-Host'a Get-Command ile baktığımızda ise CommanType'ı Cmdlet ve Source sütununda modül adı ve Version sütununda da sürüm numarası yazar. Ama Get-Help mkdir'a baktığımda gözüken yardım girdisi, New-Item'in.

PS> Get-Help mkdir

NAME
    New-Item

SYNOPSIS
    Creates a new item.

SYNTAX
    New-Item [[-Path] <System.String[]>] [-Credential <System.Management.Automation.PSCredential>] [-Force] [-ItemType
    <System.String>]
-Name <System.String> [-UseTransaction] [-Value <System.Object>] [-Confirm] [-WhatIf] [<CommonPara
    meters>]

    New-Item [[-Path] <System.String[]>] [-Credential <System.Management.Automation.PSCredential>] [-Force] [-ItemType
    <System.String>]
[-UseTransaction] [-Value <System.Object>] [-Confirm] [-WhatIf] [<CommonParameters>]

Her ne kadar bu yardım girdisinde -ItemType parametresi verilmiş olsa da mkdir ile -ItemType'ı kullanmak aşağıdaki gibi bir hataya sebep oluyor:

PS> mkdir -ItemType file -Name qwer
mkdir : A parameter cannot be found that matches parameter name 'ItemType'.
At line:1 char:7
+ mkdir -ItemType file -Name qwer
+       ~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [mkdir], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,mkdir

Bu arada help'in de bir alias değil de bir dahili komut olması da ilginç.

17.03.2023

Windows Terminal'de 2 farklı powershell profili

Windows Terminal'e birden fazla profil eklemek mümkün. Ama aynı powershell sürümü için birden fazla profil dosyası (powershell oturumu başladığında çalıştırılacak, tek profil durumunda Belgelerim\WindowsPowershell konumunda bulunan *.ps1 uzantılı dosya) nasıl yapılır sorusunun cevabı şu adreste var. Çözüm, için Windows Terminal'in settings.json dosyasını ($env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState konumunda) açıp, yeni yaratılan profilin içine 

"commandline": "powershell.exe -noprofile -noexit -command \"invoke-expression '. ''C:/PsProfile.ps1''' \"",

gibi bir satır eklemek. Burada yeni oturum çalıştırılıdığında C:\PsProfile.ps1 gibi bir dosyanın "dot sourcing" yöntemi ile çalıştırılması sağlanmış (noktaya dikkat!). Bu şekilde farklı prompt'lar, farklı diğer şeyler yaratılabilir. Bundan sonra Windows Terminal ile diğer görünüm ayarları yapılabilir. Örneğin Exhange Management Shell'e bağlanmak için PsProfile.ps1 içine

$cred = Get-Credential -Username "<domain\user>" -Message "Credential to connect to Exchange server"
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<exchange_url>/PowerShell/ -Credential $cred -Authentication Kerberos
Import-PSSession $Session -Verbose

yazarak Exhange'e özgü bir tema oluşturabiliriz. Her profilin kendine özgü bazı alias'ları, değişkenleri profil dosyasına yazılabilir.

15.03.2023

Manjaro duvar kağıtları, Simon Stalenhag, Sven Dahlstrand, bash ve Powershell

Manjaro KDE'de duvar kağıtları konusunda değişik seçenekler var. Her açılışta zevkinize göre değişik duvar kağıtlarından birini sizin için ayarlayabiliyor.

 

Seçeneklerden biri çok hoşuma gitti. İsmine bakınca koleksiyonun adının Simon Stalenhag olduğunu gördüm. Aratınca bir sürü benzer duvar kağıdının sanal alemde bulunabildiğini farkettim. Hemen Windows'a uyarlamak geldi aklıma. Önce wallpaperflare.com sitesini buldum. Ama buradaki tam boyuttaki resimler maalesef base64 formatında. Bunları powershell ile kaydetmenin  bir yolunu bulamadım. Browser ile statik olarak yüklenmiyorlar, Invoke-WebRequest ile yaptığım işlemde sayfada yer almıyor, muhtemelen bir Javascript ile yerine konuyor. Daha fazla seçenek ararken benzer zevke sahip bir sanal alem bireyi Sven Dahlstrand'ın çalışmasına denk geldim:

ROOT_URL="http://simonstalenhag.se"
MAX_PROCESSES=30
curl -s "${ROOT_URL}" |
grep -Eio "bilderbig[^\"]+\.jpg" |
sort | uniq |
xargs -P "${MAX_PROCESSES}" -n 1 basename |
xargs -P "${MAX_PROCESSES}" -n 1 -I {} curl -z {} -f -O "${ROOT_URL}/bilderbig/{}"

Bunu anlamak bile uzun sürdü. Anladıklarımı özetleyeyim.

- İlk 2 satırda sanatçının çalışmalarının yer aldığı web sayfasının adresi ile xargs komutu ile aynı anda çalıştırılacak süreç sayısı değişkenlere atanmış.

- 3. satırda web sayfasının içeriği alınmış ve 4. satırda içinde bilderbig geçen ve uzantısı .jpg olan adresleri regular expressions ile ayırmış

- 5. satırda bunları sıralayıp içinden tekrarlayan kayıtları silmiş (uniq komutunun önkoşulu girişin sıralı -alfabetik veya değil- olması)

- basename, http://simonstalenhag.se/bilderbig/image.jpg gibi bir adresin içinden sadece image.jpg bilgisini ayırıyor.

- En son satır ise 30 paralel süreçte dosyalar indirilerek her biri aynı isimle mevcut klasöre kaydediliyor.

Bunu powershell ile yapmanın yollarından biri:

$root_url = "http://simonstalenhag.se"
$content = iwr $root_url
$content.Links.href | where {$_ -like "bilderbig*"} | sort | gu | 
% { iwr -uri ($root_url+"/"+$_) -OutFile (Split-Path $_ -Leaf) } 

olabilir. Birebir aynısı değil. 30 paralel işlem yok. curl komutunun -f parametresi, dosyaların olup olmadığını da kontrol ediyor, ben etmedim. Invoke-WebRequest her seferinde üzerine yazar. Bu davranışı değiştirecek bir yol bulamadım ama -OutFile parametresini terk edip, çıkış Out-File cmdlet'ine yönlendirmek (pipe) gibi yöntemlere geçilebilir.

Paralel işlem yapabilmek için de Powershell Core kullanılabilir. Son satırda Foreach-Object'in alias'ı olarak kullanılan "%" sonrasında -Parallel ve hatta -ThrottleLimit eklenebilir:

% -Parallel -ThrottleLimit 30 { ... }

Sonrasında indirilen resimlerden birini duvar kağıdı olarak ayarlamak için daha önce bulduğum Set-Wallpaper fonksiyonu kullanılabilir.

13.03.2023

Birkaç güzel site

Windows terminalde fazla zaman geçirenler için faydalı birkaç site. Eskiden sadece nerdfonts.com vardı. Şimdi programmingfonts.org var. Çeşitli fontları, çeşitli renk temasında, çeşitli programlama dilleri ile deneme imkanı sunan görünümler, sıfır çaba ile test edilebilyor.

Varsayılan Windows Terminal renk temaları çok iç açıcı olmayabilir. Bir renk teması ayarlamak da üstün çabalar gerektirebilir. Bu iki ucun ortasında konumlanan bir çalışma olarak windowsterminalthemes.dev güzel bir çalışma.

Beğendimiz temayı uygulamak için ekranın altındaki mavi "Get theme" butonuna basmak yetmiyor. Bu, sadece json formatındaki yapılandırmayı clipboard'a kopyalıyor. Daha sonra bunu Windows Terminal'e uygulamak için programın json dosyasını favori editörünüzde $env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json dosyasını açarak "schemes" bölümü altına aşağıdaki gibi kopyalanan içeriği yapıştırmak

ve daha sonra da Windows Terminal'in ayarlarından önce "Defaults"a gelip, oradan Appearance'a, daha sonra da Color Scheme'e gelip yeni eklediğimiz temanın adını seçmek gerek.

Nihayet, bir tane de bash promptunu özelleştirmek için bir site. Prompt'ta yer almasını istediğimiz öğeleri seçip, renkleri de ayarladıktan sonra altta çıkan export PS1="..." gibi satırı koplayıp ev klasörümdeki .bashrc dosyasının sonuna yapıştırmak yeterli. Preview bölümü de var.