mirror of https://github.com/pozm/gdke.git
some work on older versions
This commit is contained in:
parent
c8606ec99b
commit
1569ca2dae
|
@ -267,6 +267,7 @@ dependencies = [
|
||||||
"dll-syringe",
|
"dll-syringe",
|
||||||
"poggers",
|
"poggers",
|
||||||
"rust-embed",
|
"rust-embed",
|
||||||
|
"thiserror",
|
||||||
"windows",
|
"windows",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
56
src/lib.rs
56
src/lib.rs
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue