Skip to content

Commit dc45399

Browse files
committed
Mmk
1 parent 21168ff commit dc45399

File tree

3 files changed

+77
-29
lines changed

3 files changed

+77
-29
lines changed

src/bindings.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
output = "win_bindings.rs"
22
binds = [
33
"MAX_PATH",
4+
"NtClose",
5+
"NtOpenProcess",
46
"NtQueryInformationProcess",
5-
"OpenProcess",
67
"ProcessBasicInformation",
78
"ProcessImageFileName",
89
"PROCESS_BASIC_INFORMATION",

src/lib.rs

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -271,69 +271,103 @@ pub fn is_powershell_parent() -> bool {
271271
use std::os::windows::ffi::OsStringExt as _;
272272
use win_bindings::*;
273273

274-
let mut pid = Some(-1 /* NtCurrentProcess */);
274+
struct NtHandle {
275+
handle: isize,
276+
}
277+
278+
impl Drop for NtHandle {
279+
fn drop(&mut self) {
280+
if self.handle != -1 {
281+
unsafe {
282+
nt_close(self.handle);
283+
}
284+
}
285+
}
286+
}
287+
288+
let mut handle = Some(NtHandle { handle: -1 });
275289

276290
unsafe {
277291
let reset = |fname: &mut [u16]| {
278292
let ustr = &mut *fname.as_mut_ptr().cast::<UnicodeString>();
279293
ustr.length = 0;
280294
ustr.maximum_length = MaxPath as _;
281-
ustr.buffer = fname
282-
.as_mut_ptr()
283-
.byte_offset(std::mem::size_of::<UnicodeString>() as _);
284295
};
285296

286297
// The API for this is extremely irritating, the struct and string buffer
287298
// need to be the same :/
288299
let mut file_name = [0u16; MaxPath as usize + std::mem::size_of::<UnicodeString>() / 2];
289300

290-
while let Some(ppid) = pid {
301+
while let Some(ph) = handle {
291302
let mut basic_info = std::mem::MaybeUninit::<ProcessBasicInformation>::uninit();
292303
let mut length = 0;
293304
if dbg!(nt_query_information_process(
294-
ppid,
305+
ph.handle,
295306
Processinfoclass::ProcessBasicInformation,
296307
basic_info.as_mut_ptr().cast(),
297308
std::mem::size_of::<ProcessBasicInformation>() as _,
298309
&mut length,
299310
)) != StatusSuccess
300311
{
301-
return false;
312+
break;
302313
}
303314

304315
if length != std::mem::size_of::<ProcessBasicInformation>() as u32 {
305-
return false;
316+
break;
306317
}
307318

308319
let basic_info = basic_info.assume_init();
309320
reset(&mut file_name);
310321

322+
let ppid = basic_info.inherited_from_unique_process_id as isize;
323+
324+
if ppid == 0 || ppid == -1 {
325+
break;
326+
}
327+
328+
let mut parent_handle = -1;
329+
let obj_attr = std::mem::zeroed();
330+
let client_id = ClientId {
331+
unique_process: ppid,
332+
unique_thread: 0,
333+
};
334+
if dbg!(nt_open_process(
335+
&mut parent_handle,
336+
ProcessAccessRights::ProcessQueryInformation,
337+
&obj_attr,
338+
&client_id
339+
)) != StatusSuccess
340+
{
341+
break;
342+
}
343+
344+
handle = Some(NtHandle {
345+
handle: parent_handle,
346+
});
347+
311348
if dbg!(nt_query_information_process(
312-
basic_info.inherited_from_unique_process_id as _,
349+
parent_handle,
313350
Processinfoclass::ProcessImageFileName,
314351
file_name.as_mut_ptr().cast(),
315352
(file_name.len() * 2) as _,
316353
&mut length,
317354
)) != StatusSuccess
318355
{
319-
return false;
356+
break;
320357
}
321358

322359
let ustr = &*file_name.as_ptr().cast::<UnicodeString>();
323-
let os = std::ffi::OsString::from_wide(
324-
&file_name[std::mem::size_of::<UnicodeString>() * 2
325-
..std::mem::size_of::<UnicodeString>() * 2 + ustr.length as usize],
326-
);
360+
let os = std::ffi::OsString::from_wide(std::slice::from_raw_parts(
361+
ustr.buffer,
362+
(ustr.length >> 1) as usize,
363+
));
327364

328365
let path = os.to_string_lossy();
329-
dbg!(&path);
366+
eprintln!("{path}");
330367
let p = std::path::Path::new(path.as_ref());
331368
if p.file_stem() == Some(std::ffi::OsStr::new("pwsh")) {
332369
return true;
333370
}
334-
335-
pid = (basic_info.inherited_from_unique_process_id != 0)
336-
.then_some(basic_info.inherited_from_unique_process_id as isize);
337371
}
338372

339373
false

src/win_bindings.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
non_camel_case_types,
66
clippy::upper_case_acronyms
77
)]
8-
#[link(name = "kernel32", kind = "raw-dylib")]
9-
extern "system" {
10-
#[link_name = "OpenProcess"]
11-
pub fn open_process(
12-
desired_access: ProcessAccessRights::Enum,
13-
inherit_handle: Bool,
14-
process_id: u32,
15-
) -> Handle;
16-
}
178
#[link(name = "ntdll", kind = "raw-dylib")]
189
extern "system" {
10+
#[link_name = "NtClose"]
11+
pub fn nt_close(handle: Handle) -> Ntstatus;
12+
#[link_name = "NtOpenProcess"]
13+
pub fn nt_open_process(
14+
process_handle: *mut Handle,
15+
desired_access: u32,
16+
object_attributes: *const ObjectAttributes,
17+
client_id: *const ClientId,
18+
) -> Ntstatus;
1919
#[link_name = "NtQueryInformationProcess"]
2020
pub fn nt_query_information_process(
2121
process_handle: Handle,
@@ -26,7 +26,11 @@ extern "system" {
2626
) -> Ntstatus;
2727
}
2828
pub const MaxPath: u32 = 260;
29-
pub type Bool = i32;
29+
#[repr(C)]
30+
pub struct ClientId {
31+
pub unique_process: Handle,
32+
pub unique_thread: Handle,
33+
}
3034
pub type Handle = isize;
3135
#[repr(C)]
3236
pub struct ListEntry {
@@ -36,6 +40,15 @@ pub struct ListEntry {
3640
pub type Ntstatus = i32;
3741
pub const StatusSuccess: Ntstatus = 0;
3842
#[repr(C)]
43+
pub struct ObjectAttributes {
44+
pub length: u32,
45+
pub root_directory: Handle,
46+
pub object_name: *mut UnicodeString,
47+
pub attributes: u32,
48+
pub security_descriptor: *mut ::core::ffi::c_void,
49+
pub security_quality_of_service: *mut ::core::ffi::c_void,
50+
}
51+
#[repr(C)]
3952
pub struct Peb {
4053
pub reserved1: [u8; 2],
4154
pub being_debugged: u8,

0 commit comments

Comments
 (0)