Esen;
Windows işletim sisteminden sürüm bilgisi çekmenin birden çok yolu var. Bu yazıda bunları açıklamaya çalışacağım. Peki neden böyle birşey yapalım? Sürüm bilgisi bizim ne işimize yarayacak? Eğer geliştirici iseniz ve sadece belli bir windows sürümüne özel program yazıyorsanız ya da özellikle belli sürümün altındakilerde çalışmasını istemiyorsanız sürüm kontrolü yaparak istediğiniz sonucu alabilirsiniz. Veya zararlı yazılım çözümlemesi yaparken zararlının nasıl çalıştığını daha iyi anlamak adına işinize yarayabilir. APT saldırısı yapıldığını düşünün. Hedefte bir kurum olsun devlet ya da özel. Saldırganlar bu kurumda sadece belli sürüm (Mesela Windows 7 SP1 Enterprise) windows kullanıldığını öğrenmiş olsun. O zaman yazacakları zararlıyı Windows 7 SP1 ve üzerinde çalışacak şekilde programlayabilirler. Bizde bunu hata ayıklarken ortaya çıkartabiliriz.
Process Environment Block – PEB kullanarak sürüm bilgisi öğrenmek
Şunu söylemeliyim PEB başlı başına bir yazı konusu olabilir. Ama kısaca da olsa anlatmak gerek. PEB (Process Environment Block) windows tarafından yüklenen bir “yapıdır – struct”. Bu yapı user-mode içerisinde çalışır ve çok değerli bilgiler içerir: Sürüm bilgisi, yığıt adresleri ve yığıt sayısı (heap address – heap number), programın debug edilip edilmediğine dair bilgi, işlemci sayısı gibi bilgiler… WinDBG ile ilgili yazımı okuyup uygulama yaptıysanız, lokalde kernel debuggerı açıp dt ntdll!_PEB komutunu yazarak PEB yapısını WinDBG ekranına basabilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 |
kd> dt ntdll!_PEB +0x000 InheritedAddressSpace : UChar +0x001 ReadImageFileExecOptions : UChar +0x002 BeingDebugged : UChar +0x003 SpareBool : UChar +0x004 Mutant : Ptr32 Void +0x008 ImageBaseAddress : Ptr32 Void +0x00c Ldr : Ptr32 _PEB_LDR_DATA +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS +0x014 SubSystemData : Ptr32 Void +0x018 ProcessHeap : Ptr32 Void [DEVAM EDİYOR...] |
Umarım kafanız karışmaz şu linke bakarak PEB hakkında windows’ün sürümlerine göre gösteren değişiklikler de ele alınarak harika bir çalışma yapılmış: PEB Combined
İşte bu yapı içerisinde ben:
1 2 3 4 5 6 |
[...DEVAM EDİYOR] 0x0a4 DWORD OSMajorVersion; 0x0a8 DWORD OSMinorVersion; 0x0ac WORD OSBuildNumber; 0x0ae WORD OSCSDVersion; [DEVAM EDİYOR...] |
bu offsetlerdeki verileri döndürerek sürüm bilgisine ulaşabilirim:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
print "Read From Process Environment Block:",13,10 ASSUME FS:Nothing mov edx,fs:[30h] ;PEB.InheritedAddressSpace mov szVer,edx ASSUME FS:ERROR mov eax,[edx+0A4h] ;eax = Major Sürüm push eax push edx print ustr$(eax),'.' pop edx push edx mov eax,[edx+0A8h] ;eax = Minor Sürüm print ustr$(eax),'.' pop edx mov eax,[edx+0ACh] ;eax = Build Bilgisi and eax,0FFFFh ;bu düzeltmeyi yapmayınca win7de hata alıyoruz print ustr$(eax),13,10,13,10 mov edx,szVer mov eax,[edx+01F0h] print ustr$(eax),13,10 pop eax |
RtlGetVersion APIsi kullanılarak sürüm bilgisi öğrenmek
RtlGetVersion apisi aşağıda da gördüğünüz gibi tek bir parametre almaktadır. Bu parametre ise RTL_OSVERSIONINFOW ya da RTL_OSVERSIONINFOEXW yapılarından birisidir.
1 2 3 |
NTSTATUS RtlGetVersion( _Out_ PRTL_OSVERSIONINFOW lpVersionInformation ); |
RtlGetVersion apisi çalıştığında ilgili verileri bu yapıya yazar. Bizde oradan bilgileri çekebiliriz.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
typedef struct _OSVERSIONINFOEXW { ULONG dwOSVersionInfoSize; ULONG dwMajorVersion; ULONG dwMinorVersion; ULONG dwBuildNumber; ULONG dwPlatformId; WCHAR szCSDVersion[128]; USHORT wServicePackMajor; USHORT wServicePackMinor; USHORT wSuiteMask; UCHAR wProductType; UCHAR wReserved; } RTL_OSVERSIONINFOEXW, *PRTL_OSVERSIONINFOEXW; |
Bu apiyi kullanmadan önce döndüreceği verileri yazması için yapıyı tanımlamamız gerekiyor. Masm32 paketi içerisinde gelmediği için biz tanımlıyoruz: RTL_OSVERSIONINFOEXW
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
RTL_OSVERSIONINFOEXW STRUCT dwOSVersionInfoSize DWORD ? dwMajorVersion DWORD ? dwMinorVersion DWORD ? dwBuildNumber DWORD ? dwPlatformId DWORD ? szCSDVersion WORD 128 dup (?) wServicePackMajor WORD ? wServicePackMinor WORD ? wSuiteMask WORD ? wProductType BYTE ? wReserved BYTE ? RTL_OSVERSIONINFOEXW ENDS rtlOsvx RTL_OSVERSIONINFOEXW <> |
Windows 10 için aşağıdaki şekilde RtlGetVersion apisini RTL_OSVERSIONINFOEXW ile kullanarak gerekli bilgileri çeker sonra da yapının içindeki verileri ekrana basabiliriz:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
mov dword ptr rtlOsvx.dwOSVersionInfoSize, sizeof rtlOsvx invoke RtlGetVersion, addr rtlOsvx print "Displaying Version Info via RtlGetVersion API",13,10 print chr$("Windows Version...........:"),9 print str$(rtlOsvx.dwMajorVersion),46 print str$(rtlOsvx.dwMinorVersion),46 print str$(rtlOsvx.dwBuildNumber),13,10 print cat$(chr$("Major Version.............:"), chr$(9),str$(rtlOsvx.dwMajorVersion)),13,10 print cat$(chr$("Minor Version.............:"), chr$(9),str$(rtlOsvx.dwMinorVersion)),13,10 print cat$(chr$("Build Number..............:"), chr$(9),str$(rtlOsvx.dwBuildNumber)),13,10 print cat$(chr$("Platform ID...............:"), chr$(9),str$(rtlOsvx.dwPlatformId)),13,10 print "Service Pack String.......:",9 print addr rtlOsvx.szCSDVersion print chr$(13,10) print cat$(chr$("Service Pack Major Version:"), chr$(9),str$(rtlOsvx.wServicePackMajor)),13,10 print cat$(chr$("Service Pack Minor Version:"), chr$(9),str$(rtlOsvx.wServicePackMinor)),13,10 invoke wrd2bin_ex,rtlOsvx.wSuiteMask, addr binBuff push edx print cat$(chr$("Suite Mask Binary.........:"), chr$(9)) pop edx print edx,13,10 print cat$(chr$("Suite Mask Word...........:"), chr$(9),str$(rtlOsvx.wSuiteMask)),13,10 ;Eğer szCSDVersion degiskenini BYTE tanimlarsam Win10 "0" donduruyor ;Eğer szCSDVersion degiskenini WORD tanimlarsam Win10 olmasi gerekeni donduruyor print cat$(chr$("Product Type..............:"), chr$(9),str$(rtlOsvx.wProductType)),13,10 |
GetVersionEx APIsi ile sürüm bilgisi döndürmek
GetVersionEx apisi tek bir parametre alır ve döndüreceği sürüm bilgisini bu parametre içerisindeki yapıya yazar. Bu API OSVERSIONINFOEX ya da OSVERSIONINFO yapılarını kullanarak sürüm bilgisi döndürür. Windows 10 ile bu APIyi kullanırsak bize yanlış bilgi döndürüyor. O yüzden bu APIyi artık Windows 10’da kullanmıyoruz. Windows 8.1’den öncesine kadar doğrudan bu apiyi çağırarak doğru sürüm bilgisi elde edilebiliyor. Windows 8.1 ‘den itibaren manifest bilgisi eklenmesi gerekiyor. Ancak benim bildiğim kadarıyla konsol programlarına manifest bilgisi eklenmiyor.
GetVersion APIsi ile sürüm bilgisi döndürmek
GetVersion APIsi parametre almaz. Çağrıldığı zaman sürüm bilgisini eax yazmacına yazar.
al= major sürüm bilgisi
ah= minor sürüm bilgisi
eax’in soldaki 4 baytı ise build-inşa bilgisini içerir.
Yukarıda açıklamaya çalıştığım GetVersinEx APIsi gibi bu da Windows 8.1’den itibaren hatalı sürüm bilgisi döndürüyor.
Kayıt Defterinden bilgi çekerek sürüm bilgisi öğrenmek
Tüm Windows sürümleri kayıt defterinde sürüm bilgisi başta olmak üzere birçok bilgiyi saklamaktadır. Bizi ilgilendiren ise şu yoldur: [HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion]
Bu yol içerisindeki anahtarlar windows sürüm, inşa servis paketi gibi bilgiler taşır. Buradan bilgi çekerek sürüm bilgisi döndürebiliriz:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
print "Displaying Version Info Via Registry",13,10 invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,addr szRegPath,0,KEY_ALL_ACCESS, addr hKey xor eax,eax invoke RegQueryValueEx,hKey, addr szRegWin10Maj, eax, eax, addr genelTampon, addr szBufferMajor mov esi,dword ptr ds:genelTampon invoke wsprintf,addr bufferMajor,addr format,esi invoke StdOut, addr bufferMajor print chr$(46) xor eax,eax invoke RegQueryValueEx,hKey, addr szRegWin10Min, eax, eax, addr genelTampon, addr szBufferMinor mov esi,dword ptr ds:genelTampon invoke wsprintf,addr bufferMinor,addr format,esi invoke StdOut, addr bufferMinor print chr$(13,10) |
Yukarıdaki kod parçası Windows 10 için geçerli. Oysa aşağıdaki kaynak kodda diğer sürümler için olan kodları da bulabilirsiniz. [HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion] yolu altında windows 10 ile beraber gelen iki yani anahtar var: “CurrentMajorVersionNumber” ve “CurrentMinorVersionNumber”. Bunlar doğru sonuç döndürür. Ancak geçmişten gelen bir anahtar var : “CurrentVersion” bunu windows 8’e kadar döndürebilirsiniz. Ama sonrasında sabit değer taşıyor.
Aşağıda kaynak kodları ekliyorum. Diğer örnekler gibi bu paket de RadASM2 ve Masm32 kullanılarak hazırlanıp derlendi. Kaynak kodlar içerisine de yorumlar ekledim. Onları da inceleyiniz. Daha iyi anlamak adına örnek kodu iyice kurcaların değişikliler yapın. Ve her gün kod yazmayı unutmayın.
[dm]159[/dm]
Comments of this post