Murat ERDEM - Personal Research Blog




Powershell 0x01 – Temel Komutlar

February 21, 2021

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.

Execution Policy Mevzusu

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.

Değişken Tanımlama ve Değişken Tipleri

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
    

Yardım Komutları

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.

Export/Import

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.

Operatörler

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 @, [], .., ,, ., $, |

Diziler

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.

Dictionary

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

Strings

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

if-elseif-else

Karar yapılarının kullanımı ve aşağıdaki bir çok yapı diğer programlama dillerine benzer şekilde kullanılmaktadır.

Switch

try-catch

While-DoWhile

For

ForEach

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.

Param

Parama komutu bir script dosyasına yada bir fonksiyona geçilebilecek parametrelerin tanımlanmasında kullanılmaktadır.

Function

Alternatif olarak parametreler aşağıdaki gibi de tanımlanabilir.

Powershell de .Net Kullanmak

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.