From 3973aeabba1528ceab7f45a077cd92e4aa1f8aa9 Mon Sep 17 00:00:00 2001 From: Anton Bulakh Date: Tue, 15 Oct 2024 06:06:06 +0300 Subject: [PATCH] memory: manually read and try to hide from windows changed: - More sneakily attach to the process to read memory so that hopefully Windows Defender stops being annoying --- .gitignore | 2 + .vscode/settings.json | 3 + CHANGELOG.md | 3 + Cargo.lock | 147 +++++++++++++-------- Cargo.toml | 18 ++- flake.nix | 5 +- src/memory/process_ref.rs | 257 +++++++++++++++++++++++++++++++------ src/noita/discovery.rs | 2 +- src/noita/mod.rs | 2 +- src/tools/process_panel.rs | 2 +- 10 files changed, 346 insertions(+), 95 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 489f7b5..033fc86 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /.direnv /result /result-[1-3] + +/.vscode diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7cb8dcd --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "rust-analyzer.cargo.target": "x86_64-pc-windows-gnu" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d2c2b20..0697ea2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ Dates in this file are in [Holocene Calendar] because it is amazing, logical, an ### Fixed - Fixed the version link (it had an extra v in the tag name) in the settings panel +### Changed + - More sneakily attach to the process to read memory so that hopefully Windows Defender stops being annoying + ## [v0.2.0] 12024-10-14 ### Added diff --git a/Cargo.lock b/Cargo.lock index a07b124..d1bc36c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1328,6 +1328,15 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "export-resolver" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e13a4a0b212c24a8a5b3e8fd495bb323088ad52bd9e0a233b9e7d826f1acfa5" +dependencies = [ + "windows 0.56.0", +] + [[package]] name = "eyre" version = "0.6.12" @@ -1849,9 +1858,9 @@ checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -1969,9 +1978,9 @@ dependencies = [ [[package]] name = "image" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" +checksum = "d97eb9a8e0cd5b76afea91d7eecd5cf8338cd44ced04256cf1f800474b227c52" dependencies = [ "bytemuck", "byteorder-lite", @@ -2132,13 +2141,13 @@ dependencies = [ [[package]] name = "libredox" -version = "0.0.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.7", ] [[package]] @@ -2169,15 +2178,6 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -[[package]] -name = "mach" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", -] - [[package]] name = "malloc_buf" version = "0.0.6" @@ -2388,17 +2388,19 @@ dependencies = [ "eframe", "egui-modal", "egui_extras", + "export-resolver", "fastrand", "futures", "iced-x86", "lazy-regex", + "libc", "memchr", "obws", "rayon", - "read-process-memory", "reqwest", "serde", "smart-default", + "str_crypter", "strfmt", "strum", "sysinfo", @@ -2407,8 +2409,9 @@ dependencies = [ "tracing", "tracing-appender", "tracing-subscriber", + "windows 0.58.0", "winresource", - "zerocopy 0.8.5", + "zerocopy 0.8.6", ] [[package]] @@ -2720,9 +2723,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -2752,9 +2755,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -2764,9 +2767,9 @@ dependencies = [ [[package]] name = "orbclient" -version = "0.3.47" +version = "0.3.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" +checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" dependencies = [ "libredox", ] @@ -2958,18 +2961,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" [[package]] name = "quick-xml" @@ -3055,18 +3058,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "read-process-memory" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8497683b2f0b6887786f1928c118f26ecc6bb3d78bbb6ed23e8e7ba110af3bb0" -dependencies = [ - "libc", - "log", - "mach", - "winapi", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -3238,9 +3229,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.14" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "once_cell", "rustls-pki-types", @@ -3260,9 +3251,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" @@ -3277,9 +3268,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -3610,6 +3601,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "str_crypter" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62c2065bd22d7902b59eb04ec3f82a0de8f20f4b0e908d49745946ab8e2c58b3" + [[package]] name = "strfmt" version = "0.2.4" @@ -4141,9 +4138,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "serde", ] @@ -4555,6 +4552,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +dependencies = [ + "windows-core 0.56.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.57.0" @@ -4584,6 +4591,18 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement 0.56.0", + "windows-interface 0.56.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.57.0" @@ -4609,6 +4628,17 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "windows-implement" version = "0.57.0" @@ -4631,6 +4661,17 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "windows-interface" version = "0.57.0" @@ -5151,11 +5192,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6129d25825e874589a0e529175dd060c13dab4f3d960c6a0b711e5535b598bb2" +checksum = "a65238aacd5fb83fb03fcaf94823e71643e937000ec03c46e7da94234b10c870" dependencies = [ - "zerocopy-derive 0.8.5", + "zerocopy-derive 0.8.6", ] [[package]] @@ -5171,9 +5212,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d917df3784b4e2f5deb708d14623b2c02833890e1aa7a5dd1088998e8e9402b1" +checksum = "3ca22c4ad176b37bd81a565f66635bde3d654fe6832730c3e52e1018ae1655ee" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 38ca292..de3217b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,10 @@ version = "0.2.0" license = "MIT" edition = "2021" +[features] +default = ["sneaky"] +sneaky = ["dep:export-resolver", "dep:str_crypter"] + [dependencies] anyhow = "1" color-eyre = "0.6" @@ -23,7 +27,6 @@ lazy-regex = "3" memchr = "2" obws = { version = "0.13", features = ["events"] } rayon = "1" -read-process-memory = "0.1" reqwest = { version = "0.12", features = ["json"] } serde = { version = "1", features = ["derive"] } smart-default = "0.7" @@ -40,5 +43,18 @@ zerocopy = { version = "0.8", default-features = false, features = [ "derive", ] } +[target.'cfg(unix)'.dependencies] +libc = "0.2" + +[target.'cfg(windows)'.dependencies] +export-resolver = { version = "1", optional = true } +str_crypter = { version = "1", optional = true } +windows = { version = "0.58", default-features = false, features = [ + "Wdk_Foundation", + "Win32_System_Threading", + "Win32_System_Diagnostics_Debug", + "Win32_System_WindowsProgramming", +] } + [build-dependencies] winresource = { version = "0.1", default-features = false } diff --git a/flake.nix b/flake.nix index a3ff427..42dcea5 100644 --- a/flake.nix +++ b/flake.nix @@ -176,7 +176,10 @@ inputsFrom = builtins.attrValues packages; nativeBuildInputs = with pkgs; [ - pkg-config + # # inputsFrom does not seem to include the depsBuildBuild thing + # pkgsCross.mingwW64.stdenv.cc + # pkgsCross.mingwW64.windows.pthreads + rust-analyzer-nightly pkgs.fenix.default.rustfmt-preview cargo-nextest diff --git a/src/memory/process_ref.rs b/src/memory/process_ref.rs index 18aff3f..a753359 100644 --- a/src/memory/process_ref.rs +++ b/src/memory/process_ref.rs @@ -1,65 +1,248 @@ -use std::{ - fmt::{self, Debug}, - io, -}; - -use read_process_memory::{CopyAddress, Pid, ProcessHandle}; +use std::io; use zerocopy::{FromBytes, IntoBytes}; -/// A a bit of a nicer wrapper over `read_process_memory` crate API. -/// Could reimplement it/swap it here. -#[derive(Clone)] -pub struct ProcessRef { - /// pid is used for debug and equality - pid: u32, - /// On Linux handle is just the pid again, but on win it's a HANDLE - /// The win handle is in an Arc so it's cheap to clone around - handle: ProcessHandle, -} +#[derive(Debug, Clone)] +pub struct ProcessRef(platform::Handle); impl PartialEq for ProcessRef { fn eq(&self, other: &Self) -> bool { - self.pid == other.pid + self.0.pid() == other.0.pid() } } impl Eq for ProcessRef {} -impl Debug for ProcessRef { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("ProcessRef").field(&self.pid).finish() - } -} - impl ProcessRef { pub fn connect(pid: u32) -> io::Result { - Ok(Self { - pid, - handle: (pid as Pid).try_into()?, - }) + platform::Handle::connect(pid).map(Self) } pub fn read_multiple(&self, addr: u32, len: u32) -> io::Result> { - let mut v = T::new_vec_zeroed(len as usize).unwrap(); - self.handle.copy_address(addr as usize, v.as_mut_bytes())?; + let mut v = T::new_vec_zeroed(len as usize).expect("alloc error"); + self.0.read_memory(addr as usize, v.as_mut_bytes())?; Ok(v) } pub fn read(&self, addr: u32) -> io::Result { let mut t = T::new_zeroed(); - self.handle.copy_address(addr as usize, t.as_mut_bytes())?; + self.0.read_memory(addr as usize, t.as_mut_bytes())?; Ok(t) } } -impl TryFrom for ProcessRef { - type Error = io::Error; +/// A shortcut for the zerocopy traits and sanity bounds +pub trait Pod: IntoBytes + FromBytes + Sized + 'static {} + +impl Pod for T {} + +#[cfg(target_os = "linux")] +mod platform { + use libc::{c_void, iovec, process_vm_readv}; + use std::io; + + #[derive(Debug, Clone)] + pub struct Handle { + pid: libc::pid_t, + } + + impl Handle { + pub fn connect(pid: u32) -> io::Result { + Ok(Self { + pid: pid as libc::pid_t, + }) + } + + pub fn pid(&self) -> u32 { + self.pid as _ + } - fn try_from(pid: u32) -> Result { - Self::connect(pid) + pub fn read_memory(&self, addr: usize, buf: &mut [u8]) -> io::Result<()> { + if buf.is_empty() { + return Ok(()); + } + let local_iov = iovec { + iov_base: buf.as_mut_ptr() as *mut c_void, + iov_len: buf.len(), + }; + let remote_iov = iovec { + iov_base: addr as *mut c_void, + iov_len: buf.len(), + }; + let result = unsafe { process_vm_readv(self.pid, &local_iov, 1, &remote_iov, 1, 0) }; + if result == -1 { + Err(io::Error::last_os_error()) + } else { + Ok(()) + } + } } } -/// A shortcut for the zerocopy traits and sanity bounds -pub trait Pod: IntoBytes + FromBytes + Sized + 'static {} +#[cfg(windows)] +mod platform { + use std::{io, rc::Rc}; + use windows::{ + core::Owned, + Win32::{ + Foundation::HANDLE, + System::{Diagnostics::Debug::ReadProcessMemory, Threading::PROCESS_VM_READ}, + }, + }; -impl Pod for T {} + #[derive(Debug, Clone)] + pub struct Handle { + pid: u32, + handle: Rc>, + } + + fn better_message(e: windows::core::Error) -> io::Error { + io::Error::new(io::ErrorKind::Other, e.to_string()) + } + + impl Handle { + pub fn connect(pid: u32) -> io::Result { + Ok(Self { + pid, + handle: Rc::new(open_process(PROCESS_VM_READ, pid).map_err(better_message)?), + }) + } + + pub fn pid(&self) -> u32 { + self.pid + } + + pub fn read_memory(&self, addr: usize, buf: &mut [u8]) -> io::Result<()> { + if buf.is_empty() { + return Ok(()); + } + + unsafe { + ReadProcessMemory( + **self.handle, + addr as _, + buf.as_mut_ptr() as _, + buf.len(), + None, + ) + } + .map_err(better_message)?; + Ok(()) + } + } + + #[cfg(not(feature = "sneaky"))] + fn open_process( + access: windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS, + pid: u32, + ) -> windows::core::Result> { + use windows::Win32::System::Threading::OpenProcess; + + unsafe { OpenProcess(access, false, pid).map(|h| Owned::new(h)) } + } + + #[cfg(feature = "sneaky")] + use direct_syscall::open_process; + + /// A quick and dirty copypaste of the "Hells Gate" technique + /// (https://fluxsec.red/rust-edr-evasion-hells-gate) + /// to hopefully stop Windows Defender from being annoying + /// by *LITERALLY* employing detection evasion rofl + /// + /// The idea is that we don't link to NtOpenProcess (which is sus) and + /// instead do a complicated pointer dance to figure out it's address + /// without linking to other sus things (thankfully that one is handled by + /// `export_resolver` crate from the author of the blog post) + /// and then from that we get the syscall number (which are not static) for + /// the NtOpenProcess syscall, which we proceed to manually invoke with + /// (more) inline assembly. + #[cfg(feature = "sneaky")] + mod direct_syscall { + use std::arch::asm; + use str_crypter::{decrypt_string, sc}; + use windows::{ + core::Owned, + Wdk::Foundation::OBJECT_ATTRIBUTES, + Win32::{ + Foundation::{HANDLE, NTSTATUS}, + System::Threading::PROCESS_ACCESS_RIGHTS, + System::WindowsProgramming::CLIENT_ID, + }, + }; + + pub fn open_process( + access: PROCESS_ACCESS_RIGHTS, + pid: u32, + ) -> windows::core::Result> { + let mut process_handle = HANDLE::default(); + + let mut object_attributes = OBJECT_ATTRIBUTES { + Length: size_of::() as u32, + ..Default::default() // zeroed + }; + let mut client_id = CLIENT_ID { + UniqueProcess: HANDLE(pid as _), + ..Default::default() // zeroed + }; + + let status = unsafe { + nt_open_process( + &mut process_handle, // out + access.0, + &mut object_attributes, + &mut client_id, // contains the pid + ) + }; + if status.is_ok() { + Ok(unsafe { Owned::new(process_handle) }) + } else { + Err(windows::core::Error::from_win32()) + } + } + + static SSN: std::sync::LazyLock> = std::sync::LazyLock::new(|| { + let mut exports = export_resolver::ExportList::new(); + + // don't put sus strings in .rdata + let op = sc!("NtOpenProcess", 42).unwrap(); + let dll = sc!("ntdll.dll", 42).unwrap(); + + // ok the api is a bit weird, the guy is 1000x smarter than me, + // but is a rust newbie probably with a bunch of c/c++ preconceptions or something + exports.add(&dll, &op).ok()?; + // never fails if above succeeded + let f = exports.get_function_address(&op).unwrap(); + + let ssn: u16 = unsafe { *(f as *const u8).add(4).cast() }; + + if ssn != 38 { + tracing::warn!(ssn, "Weird SSN, on last Windows versions it should be 38"); + } + + Some(ssn as _) + }); + + unsafe fn nt_open_process( + process_handle: *mut HANDLE, + desired_access: u32, + object_attributes: *mut OBJECT_ATTRIBUTES, + client_id: *mut CLIENT_ID, + ) -> NTSTATUS { + let ssn = SSN.expect("SSN not found"); + + let status: i32; + asm!( + "mov r10, rcx", + "mov eax, {0:e}", // move the syscall number into EAX + "syscall", + in(reg) ssn, // input: Syscall number goes into EAX + // Order: https://web.archive.org/web/20170222171451/https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx + in("rcx") process_handle, // passed to RCX (first argument) + in("rdx") desired_access, // passed to RDX (second argument) + in("r8") object_attributes, // passed to R8 (third argument) + in("r9") client_id, // passed to R9 (fourth argument) + lateout("rax") status, // output: returned value of the syscall is placed in RAX + options(nostack), // dont modify the stack pointer + ); + NTSTATUS(status) + } + } +} diff --git a/src/noita/discovery.rs b/src/noita/discovery.rs index 0c6c62b..af4df8f 100644 --- a/src/noita/discovery.rs +++ b/src/noita/discovery.rs @@ -259,7 +259,7 @@ fn test() -> anyhow::Result<()> { .find(|p| p.thread_kind().is_none()) .context("Noita process not found")?; - let proc = noita_pid.pid().as_u32().try_into()?; + let proc = ProcessRef::connect(noita_pid.pid().as_u32())?; let header = PeHeader::read(&proc)?; if header.timestamp() != 0x66ba59d6 { bail!("Timestamp mismatch: 0x{:x}", header.timestamp()); diff --git a/src/noita/mod.rs b/src/noita/mod.rs index 0967f58..95648a3 100644 --- a/src/noita/mod.rs +++ b/src/noita/mod.rs @@ -338,7 +338,7 @@ fn test() -> anyhow::Result<()> { .find(|p| p.thread_kind().is_none()) .context("Noita process not found")?; - let proc = noita_pid.pid().as_u32().try_into()?; + let proc = ProcessRef::connect(noita_pid.pid().as_u32())?; let noita = Noita::new(proc, NoitaGlobals::debug()); println!("{:#?}", noita.read_stats()?); diff --git a/src/tools/process_panel.rs b/src/tools/process_panel.rs index 041846b..2f198a0 100644 --- a/src/tools/process_panel.rs +++ b/src/tools/process_panel.rs @@ -51,7 +51,7 @@ impl NoitaData { exe_name: Option, state: &AppState, ) -> Result { - let proc = pid.as_u32().try_into()?; + let proc = ProcessRef::connect(pid.as_u32())?; let header = PeHeader::read(&proc)?; if state.settings.check_export_name {