Burada anlatılanlar benim küçük/büyük sorunlarımı çözerken izlediğim adımlardır. İlerde bu bilgilere kendim her yerden erişeyim diye, veya benzer sorunları yaşayan başkaları da erişebilsin diye burada biriktiriyorum. Bu adımları uygulamak, hata yapmamak ve doğabilecek herhangi bir hasar sizin kendi sorumluluğunuzdadır. Yazar(lar) veya yazılardaki bağlantıların sahipleri hiçbir şekilde oluşabilecek hata/hasarlardan dolayı sorumlu tutulamazlar.
20.08.2021
Fedora ve Ubuntu'da unutulan parolayı sıfırlamak
Parolalar unutulur. Unutulduğunda sıfırlanmaları gerekir. Bu her işletim sistemi için geçerli.
Ubuntu ile başlayalım. Açılıştaki Grub menüsünden recovery seçeneği ile başlamak gerek. Recovery genelde Advanced Options altında kurulu her çekirdek (kernel) sürümü için ayrı ayrı verilmiştir. En yenisi ile başlayabiliriz. Bu adımdan sonra bir nonktada aşağıdaki gibi bir ekran ile karşılaşacağız.
Burada kırmızı ile belirtilen root seçimi ile ilerleyeceğiz. Bir sonrak aşamada
Press Enter for maintenance
(or press Control-D to continue):
mesajı bizi karşılayacak. Enter'a basıp root ile giriş yapacağımız terminali açalım. Control-D sadece normal açılışa devam etmek için. Bizim istediğimiz bu değil.
Artık burada
# passwd <kullanıcı_adi>
komutu ile parolamızı değiştirebiliriz. Yetki hatası alırsak
# mount -o remount,rw /
komutu ile diskimizi yazma modunda mount ederek passwd komutunu tekrar deneyebiliriz.
Eğer kullanıcı adımızı da unuttuysak
ls /home
komutu ile sisteme oturum açmış kullanıcıların ev klasörleri arasından seçim yapabiliriz. Şifre değiştirme işlemi tamamlandıktan sonra
# reboot
komutu ile sistemi tekrar başlatabiliriz.
Fedora için işler biraz daha farklı. Açılışta grub menüsündeyken Fedora'nın satırında "e"ye basarak düzenleme moduna geçip aşağıdaki ekranda kırmızı ile işaretlediğim satırı
load_video
set gfxpayload=keep
insmod gzio
linux ($root)/vlinux-5.13.9-200.fc34.x86_64 root=/dev/mapper/fedora_localhost\
--live-root ro resume=/dev/mapper/fedora_localhost--live-swap rd.lvm.lv=fedora\
_localhost-live/root rd.lvm.lv=fedora_localhost-live/swap rhgb quiet
initrd ($root)/initramfs-5.13.9-200.fc34.x86_64.img
Şununla değiştirmemiz gerek:
rd.break enforcing=0
Değiştirdikten sonra bu ayalarla sistemi başlatmak için Ctrl+X'e basalım. Sistem yine grafik arayüz olmadan tek kullanıcılı modda açılacak. Burada yine Ubuntu'daki gibi
Press Enter for maintenance
(or press Control-D to continue):
Ekranı gelecek. Enter'la devam edelim. Fedora'da root partition'ı yazma modunda tekrar mount etmek şifreyi değiştirmek için:
# mount -o remount,rw /sysroot,
# chroot /sysroot
# passwd <username>
yapmak gerek. İşler bittiğinde 2 kez exit yazıp enter'a basarak tekrar başlatacağız.
Açılışta Fedora SELinux koruması bize /etc/shadow dosyasının SELinux etiketlerinin yanlış olduğuyla ilgili uyarılar verebilir. Bir komut satırı açıp şunları yazmamız gerekecek:
# sudo restorecon -v /etc/shadow
Bunun öncesinde
# ls -Z /etc/shadow
system_u:object_r:unlabeled_t:s0 /etc/shadow
olan SELinux etkiketinin sonrasında
# ls -Z /etc/shadow
system_u:object_r:shadow_t:s0 /etc/shadow
olarak değiştirildiğini görebiliriz. Son olarak
# sudo set enforcing 1
ile SELinux'u tekrar etkinleştirebiliriz.
Yayın tarihi 8/20/2021 02:11:00 ÖS 0 yorum yapılmış
Labels: güvenlik, linux
Server üzerinde bir süreç sonlanınca eposta göndersin
Temel olarak Windows olay günlüğüne belli bir yeni olay düştüğünde eposta göndermek veya başka bir komut çalıştırmak mümkün. Ben de bir sürecin sonlanması durumunda eposta göndereceğim. Sürecin sonlanmasını da Sysinternals arası Sysmon ile denetleyeceğim. İstenmesi durumunda:
Bir sürecin başlaması veya sonlanması
Bir dosyanın oluşturulması veya silinmesi
Kayıt defterinde bir değer oluşturulması veya silinmesi
Belirli bir IP adresine/porta ağ bağlantısı yapılması
gibi durumlarda istenen hareket yapılabilir.
Öncelikle sysmon'u istenen sürecin sonlanması durumu için bir yapılandıralım. İlk iş, sistemde var olan bir sysmon yapılandırması bulunuyor mu, bakalım:
> sysmon64 -c
Bu satırdan sonra "Sysmon is not installed on this computer" yazdıysa sistemde var olan bir yapılandırma yoktur ve sıfırdan başlayabiliriz. Eğer bir yapılandırma varsa onu bozmadan üzerine yapılandırma yapmak gerek. -c anahtarıyla gösterilen xml dosyasını bulup yapılandırmamızı bunun üzerine yapmamız gerekecek. Bu konumuz dışında. Eğer varolan bir yapılandırma varsa ve sıfırlamak istiyorsak
> sysmon64 -c --
ile sıfırlayabiliriz.
Tekrar başa dönelim; "Sysmon is not installed on this computer" yazdıysa sistemde hiç sysmon hizmet sürücüsü kurulmamış demektir. Bu durumda sysmon'u -i anahtarıyla çalıştırarak hizmet sürücüsünü kurabiliriz. Ben 64-bitlik sürümünü kullanacağım. Ayrıca ilk çalıştırmada son kullanıcı lisans anlaşmasını (EULA) da kabul etmem gerek (-accepeula).
> sysmon64 -accepteula -i process_end.xml
Terminalimiz Powershell ise dosyaları belirtirken önlerine tam adlarını (aynı klasördeysek de .\process_end.xml şeklinde) yazmamız gerek. Tab tamamlaması bu durumda çok işe yarar.
process_end.xml dosyası oluşturmadan sadece -i anahtarını kullanarak başlarsak varsayılan ayarlar geçerli olur ve takibini yapmak istediğimiz olay sadece bizim ilgilendiğimiz uygulama için değil, sistemdeki tüm uygulamalar için yaratılır, ve çok fazla eposta almaya başlarız. Bunun için böyle bir xml dosyası ile hedefimizi daraltmamız gerekecek.
Gelelim xml dosyasının oluşturulmasına. Şu anda bende sürüm 13.22 yüklü. Bu sürümde şema sürümü de 4.70. Bunu da xml dosyamızda belirtmemiz gerekecek. 13.22 ile birlikte 4.70 veya öncesi şema sürümleri de kullanılabilir ama sürümler arası fark bazen beklenmeyen sonuçlar verdiği için (RuleGrup'ların mantıksal operatörleri varsayılan işleme biçimi gibi) ne yaptığımızı bildiğimizden emin olmamız gerek. XML dosyasındaki ilk satır şema versiyonu:
<Sysmon schemaversion="4.7">
Bu satırdan sonra hash algoritmamızı belirtelim. Olay günlüğüne çalıştırılan her uygulamanın hash'i de hesaplanıp yazılacak.
<HashAlgorithms>sha256</HashAlgorithms>
Sadece 1 ölçütüm (süreç sonlanma) olduğu için daha fazla karıştırmadan bununla ilgili process terminate tag'ını girelim
<EventFiltering>
<ProcessTerminate onmatch="include">
Takip ettiğimiz sürecin hangi özelliği ile ilgileniyoruz? Örnek olarak sistemdeki process explorer'ı takip edelim (procexp64.exe)
<Image condition="end with">procexp64.exe</Image>
Nihai olarak açık taglarımızı kapatlım:
</ProcessTerminate>
</EventFiltering>
</Sysmon>
Her process explorer'ın sonlanmasında "Microsoft-Windows-Sysmon/Operational" EWT olay günlüğüne 5 numaralı olay kayıtları düşer. Görmek için olay günlüğünde Uygulama ve Hizmet Logları (Applications and Services Logs)>Microsoft>Windows>Sysmon>Operational altına bakmak gerek. Gelelim bu olay kayıtları için bir hareket oluşturmaya. Olay günlüğüne bir tane 5 numaralı olay düştükten sonra olay görüntüleyicisi penceresinin sağ kısmında "Bu olaya göreve ekle (Attach Task to this Event)"e tıklayarak işleme devam edebiliriz. Uygulama çalıştırmanın dışındaki diğer seçenekler (eposta göndermek ve bir mesaj görüntülemek) artık terk edilmiş hareketler. Biz eposta gönderebilmek için bir powershell script'i kullanacağız. Şöyle bir script işimizi görür:
$EmailFrom = "gonderen@mailadresi.com"
$EmailTo = "alici@alantaraf.com"
$Subject ="procexp sonlandı"
$Body = "Bekledigimiz Process Explorer'ın sonlanması şu an gerçekleşti."
$SMTPServer = "smtpsunucu.mailadresi.com"$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
Bu dosyanın ilk 5 satırı sırasıyla gönderenin eposta adresi, alıcının eposta adresi, eposta mesajının konusu, mesajın içeriği ve eposta sunucumuz şeklinde. Bunları uygun şekilde değiştirmek gerek.
Bu scriptin C:\Users\metin\Belgeler\eposta_gonder.ps1 gibi bir konumuna kaydedildiğini varsayalım.
En son olaya görev ekleme aşamasında kalmıştık. Bu pencerede3 kutu var. Birincisi çalıştırılacak program. Buraya powershell.exe'nin konumunu yazmamız gerek. Bu çoğu durumda
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
şeklindedir. Argumanlar için yapmamız gereken birinci iş geçici olarak Execution Policy'yi devre dışı bırakmamız ve scriptimizi bir -File anahtarı ile göstermemiz. Hepsi birlikte şöyle olabilir:
-ExecutionPolicy Bypass -File C:\Users\metin\Belgeler\eposta_gonder.ps1
Üçüncü kutu sadece çalışacak script bulunduğu klasörle ilgili bir dosya işlemi yapacaksa gerekli. Bizimki gerekmeyeceği için boş bırakabiliriz. Boş kalmasın diyenler C:\Users\metin\Belgeler\ gibi birşey yazabilir.
Yayın tarihi 8/20/2021 11:22:00 ÖÖ 0 yorum yapılmış
Labels: güvenlik, windows
19.08.2021
Regular Expressions
Bu konu bir blog yazısında anlatılacak kadar kısa bir konu değil; farkındayım. Ama konunun ana hatlarını yine de özetlemek istiyorum.
Bir metnin içinde (düzyazı, program, bir klasördeki dosya içerikleri, URL dizileri, dosys sistemi yolları vs) bir "dünya" var mı yok mu aramak istiyoruz. Örneğin bir klasördeki txt uzantılı dosyaların içinde. Bunu powershell ile yapmanın yolu
> Select-String -Pattern "dünya" -Path *.txt
Bu arama bize bazı sonuçlar döner. Ama diyelim ki dosyaların bazılarında "ü" yerine "u" kullanıldığını farkettik. Bu durumda "dunya" anahtar kelimesini de içerecek şekilde aramamızı değiştirelim. Ayrıca varsayılan parametre sıralaması ve alias kullanımıyla komutu biraz kısalatalım.
> sls "dünya|dunya" *.txt
"|" operatörü VEYA işlemi görür. Burada değişen 1 harf olduğu için bunu ü VEYA u şeklinde de yapabilirdik.
> sls "d[u|ü]nya" *.txt
Köşeli parantezler, bir karakter kümesi belirtmek için kullanılır. Örneğin sadece d,u,ü,n,y ve a'dan oluşan 5 veya 6 harfli kelimeleri bulmak istersek
> sls "[adnuüy]{5,6}" *.txt
yazabiliriz. Bu satırla sadece dünya ve dunya anahtar kelimelerini bulmakla kalmayacağız, ayrıca içinde herhangi bir sırada bu harflerin 5 veya 6'sı geçen başka kelimeleri de bulacağız. Ayrıca bunlar tam kelimeler de olmayacak, kelimenin herhangi bir bölümünde bu harflerin 5 veya 6'sının geçmesi yeterli olacak.
Bazı özel operatörleri listeleyelim:
? Önceki karakter 0 veya 1 kez geçecek
* Önceki karakter 0 veya daha fazla geçecek.
+ Önceki karakter 1 veya daha fazla geçecek.
{n,} Önceki karakter n veya daha fazla geçecek.
{n,m} Önceki karakter en az n kere, en fazla m kere geçecek. Arasındaki sayılarda da olabilir.
. Yeni satır karakteri hariç her tekil karakteri bulur.
[a-z] Yalnızca "a" ve "z" arazındaki karakterleri bulur.
[^abc] a, b ve c olmayan her karakteri bulur.
^ Satırın başını bulur.
$ Satırın sonunu bulur.
( ) Gruplandırma için. Parantezin içindeki ifade hatırlanır ve daha sonra \n veya $n gibi bir operatör ile kullanılabilir.
(?:) Aynen ( ) gibi gruplandırma için kullanılır, ama parantezin içindeki ifade hatırlanmaz
| veya operatörü
\w tüm harfleri bulur.
\W harf olmayan karakterleri bulur.
\s Boşluk karakterlerini bulur.
\S Boşluk olmayan karakterleri bulur.
\d Sayıları bulur.
\D Sayı olmayanları bulur.
\A String'in başını bulur.
\Z String'in sonunu bulur. Bir yeni satır karakteri varsa ondan hemen öncesini bulur.
\z String'in sonunu bulur.Yeni satır karakterini de atlar.
\G En son aramanın bulduğu noktanın bir sonrasını bulur.
\b Kelime sınırlarını bulur.
\B Kelime olmayan sınırları bulur\.
Bir string değişkenimiz olsun, aşağıdaki gibi
> $str1 = "Bugün günlerden Pazartesi"
Regular expression ifadelerimizin nasıl çalıştığını bu string üzerinde deneyerek görelim. Powershell'de -match operatörü regular expression kullanır. Ama -like kullanmaz. Değiştirme operatörü -replace de regular expression kullanır. Değişkenin içinde "gün" geçiyor mu bakalım:
> $str1 -match "gun"
False
Sonuç altta "False" olarak verildi. "u" ve "ü" alternatifli olarak deneyelim:
> $str1 -match "g[u|ü]n"
True
Bu şekilde bir eşleşme bulundu. Pazartesi geçen kelimeleri Salı ile değiştirmek için
> $str1 -replace "Pazartesi","Salı"
Bugün günlerden Salı
Çok karşılaşılabilecek bir şey, ay\gün\yıl şeklinde yazılan tarihlerin gün.ay.yıl şeklinde çevrilmesi olabilir. Bunun için back reference denen gruplandırma operatörü olarak yukarıdaki tabloda listelediğim parantezleri kullanmalıyız. İşlem şu şekilde olacak, 2 haneli ay bilgisi bulunacak, 2 haneli gün bilgisi bulunacak, bunlar yer değiştirilecek ve ayraç olarak kullanılan "\" yerine "." konacak ve sonrasında gelen 4 haneli yıl bilgisi değiştirilmeyecek. Bunun için bulduğu gün, ay ve yıl verilerini hatırlaması gerekecek.
> $str1 = "bugün 11\20\1974"
> $str1 -replace '(\d{2})\\(\d{2})\\(\d{4})','$2.$1.$3'
bugün 20.11.1974
Burada çift tırnak yerine tek tırnak kullanmaya dikkat.
Çok sık yaşadığım bir konu, bir klasörde bir dosya arıyorum. Dosya adında geçen bir anahtar kelimeye göre aramak kolay. Ama 2 anahtar kelimem var ve hangisi önce gelecek, hangisi sonra gelecek, aralarında başka kelime olacak mı, bu ayrıntılar önemli değil. Sadece bu 2 anahtar kelimenin dosya adında geçmesini istiyorum. Bunun için yapılması gereken [3]:
> dir * | where {$_.Name -match "(?=.*format)(?=.*powershell)"}
Benzer şekilde bir klasördeki dosyaların içinde de geçmesini istediğim 2 anahtar kelime için arama yapabilirim:
> sls "(?=.*black)(?=.*star)" *-d.txt
---
[1] https://en.wikipedia.org/wiki/Regular_expression
[2] https://regexr.com/
[3] https://www.baeldung.com/string-contains-multiple-words
[4] https://www.regular-expressions.info/
[5] https://www3.ntu.edu.sg/home/ehchua/programming/howto/Regexe.html
[6] https://regex101.com/
[7] https://www.geeksforgeeks.org/write-regular-expressions/
Yayın tarihi 8/19/2021 11:14:00 ÖÖ 0 yorum yapılmış
16.08.2021
Powershell, diziler ve Add-Member
Şöyle bir hedefim var; Bir klasördeki dosyaları tablo olarak listelerken bir sütunda dosya sistemindeki sahip bilgisini de görmek istiyorum. Boş bir dizi oluşturayım.
> $dosyalar = @()
Sonra bu diziyi dosya bilgileri ile doldurayım.
> dir | % { $dosyalar += [PSCustomObject]@{
Isim = $_.FullName
Boyut = $_.Length
}
Bu adımda $dosyalar dizisi şöyle olur:
Isim Boyut
----- -----
D:\Klasor\Dosya1.txt 22
D:\BaskaKlasor\Dosya2.doc 1366
Bu şekilde Isim ve Boyut sütunları olan bir dizi oluştu. Şimdi NTFS dosya sisteminde dosyayı oluşturan kullanıcı olan "sahip" (owner) bilgisini de eklemek istiyorum.
Oluşturma aşamasında da sahip bilgisini ekleyebilirdik, ama örnek olması açısından bu nesneye oluşturduktan sonra ekleyelim.
> Add-Member -InputObject $dosyalar -MemberType ScriptProperty -Name Sahip -Value {(Get-Acl $this.Isim).Owner}
Bu işlem sonunda şu şekilde bir tablomuz olur:
Isim Boyut Sahip
----- ----- -----
D:\Klasor\Dosya1.txt 22 metin
D:\BaskaKlasor\Dosya2.doc 1366 arda
Yayın tarihi 8/16/2021 05:36:00 ÖS 0 yorum yapılmış
Labels: powershell
12.08.2021
Powershell ile metin dosyalarını incelemek
Grafik arayüzlü metin editörleri varken ne gerek var Powershell'e. Ama çok büyük metin dosyaları ile çalışırken bütün dosyayı açıp incelemek sorun olabilir. Çok büyük derken örneğin 250 GB. Bu kadar dosyayı açıp belleğe almak bile ciddi bir iş.
Onun yerine Get-Content ve Select-String gibi cmdlet'ler kullanılabilir mi?
Öncelikle alias'ları da kullanarak dosyanın başından 20 satırını bir inceleyelim.
> cat -TotalCount 20 .\network.log
Bir de sondan 20 satırı görelim
> cat -Tail 20 .\network.log
Buraya kadar gördüklerimizden dosyanın genel bütün satırlarının System.Net.Sockets ile başladığını gördük diyelim. Peki bununla başlamayanlar var mı? (bkz [1],[2])
> sls "^(?!System.Net.Sockets)" .\network.log
Ve diyelim ki dosyanın içinde bir IIS logu benzeri bir yapı bulduk. Virgülle ayrılmış değerler. İlk alan tarih, daha sonra saat, kaynak ve hedef IP adresleri, kaynak ve hedef portları gibi:
2021-08-10,09:38:22,192.168.7.3,8.8.8.8,1356,443
Bu satırlardan da sadece kaynak IP adresi ve kaynak hedef portu ile ilgileniyoruz. Bu alanları alıp ekrana basmak için kullanabileceğimiz ConvertFrom-String cmdlet'i var. -Delimiter parametresi ile verilen karakterlerle ayrılmış alanları ayrıştırıp P1'den P(N)'e kadar alan isimlerini otomatik yaratıp kullanımımıza sunuyor. Bizim örneğimizde kaynak IP ile hedef portu 4. ve 6. alanalar olduğu için bunları aşağıdaki gibi süzebiliriz:
> sls "^(?!System.Net.Sockets)" .\network.log | ConvertFrom-String | select P4,P6
P4 P6
------- ---
8.8.8.8 443
1.1.1.1 443
gibi bir sonuç elde edilir.
Dosyanın içinde 192.168 ile başlayan IP adresleri var mı diye bir bakalım:
> sls "192\.168\.\d{1,3}\.\d{1,3}" .\network.log
Ya da tarih (örneğin 2021-08-10 formatında) yazıyor mu hiç:
> sls "\d{4}-\d{2}-\d{2}" .\network.log
Belki de tarih formatımız 2021.08.10 veya 20210810 da olabilir:
> sls "\d{4}.?\d{2}.?\d{2}" .\network.log
Tüm bunları yaparken bütün dosyayı değil de ilk 1000 veya son 1000 satır üzerinden işlem yapmak da isteyebiliriz. Bunun için "|" operatörü ile cmdlet'leri bağlayabiliriz:
> cat -Totalcount 1000 .\network.log | sls "\d{4}.?\d{2}.?\d{2}"
---
[1] https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_regular_expressions?view=powershell-7.1
[2] https://www.tutorialspoint.com/powershell/powershell_regex.htm
Yayın tarihi 8/12/2021 10:24:00 ÖÖ 0 yorum yapılmış
Labels: powershell
6.08.2021
Çok sayıdaki olay kaydını tarihlerine göre gruplamak
Bir bilgisayarda sistem olay günlüğünde çok sayıda diskle ilgili 51 kimlikli kaydın olduğunu gördüm. Genel bir bakışla olayların birkaç günde yoğunlaştığını farkettim.
Get-WinEvent -computer BILGISAYAR -FilterHashTable @{LogName="System";ProviderName="disk";Id=51} | Measure-Object
ile 30.000+ olay kaydı olduğu saydım, ama bunlar her güne düzgün yayılmamıştı. Tarihe göre gruplayarak bir günlük sayıya ulaşmak istedim ama
Get-WinEvent -computer BILGISAYAR -FilterHashTable @{LogName="System";ProviderName="disk";Id=51} | Group-Object -Property TimeCreated
gibi bir sorgu işe yaramaz, çünkü TimeCreated sadece tarih değil saat, dakika ve saniye bilgilerini de içerir. Dolayısıyla en iyi ihtimalle güne göre değil, saniyeye göre sayı verebilir ki bu da isteğimizin çok daha üstünde bir çözünürlük.
Bunun yerine yeni bir alan oluşturmalı ve o alanı TimeCreated alanının sadece tarih bilgileri ile donatmalıyız. Kısa bir arama ile daha önce hiç kullanmadığım bir yöntem kullanan şu Stackowerflow gönderisine ulaştım:
Get-EventLog -Logname system -Source "Microsoft-Windows-GroupPolicy" -EntryType "Information" |
Add-Member Day -MemberType ScriptProperty -Value { $this.TimeGenerated.ToString('dd.MM.yyyy') } -PassThru |
Group-Object 'Day', 'Source'
Aslında bu miktarda olayı kendi bilgisayarıma aktarıp da saymak yerine yerinde yapmak daha mantıklı olurdu. Bu sebeple Invoke-Command ile yukarıdaki bilgiyi de kullanarak
Invoke-Command -ComputerName BILGISAYAR -Command { Get-WinEvent -FilterHashTable @{LogName="System";ProviderName="disk";Id=51} | Add-Member Day -MemberType ScriptProperty -Value { $this.TimeCreated.ToString("dd.MM.yyyy"} -PassThru | Group-Object "Day", "Source" -NoElement
aşağıdaki sonuca ulaştım:
Count Name PSComputerName
----- ---- --------------
2542 19.04.2021 BILGISAYAR
9044 26.01.2021 BILGISAYAR
19841 25.01.2021 BILGISAYAR
Babadan kalma yöntemlerle yapmak isteseydik
Invoke-Command -computer BILGISAYAR -command { Get-WinEvent -FilterHashtable @{LogName="System";ProviderName="disk";Id=51} | Select Id,@{N="Day";E={$_.TimeCreated.ToString("dd.MM.yyyy")}} | Group-Object 'Day' -NoElement}