Bugünkü yazımda STUXnet analizine devam ediyoruz. Bu bölümde STUXnet güncelleme mekanizmalarını, Rootkit yapısını ve Yükleme mekanizmasını sizlerle paylaşacağım.
www.mypremierfutbol.com
www.todaysfutbol.com
Aşağıdaki şekilde şifreli veri gönderir:
http://www.mypremierfutbol.com/index.php?data=data_to_send
Bu veriler IP, Bağdaştırıcı adı ve açıklamasını ve virüs bulaşmış makine ve stuxnet ile ilgili diğer verileri içerir. Bundan sonra stuxnet’in yeni bir versiyonunu alır (şifrelenmiş formda) imagebase’den sonra bir flag ve en son çalıştırılabilir imaj ile başlar.
2. Eşler arası bağlantı (Peer-to-peer) ile Günceleme: Stuxnet bir makineye bulaştıktan sonra, bir RPC sunucusu yaratır ve Ağ üzerindeki herhangi bir PC’den gelen bağlantıları dinler. Ağdaki diğer bilgisayarlarla, stuxnet bu RPC Sunucusuyla bağlantı kurar. İlk olarak, RPC sunucusundaki stuxnet sürümünü gönderen fonksiyon 0’ı çağırır. Daha yeniyse, RPC sunucusunun stuxnet dll dosyasının bir kopyasını hazırlamasını ve stuxnet istemcisine göndermesini sağlayan fonksiyon 1’i çağırır.
İstemci yeni sürümü aldıktan ve seçili bir sürece enjekte ettikten sonra eğer RPC sunucusunun daha eski bir stuxnet sürümü varsa, istemci fonksiyon 4 işlevini çağırır ve hazırlar. Yeni stuxnet dosyasının bir kopyası ve yüklemek için RPC sunucusuna gönderir.
Bu şekilde stuxnet’in kendisini yalıtılmış bilgisayarlarda (Internet’ten) güncellemesine izin verir, fakat ağda bir bilgisayarın internete bağlanma yeteneğine sahiptir. Bu yol ile şirketlere bulaşırken, bazı PC’lerin doğrudan internete bağlanabilme yeteneğinin olmadığı için zekice bir şekilde tasarlanmıştır.
arar) import tablosunu değiştirerek bu işlevlerin adresini rootkit içindeki başka bir işlevlerin adreslerine değiştirerek yakalar.
Bu fonksiyonlar orijinal fonksiyonları çağırır (Windows API’leri) ve ardından stuxnet dosyalarını gizlemek için çıktılarını değiştirir.
Çıktıyı, belirli bir boyutta (4171 bytes) .LNK dosyaları içeriyorsa veya ~ WTRabcd.TMP (a + b + c + d = 10 olarak) adında bir dosya içerip içermediğini kontrol eder.
Bu rootkit bir PC’ye bulaşırken yalnızca bir kez kullanılır, ancak bundan sonra stuxnet “MRxNet” adında bir rootkit daha kurar ve bu Kernel-mod rootkit’dir.
1. Kernel-Mode Rootkit (MRxNet) : MRxNet, kullanıcı modu rootkit’te olduğu gibi USB flash bellekte (.LNK ve TMP dosyaları) oluşturulan dosyaları gizlemek için oluşturulan basit bir dosya sistemi filtresidir. IDA Pro’yu kullanarak bu sürücüyü elle C ++ uygulamasına geri döndürdüm.
Ancak bu rootkit, içe aktarma tablosundaki adresleri değiştirmiyor, ancak kendisini aşağıdaki sürücülerin sürücü zincirine ekliyor.
\\FileSystem\\ntfs
\\FileSystem\\fastfat
\\FileSystem\\cdfs
Bu sürücüler, makinenizdeki dosya ve klasörleri yönetmek için ana sürücülerdir. MRxNet kendisini sürücü zincirine eklediğinde, bu sürücüler onları almadan önce talepleri (Giriş / Çıkış İstek Paketleri ISPs) alır.
Bu isteklerin alınması, MRxNet’in bu sürücülere girişi değiştirmesini sağlar. Ve bu numarayı kullanarak MRxNet adında bir dizini gizler:
{58763ECF-8AC3-4a5f-9430-1A310CE4BE0A}
Adını giriş isteğinden (ISP) bu sürücülere kadar siler. Bu adın neyi temsil ettiğini bilmiyorum, bir GUID gibi görünüyor. Ancak MRxNet’in asıl amacı bu sürücülerin çıktılarını değiştirmektir, bu nedenle MRxNet bir “IOCompletionRoutine” isteğine eklenir. Bu rutin, sonuçtan sonra zincirde yürütülen son sürücünün (isteğin cevabını) yürütmesi ve kullanıcıya tekrar gönderilmesi gerekiyor. Bu fonksiyon, MRxNet’in yaptığı herhangi bir sürücünün çıktısını değiştirmek için Windows tarafından oluşturulmuştur.
MRxNet, kullanıcı modu rootkit gibi çıktıları değiştirir ve stuxnet dosyası gibi görünen aşağıda gördüğünüz şekilde siler:
MRxNet, verilerinde garip bir dize içeriyor (daha önce bir hata ayıklama mesajı gibi görünüyor):
b:\\myrtus\\src\\objfre_w2k_x86\\i386\\guava.pdb
Bu garip dize “myrtus” kelimesini içerir ve bu kelime “MyRTUs” temsil eder veya İbranice bir kelimeyi temsil etmektedir. Bu saldırının arkasındaki suçluları (İsrail Hükümetini) veya başka bir ülkeyi işaret ediyor olabilir 🙂
2. MRxCls Yükleyici Sürücüsü : Bu dosya (daha önce söylediğim gibi) LNK Güvenlik Açığı tarafından yüklenmiştir. Bu dosya Ana Stuxnet dropper’ı bilinen bir şekilde yükler. Yüklemek için LoadLibraryA’yı çağırır ve LoadLibraryA bu dropper stuxnet’i yükleyip kurması için ana giriş noktasını yürütür.
Detaylı olarak incelediğimizde MrxCls’in çok karmaşık bir proje gibi gözükmektedir. Herhangi bir Antivirüs uygulamasının özel olarak davranışsal antivirüslerin dikkatini çekmeden bir programı gizlice yüklemesi için birçok özellik ve yetenek içerir. Bu virüs sanki ayrı bir proje gibi görünüyor, Stuxnet solucanının yaratıcıları tarafından yaratılmadığını düşünüyorum. Stuxnet’i oluşturan organizasyondaki başka bir departman tarafından yaratıldığı anlaşılıyor. Bu sürücü stuxnet sürümleriyle birlikte değiştirilmedi ve stuxnet solucanı tarafından kullanılmayan pek çok özellik içeriyor. Bu organizasyon sadece programlama için bir organizasyon değil, Realtek Semi-Conductor Co-Op gibi büyük firmalardan bazı sertifikalar çalmasını sağlayan casusluk ve hırsızlık yeteneklerine sahiptir. Bu sürücü, Realtek şirketinden bir ürün olarak imzalanabilmektedir.
Bu virüsün bazı virüs yazarlarının bir oyunu değil, planlı bir suç olduğu görülmektedir. Bu bölümde sürücünün teknik detayları, nasıl çalıştığı ve iç yapısı hakkında size biraz detaylı bilgi vereceğim. İki ana başlıkta detaylı bir şekilde incelemek için önce sürücünün girdisi hakkında bilgi vereceğim, sonra bu sürücünün nasıl başlatıldığı hakkında bilgi vereceğim.
- Sürücü Girdisi : MrxCls parametrelerini kayıt defterinden bir anahtar adından alır:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MRxCls
Bu anahtardaki “Veri” değeri sürücünün parametresi olarak okunur. Bu veri şifreli bir veri içeriyor. Şifresini çözdükten sonra, aşağıdaki değerleri buluyoruz:
Bu veri, stuxnet dosyalarının bazı sistem fonksiyonlarının ve dosya adlarının adını içerir. Bu veriler sürücüye stuxnet dosyasının dosya adını ve stuxnet’in kendi dosyasını içine enjekte etmesi gereken işlemi bildirir. Bu veriler aşağıdaki gibi düzenlenmiştir:
İlk önce Başlık ve boyutu dinamiktir.
Bundan sonra, başlıktaki Enjeksiyon Sayısı ile tanımlanan bir dizi eleman var. Her öğe virüslü işlemin adını, bu işleme enjekte edilecek dll dosyasını, flag’leri ve virüsün şifresini çözen anahtarı içerir. Tüm stuxnet dosyaları sıfıra eşit bir anahtarla şifrelenir. Bu öğelerin yapısı şöyledir: İlk önce enfeksiyonun ayrıntılarıyla başlar ve ardından işlem adının ve stuxnet dosya adının Unicode dizeleriyle devam eder.
Ardından gelen Unicode dizeleri şöyle olur:
Ve bu, dizideki her öğe için tekrarlanır. Element Header’daki bayraklar 2 bit içerir. İlk bit, dosyanın (enjekte edilmesi gereken) şifreli olup olmadığını (ve her zaman şifreli) açıklar. Ve ikinci bit, virüs bulaşmış işlemin şifresi çözülmüş stuxnet dosyasını içerip içermediğini (dahili bir PE yükleyici tarafından yüklenecek) veya sadece kullanıcı modunda LoadLibraryW tarafından yüklenecek stuxnet dosyasının dosya adını içereceğini açıklar.
Bu nedenle, Stuxnet solucanı bu bilgileri içeren sürücüye aşağıdaki gibi bir girdi verisi olarak yazar:
services.exe –> \SystemRoot\inf\oem7A.PNF (stuxnet ana dll) ve Export 1 çağırır
S7tgtopx.exe –> \SystemRoot\inf\oem7A.PNF ve Export 2’yi çağırır. (SCADA’ya zararlı yazılım bulaştırmak için)
CCProjectMgr.exe –> SystemRoot\inf\oem7A.PNF ve Export 2’yi çağırır.
explorer.exe –> \SystemRoot\inf\oem7m.PNF ve Export 2’yi çağırır.
Stuxnet ayrıca bayrakları her zaman “11” veya “3”‘e eşit olarak ayarlar ve bu, stuxnet dosyasının şifrelenmiş olması ve şifresinin çözülmesi gerektiği ve sürücünün onu okuması ve şifresini çözmesi gerektiği ve virüslü işlemdeki belleği dosyanın boyutuna eşit olması gerektiği anlamına gelir. Bundan sonra kullanıcı modunda dosya, enjekte edilen dosyanın yanındaki işlem belleğine enjekte edilen yerleşik bir PE yükleyici tarafından yüklenir.
- Sürücünün Başlatılması : İlk olarak, stuxnet bir kayıt defteri anahtarı yaratır ve her başlangıçta yüklenecek MrxCls sürücüsünü kaydetmek için bazı değerler ekler. Bu anahtar “ SYSTEM\CurrentControlSet\Services\MRxCls” şeklindedir. Daha sonra sürücünün parametrelerini içeren, önyükleme sürücüsü olarak yüklenmesini sağlayan ve birçok servis uygulaması sürücüsünden önce yüklenmesini sağlayan “Veri” değerini ekler.
Yüklendiğinde, bir parçanın 0x278 bayt boyutundaki verilerinden şifresini çözerek başlar ve aşağıdaki verileri alır:
Bundan sonra “Data” değerinden parametreleri alır, şifresini çözer ve genel bir tabloda bir eleman olarak kaydeder. Ayrıca “InitSafeBootMode” ’u ve“ KdDebuggerEnabled ”ını kontrol eder. Kd hata ayıklayıcısını etkinleştirdiyseniz, sona erer.
Ardından “IoCreateDevice” API’yi çağırarak yeni bir cihaz yaratır ve “\Device\MRxClsDvX” adında yeni bir sürücü oluşturur. Daha sonra “RtlGetVersion” ve “KeAreAllApcsDisabled” gibi bazı fonksiyonlar “MmGetSystemRoutineAddress” (GetProcAddress değil) adlı bir fonksiyonla elde edilir.
Sonunda, bir işlem veya modül belleğe her yüklendiğinde çağrılacak bir işlevi kaydetmek için “PsSetLoadImageNotifyRoutine” işlevini çağırır (sürücüde kullanılacak olan services.exe ve kernel32.dll dahil). Şimdi NotifyRoutine ve stuxnet dosyalarının bir sistem sürecine nasıl enjekte edildiği ile ilgili 3 aşamayı sizinle detaylı olarak paylaşacağım.
Birinci Aşama: Kernel Modunda Veri Enjekte Etme : Bir işlem veya modül belleğe her yüklendiğinde, bu işlem üç parametre olarak adlandırılır: Modülün adı, ProcessId ve ImageInfo. Yüklenen modülün “kernel32.dll” ile kontrol edilmesiyle başlar ve kernel32 değilse, kayıt defteri verilerini ayrıştırır (daha önce yüklenmiş ve şifresi çözülmüş) ve stuxnet dosyasını içine enjekte etmesi ve yüklenen işlemin adıyla karşılaştırması gereken işlemin adını arayan bu veri unsurları üzerinde durur. Bulduğunda stuxnet dosyasını içine enjekte etmek için bir işlem gereklidir. Stuxnet dosyasını işlemin belleğine yükler ve şifresini çözer. Bundan sonra, işlemin belleğine bir veri yığınını (kod içeren) kopyalar ve ardından bu veri yığınına “MZ” ve “PE” ve diğer bazı verileri yazar. Bu veri çöplüğü, iki PE dosyası olduğunu ve bunlardan bazı PE dosyalarının (örneğin MZ, PE, 0x14C, 0xE0 vb.) ortak işaretlerinden silindiğini gösteriyor. Bu baytlar bunun bir PE dosyası olduğunu kanıtlar, böylece MrxCls yazarı onları silmiş ve tekrar tekrar yerlerine yazmak için bir kod yazmıştır (Ve bu kesinlikle onları gizlemenin ve bu önemsiz verilerin anlamını gizlemenin bir yoludur). Sadece bu değil, aynı zamanda tüm bölümlerin adını silmiş. Ardından, sürücü işleminin hafızasında MZ başlığının başlangıcına işaretçi yazar (ondan önce 0x101C bayt var, bunu hatırlayın çünkü üçüncü aşamada tekrar konuşacağız) ve bu PE modülünün boyutu, MZ modülünün içindeki bellekte belirli yerlerde bulunur. Bundan sonra işlem PE modülüne atlar. PE’sini ayrıştırmakla başlar ve işlem modülünün giriş noktasını alır ve ardından giriş noktası ile giriş noktası + 0xC arasında yer değiştirilemez olup olmadığını kontrol eder (0xC, giriş noktasındaki üzerine yazılmış kodun boyutu olduğundan emin olmak için denetler. Bu sayede giriş noktasının üzerine yazmakta hiçbir sorun yaşanmaz). Ardından, “Ntoskrnl.exe” işleminde veya “Ntkrnlpa.exe” işleminde bir kod parçacığı arar.
Ve bu kod parçacığı şudur: Windows 2000 veya daha düşük işletim sistemi
mov eax,77
lea edx,dword ptr [esp+4]
int 2E
retn 14
Veya Windows XP veya sonraki sürümlerde:
push 104
call loc_1
???
loc_1:
mov eax,0
lea edx,dword ptr [esp+4]
pushfd
push 8
call ZwAllocateVirtualMemory
retn 14
Gördüğünüz gibi bu kod parçacıkları ZwAllocateVirtualMemory’i çağırıyor. Bu nedenle, sürücü bunlardan birine ZwAllocateVirtualMemory’yi çağırmak için işlem giriş noktasının bellek izinlerini READ_ONLY’den COPY_ON_WRITE olarak değiştiren parametreler göz önüne alındığında, ZWAllocateVirtualMemory’e çağırır (bu parametre ile ZwAllocateVirtualMemory çağrısı değiştirilmesinin önlenmesi için bir parametre olarak görünmektedir).
Sonunda, stuxnet dosyasının boyutuna artı 0x28 bayt boyutuna eşit boyutta bir tampon oluşturur ve daha sonra stuxnet dosyasını bu tampona (0x28 bayttan sonra) kopyalar ve bazı önemli verileri kullanıcı modundaki koduna (aşama 3) yazar. Aşağıdaki yapıya sahip 0x28 bayt:
Ardından, genel tabloda, şu verilerle yeni bir öğe oluşturur:
Sonunda, bu tamponun (stuxnet dosyası dahil) yerini kopyalanan PE modülündeki (daha önce işlemin belleğine kopyalanan verilerin hurdası) belirli bir yere yazar.
İkinci Aşama: KERNEL32 Import, Oluşturma ve Giriş Noktasının Üzerine Yazma : Önceki aşamada anlattığım gibi, yüklü modülü “kernel32.dll” ile kontrol ederek başlar. Eşit değilse, 1. aşamaya atlar. Ancak kernel32.dll eşitse, 2. aşamaya atlar. Bu nedenle 2. aşama bu aşamanın 1’in geçip geçmediğini kontrol ederek başlar. Genel tablodaki bir öğeyi arar, yukarıdaki genel tablo öğesini belirtilen yapıyla almak için processId (çekirdek çekirdek modülünün yüklendiği prcoessId) ile başlar. Ardından, kullanıcı modu için bir içe aktarma tablosu oluşturur ve bunları genel tablo öğesindeki 2. öğenin bulunduğu yere yazar (“MZ” + 0x2B8’de InjectedMemory). VirtualAlloc, VirtualFree, GetProcAddress, GetModuleHandle, LoadLibraryA, LoadLibraryW, lstrcmp, lstrcmpi, GetVersionEx, DeviceIoControl isminde 10 fonksiyon alır. Bu fonksiyonları sürücünün içine yazılmış sağlama toplamları kullanarak alır.
Sonra, import tablosundan sonraki ilk 0xC baytını (12 bayt) bazı baytlarca kaydeder ve ardından giriş noktasını aşağıdaki şekilde değiştirir:
mov eax, 0
call eax
Daha sonra genel tablo tamponunun 3. öğesiyle (“MZ + + 0x560’da InjectedMemory”) ve bu, enjekte edilen kodun giriş noktası olan “mov eax, 0” ın derhal değiştirir. “MZ” + 0x2B8’deki InjectedMemory şu şekilde olur:
Sonunda, kullanıcı modunda bir işlemde enjekte stuxnet dosyasının 3. aşamasına başlamak için bildirim yordamından çıkar.
Üçüncü Aşama: Kullanıcı Modunda Stuxnet’i Yükleme ve Çalıştırma : Bir uygulamaya bu verileri (import tablosu da dahil) enjekte ederek bu kısmı tersine çevirmeye başlıyoruz (stuxnet ile virüs bulaşmış işlem olarak windbg’yi seçiyorum) ve Ollydbg kullanarak bu kısmı tersine çevirmeye başlıyoruz. Bu hazırlanmış kod, yeni bir MZ header’ı oluşturarak başlar (veya eksik verileri değiştirilmiş bir PE modülüne yazar), “MZ” veya “PE” gibi. Enjekte edilen hafızada, 2. MZ header’ı 0x101C bayt olur. Ve sonra, bazı fonksiyonların adresini alır ve aşağıdaki gibi bu fonksiyonlarla bir dizi oluşturur:
0xF90, enjekte edilen koddaki 2. MZ başlığının boyutudur. Daha sonra hazırlanmış kod, bu enjekte edilen modüllerin her ikisini de (bu PE başlıkları ile birlikte), yerleşik bir PE Yükleyici kullanarak virüslü işlemin sanal belleği içindeki yeni ayrılmış hafızalara yükler.
Bu PE yükleyici, yer değiştirebilir parçaları sabitleme ve başlıkları ve bölümleri doğru yere yerleştirme yeteneğine sahiptir. Bundan sonra 1. Modülün giriş noktasını çağırır. Bu modül SHE’yi kaydederek başlar ve Stuxnet Dosyasını, LoadLibraryW veya PEloader’ı kullanarak, stuxnet tamponunun başlangıç verilerinin flag’lerindeki 2. biti kontrol ederek yükler.
Stuxnet’i yükledikten sonra, stuxnet modülünde seçilen dışa aktarma işlevini çağırır. Sonunda, değiştirilmiş giriş noktasını daha önce belleğe kaydedilmiş orijinal kodla yeniden yazar. Sonunda, giriş noktasının + 0C giriş noktası izinlerini orijinal durumuna (Reset) yeniden sıfırlamak için mrxcls sürücüsüne bir istek paketi gönderen DeviceIoControl’ü çağırır ve işlemi çalıştırmak için giriş noktasına çağırır.