Bu yazımızda VERT Araştırma İpuçlarını inceleyeceğiz. Kelime bölme, aşina olmadığımız bir BASH işlevidir. Ancak son araştırmayı kesinlikle etkileyen bir işlevdir.
VERT bash(1) kılavuz sayfasından:
IFS
Genişletme sonrası sözcük bölmek ve read yerleşik komutuyla satırları sözcüklere bölmek için kullanılan Dahili Alan Ayırıcı. Varsayılan değer <boşluk><tab><yenisatır> şeklindedir.
Kelime Bölme
VERT ipucu olarak kullanabileceğiniz kelime bölmeyi anlatmaya başlayalım. Kabuk, sözcük bölme için çift tırnak içinde gerçekleşmeyen parametre genişletme, komut değiştirme ve aritmetik genişletme sonuçlarını tarar.
Kabuk, IFS’nin her karakterini bir sınırlayıcı olarak ele alır ve bu karakterleri alan sonlandırıcılar olarak kullanarak diğer genişletmelerin sonuçlarını sözcüklere böler. IFS ayarlanmamışsa veya değeri tam olarak <boşluk><tab><yenisatır> ise,bu durumda önceki genişletmelerin sonuçlarının başında ve sonunda <boşluk>, <tab> ve <yenisatır> dizileri yok sayılır ve başında veya sonunda olmayan herhangi bir IFS karakteri dizisi, sözcükleri sınırlandırmaya yarar. IFS’nin varsayılandan farklı bir değeri varsa, boşluk karakteri IFS (bir IFS boşluk karakteri) değerinde olduğu sürece, kelimenin başında ve sonunda boşluk karakterleri boşluk ve sekme dizileri yok sayılır. IFS’de IFS boşluk olmayan herhangi bir karakter, herhangi bir bitişik IFS boşluk karakteriyle birlikte bir alanı sınırlar. Bir dizi IFS boşluk karakteri de sınırlayıcı olarak kabul edilir. IFS’nin değeri null ise, sözcük bölme işlemi gerçekleşmez. Açık boş argümanlar (“ veya ”) korunur. Değeri olmayan parametrelerin genişletilmesinden kaynaklanan tırnak içine alınmamış örtük boş argümanlar kaldırılır. Değeri olmayan bir parametre çift tırnak içinde genişletilirse, bir boş argüman ortaya çıkar ve korunur. Genişletme olmazsa, bölme yapılmayacağını unutmayın.
Bash(1) kılavuz sayfasından yardımcı olabilecek birkaç ek not:
Komut Değiştirme
Komut ikamesi, bir komutun çıktısının komut adını değiştirmesine izin verir. İki form vardır: $(command) veya “command”
Bash, komutu yürüterek ve komut değiştirmeyi komutun standart çıktısıyla, sondaki yeni satırlar silinerek değiştirerek genişletmeyi gerçekleştirir. Gömülü yeni satırlar silinmez, ancak sözcük bölme sırasında kaldırılabilirler.
Süreç Değiştirme
İşlem ikamesi, adlandırılmış yönlendirmeleri (FIFO’lar) veya /dev/fd açık dosyaları adlandırma yöntemini destekleyen sistemlerde desteklenir. <(liste) veya >(liste) şeklini alır. İşlem listesi, girişi veya çıkışı bir FIFO’ya veya /dev/fd içindeki bir dosyaya bağlı olarak çalıştırılır. Bu dosyanın adı, genişletmenin sonucu olarak geçerli komuta bir argüman olarak iletilir. >(liste) formu kullanılırsa dosyaya yazılması liste için girdi sağlayacaktır. <(list) formu kullanılırsa, liste çıktısını elde etmek için argüman olarak iletilen dosya okunmalıdır.
Mevcut olduğunda, süreç değiştirme, parametre ve değişken genişletme, komut ikamesi ve aritmetik genişletme ile aynı anda gerçekleştirilir.
Genişleme
Genişletme, kelimelere bölündükten sonra komut satırında gerçekleştirilir. Gerçekleştirilen yedi tür genişletme vardır:
- Köşeli ayraç genişletme,
- Tilde genişletme,
- Parametre ve değişken genişletme,
- Komut değiştirme,
- Aritmetik genişletme,
- Sözcük bölme,
- Yol adı genişletme
Genişletmelerin sırası şöyledir: köşeli ayraç genişletme, tilde genişletme, parametre ve değişken genişletme, aritmetik genişletme ve komut değiştirme (soldan sağa yapılır), kelime bölme ve yol adı genişletme.
Bu örnek için, son VERT gönderisinde kullandığımız aynı kabuk koduyla başlayacağız. Ancak daha sonra onu, sözcük bölünmesinden etkilenecek daha fazla karakter içerecek şekilde değiştireceğiz.
VERT Kabuk kodunu oluşturduktan sonra, IFS’yi kaldırdım ve kabuk kodu dosyamı değiştirdim. IFS’nin değiştirdiği karakterleri – 0x0a (yeni satır), 0x09 (sekme) ve 0x20 (boşluk) – aldım ve onları buf değişkenine yerleştirdim. Bu artık geçerli bir kabuk kodu değil, ancak buna kabuk kodumuz olarak atıfta bulunmaya devam edeceğim.
İlk örneğimizde Python’u çalıştırıyoruz ve çıktıyı xxd’ye aktarıyoruz. Kabuk kodumuzun dosya içindekiyle aynı göründüğünü görebiliriz.
Burada süreç ikamesinden aynı çıktıyı aldığımızı görebiliriz. Bunun nedeni, işlem ikamesinde sözcük bölme yapılmamasıdır.
Komut ikamesini kullanan yukarıdaki örnekte, çıktımızın aniden değiştiğine dikkat edin.
- Tüm 0x00’ımızı kaybettik.
- Tüm 0x09’umuzu kaybettik.
- Var oldukları yer, tek bir 0x20 ile değiştirilmiş gibi görünüyor.
- İşlem genişletme örneğinde 0x10 konumuna bakarsak, şunu görürüz: 0xe7, 0x68, 0x2f, 0x0a, 0x0a, 0x09, 0x09, 0x73, 0x68.
- Komut genişletme örneğinde, aynı 0xe7’yi 0x0B konumunda bulabiliriz. Şu sıraya sahiptir: 0xe7, 0x68, 0x2f, 0x20, 0x73, 0x68.
- Sekmeler (0x9) tek bir boşlukla (0x20) değiştirildi
- İçeriğin sonundaki tek 0x0a dışında tüm 0x0a örneklerimiz kaldırıldı.
- 0x20 örneklerimizin tamamında kopyalar kaldırıldı.
İlk düşünceniz muhtemelen, “Ama OZZTECH, aynı komutları kullanmıyorsunuz!” %100 haklısın, sana kullandığın komuta göre işlerin nasıl değiştiğini ve bunun neden msfvenom’da kullandığın badchars filtresini etkileyebileceğini göstermeye çalışıyorum.
Bu komutlar arasındaki farkı daha iyi anlamak için aynı komutlara grep kullanarak bir göz atalım.
İlk komutta, işlem ikamesini kullanıyoruz. Anonim bir kanalda (/dev/fd/63) grep’in arama yaptığını görebilirsiniz. Komut ikamesiyle, verileri standart girdiden ileten bir -string kullanıyoruz. Burada dizeler, “stdin’e bir dosya gibi davranın” demenin bir yoludur. Ek olarak, her iki dosyada da ‘sh’ dizesini bulsak da, sekmemizin (\t veya 0x09) komut ikamesinde bulunmadığına dikkat edin.
Daha fazla açıklama istiyorsanız, aşağıdaki resme bakın. Yukarıdaki komut ikameli burada dizgimizin aşağıdaki borulu Python çıktısıyla aynı şekilde davrandığını unutmayın. Komut ikamemiz grep’e aktarılırken ve grep için bir argüman olarak komut ikamemiz, ikili çıktıyı işlerken hatalar üretir.
Şimdiye kadar, tüm bunlar, belirli kabuk kodu üretmek için neden sıklıkla kötü karakter kullandığınızın ve farklı komut yürütme yöntemlerinin nasıl beklenmedik çıktılar üretebileceğinin karmaşık bir açıklamasıydı. Ancak, başlangıçta atıfta bulunduğumuz IFS değişkeni nedeniyle biraz daha zorlaşıyor. IFS’nin değerini değiştirdiğimizde ne olduğuna bir göz atalım. Kullanım sırasında en fazla değişikliği gören burada-string komut ikamesine özellikle bakacağız.
Bir değişikliği görmenin en kolay yolu olduğu için grep çıktısıyla başlayalım. IFS ayarlanmadığında veya varsayılana ayarlandığında, dosyada \t (0x09)’umuzu bulamayız. Ancak, IFS’yi hiçbir şeye ayarladığımızda, aniden aynı sonuçta bir eşleşme elde ederiz. Ardından, çıktıyı xxd’de karşılaştıralım.
Burada xxd’de görüntülenen aynı dosyanın çıktısına sahibiz ve üç çıktı setimiz var. IFS’yi varsayılandan boş bir dizeye değiştirerek 0x09 ve 0x20 karakterlerimizi geri aldığımızı görebilirsiniz. Ayrıca 0x0a karakterlerimizi geri almış gibiyiz. Bununla birlikte, burada bir istisna vardır, o da son çıktımızda (tam bayt dizisidir), bir çift 0x0a ile bittiğimizdir… önceki örnekte, kopya sıyrılmıştır. Son olarak, dize içindeki 0x00 karakterlerimizi de kaybettik.
Bu sorunlar maalesef kaçınılmaz olan sorunlardır. Gereksinim duyduğunuz verileri oluşturmak için komutlarınızı yürütme biçiminiz, alacağınız çıktının türünü belirleyecektir. Bu nedenle, gelecekte, kabuk kodu veya diğer herhangi bir ikili veri üzerinde çalışırken ve bunu programlar arasında iletmek istediğinizde, bir şey biraz riskli görünüyorsa, bir adım geri atın ve yöntemlerinizi değerlendirin. Bazen, en temiz, en basit yöntemler, kullandığınız teknikler için bir seçenek olmayabilir, bu nedenle karakter setinizde hangi karakterlere izin vereceğinizi ayarlamanız gerekebilir. Umarım bu, yolculuğunuzda size yardımcı olur ve yeni bir şey öğrendiğinizi unutmayın.
VERT Araştırma İpuçları: Kelime Bölmeyi Anlamak adlı yazımızın sonuna geldik, öğretici bilgiler için blog yazılarımızı incelemeyi unutmayınız.