Module: Msf::Exploit::Local::WindowsKernel::HandleEnum
- Defined in:
- lib/msf/core/exploit/local/windows_kernel/handle_enum.rb
Constant Summary collapse
- SYSTEMHANDLEINFORMATION =
64.freeze
Instance Method Summary collapse
-
#enum_system_handles(session, max_handles = 50000, timeout = 30) ⇒ Object
HandleEnum provides methods for enumerating Windows kernel handles via NtQuerySystemInformation for security research purposes.
- #format_file_size(bytes) ⇒ Object
- #get_process_name(session, pid) ⇒ Object
- #get_type_hint(type_idx) ⇒ Object
- #kernel_address?(addr) ⇒ Boolean
Instance Method Details
#enum_system_handles(session, max_handles = 50000, timeout = 30) ⇒ Object
HandleEnum provides methods for enumerating Windows kernel handles via NtQuerySystemInformation for security research purposes.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/msf/core/exploit/local/windows_kernel/handle_enum.rb', line 11 def enum_system_handles(session, max_handles = 50000, timeout = 30) pointers = [] max_attempts = 5 attempt = 0 buffer_size = 1024 * 1024 begin Timeout.timeout(timeout) do while attempt < max_attempts vprint_status("HandleEnum: Attempt #{attempt + 1}: Trying buffer size #{buffer_size} bytes") begin buffer = "\x00" * buffer_size rescue ArgumentError print_error("HandleEnum: Failed to allocate buffer of size #{buffer_size}") return nil end result = session.railgun.ntdll.NtQuerySystemInformation(SYSTEMHANDLEINFORMATION, buffer, buffer_size, 4) if result.blank? print_error('HandleEnum: NtQuerySystemInformation returned nil/empty') return nil end if result['return'] == 0 vprint_good("HandleEnum: Success with buffer size #{buffer_size}") data = result['SystemInformation'] break elsif result['return'] == 0xC0000004 if result['ReturnLength'] && result['ReturnLength'] > buffer_size buffer_size = result['ReturnLength'] vprint_status("HandleEnum: Buffer too small, need #{buffer_size} bytes") else buffer_size *= 2 vprint_status("HandleEnum: Doubling buffer to #{buffer_size} bytes") end attempt += 1 else print_error("HandleEnum: NtQuerySystemInformation failed: 0x#{result['return'].to_s(16)}") return nil end end if attempt >= max_attempts print_error("HandleEnum: Failed to get valid buffer after #{max_attempts} attempts") return nil end if data.blank? || data.length < 16 print_error('HandleEnum: Invalid response data') return nil end num_handles = data[0, 8].unpack('Q').first vprint_good("HandleEnum: System has #{num_handles} total handles") if max_handles > 0 && num_handles > max_handles vprint_status("HandleEnum: Limiting to #{max_handles} handles") num_handles = max_handles end vprint_status("HandleEnum: Processing #{num_handles} handles...") offset = 16 entry_size = 48 num_handles.times do |i| entry_offset = offset + (i * entry_size) break if entry_offset + entry_size > data.length entry = data[entry_offset, entry_size] begin object_ptr = entry[0, 8].unpack('Q').first pid = entry[8, 8].unpack('Q').first handle = entry[16, 8].unpack('Q').first access = entry[24, 4].unpack('V').first type_idx = entry[30, 2].unpack('v').first if kernel_address?(object_ptr) pointers << { address: object_ptr, pid: pid, handle: handle, access: access, type_index: type_idx } end rescue StandardError => e vprint_error("HandleEnum: Error parsing handle #{i}: #{e.}") end end vprint_good("HandleEnum: Processed #{num_handles} handles, found #{pointers.size} kernel addresses") end rescue Timeout::Error print_error("HandleEnum: Enumeration timed out after #{timeout} seconds") return nil rescue StandardError => e print_error("HandleEnum: Error during enumeration: #{e.}") return nil end pointers end |
#format_file_size(bytes) ⇒ Object
163 164 165 166 167 168 169 170 171 |
# File 'lib/msf/core/exploit/local/windows_kernel/handle_enum.rb', line 163 def format_file_size(bytes) if bytes < 1024 "#{bytes} bytes" elsif bytes < 1024 * 1024 "#{(bytes / 1024.0).round(2)} KB" else "#{(bytes / (1024.0 * 1024.0)).round(2)} MB" end end |
#get_process_name(session, pid) ⇒ Object
152 153 154 155 156 157 158 159 160 161 |
# File 'lib/msf/core/exploit/local/windows_kernel/handle_enum.rb', line 152 def get_process_name(session, pid) begin session.sys.process.each_process do |p| return p['name'] if p['pid'] == pid end rescue StandardError nil end "PID:#{pid}" end |
#get_type_hint(type_idx) ⇒ Object
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/msf/core/exploit/local/windows_kernel/handle_enum.rb', line 125 def get_type_hint(type_idx) hints = { 7 => 'Process', 8 => 'Thread', 16 => 'Key', 24 => 'File', 32 => 'ALPC', 33 => 'ALPC', 34 => 'ALPC', 35 => 'ALPC Port', 36 => 'ALPC Port', 37 => 'ALPC Port', 38 => 'ALPC Port', 39 => 'ALPC Port', 40 => 'ALPC Port', 41 => 'ALPC Port', 42 => 'ALPC Section', 43 => 'ALPC', 44 => 'ALPC', 45 => 'ALPC', 46 => 'ALPC', 47 => 'ALPC', 48 => 'ALPC' } hints[type_idx] || 'Unknown' end |
#kernel_address?(addr) ⇒ Boolean
118 119 120 121 122 123 |
# File 'lib/msf/core/exploit/local/windows_kernel/handle_enum.rb', line 118 def kernel_address?(addr) return false if addr.nil? || addr == 0 high_bits = (addr >> 48) & 0xFFFF high_bits == 0xFFFF end |