Grab addresses of globals.

This commit is contained in:
IQuant 2024-11-12 00:08:53 +03:00
parent f47a91150e
commit f1a0bbf07f
4 changed files with 90 additions and 1 deletions

16
ewext/Cargo.lock generated
View file

@ -43,6 +43,7 @@ name = "ewext"
version = "0.1.0"
dependencies = [
"backtrace",
"iced-x86",
"libloading",
]
@ -52,6 +53,21 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "iced-x86"
version = "1.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c447cff8c7f384a7d4f741cfcff32f75f3ad02b406432e8d6c878d56b1edf6b"
dependencies = [
"lazy_static",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.162"

View file

@ -14,3 +14,4 @@ strip = true
[dependencies]
libloading = "0.8.5"
backtrace = "0.3.74"
iced-x86 = "1.21.0"

27
ewext/src/addr_grabber.rs Normal file
View file

@ -0,0 +1,27 @@
use std::{os::raw::c_void, ptr};
use iced_x86::{Decoder, DecoderOptions, Mnemonic};
pub(crate) unsafe fn grab_addr_from_instruction(
func: *const c_void,
offset: isize,
expected_mnemonic: Mnemonic,
) -> *mut c_void {
let instruction_addr = func.wrapping_offset(offset);
// We don't really have an idea of how many bytes the instruction takes, so just take *enough* bytes for most cases.
let instruction_bytes = ptr::read_unaligned(instruction_addr.cast::<[u8; 16]>());
let mut decoder = Decoder::with_ip(
32,
&instruction_bytes,
instruction_addr as u64,
DecoderOptions::NONE,
);
let instruction = decoder.decode();
if instruction.mnemonic() != expected_mnemonic {
println!("Encountered unexpected mnemonic: {}", instruction);
}
assert_eq!(instruction.mnemonic(), expected_mnemonic);
instruction.memory_displacement32() as *mut c_void
}

View file

@ -4,13 +4,16 @@ use std::{
sync::LazyLock,
};
use lua_bindings::{lua_State, Lua51};
use iced_x86::Mnemonic;
use lua_bindings::{lua_State, Lua51, LUA_GLOBALSINDEX};
use noita::{NoitaPixelRun, ParticleWorldState};
mod lua_bindings;
mod noita;
mod addr_grabber;
static LUA: LazyLock<Lua51> = LazyLock::new(|| unsafe {
let lib = libloading::Library::new("./lua51.dll").expect("library to exist");
Lua51::from_library(lib).expect("library to be lua")
@ -20,9 +23,15 @@ thread_local! {
static STATE: LazyCell<RefCell<ExtState>> = LazyCell::new(|| ExtState::default().into());
}
struct GrabbedGlobals {
game_global: *const c_void,
world_state_entity: *const c_void,
}
#[derive(Default)]
struct ExtState {
particle_world_state: Option<ParticleWorldState>,
globals: Option<GrabbedGlobals>,
}
// const EWEXT: [(&'static str, Function); 1] = [("testfn", None)];
@ -61,6 +70,40 @@ unsafe extern "C" fn encode_area(lua: *mut lua_State) -> c_int {
1
}
unsafe fn grab_addrs(lua: *mut lua_State) {
LUA.lua_getfield(lua, LUA_GLOBALSINDEX, c"GameGetWorldStateEntity".as_ptr());
let base = LUA.lua_tocfunction(lua, -1).unwrap() as *const c_void;
let world_state_entity =
addr_grabber::grab_addr_from_instruction(base, 0x007aa7ce - 0x007aa540, Mnemonic::Mov);
println!(
"World state entity addr: 0x{:x}",
world_state_entity as usize
);
// Pop the last element.
LUA.lua_settop(lua, -2);
LUA.lua_getfield(lua, LUA_GLOBALSINDEX, c"GameGetFrameNum".as_ptr());
let base = LUA.lua_tocfunction(lua, -1).unwrap() as *const c_void;
let load_game_global =
addr_grabber::grab_addr_from_instruction(base, 0x007bf3c9 - 0x007bf140, Mnemonic::Call); // CALL load_game_global
println!("Load game global addr: 0x{:x}", load_game_global as usize);
let game_global = addr_grabber::grab_addr_from_instruction(
load_game_global,
0x00439c17 - 0x00439bb0,
Mnemonic::Mov,
);
println!("Game global addr: 0x{:x}", game_global as usize);
// Pop the last element.
LUA.lua_settop(lua, -2);
STATE.with(|state| {
state.borrow_mut().globals = Some(GrabbedGlobals {
game_global,
world_state_entity,
});
});
}
/// # Safety
///
/// Only gets called by lua when loading a module.
@ -68,6 +111,8 @@ unsafe extern "C" fn encode_area(lua: *mut lua_State) -> c_int {
pub unsafe extern "C" fn luaopen_ewext0(lua: *mut lua_State) -> c_int {
println!("Initializing ewext");
unsafe {
grab_addrs(lua);
LUA.lua_createtable(lua, 0, 0);
LUA.lua_pushcclosure(lua, Some(init_particle_world_state), 0);