Bu yazımızda Windows sistemlerde Powershell konusuna odaklanacağız. Powershell de script yazma ve ExecutionPolicy ne işe yarar biraz bu konulara değineceğiz.
Windows varsayılan olarak güvenlik gerekçesiyle imzasız powershell sciptlerini yürütmeye izin vermemektedir. Bu güvenilmez scriptere kendi lokalimizde yazdıklarımızda dahildir. Ancak burada Execution Policy’in bir güvenlik önlemi olduğunu düşünmemeliyiz. Çünkü bu tam anlamıyla bir güvenlik önlemi değildir. Burada disk üzerinden yükleme işlemleri kontrol edilmektedir. Bu noktada malware developerların fileless atacklar kullanarak sadece memory üzerindeki saldırıları bu kontrolleri bypass etmektedir. Bunun yanında netspi sitesinde bu kontrolleri bypass etmenin 15 farklı yolu anlatılmış göz atmanızı tavsiye ederim. Buradaki bypass tekniklerinden bazılarını denedim ve başarılı bir şekilde execution policy bypass etmeyi başardım.
Execution policy değeri varsayılan olarak Restricted olarak gelir. Get-ExecutionPolicy komutu ile o anki geçerli değeri öğrenebiliriz. 6 farklı değeri bulunmaktadır.
Restricted | Varsayılan olarak gelmektedir. Hiç bir script dosyasını çalıştırmaz sadece consoldan girilen komutları çalıştırmaktadır. |
RemoteSigned | Sadece imzalı olan scriptleri çalıştırır |
AllSigned | İmzalı yada sizin yazdığınız scriptleri çalıştırır |
Unrestricted | PS 6.0 dan sonra default değerdir. Tüm scriptleri çalıştırır sadece download edilenler için izin ister |
Undefined | Execution policy değerini kaldırır. |
Bypass | Bütün scriptleri onay istemeden çalıştırır |
Set-ExecutionPolicy komutu ile bu izinler değiştirilebilir ancak admin yetkisi gerekmektedir.
Burada execution policy değerini bypass olarak değiştirdik bu şekilde sorunsuz olarak script dosyalarımızı çalıştırabileceğiz.
Powershell değişken tanımlama yapmak için “$” işaretini kullanır. “$isim” şeklinde tanımlama yapılabilir. Bu şekilde yapılan tanımlamalarda içerisine gönderilen veri tipine bakmaksızın kabul eder ve o veriyi tutar. Ancak biz belirli tiplerdeki verileri tutmasını istiyorsak bunu da tanımlama sırasında belirtebiliriz. aşağıda temel tiplerde nasıl tanımlama yapacağı gösterilmiştir.
>>$var=123
>>$var="aaaa"
>>[Int]$sayi=1234
>>[String]$metin="aaaa"
>>[datetime]$tarih="01.01.2020"
>>[bool]$boolean=$True
>>[Object]$liste = 1,2,3,4
Get-Command ve Get-Help komutları iki önemli yardımcı komutumuzdur. Get-Command powershell üzerinde tanımlanmış komutları, fonksiyonları yada aliasları gösteren bir yardımcı komuttur. Get-Help ise argüman olarak verilen komutun kullanımı ile ilgili bilgiler verir.
Bir çıktı oluşturacağımızda yada bir dosyayı import edeceğimizde bunu farklı şekillerde yapabiliriz. Örnek olarak xml yada json formatları aşağıdaki gibi kullanılabilir.
Import-Clixml | Xml olarak bir dosyadan okuma yapar |
Export-Clixml | Xml olarak bir dosyaya çıktı oluşturur |
Export-CSV | CSV olarak bir dosyaya çıktı oluşturur |
Out-File | Çıktıyı dosyaya yönlendirir |
Bunların yanında Convert işlemleri de kullanılabilir. Bu işlemlerde ConvertTo-xxx yada ConvertFrom-xxx komutları kullanılmaktadır. En çok kullanılan formatlardan birisi olan json ile çalışırken ConvertTo-Json methodu ile bir çıktıyı json formatına çevirebiliriz. Bunun yanında ConverFrom-Json ile de jsondan powershell üzerinde kullanabileceğimiz bir nesne formatına dönüştürebiliriz.
Powershell scripti yazarken en çok kullanılan operatörler ve kullanım alanları aşağıdaki gibidir.
Ön tanımlı değişkenleri listesi | Get-ChildrenItem Variable |
Aritmetik | +, -, *, /, % |
Atama | =, +=, -=, *=, /=, %= |
Karşılaştırma | -eq, -gt, -ne, -lt, -le, -ge |
mantıksal | -and, -or, -not, -xor, ! |
Yönlendirme | >, >>, 2>, 2>> |
tip | -is, -isnot, -as |
özel karakterler | @, [], .., ,, ., $, | |
Bildiğimiz gibi diziler içerisinde birden fazla veri tutmayı sağlarlar. Powershell üzerinde de arraylar bulunmaktadır ancak bu arrayların farklı tanımlama şekilleri vardır.
>>$array = 1,2,3,4,5,6,7,8,9
>>$array = @{1,2,3,4.2,"selam",$False)
>>$array = 1..50
>>[int32[]]$array = 1,2,3
>>$array = New-Object System.Collections.ArrayList
dizilerde kullanabileceğimiz bazı fonksiyonlar vardır. Bunlar programlama işlemimizi kolaylaştıracaktır.
$array.Coun | Dizideki eleman sayısını döner |
$array[1] | Dizinin birinci elemanını döner |
$array[-1] | dizinin son elamanını döner |
$array[0…5 | dizinin ilk 5 elemanını döner |
$array[-1..-6] | dizinin son 5 elemanını döner |
$array.length | dizinin uzunluğunu döner |
$arrray[-1..$array.length] | diziyi ters çevirir |
$array+=$veri | diziye eleman ekler |
Bunların yanında eğer dizi System.Collections.ArrayList ile oluşturulan diziler için Add komutu eleman eklemeye ,Remove komutu eleman silmeye yaramaktadır.
Sözlükler oldukça kullanışlı yapılardır ve içerisinde key-value ilişkisi ile veri tutmak için kullanılmaktadır.
$dic.keys | tanımlı keyleri döner |
$dic.values | tanımlı değerleri döner |
$dic.Add(“Key”,”Value”) | eleman ekler |
$dic+=@{“key”=”value”} | eleman ekler |
$dic.Remove(“Key”) | eleman siler |
Powershellde de diğer programlama dillerindeki gibi kullanılırlar. Burada önemli nokta tek tırnak(‘) ve çift tırnak(“) arasındaki farktır. tek tırnak ile yazılan bir string içerisinde değişken kullanılamaz ama çift tırnak içerisinde yazılan bir string ifade içerisinde değişkenler kullanılabilir.
$string.CompareTo(“metin”) | Karşılaştırma işlemi yapar (case-insensitive) |
[string]::Compare(“metin”,”metin”,$True) | Karşılaştırma yapar (case-sensitive) |
$string.StartsWith(“metin”) | Başlangıç değerini karşılaştırır (case-sensitive) |
$string.EndsWith(“metin”) | Bitiş Değerini karşılaştırır (case-sensitive) |
$string.ToLower() | Küçük harfe çevirir |
$string.ToUpper() | Büyük harfe çevirir |
$string.Contains(“metin”) | İçerisinde bulunup bulunmadığını kontrol eder |
$string.Replace(“metin”,”metin”) | Metin değiştirme yapar |
$string.SubString(3,10) | 3 ten 10 a kadar olan indekslerdeki metni döner |
$string.Split(“a”) | a harflerinden parçalar |
$string.ToByteArray() | Byte tipine dönüştürür |
Karar yapılarının kullanımı ve aşağıdaki bir çok yapı diğer programlama dillerine benzer şekilde kullanılmaktadır.
ForEach döngüsünü pipeline içerisine kullanırken aşağıdaki gibi kullanabiliriz.
Burada “%” işareti foreach döngüsünün alias tanımlamasıdır, “$_” ifadesi ise o anki geçerli elemanını göstermektedir.
Parama komutu bir script dosyasına yada bir fonksiyona geçilebilecek parametrelerin tanımlanmasında kullanılmaktadır.
Alternatif olarak parametreler aşağıdaki gibi de tanımlanabilir.
Powershell’in en güzel özelliklerinden biriside .net ile birlikte program kullanılabilmesidir. Bunu yapmanın farklı yolları vardır. En basit yolu direk olarak kullanmak istediğimiz fonksiyonu konsoldan çağırmaktır.
>>[System.Console]::WriteLine("moncasp")
moncasp
Bu şekilde ilgili fonksiyonu dahil olduğu kütüphane ile birlikte çağırabiliriz. Eğer çağırmak istediğimiz kütüphane powershell üzerinde tanımlı değilse aşağıdaki komut ile yüklenebilir.
>>[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
Bu fonksiyonları kullanmanın başka bir yolu da ilgili sınıfın nesnesini oluşturmaktır. Bunu aşağıdaki gibi tanımlayıp kullanabiliriz.
>>New-Variable -Name myconsole -Value ([System.Console])
>>$myconsole::WriteLine("moncasp")
moncasp
Kütüphane kullanmanın yanında farklı işlemleri de .net kullanarak gerçekleştirmek istiyorsak aşağıdaki gibi bir kullanıma başvurabiliriz.
Add-Type -TypeDefinition @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace powershellNet
{
public static class Program
{
public static void Main()
{
string message = "Hello World!!";
Console.WriteLine(message);
}
}
}
"@ -ReferencedAssemblies System.Windows.Forms
[powershellNet.Program]::Main();
Burada Program sınıfı ve main fonksiyonunun public olmasına dikkat etmek gerekmektedir.