From 1569ca2daee1b9b208f9b28f641244e0e9fe46c6 Mon Sep 17 00:00:00 2001 From: pozm <44528100+pozm@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:09:16 +0000 Subject: [PATCH] some work on older versions --- Cargo.lock | 1 + Cargo.toml | 1 + gdkeinj/src/lib.rs | 71 +++++++++++++++++++++++++++++++--------------- src/lib.rs | 56 ++++++++++++++++++++++++++++++++---- src/versioning.rs | 20 ++++++------- 5 files changed, 110 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 002c22a..910e80a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -267,6 +267,7 @@ dependencies = [ "dll-syringe", "poggers", "rust-embed", + "thiserror", "windows", ] diff --git a/Cargo.toml b/Cargo.toml index 5dd8ce6..ac226f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ rust-embed = { version = "*", features = [ "interpolate-folder-path", ] } anyhow = "*" +thiserror = "*" windows = { features = [ "Win32_Foundation", "Win32_System", diff --git a/gdkeinj/src/lib.rs b/gdkeinj/src/lib.rs index 4c195c8..e1534da 100644 --- a/gdkeinj/src/lib.rs +++ b/gdkeinj/src/lib.rs @@ -14,37 +14,62 @@ static_detour! { pub static OpenAndParse: unsafe extern "fastcall" fn(*const i32, *const i32, *const u8, bool) -> (); } -#[cfg_attr(debug_assertions, poggers_derive::create_entry)] -#[cfg_attr(not(debug_assertions), poggers_derive::create_entry(no_console))] -pub fn main() { - let mut sigs = HashMap::::new(); - sigs.insert( - 1, - ("E8 ? ? ? ? 85 C0 0F 84 ? ? ? ? 49 8B 8C 24 ? ? ? ?", -0x3c), - ); - let sock = UdpSocket::bind("127.0.0.1:29849").unwrap(); - sock.connect("127.0.0.1:28713").expect("uanble to connect"); - +const SIGS: [&str; 2] = [ + // call into open_and_parse + "E8 ? ? ? ? 85 C0 0F 84 ? ? ? ? 49 8B 8C 24 ? ? ? ?", // 4.x (4.2.1) + "E8 ? ? ? ? 8B D8 85 C0 0F 84 ? ? ? ? 49 8B 04 24", // 3.x +]; +#[repr(u8)] +#[derive(Debug)] +enum SigErrors { + NotFound, +} +fn find_sig_addr(sig_type: usize) -> Result<*const c_void, SigErrors> { let proc = Process::this_process(); let modd = proc.get_base_module().unwrap(); - println!("sending data, waiting for sig ver"); - let buf = [1; 1]; - sock.send(&buf).ok(); - - let mut sig_type = [0; 4]; - sock.recv(&mut sig_type).unwrap(); - let int_sig = u32::from_ne_bytes(sig_type); - let sig = sigs.get(&int_sig).expect("sig type match not compatible"); - let addr = modd.scan(sig.0).unwrap().unwrap() as isize; + let sig = SIGS + .get(sig_type as usize) + .ok_or_else(|| SigErrors::NotFound)?; + let addr = modd + .scan(sig) + .map_err(|_| SigErrors::NotFound)? + .ok_or_else(|| SigErrors::NotFound)? as isize; + println!("sig found: {:x} ", addr); let ptr_to_fn = (addr as usize + size_of::()) as *const u8; let mut addr_offset = [0; 4]; unsafe { std::ptr::copy(ptr_to_fn, addr_offset.as_mut_ptr(), 4) }; let by = i32::from_ne_bytes(addr_offset); let fn_ptr = (addr + by as isize + 5) as *const c_void; - println!("fnptr = {:x?}", fn_ptr); + println!("fnptr = {:x?} B = ${addr_offset:?}, ${by:?}", fn_ptr); + + Ok(fn_ptr) +} +#[cfg_attr(debug_assertions, poggers_derive::create_entry(no_free))] +#[cfg_attr(not(debug_assertions), poggers_derive::create_entry(no_console))] +pub fn main() { + let sock = UdpSocket::bind("127.0.0.1:29849").unwrap(); + sock.connect("127.0.0.1:28713").expect("uanble to connect"); + + println!("sending data, waiting for sig ver"); + let buf = []; + sock.send(&buf).ok(); + + let mut sig_type = [0; 4]; + sock.recv(&mut sig_type).unwrap(); + let int_sig = u32::from_ne_bytes(sig_type); + let fn_ptr = find_sig_addr(int_sig as usize); + let fn_ptr = match fn_ptr { + Ok(x) => x, + Err(err) => { + println!("err {err:?}"); + + std::thread::sleep(Duration::from_secs(100)); + sock.send(&[err as u8]).ok(); + return; + } + }; - println!("sig found: {:x} ", addr); let sock2 = sock.try_clone().unwrap(); unsafe { let open_and_parse = std::mem::transmute::(fn_ptr as isize); @@ -61,5 +86,5 @@ pub fn main() { opp.enable().expect("failed to enable detour"); println!("detour enabled {}", opp.is_enabled()); } - sock.send(&[]).ok(); + sock.send(&(400195u32.to_ne_bytes())).ok(); } diff --git a/src/lib.rs b/src/lib.rs index a8af0de..93a0659 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ use std::{ use dll_syringe::{process::OwnedProcess, Syringe}; use poggers::{exports::HANDLE, structures::process::Process, traits::Mem}; use rust_embed::RustEmbed; +use thiserror::Error; use windows::{ core::{PCSTR, PSTR}, Win32::{ @@ -28,6 +29,22 @@ use windows::{ Win32::System::{Diagnostics::Debug::IMAGE_NT_HEADERS64, Threading::ResumeThread}, }; +use crate::versioning::check_gd_ver; +#[repr(u8)] +#[derive(Error, Debug)] +enum SigErrors { + #[error("Signature not found")] + NotFound, +} +impl From for SigErrors { + fn from(value: u8) -> Self { + match value { + 0 => Self::NotFound, + default => Self::NotFound, + } + } +} + fn create_pstr(c_str: &CStr) -> PSTR { PSTR::from_raw(c_str.as_ptr() as *mut u8) } @@ -106,7 +123,7 @@ pub unsafe fn spawn_and_inject(proc: &str) -> anyhow::Result<[u8; 32]> { ResumeThread(proc_info.hThread); // wait until trapped... and inject let sock = UdpSocket::bind("127.0.0.1:28713").expect("failed to bind socket"); - { + let res: anyhow::Result<()> = { let target = OwnedProcess::from_pid(proc.get_pid()).unwrap(); let syrnge = Syringe::for_process(target); let dll_loc = if cfg!(debug_assertions) { @@ -123,21 +140,50 @@ pub unsafe fn spawn_and_inject(proc: &str) -> anyhow::Result<[u8; 32]> { file.write_all(&gdke_inj_dll.data).unwrap(); loc.to_str().map(|x| x.to_string()).unwrap() }; + let game_ver = check_gd_ver(pth)?; + println!("gamever = {game_ver}"); + let sig_id = match game_ver + .chars() + .next() + .ok_or(anyhow::anyhow!("unable to check gd version"))? + { + '4' => 0u32, + '3' => 1u32, + _ => return Err(anyhow::anyhow!("invalid godot version")), + }; + println!("injecting dll ({})", dll_loc); - syrnge.inject(dll_loc).unwrap(); + syrnge.inject(dll_loc)?; println!("waiting until udp is ok "); let (_, addr) = sock.recv_from(&mut [0]).unwrap(); - sock.send_to(&1_u32.to_ne_bytes(), addr).unwrap(); - sock.recv(&mut [])?; - } + println!("using sig id {sig_id}"); + sock.send_to(&sig_id.to_ne_bytes(), addr).unwrap(); + let mut error = [0u8; 4]; + sock.recv(&mut error)?; + println!("errors -> {error:?}"); + if error.is_empty() { + return Err(SigErrors::from(error[0]).into()); + } + Ok(()) + }; + res?; // we're done. let's kill the process. println!("done, running code",); + #[cfg(debug_assertions)] + { + println!("[debug] waiting for input"); + std::io::stdin().read_line(&mut String::new()); + } proc.write(code_entry as usize, &entry_insts)?; println!("waiting for call."); let mut key = [0; 32]; sock.recv(&mut key)?; + if key.len() == 1 { + eprintln!("recieved err"); + return Err(SigErrors::from(key[0]).into()); + } println!("recieved key, term"); Ok(key) } diff --git a/src/versioning.rs b/src/versioning.rs index a1df36a..94e5508 100644 --- a/src/versioning.rs +++ b/src/versioning.rs @@ -1,20 +1,18 @@ use std::{ - io::{BufRead, Cursor}, + io::{BufRead, Cursor, Read}, path::Path, process::{Command, Stdio}, }; -fn check_gd_ver(exe: &Path) -> anyhow::Result { +pub fn check_gd_ver(exe: &Path) -> anyhow::Result { assert!(exe.exists()); let stdo = Command::new(exe) - .arg("-V") - .arg("-s") - .arg("random-no-way-a-game-has-this-btw") - .stdout(Stdio::null()) + .arg("--version") + // .stderr(Stdio::null()) .output()?; - let bufr = Cursor::new(stdo.stdout); + let mut bufr = Cursor::new(stdo.stdout); - Ok(bufr - .lines() - .next() - .ok_or(anyhow::anyhow!("unable to read version"))??) + let mut out = String::new(); + bufr.read_to_string(&mut out) + .map_err(|_| anyhow::anyhow!("unable to read version"))?; + Ok(out.trim().to_string()) }