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",
"poggers",
"rust-embed",
"thiserror",
"windows",
]

View File

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

View File

@ -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::<u32, (&'static str, i32)>::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::<u8>()) 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::<isize, open_and_parse_t>(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();
}

View File

@ -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<u8> 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)
}

View File

@ -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<String> {
pub fn check_gd_ver(exe: &Path) -> anyhow::Result<String> {
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())
}