(FUD) Malware Development – 2

Bu yazıda,

  • Socket nedir ?
  • Encoding-Decoding ve Encryption-Decryption işlemleri nedir ?
  • Socket programming nasıl yapılır ? 
  • Socket programming yaparken nelere dikkat edilmelidir?

sorularını elimden geldiğince cevaplayacağım. Ayrıca ileride zararlı yazılımımızın iletişimi için kullanacağımız server-client mimarisinde basit ve stabil bir iletişim sağlayan socket programı yazacağız. Bütün bunların dışında ilk yazıda olduğu gibi önemli terimleri açıklayacak ve karıştırılmaması gereken terimlerin neler olduklarına bakacağız.

Socket nedir?

Kelime olarak “yuva” anlamına gelmektedir. Socket “server”(sunucu) ve “client”(istemci)ın birer port aracılığı ile veri akışı sağladığı bir köprüdür. İstemci , sunucunun açık olan portuna bağlanmak için bir istek yollarken sunucu tarafı o port üzerinde dinleme yapıyorsa ve dinleme sonrası bağlantıyı kabul ediyorsa köprü kurulur. Bu köprü aracılığı ile veri akışı sağlanır ancak bu verilerin encoded bir şekilde gönderilmesi gerekmektedir. Peki encode ve decode işlemleri nedir?

(FUD) Malware Development - 2 Riftsec

Encoding-Decoding Kavramları

Encoding, karakter serilerini (sayılar, noktalamalar, harfler ve semboller) özel bir formata çevirme işlemidir.

Decoding, encoding işleminin tersidir. Encode edilmiş verinin orijinal karakter serisine çevirme işlemidir.

Encoding ve decoding kavramları sıkça “encryption” ve “decryption” kavramları ile karıştırılmaktadır. Bu yüzden hazır bu kavramlardan bahsettik aralarındaki farkları da açıklayalım.

(FUD) Malware Development - 2 Riftsec

Encryption-Decryption Kavramları

Not: Biz bu yazı serisi boyunca daha çok Simetrik Şifreleme üzerinde duracağız, bu yüzden aşağıda bulunan encryption ve decryption tanımları Simetrik Şifrelemeye yöneliktir.

Encryption, bir verinin (plain data) “anahtar” (key) kullanılarak bir şifreleme algoritması aracılığı ile farklılaştırılmasıdır. Şifrelenmiş veri (cipher data) doğru anahtar olmadan asla geri çevrilemez ancak encoding ve decoding işlemlerini yaparken herhangi bir anahtara ihtiyaç yoktur ve herkes tarafından eski hallerine dönüştürülebilirler.

Decryption, şifrelenmiş verinin (cipher data) şifrelenirken kullanılan anahtar ve algoritma ile normal veriye (plain data) çevrilmesidir.

(FUD) Malware Development - 2 Riftsec

Socket aracılığı ile ağda gerçekleşen iletişime “network communication” denilir.

akademi.riftsec.com’da verdiğimiz eğitimlerde de üzerinde çokça durduğumuz ve ilk yazımda da kısaca bahsettiğim gibi antivirusler zararlı yazılım üzerinde dinamik analiz gerceklestirir. Analiz sürecinde antivirüsler yazılım; hangi processler ile etkileşime geçiyor, hangi Windows API’larını kullanıyor ve bu API’lar ile ne yapıyor, ağda herhangi bir faaliyet gerçekleştiriyor mu gerçekleştirmiyor mu, eğer bir ağ faaliyeti gerçekleştiriyorsa bağlantı hangi IP adresinin hangi portuna gidiyor gibi soruların cevabını arar ve bu soruların cevaplarına göre bir puan (skor) verir. Bu yüzden özellikle network communication içerisinde zararlı olabilecek komutların var olması büyük problem teşkil edeceği için sunucu(server) ile istemci(client) arasındaki iletişimin korunması, saklanması gerekir. Bu sebepten ötürü iletişimimizi şifreli bir şekilde gerçekleştirmek hem ağı izlemekte olan kişileri hem de güvenlik çözümlerini (IPS/IDS gibi) atlatabilmek için çok önemli bir işlemdir.

Bu seri içerisinde öğrendiklerimizi uygulayabilmek için önce elimizde bir zararlı yazılım olması gerekiyor 🙂 Bu yazıda zararlı yazılımımızın ilk kısmını yazacağız. Başlangıç olarak sunucu ile istemci arasında basit bir iletişim kuracağız.

Sunucu tarafı:

Yukarıda “Socket Nedir?” başlığı altında anlattığım işlemleri aşağıdaki sıralama ile yazmamız gerekiyor.

  1. Socket oluşturma
  2. Socketi bağlama (Socket binding) -> Oluşturduğumuz socketi ağ adresimize (ip-port) bağlama işlemidir.
  3. Dinleme
  4. Bağlantı kabul etme

Öncelikle “socket” modülünü import edelim.

(FUD) Malware Development - 2 Riftsec

İlk aşamamız socket oluşturmaktı. Socket oluşturmak için socket modülünün socket classının constructorını kullanacağız.

(FUD) Malware Development - 2 Riftsec

Evet artık bir socketimiz var ancak herhangi bir ağ adresine bağlı değil. Şimdiki aşamamız bu socketi ağ adresimize bağlamak. Yani “socket binding” gerçekleştirmek. Bu kodda socketi bağladıktan sonra 19. satırda görebileceğiniz üzere dinleme işlemini de başlatıyoruz.

(FUD) Malware Development - 2 Riftsec

Socket oluşturduk, socketi ağ adresimize bağladık ve dinlemeye başladık. Artık tek yapmamız gereken bağlantı isteklerini kabul etmek.

(FUD) Malware Development - 2 Riftsec

Bir connection objesi alan send_commands() metodu sayesinde artık istemci ile iletişim kurabiliriz. (Connection objesi kod içerisindeki conn, 25.satır)

(FUD) Malware Development - 2 Riftsec
(FUD) Malware Development - 2 Riftsec

Şu anda bizden aldığı inputları istemciye ileten bir sunucumuz var 🙂

İstemci tarafı:

Eğer bir sunucuya bağlanmak istiyorsak yapmamız gereken şeyler sırasıyla aşağıdaki gibi:

  1. Bağlanmak istediğimiz ip ve portu belirlemek
  2. Socket oluşturmak
  3. Bağlantı isteği atmak

Yukarıda socket oluşturmayı öğrendik. Tek yapmamız gereken istek atmayı öğrenmek ve gönderilen komutları almak.

(FUD) Malware Development - 2 Riftsec

14.satırda bağlantı isteği gönderiyoruz ve “while True” döngüsü içerisinde sunucudan gelen komutları alıyoruz ve Stringe çeviriyoruz (17.satır) daha sonra gelen komutu ekrana basıyoruz.

Önce Sunucu(server) tarafını çalıştırıyoruz ve daha sonra İstemci(client) tarafını çalıştırıyoruz.  Bağlantımız geliyor 🙂 Şu anda istemci tarafında belli kontroller sağlayarak bir döngü içerisinde bağlantı isteği atmadığımız için önce sunucu tarafını çalıştırmazsanız bağlantı alamazsınız,  3.yazı bu problemi çözeceğiz merak etmeyin 🙂

(FUD) Malware Development - 2 Riftsec

Sunucu tarafı:

(FUD) Malware Development - 2 Riftsec

İstemci tarafı:

(FUD) Malware Development - 2 Riftsec

Basit bir iletişim sağladık ancak bağlantı stabil durumda değil. Örneğin sunucu kapanırsa bağlantı da kopacak veyahut önce istemciyi çalıştırırsanız sunucu ile bir bağlantı sağlanmayacak. Peki bu problemi nasıl çözebiliriz ?

Stabil bir bağlantı sağlayabilmek için bir connection() metodu yazalım. Bu metot içerisinde istemci bağlantı sağlanmadıkça sürekli bir şekilde bağlantı isteği atsın. Sunucu kapanırsa da re-connect (tekrar bağlantı) sağlasın.

(FUD) Malware Development - 2 Riftsec

Artık bağlantı stabil durumda. Eğer sunucu tarafından bağlantı kesilirse 36.satırda tekrardan bağlanmak için denemeler yapılmasını sağlıyoruz, bu sırada sunucu tekrardan aktif hale gelirse bağlantı sağlanacak gelmez ise denenmeye devam edecek. Bu kodda connect() metodu içerisinde neden bir to_return değişkenini neden oluşturulduğunu merak edebilirsiniz. to_return değişkenini oluşturmaz isek bağlantı gerçekleştikten sonra socket yenilenmediği için iletişim kurulmamaktadır. Dilerseniz bir debugger ile to_return değişkenini oluşturmadan iletişimi izleyebilirsiniz. (socket closed durumda kalıyor.)

Şu anda elimizde stabil bir şekilde iletişim kurabileceğimiz bir yazılımımız var. Bir sonraki yazıda bu iletişimi nasıl şifreleyebiliriz?, nasıl bir reverse shell elde edebiliriz? gibi soruları yanıtlayacağım. Nasıl? sorularını cevapladıktan sonra yine birlikte anlattıklarımı kodlayacağız 🙂 

Kendinize iyi bakın, takipte kalın.