📦 Game Update 13963 (2)

This commit is contained in:
a2x
2023-10-20 15:23:43 +10:00
parent 415cbf1ec5
commit 74a0693f53
100 changed files with 845 additions and 630 deletions

View File

@@ -1,7 +1,9 @@
use std::ffi::c_char;
use std::mem::offset_of;
use crate::error::Result;
use anyhow::Result;
use crate::mem::Address;
use crate::remote::Process;
#[derive(Debug)]
@@ -13,21 +15,29 @@ pub struct InterfaceReg {
}
impl InterfaceReg {
pub fn ptr(&self, process: &Process) -> Result<usize> {
/// Returns the pointer of the interface.
pub fn pointer(&self, process: &Process) -> Result<Address> {
process
.read_memory::<usize>(self as *const _ as usize + offset_of!(InterfaceReg, create_fn))
.read_memory::<usize>(
(self as *const _ as usize + offset_of!(InterfaceReg, create_fn)).into(),
)
.map(|ptr| ptr.into())
}
/// Returns the name of the interface.
/// E.g. "Source2Client002"
pub fn name(&self, process: &Process) -> Result<String> {
let name_ptr = process
.read_memory::<usize>(self as *const _ as usize + offset_of!(InterfaceReg, name))?;
let name_ptr = process.read_memory::<usize>(
(self as *const _ as usize + offset_of!(InterfaceReg, name)).into(),
)?;
process.read_string(name_ptr)
process.read_string(name_ptr.into())
}
/// Returns the next interface in the list.
pub fn next(&self, process: &Process) -> Result<*mut InterfaceReg> {
process.read_memory::<*mut InterfaceReg>(
self as *const _ as usize + offset_of!(InterfaceReg, next),
(self as *const _ as usize + offset_of!(InterfaceReg, next)).into(),
)
}
}

View File

@@ -1,31 +1,40 @@
use crate::error::Result;
use anyhow::Result;
use crate::mem::Address;
use crate::remote::Process;
use super::SchemaType;
/// Represents a class field in a schema.
pub struct SchemaClassFieldData<'a> {
process: &'a Process,
address: usize,
/// Address of the class field.
addr: Address,
}
impl<'a> SchemaClassFieldData<'a> {
pub fn new(process: &'a Process, address: usize) -> Self {
Self { process, address }
pub fn new(process: &'a Process, addr: Address) -> Self {
Self { process, addr }
}
/// Returns the name of the field.
pub fn name(&self) -> Result<String> {
let name_ptr = self.process.read_memory::<usize>(self.address)?;
let name_ptr = self.process.read_memory::<usize>(self.addr + 0x0)?;
self.process.read_string(name_ptr)
self.process.read_string_len(name_ptr.into(), 64)
}
/// Returns the type of the field.
pub fn r#type(&self) -> Result<SchemaType> {
let type_ptr = self.process.read_memory::<usize>(self.address + 0x8)?;
Ok(SchemaType::new(self.process, type_ptr))
Ok(SchemaType::new(
self.process,
self.process.read_memory::<usize>(self.addr + 0x8)?.into(),
))
}
/// Returns the offset of the field.
pub fn offset(&self) -> Result<u16> {
self.process.read_memory::<u16>(self.address + 0x10)
self.process.read_memory::<u16>(self.addr + 0x10)
}
}

View File

@@ -1,59 +1,76 @@
use crate::error::Result;
use anyhow::Result;
use crate::mem::Address;
use crate::remote::Process;
use super::SchemaClassFieldData;
/// Represents a class in a schema.
pub struct SchemaClassInfo<'a> {
process: &'a Process,
address: usize,
/// Address of the class.
addr: Address,
/// Name of the class.
class_name: String,
}
impl<'a> SchemaClassInfo<'a> {
pub fn new(process: &'a Process, address: usize, class_name: &str) -> Self {
pub fn new(process: &'a Process, addr: Address, class_name: &str) -> Self {
Self {
process,
address,
addr,
class_name: class_name.to_string(),
}
}
/// Returns the name of the class.
#[inline]
pub fn name(&self) -> &str {
&self.class_name
}
/// Returns a list of fields in the class.
pub fn fields(&self) -> Result<Vec<SchemaClassFieldData>> {
let addr = self.process.read_memory::<usize>(self.addr + 0x28)?;
if addr == 0 {
return Ok(Vec::new());
}
let count = self.fields_count()?;
let base_address = self.process.read_memory::<usize>(self.address + 0x28)?;
let fields: Vec<SchemaClassFieldData> = (0..count as usize)
.map(|i| base_address + (i * 0x20))
.filter_map(|address| {
if address != 0 {
Some(SchemaClassFieldData::new(self.process, address))
} else {
None
}
})
let fields: Vec<SchemaClassFieldData> = (addr..addr + count as usize * 0x20)
.step_by(0x20)
.map(|address| SchemaClassFieldData::new(self.process, address.into()))
.collect();
Ok(fields)
}
/// Returns the number of fields in the class.
pub fn fields_count(&self) -> Result<u16> {
self.process.read_memory::<u16>(self.address + 0x1C)
self.process.read_memory::<u16>(self.addr + 0x1C)
}
/// Returns the parent class.
pub fn parent(&self) -> Result<Option<SchemaClassInfo>> {
let addr = self.process.read_memory::<u64>(self.address + 0x38)?;
let addr = self.process.read_memory::<usize>(self.addr + 0x38)?;
if addr == 0 {
return Ok(None);
}
let parent = self.process.read_memory::<u64>(addr as usize + 0x8)?;
let name = self.process.read_string(self.process.read_memory::<usize>(parent as usize + 0x8)?)?;
Ok(Some(SchemaClassInfo::new(self.process, parent as usize, &name)))
let parent = self.process.read_memory::<usize>((addr + 0x8).into())?;
let name_ptr = self.process.read_memory::<usize>((parent + 0x8).into())?;
let name = self.process.read_string(name_ptr.into())?;
Ok(Some(SchemaClassInfo::new(
self.process,
parent.into(),
&name,
)))
}
}

View File

@@ -1,42 +1,53 @@
use std::mem;
use crate::error::Result;
use anyhow::{bail, Result};
use crate::mem::Address;
use crate::remote::Process;
use super::SchemaSystemTypeScope;
/// Represents the schema system.
pub struct SchemaSystem<'a> {
process: &'a Process,
address: usize,
/// Address of the schema system.
addr: Address,
}
impl<'a> SchemaSystem<'a> {
pub fn new(process: &'a Process) -> Result<Self> {
let mut address = process.find_pattern(
let mut addr = process.find_pattern(
"schemasystem.dll",
"48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 83 EC 28"
)?;
address = process.resolve_rip(address, None, None)?;
addr = process.resolve_rip(addr, None, None)?;
Ok(Self { process, address })
Ok(Self { process, addr })
}
/// Returns a list of type scopes.
pub fn type_scopes(&self) -> Result<Vec<SchemaSystemTypeScope>> {
let size = self.process.read_memory::<u32>(self.address + 0x190)?;
let data = self.process.read_memory::<usize>(self.address + 0x198)?;
let size = self.process.read_memory::<u32>(self.addr + 0x190)?;
if size == 0 {
bail!("Type scopes size is 0");
}
let data = self.process.read_memory::<usize>(self.addr + 0x198)?;
let mut addresses: Vec<usize> = vec![0; size as usize];
self.process.read_memory_raw(
data,
data.into(),
addresses.as_mut_ptr() as *mut _,
addresses.len() * mem::size_of::<usize>(),
)?;
let type_scopes: Vec<SchemaSystemTypeScope> = addresses
.iter()
.map(|&address| SchemaSystemTypeScope::new(self.process, address))
.map(|&addr| SchemaSystemTypeScope::new(self.process, addr.into()))
.collect();
Ok(type_scopes)

View File

@@ -1,42 +1,49 @@
use crate::error::Result;
use anyhow::Result;
use crate::mem::Address;
use crate::remote::Process;
use super::{SchemaClassInfo, SchemaTypeDeclaredClass, UtlTsHash};
/// Represents a schema system type scope.
pub struct SchemaSystemTypeScope<'a> {
process: &'a Process,
address: usize,
/// Address of the schema system type scope.
addr: Address,
}
impl<'a> SchemaSystemTypeScope<'a> {
pub fn new(process: &'a Process, address: usize) -> Self {
Self { process, address }
pub fn new(process: &'a Process, addr: Address) -> Self {
Self { process, addr }
}
/// Returns a list of classes in the type scope.
pub fn classes(&self) -> Result<Vec<SchemaClassInfo>> {
let classes = self
let declared_classes = self
.process
.read_memory::<UtlTsHash<*mut SchemaTypeDeclaredClass>>(self.address + 0x588)?;
.read_memory::<UtlTsHash<*mut SchemaTypeDeclaredClass>>(self.addr + 0x588)?;
let classes: Vec<SchemaClassInfo> = classes
let classes: Vec<SchemaClassInfo> = declared_classes
.elements(self.process)?
.iter()
.filter_map(|&address| {
let address = address as usize;
.filter_map(|&addr| {
let addr = Address::from(addr as usize);
let declared_class = SchemaTypeDeclaredClass::new(self.process, address);
let declared_class = SchemaTypeDeclaredClass::new(self.process, addr);
declared_class
.name()
.ok()
.map(|name| SchemaClassInfo::new(self.process, address, &name))
.map(|name| SchemaClassInfo::new(self.process, addr, &name))
})
.collect();
Ok(classes)
}
/// Returns the name of the module that the type scope belongs to.
pub fn module_name(&self) -> Result<String> {
self.process.read_string(self.address + 0x8)
self.process.read_string_len(self.addr + 0x8, 256)
}
}

View File

@@ -1,12 +1,15 @@
use std::collections::HashMap;
use anyhow::Result;
use lazy_static::lazy_static;
use regex::Regex;
use crate::error::Result;
use crate::mem::Address;
use crate::remote::Process;
/// Map of type names to their C equivalents.
const TYPE_MAP: &[(&'static str, &'static str)] = &[
("uint8", "uint8_t"),
("uint16", "uint16_t"),
@@ -32,22 +35,26 @@ lazy_static! {
};
}
/// Represents a schema type.
pub struct SchemaType<'a> {
process: &'a Process,
address: usize,
/// Address of the schema type.
addr: Address,
}
impl<'a> SchemaType<'a> {
pub fn new(process: &'a Process, address: usize) -> Self {
Self { process, address }
pub fn new(process: &'a Process, addr: Address) -> Self {
Self { process, addr }
}
/// Returns the name of the type.
pub fn name(&self) -> Result<String> {
let name_ptr = self.process.read_memory::<usize>(self.address + 0x8)?;
let name_ptr = self.process.read_memory::<usize>(self.addr + 0x8)?;
let name = self
.process
.read_string(name_ptr)?
.read_string(name_ptr.into())?
.replace(" ", "")
.to_string();

View File

@@ -1,19 +1,25 @@
use crate::error::Result;
use anyhow::Result;
use crate::mem::Address;
use crate::remote::Process;
/// Represents a schema type declared class.
pub struct SchemaTypeDeclaredClass<'a> {
process: &'a Process,
address: usize,
/// Address of the schema type declared class.
addr: Address,
}
impl<'a> SchemaTypeDeclaredClass<'a> {
pub fn new(process: &'a Process, address: usize) -> Self {
Self { process, address }
pub fn new(process: &'a Process, addr: Address) -> Self {
Self { process, addr }
}
/// Returns the name of the class.
pub fn name(&self) -> Result<String> {
let name_ptr = self.process.read_memory::<usize>(self.address + 0x8)?;
let name_ptr = self.process.read_memory::<usize>(self.addr + 0x8)?;
self.process.read_string(name_ptr)
self.process.read_string_len(name_ptr.into(), 64)
}
}

View File

@@ -1,8 +1,10 @@
use anyhow::Result;
use std::mem::offset_of;
use crate::error::Result;
use crate::remote::Process;
/// Represents a hash bucket.
#[derive(Debug)]
#[repr(C)]
pub struct HashFixedDataInternal<T, K> {
@@ -14,11 +16,12 @@ pub struct HashFixedDataInternal<T, K> {
impl<T, K> HashFixedDataInternal<T, K> {
pub fn next(&self, process: &Process) -> Result<*mut HashFixedDataInternal<T, K>> {
process.read_memory::<*mut HashFixedDataInternal<T, K>>(
(self as *const _ as usize) + offset_of!(HashFixedDataInternal<T, K>, next),
(self as *const _ as usize + offset_of!(HashFixedDataInternal<T, K>, next)).into(),
)
}
}
/// Represents a hash bucket.
#[derive(Debug)]
#[repr(C)]
pub struct HashBucketDataInternal<T, K> {
@@ -30,11 +33,12 @@ pub struct HashBucketDataInternal<T, K> {
impl<T, K> HashBucketDataInternal<T, K> {
pub fn next(&self, process: &Process) -> Result<*mut HashFixedDataInternal<T, K>> {
process.read_memory::<*mut HashFixedDataInternal<T, K>>(
(self as *const _ as usize) + offset_of!(HashBucketDataInternal<T, K>, next),
(self as *const _ as usize + offset_of!(HashBucketDataInternal<T, K>, next)).into(),
)
}
}
/// Represents a hash table.
#[derive(Debug)]
#[repr(C)]
pub struct HashAllocatedData<T, K> {
@@ -45,11 +49,12 @@ pub struct HashAllocatedData<T, K> {
impl<T, K> HashAllocatedData<T, K> {
pub fn list(&self, process: &Process) -> Result<[HashFixedDataInternal<T, K>; 128]> {
process.read_memory::<[HashFixedDataInternal<T, K>; 128]>(
(self as *const _ as usize) + offset_of!(HashAllocatedData<T, K>, list),
(self as *const _ as usize + offset_of!(HashAllocatedData<T, K>, list)).into(),
)
}
}
/// Represents a hash table.
#[derive(Debug)]
#[repr(C)]
pub struct HashUnallocatedData<T, K> {
@@ -63,23 +68,24 @@ pub struct HashUnallocatedData<T, K> {
impl<T, K> HashUnallocatedData<T, K> {
pub fn next(&self, process: &Process) -> Result<*mut HashUnallocatedData<T, K>> {
process.read_memory::<*mut HashUnallocatedData<T, K>>(
self as *const _ as usize + offset_of!(HashUnallocatedData<T, K>, next),
(self as *const _ as usize + offset_of!(HashUnallocatedData<T, K>, next)).into(),
)
}
pub fn ui_key(&self, process: &Process) -> Result<K> {
process.read_memory::<K>(
(self as *const _ as usize) + offset_of!(HashUnallocatedData<T, K>, ui_key),
(self as *const _ as usize + offset_of!(HashUnallocatedData<T, K>, ui_key)).into(),
)
}
pub fn block_list(&self, process: &Process) -> Result<[HashBucketDataInternal<T, K>; 256]> {
process.read_memory::<[HashBucketDataInternal<T, K>; 256]>(
(self as *const _ as usize) + offset_of!(HashUnallocatedData<T, K>, block_list),
(self as *const _ as usize + offset_of!(HashUnallocatedData<T, K>, block_list)).into(),
)
}
}
/// Represents a hash bucket.
#[derive(Debug)]
#[repr(C)]
pub struct HashBucket<T, K> {
@@ -100,17 +106,20 @@ pub struct UtlMemoryPool {
}
impl UtlMemoryPool {
/// Returns the number of blocks per blob.
#[inline]
pub fn block_size(&self) -> i32 {
self.blocks_per_blob
}
/// Returns the number of blocks allocated.
#[inline]
pub fn count(&self) -> i32 {
self.block_allocated_size
}
}
/// Represents a thread-safe hash table.
#[derive(Debug)]
#[repr(C)]
pub struct UtlTsHash<T, K = u64> {
@@ -122,16 +131,19 @@ impl<T, K> UtlTsHash<T, K>
where
T: Copy,
{
/// Returns the number of blocks per blob.
#[inline]
pub fn block_size(&self) -> i32 {
self.entry_memory.block_size()
}
/// Returns the number of blocks allocated.
#[inline]
pub fn count(&self) -> i32 {
self.entry_memory.count()
}
/// Returns a list of elements in the hash table.
pub fn elements(&self, process: &Process) -> Result<Vec<T>> {
let min_size = (self.block_size() as usize).min(self.count() as usize);