feat: make tool independant of hardcoded sigs

This commit is contained in:
char-ptr 2024-08-19 09:14:07 +01:00
parent f33c8dbf43
commit 51580183a7
3 changed files with 36 additions and 33 deletions

View File

@ -18,25 +18,16 @@ type open_and_parse_t = unsafe extern "fastcall" fn(*const i32, *const i32, *con
static_detour! { 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) -> ();
} }
const SIGS: [&str; 5] = [
// call into open_and_parse
"E8 ? ? ? ? 85 C0 0F 84 ? ? ? ? 49 8B 8C 24 ? ? ? ?", // 4.x (4.2.1)
"E8 ? ? ? ? 89 44 24 50 83 7C 24 ? ? 0F 84 ? ? ? ? 48 8B 44 24 ?", // 3.5.1
"E8 ? ? ? ? 89 44 24 50 83 7C 24 ? ? 0F 84 ? ? ? ? 48 8B 44 24 ?", // 3.5.1
"E8 ? ? ? ? 8B D8 85 C0 0F 84 ? ? ? ? 49 8B 04 24", // 3.x
"E8 ? ? ? ? 48 8B 4C 24 ? 89 C5 48 85 C9", // 4.3
];
#[repr(u8)] #[repr(u8)]
#[derive(Debug)] #[derive(Debug)]
enum SigErrors { enum SigErrors {
NotFound, NotFound,
} }
fn find_sig_addr(sig_type: usize) -> Result<*const c_void, SigErrors> { fn find_sig_addr(sig: &str) -> 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();
let sig = SIGS.get(sig_type).ok_or(SigErrors::NotFound)?; // let sig = SIGS.get(sig_type).ok_or(SigErrors::NotFound)?;
let addr = modd let addr = modd
.scan(sig) .scan(sig)
.map_err(|_| SigErrors::NotFound)? .map_err(|_| SigErrors::NotFound)?
@ -63,11 +54,15 @@ pub fn main() {
let buf = []; let buf = [];
sock.send(&buf).ok(); sock.send(&buf).ok();
let mut sig_type = [0; 4]; let mut capy = vec![0u8; 256];
sock.recv(&mut sig_type).unwrap(); sock.recv(&mut capy).unwrap();
println!("received sig type: {:?}", sig_type); let mut sizer = [0; 8];
let int_sig = u32::from_ne_bytes(sig_type); sizer.copy_from_slice(&capy[..8]);
let fn_ptr = find_sig_addr(int_sig as usize); let sizer_usize = usize::from_ne_bytes(sizer);
let content = &capy[std::mem::size_of::<usize>()..];
let string_content = String::from_utf8_lossy(content);
let str_content = &string_content[..sizer_usize];
let fn_ptr = find_sig_addr(str_content);
let fn_ptr = match fn_ptr { let fn_ptr = match fn_ptr {
Ok(x) => x, Ok(x) => x,
Err(err) => { Err(err) => {

View File

@ -1,7 +1,7 @@
pub mod versioning; pub mod versioning;
use std::{ use std::{
ffi::{c_void, CStr, CString}, ffi::{c_void, CStr, CString},
io::Write, io::{Read, Write},
mem::{size_of, transmute}, mem::{size_of, transmute},
net::UdpSocket, net::UdpSocket,
path::Path, path::Path,
@ -61,7 +61,7 @@ impl Drop for ProcKiller {
} }
} }
} }
pub unsafe fn spawn_and_inject(proc: &str) -> anyhow::Result<[u8; 32]> { pub unsafe fn spawn_and_inject(proc: &str, sig: &str) -> anyhow::Result<[u8; 32]> {
let pth = Path::new(proc); let pth = Path::new(proc);
if !pth.is_file() { if !pth.is_file() {
panic!("file does not exist"); panic!("file does not exist");
@ -142,17 +142,17 @@ pub unsafe fn spawn_and_inject(proc: &str) -> anyhow::Result<[u8; 32]> {
}; };
let game_ver = check_gd_ver(pth)?; let game_ver = check_gd_ver(pth)?;
println!("gamever = {game_ver}"); println!("gamever = {game_ver}");
let sig_id = match &game_ver // let sig_id = match &game_ver
.chars().collect::<Vec<char>>()[..] // .chars().collect::<Vec<char>>()[..]
// .next() // // .next()
// .ok_or(anyhow::anyhow!("unable to check gd version"))? // // .ok_or(anyhow::anyhow!("unable to check gd version"))?
{ // {
['4','.','3',..] => 4u32, // ['4','.','3',..] => 4u32,
['4',..] => 0u32, // ['4',..] => 0u32,
['3','.','6',..] => 2u32, // ['3','.','6',..] => 2u32,
['3',..] => 1u32, // ['3',..] => 1u32,
_ => return Err(anyhow::anyhow!("invalid godot version")), // _ => return Err(anyhow::anyhow!("invalid godot version")),
}; // };
println!("injecting dll ({})", dll_loc); println!("injecting dll ({})", dll_loc);
syrnge.inject(dll_loc)?; syrnge.inject(dll_loc)?;
@ -160,8 +160,13 @@ pub unsafe fn spawn_and_inject(proc: &str) -> anyhow::Result<[u8; 32]> {
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();
println!("using sig id {sig_id}"); // println!("using sig id {sig_id}");
sock.send_to(&sig_id.to_ne_bytes(), addr).unwrap(); let mut meow_sigger = sig.to_owned();
let meow_sigger = meow_sigger.as_bytes_mut();
let mut meower = Vec::from(meow_sigger.len().to_ne_bytes());
meower.append(&mut Vec::from(meow_sigger));
sock.send_to(meower.as_slice(), addr).unwrap();
let mut error = [0u8; 4]; let mut error = [0u8; 4];
sock.recv(&mut error)?; sock.recv(&mut error)?;
println!("errors -> {error:?}"); println!("errors -> {error:?}");

View File

@ -2,8 +2,11 @@ use gdke::spawn_and_inject;
fn main() { fn main() {
unsafe { unsafe {
let key = let key = spawn_and_inject(
spawn_and_inject(&std::env::args().nth(1).unwrap()).expect("failed to resolve key"); &std::env::args().nth(1).unwrap(),
&std::env::args().nth(2).unwrap(),
)
.expect("failed to resolve key");
print!("key: "); print!("key: ");
for val in key { for val in key {
print!("{:0>2x}", val); print!("{:0>2x}", val);