some work on older versions

This commit is contained in:
pozm 2024-02-12 10:09:16 +00:00
parent c8606ec99b
commit 1569ca2dae
No known key found for this signature in database
GPG Key ID: 5AB655AFC8AAA822
5 changed files with 110 additions and 39 deletions

1
Cargo.lock generated
View File

@ -267,6 +267,7 @@ dependencies = [
"dll-syringe", "dll-syringe",
"poggers", "poggers",
"rust-embed", "rust-embed",
"thiserror",
"windows", "windows",
] ]

View File

@ -24,6 +24,7 @@ rust-embed = { version = "*", features = [
"interpolate-folder-path", "interpolate-folder-path",
] } ] }
anyhow = "*" anyhow = "*"
thiserror = "*"
windows = { features = [ windows = { features = [
"Win32_Foundation", "Win32_Foundation",
"Win32_System", "Win32_System",

View File

@ -14,37 +14,62 @@ static_detour! {
pub static OpenAndParse: unsafe extern "fastcall" fn(*const i32, *const i32, *const u8, bool) -> (); pub static OpenAndParse: unsafe extern "fastcall" fn(*const i32, *const i32, *const u8, bool) -> ();
} }
#[cfg_attr(debug_assertions, poggers_derive::create_entry)] const SIGS: [&str; 2] = [
#[cfg_attr(not(debug_assertions), poggers_derive::create_entry(no_console))] // call into open_and_parse
pub fn main() { "E8 ? ? ? ? 85 C0 0F 84 ? ? ? ? 49 8B 8C 24 ? ? ? ?", // 4.x (4.2.1)
let mut sigs = HashMap::<u32, (&'static str, i32)>::new(); "E8 ? ? ? ? 8B D8 85 C0 0F 84 ? ? ? ? 49 8B 04 24", // 3.x
sigs.insert( ];
1, #[repr(u8)]
("E8 ? ? ? ? 85 C0 0F 84 ? ? ? ? 49 8B 8C 24 ? ? ? ?", -0x3c), #[derive(Debug)]
); enum SigErrors {
let sock = UdpSocket::bind("127.0.0.1:29849").unwrap(); NotFound,
sock.connect("127.0.0.1:28713").expect("uanble to connect"); }
fn find_sig_addr(sig_type: usize) -> Result<*const c_void, SigErrors> {
let proc = Process::this_process(); let proc = Process::this_process();
let modd = proc.get_base_module().unwrap(); let modd = proc.get_base_module().unwrap();
println!("sending data, waiting for sig ver"); let sig = SIGS
let buf = [1; 1]; .get(sig_type as usize)
sock.send(&buf).ok(); .ok_or_else(|| SigErrors::NotFound)?;
let addr = modd
let mut sig_type = [0; 4]; .scan(sig)
sock.recv(&mut sig_type).unwrap(); .map_err(|_| SigErrors::NotFound)?
let int_sig = u32::from_ne_bytes(sig_type); .ok_or_else(|| SigErrors::NotFound)? as isize;
let sig = sigs.get(&int_sig).expect("sig type match not compatible"); println!("sig found: {:x} ", addr);
let addr = modd.scan(sig.0).unwrap().unwrap() as isize;
let ptr_to_fn = (addr as usize + size_of::<u8>()) as *const u8; let ptr_to_fn = (addr as usize + size_of::<u8>()) as *const u8;
let mut addr_offset = [0; 4]; let mut addr_offset = [0; 4];
unsafe { std::ptr::copy(ptr_to_fn, addr_offset.as_mut_ptr(), 4) }; unsafe { std::ptr::copy(ptr_to_fn, addr_offset.as_mut_ptr(), 4) };
let by = i32::from_ne_bytes(addr_offset); let by = i32::from_ne_bytes(addr_offset);
let fn_ptr = (addr + by as isize + 5) as *const c_void; 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(); let sock2 = sock.try_clone().unwrap();
unsafe { unsafe {
let open_and_parse = std::mem::transmute::<isize, open_and_parse_t>(fn_ptr as isize); let open_and_parse = std::mem::transmute::<isize, open_and_parse_t>(fn_ptr as isize);
@ -61,5 +86,5 @@ pub fn main() {
opp.enable().expect("failed to enable detour"); opp.enable().expect("failed to enable detour");
println!("detour enabled {}", opp.is_enabled()); println!("detour enabled {}", opp.is_enabled());
} }
sock.send(&[]).ok(); sock.send(&(400195u32.to_ne_bytes())).ok();
} }

View File

@ -10,6 +10,7 @@ use std::{
use dll_syringe::{process::OwnedProcess, Syringe}; use dll_syringe::{process::OwnedProcess, Syringe};
use poggers::{exports::HANDLE, structures::process::Process, traits::Mem}; use poggers::{exports::HANDLE, structures::process::Process, traits::Mem};
use rust_embed::RustEmbed; use rust_embed::RustEmbed;
use thiserror::Error;
use windows::{ use windows::{
core::{PCSTR, PSTR}, core::{PCSTR, PSTR},
Win32::{ Win32::{
@ -28,6 +29,22 @@ use windows::{
Win32::System::{Diagnostics::Debug::IMAGE_NT_HEADERS64, Threading::ResumeThread}, 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<u8> for SigErrors {
fn from(value: u8) -> Self {
match value {
0 => Self::NotFound,
default => Self::NotFound,
}
}
}
fn create_pstr(c_str: &CStr) -> PSTR { fn create_pstr(c_str: &CStr) -> PSTR {
PSTR::from_raw(c_str.as_ptr() as *mut u8) 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); ResumeThread(proc_info.hThread);
// wait until trapped... and inject // wait until trapped... and inject
let sock = UdpSocket::bind("127.0.0.1:28713").expect("failed to bind socket"); 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 target = OwnedProcess::from_pid(proc.get_pid()).unwrap();
let syrnge = Syringe::for_process(target); let syrnge = Syringe::for_process(target);
let dll_loc = if cfg!(debug_assertions) { 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(); file.write_all(&gdke_inj_dll.data).unwrap();
loc.to_str().map(|x| x.to_string()).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); println!("injecting dll ({})", dll_loc);
syrnge.inject(dll_loc).unwrap(); syrnge.inject(dll_loc)?;
println!("waiting until udp is ok "); println!("waiting until udp is ok ");
let (_, addr) = sock.recv_from(&mut [0]).unwrap(); let (_, addr) = sock.recv_from(&mut [0]).unwrap();
sock.send_to(&1_u32.to_ne_bytes(), addr).unwrap(); println!("using sig id {sig_id}");
sock.recv(&mut [])?; 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. // we're done. let's kill the process.
println!("done, running code",); 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)?; proc.write(code_entry as usize, &entry_insts)?;
println!("waiting for call."); println!("waiting for call.");
let mut key = [0; 32]; let mut key = [0; 32];
sock.recv(&mut key)?; sock.recv(&mut key)?;
if key.len() == 1 {
eprintln!("recieved err");
return Err(SigErrors::from(key[0]).into());
}
println!("recieved key, term"); println!("recieved key, term");
Ok(key) Ok(key)
} }

View File

@ -1,20 +1,18 @@
use std::{ use std::{
io::{BufRead, Cursor}, io::{BufRead, Cursor, Read},
path::Path, path::Path,
process::{Command, Stdio}, process::{Command, Stdio},
}; };
fn check_gd_ver(exe: &Path) -> anyhow::Result<String> { pub fn check_gd_ver(exe: &Path) -> anyhow::Result<String> {
assert!(exe.exists()); assert!(exe.exists());
let stdo = Command::new(exe) let stdo = Command::new(exe)
.arg("-V") .arg("--version")
.arg("-s") // .stderr(Stdio::null())
.arg("random-no-way-a-game-has-this-btw")
.stdout(Stdio::null())
.output()?; .output()?;
let bufr = Cursor::new(stdo.stdout); let mut bufr = Cursor::new(stdo.stdout);
Ok(bufr let mut out = String::new();
.lines() bufr.read_to_string(&mut out)
.next() .map_err(|_| anyhow::anyhow!("unable to read version"))?;
.ok_or(anyhow::anyhow!("unable to read version"))??) Ok(out.trim().to_string())
} }