| 282 | } |
| 283 | |
| 284 | fn get_remote_thread_handle(process_id: u32) -> Result<Vec<HANDLE>, String> { |
| 285 | let mut buffer: Vec<u8> = Vec::with_capacity(1024 * 1024); |
| 286 | let mut return_length: ULONG = 0; |
| 287 | |
| 288 | let status = unsafe { |
| 289 | NtQuerySystemInformation( |
| 290 | SystemProcessInformation, |
| 291 | buffer.as_mut_ptr() as *mut c_void, |
| 292 | buffer.capacity() as ULONG, |
| 293 | &mut return_length |
| 294 | ) |
| 295 | }; |
| 296 | |
| 297 | if !NT_SUCCESS(status) { |
| 298 | return Err("Failed to call NtQuerySystemInformation".to_owned()); |
| 299 | } |
| 300 | |
| 301 | unsafe { |
| 302 | buffer.set_len(return_length as usize); |
| 303 | } |
| 304 | |
| 305 | let mut offset: usize = 0; |
| 306 | let mut thread_handles: Vec<HANDLE> = Vec::new(); |
| 307 | |
| 308 | while offset < buffer.len() { |
| 309 | let process_info: &SYSTEM_PROCESS_INFORMATION = unsafe { &*(buffer.as_ptr().add(offset) as *const SYSTEM_PROCESS_INFORMATION) }; |
| 310 | |
| 311 | if process_info.UniqueProcessId == process_id as PVOID { |
| 312 | let thread_array_base = (process_info as *const _ as usize) + std::mem::size_of::<SYSTEM_PROCESS_INFORMATION>() - std::mem::size_of::<SYSTEM_THREAD_INFORMATION>(); |
| 313 | |
| 314 | for i in 0..process_info.NumberOfThreads as usize { |
| 315 | let thread_info_ptr = (thread_array_base + i * std::mem::size_of::<SYSTEM_THREAD_INFORMATION>()) as *const SYSTEM_THREAD_INFORMATION; |
| 316 | let thread_info = unsafe { &*thread_info_ptr }; |
| 317 | |
| 318 | let mut thread_handle: HANDLE = null_mut(); |
| 319 | let mut object_attrs: OBJECT_ATTRIBUTES = unsafe { std::mem::zeroed() }; |
| 320 | let mut client_id: CLIENT_ID = unsafe { std::mem::zeroed() }; |
| 321 | client_id.UniqueThread = thread_info.ClientId.UniqueThread; |
| 322 | |
| 323 | let status = unsafe { |
| 324 | NtOpenThread( |
| 325 | &mut thread_handle, |
| 326 | THREAD_ALL_ACCESS, |
| 327 | &mut object_attrs, |
| 328 | &mut client_id |
| 329 | ) |
| 330 | }; |
| 331 | |
| 332 | if NT_SUCCESS(status) { |
| 333 | thread_handles.push(thread_handle); |
| 334 | } |
| 335 | } |
| 336 | } |
| 337 | |
| 338 | if process_info.NextEntryOffset == 0 { |
| 339 | break; |
| 340 | } |
| 341 | offset += process_info.NextEntryOffset as usize; |