From ddbd24554d395edfed8e8b9f13c4cbb3d1e15fdf Mon Sep 17 00:00:00 2001 From: Ashley Donaldson Date: Wed, 31 May 2023 13:42:18 +1000 Subject: [PATCH] Take into account Windows 10 revision number --- lib/msf/core/post/windows/version.rb | 16 +++++++++------- lib/msf/core/windows_version.rb | 11 +++++++++-- spec/lib/msf/core/post/windows/version_spec.rb | 8 ++++++++ 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/msf/core/post/windows/version.rb b/lib/msf/core/post/windows/version.rb index f25a3cfe3b..e8b4de030d 100644 --- a/lib/msf/core/post/windows/version.rb +++ b/lib/msf/core/post/windows/version.rb @@ -32,15 +32,15 @@ module Msf::Post::Windows::Version end def get_version_info_fallback_impl - build_num_raw = cmd_exec('ver') + build_num_raw = cmd_exec('cmd.exe /c ver') groups = build_num_raw.match(/.*Version\s+(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?/) if groups.nil? return nil end - major, minor, build, _revision = groups.captures + major, minor, build, revision = groups.captures # Default to workstation, since it'll likely be an older OS - pre Server editions - return Msf::WindowsVersion.new(major.to_i, minor.to_i, build.to_i, 0, Msf::WindowsVersion::VER_NT_WORKSTATION) + return Msf::WindowsVersion.new(major.to_i, minor.to_i, build.to_i, 0, revision, Msf::WindowsVersion::VER_NT_WORKSTATION) end def get_version_info_impl @@ -52,7 +52,8 @@ module Msf::Post::Windows::Version build = os_version_info_ex[3] service_pack = os_version_info_ex[6] product_type = os_version_info_ex[9] - + + session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', KEY_READ) Msf::WindowsVersion.new(major, minor, build, service_pack, product_type) else # Command shell - we'll try reg commands, and fall back to `ver` @@ -92,11 +93,12 @@ module Msf::Post::Windows::Version # This is Windows 10+ - the version numbering is calculated differently major = shell_registry_getvaldata('HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentMajorVersionNumber', Msf::Post::Windows::Registry::REGISTRY_VIEW_NATIVE) minor = shell_registry_getvaldata('HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentMinorVersionNumber', Msf::Post::Windows::Registry::REGISTRY_VIEW_NATIVE) - if major.nil? || minor.nil? + ubr = shell_registry_getvaldata('HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'UBR', Msf::Post::Windows::Registry::REGISTRY_VIEW_NATIVE) + if major.nil? || minor.nil? || ubr.nil? return get_version_info_fallback_impl end - Msf::WindowsVersion.new(major, minor, build_num, 0, product_type) + Msf::WindowsVersion.new(major, minor, build_num, 0, ubr, product_type) else # Pre-Windows 10 service_pack_raw = shell_registry_getvaldata('HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CSDVersion', Msf::Post::Windows::Registry::REGISTRY_VIEW_NATIVE) @@ -112,7 +114,7 @@ module Msf::Post::Windows::Version end end - Msf::WindowsVersion.new(major, minor, build_num, service_pack, product_type) + Msf::WindowsVersion.new(major, minor, build_num, service_pack, 0, product_type) end end end diff --git a/lib/msf/core/windows_version.rb b/lib/msf/core/windows_version.rb index ff3de2d7e5..10fae3876e 100644 --- a/lib/msf/core/windows_version.rb +++ b/lib/msf/core/windows_version.rb @@ -69,14 +69,21 @@ module Msf Server2016Plus = 'Windows Server 2016+'.freeze end - def initialize(major, minor, build, service_pack, product_type) + def initialize(major, minor, build, service_pack, revision, product_type) self._major = major self._minor = minor self._build = build self._service_pack = service_pack + self._revision = revision self.product_type = product_type end + # The specific revision number of this version + # This is mainly going to be present on Windows 10+, wherein it's easy to get it from the registry. + def revision_number + _revision + end + # The specific build number of this version (major.minor.build.service_pack) def build_number Rex::Version.new("#{_major}.#{_minor}.#{_build}.#{_service_pack}") @@ -132,7 +139,7 @@ module Msf private - attr_accessor :_major, :_minor, :_build, :_service_pack, :product_type + attr_accessor :_major, :_minor, :_build, :_service_pack, :_revision, :product_type # The major release within which this build fits def major_release_name diff --git a/spec/lib/msf/core/post/windows/version_spec.rb b/spec/lib/msf/core/post/windows/version_spec.rb index 963543be44..4d42cee3f8 100644 --- a/spec/lib/msf/core/post/windows/version_spec.rb +++ b/spec/lib/msf/core/post/windows/version_spec.rb @@ -43,6 +43,10 @@ RSpec.describe Msf::Post::Windows::Version do 'CurrentMajorVersionNumber' end + let(:ubr) do + 'UBR' + end + let(:product_type_key) do 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ProductOptions' end @@ -81,10 +85,12 @@ RSpec.describe Msf::Post::Windows::Version do respond_to_reg_query(subject, current_version_key, current_version, '6.3', 'REG_SZ') respond_to_reg_query(subject, current_version_key, major_version, '0xa', 'REG_DWORD') respond_to_reg_query(subject, current_version_key, minor_version, '0x0', 'REG_DWORD') + respond_to_reg_query(subject, current_version_key, ubr, '0x100', 'REG_DWORD') respond_to_reg_query(subject, product_type_key, product_type, 'WinNT', 'REG_SZ') allow(subject).to receive_message_chain('session.type').and_return('shell') version = subject.get_version_info expect(version.build_number).to eq(Msf::WindowsVersion::Win10_22H2) + expect(version.revision).to eq(256) expect(version.windows_server?).to eq(false) expect(version.domain_controller?).to eq(false) end @@ -94,10 +100,12 @@ RSpec.describe Msf::Post::Windows::Version do respond_to_reg_query(subject, current_version_key, current_version, '6.3', 'REG_SZ') respond_to_reg_query(subject, current_version_key, major_version, '0xa', 'REG_DWORD') respond_to_reg_query(subject, current_version_key, minor_version, '0x0', 'REG_DWORD') + respond_to_reg_query(subject, current_version_key, ubr, '0x100', 'REG_DWORD') respond_to_reg_query(subject, product_type_key, product_type, 'LanmanNT', 'REG_SZ') allow(subject).to receive_message_chain('session.type').and_return('shell') version = subject.get_version_info expect(version.build_number).to eq(Msf::WindowsVersion::Server2022) + expect(version.revision).to eq(256) expect(version.windows_server?).to eq(true) expect(version.domain_controller?).to eq(true) end