From 320e7b14a5a29838ed2cb909cadfd7c448c6849b Mon Sep 17 00:00:00 2001 From: navewindre Date: Sun, 14 Jul 2024 08:43:58 +0200 Subject: schemas --- src/cs2/cs2.cpp | 21 +++++ src/cs2/cs2.h | 22 ++---- src/cs2/hack.cpp | 2 - src/cs2/iface.h | 7 +- src/cs2/schema.h | 166 +++++++++++++++++++++++++++++++++++++++ src/cs2/sdk.h | 88 +++++++++++++++++++++ src/heavens-gate.vcxproj | 3 + src/heavens-gate.vcxproj.filters | 9 +++ src/source.cpp | 2 - 9 files changed, 300 insertions(+), 20 deletions(-) create mode 100644 src/cs2/cs2.cpp create mode 100644 src/cs2/sdk.h diff --git a/src/cs2/cs2.cpp b/src/cs2/cs2.cpp new file mode 100644 index 0000000..224e445 --- /dev/null +++ b/src/cs2/cs2.cpp @@ -0,0 +1,21 @@ +#include "cs2.h" +#include "schema.h" + +bool CS2::open() { + if( !PROCESS64::open() ) + return false; + + mod.client = get_module64( "client.dll"fnv ); + mod.engine = get_module64( "engine.dll"fnv ); + mod.schema = get_module64( "schemasystem.dll"fnv ); + + // todo: handle this using loader + iface.client = get_iface( "Source2Client0" ); + iface.engine = get_iface( "Source2EngineToClient0" ); + iface.schema = get_iface( "SchemaSystem_0" ); + + // also handle w/ loader + netvars = schema_get_all( this ); + + return true; +} diff --git a/src/cs2/cs2.h b/src/cs2/cs2.h index 58eba14..db136b9 100644 --- a/src/cs2/cs2.h +++ b/src/cs2/cs2.h @@ -1,25 +1,14 @@ #pragma once - #include "../process64.h" +#include "iface.h" + +#include "sdk.h" class CS2 : public PROCESS64 { public: CS2() : PROCESS64( "cs2.exe" ) {}; - bool open() { - if( !PROCESS64::open() ) - return false; - - mod.client = get_module64( "client.dll"fnv ); - mod.engine = get_module64( "engine.dll"fnv ); - mod.schema = get_module64( "schemasystem.dll"fnv ); - - // todo: handle this using loader - iface.client = get_iface( "Source2Client0" ); - iface.engine = get_iface( "Source2EngineToClient0" ); - - return true; - } + bool open(); IFACE_ENTRY get_iface( const char* name ) { VECTOR entries = iface_get_all( this ); @@ -42,5 +31,8 @@ public: struct { IFACE_ENTRY client; IFACE_ENTRY engine; + IFACE_ENTRY schema; } iface; + + VECTOR netvars; }; \ No newline at end of file diff --git a/src/cs2/hack.cpp b/src/cs2/hack.cpp index b5f0242..ef4008d 100644 --- a/src/cs2/hack.cpp +++ b/src/cs2/hack.cpp @@ -12,8 +12,6 @@ PROCESS64* hack_init() { return nullptr; } - VECTOR entries = iface_get_all( p ); - return p; } diff --git a/src/cs2/iface.h b/src/cs2/iface.h index 6c3b34b..be2137d 100644 --- a/src/cs2/iface.h +++ b/src/cs2/iface.h @@ -42,6 +42,8 @@ inline U64 iface_get_address( PROCESS64* p, U64 create_fn ) { U32 off = *(U32*)&data[3]; U64 addr = create_fn + off + 7; + + return addr; } inline U64 iface_get_createinterface( PROCESS64* p, U64 module ) { @@ -77,7 +79,10 @@ inline VECTOR iface_dump_module( PROCESS64* p, MODULE_ENTRY module for( ;; ) { IFACE_ENTRY entry; p->read( reg.name, entry.name.data, 64 ); - entry.ptr = reg.create_fn; + + U64 ptr = iface_get_address( p, reg.create_fn ); + + entry.ptr = ptr; entry.module = module.base; entry.module_name = module.name; entries.push_back( entry ); diff --git a/src/cs2/schema.h b/src/cs2/schema.h index e69de29..f99683d 100644 --- a/src/cs2/schema.h +++ b/src/cs2/schema.h @@ -0,0 +1,166 @@ +#pragma once +#include "cs2.h" +#include "../util.h" +#include "sdk.h" + + +inline CS2_SCHEMA_FIELD* schema_class_get_fields( CS2* p, CS2_SCHEMA_CLASS* schclass ) { + if( !schclass->fields || !schclass->num_fields ) + return 0; + + U32 c = schclass->num_fields; + CS2_SCHEMA_FIELD* fields = (CS2_SCHEMA_FIELD*)malloc( sizeof(CS2_SCHEMA_FIELD) * c ); + + p->read( schclass->fields, fields, sizeof(CS2_SCHEMA_FIELD) * c ); + + return fields; +} + +inline CS2_SCHEMA_CLASS* schema_scope_get_classes( CS2* p, CS2_SCHEMA_SCOPE* scope ) { + U32 c = scope->num_classes; + CS2_SCHEMA_ENTRY* entries = (CS2_SCHEMA_ENTRY*)malloc( sizeof(CS2_SCHEMA_ENTRY) * (c) ); + CS2_SCHEMA_CLASS* ret = (CS2_SCHEMA_CLASS*)malloc( sizeof(CS2_SCHEMA_CLASS) * (c) ); + + p->read( scope->declared_classes, entries, sizeof(CS2_SCHEMA_ENTRY) * (c) ); + + for( U32 i = 0; i < c; ++i ) { + CS2_SCHEMA_ENTRY* e = &entries[i]; + + CS2_SCHEMA_DECLARED_CLASS _class; + p->read( e->declared_class, &_class, sizeof( _class ) ); + p->read( _class.class_ptr, &ret[i], sizeof(CS2_SCHEMA_CLASS) ); + } + + free( entries ); + return ret; +} + +inline CS2_SCHEMA_SCOPE* schema_get_scopes( CS2* p, CS2_SCHEMA schema ) { + U32 c = (U32)schema.scope_size; + U64* ptrarr = (U64*)malloc( sizeof(U64) * c ); + CS2_SCHEMA_SCOPE* ret = (CS2_SCHEMA_SCOPE*)malloc( sizeof(CS2_SCHEMA_SCOPE) * c ); + + p->read( schema.scopes, ptrarr, sizeof(U64) * c ); + + for( U32 i = 0; i < c; ++i ) { + p->read( ptrarr[i], &ret[i], sizeof(CS2_SCHEMA_SCOPE) ); + } + + free( ptrarr ); + return ret; +} + +inline CS2_SCHEMA schema_read_iface( CS2* p, U64 schemasys ) { + CS2_SCHEMA ret; + + p->read( schemasys, &ret, sizeof(CS2_SCHEMA) ); + + return ret; +} + +// CAUTION: SLOW!!!! +static VECTOR schema_get_all( CS2* p ) { + VECTOR entries; + CS2_SCHEMA schema = schema_read_iface( p, p->iface.schema.ptr ); + CS2_SCHEMA_SCOPE* scopes = schema_get_scopes( p, schema ); + + for( U32 i = 0; i < schema.scope_size; ++i ) { + CS2_SCHEMA_SCOPE* scope = &scopes[i]; + + if( !scope->declared_classes ) + continue; + + CS2_SCHEMA_CLASS* classes = schema_scope_get_classes( p, scope ); + + for( U32 j = 0; j < scope->num_classes; ++j ) { + CS2_SCHEMA_CLASS* schclass = &classes[j]; + + STR<128> classname{}; + p->read( schclass->name, classname.data, 128 ); + + if( classname.data[0] == 0 || !strlen( classname ) ) + continue; + + if( !schclass->fields || !schclass->num_fields ) + continue; + + CS2_SCHEMA_FIELD* fields = schema_class_get_fields( p, schclass ); + + for( U32 k = 0; k < schclass->num_fields; ++k ) { + CS2_SCHEMA_FIELD* field = &fields[k]; + NETVAR_ENTRY entry{}; + + STR<256> buf; + p->read( field->name, buf.data, 256 ); + entry.prop = buf; + entry.clientclass = buf; + entry.scope = scope->name; + entries.push_back( entry ); + } + + free( fields ); + } + + free( classes ); + } + + free( scopes ); + return entries; +} + +static void schema_dump_to_file( CS2* p ) { + CS2_SCHEMA schema = schema_read_iface( p, p->iface.schema.ptr ); + + static STR<9999999> output; + memset( output, 0, sizeof(output.data) ); + + sprintf( output.data, "schema: %llx %llx\n", schema.scopes, schema.scope_size ); + + CS2_SCHEMA_SCOPE* scopes = schema_get_scopes( p, schema ); + + for( U32 i = 0; i < schema.scope_size; ++i ) { + CS2_SCHEMA_SCOPE* scope = &scopes[i]; + + sprintf( output.data, "%s --scope %s: %d classes [%llx]\n", output.data, scope->name, scope->num_classes, scope->declared_classes ); + + if( !scope->declared_classes ) + continue; + + CS2_SCHEMA_CLASS* classes = schema_scope_get_classes( p, scope ); + + for( U32 j = 0; j < scope->num_classes; ++j ) { + CS2_SCHEMA_CLASS* schclass = &classes[j]; + + STR<128> classname{}; + p->read( schclass->name, classname.data, 128 ); + + if( classname.data[0] == 0 || !strlen( classname ) ) + continue; + + sprintf( output.data, "%s ----class %s: %d fields\n", output.data, classname.data, schclass->num_fields ); + + if( !schclass->fields || !schclass->num_fields ) + continue; + + CS2_SCHEMA_FIELD* fields = schema_class_get_fields( p, schclass ); + + for( U32 k = 0; k < schclass->num_fields; ++k ) { + CS2_SCHEMA_FIELD* field = &fields[k]; + + STR<256> buf; + p->read( field->name, buf.data, 256 ); + sprintf( output.data, "%s ------field %s 0x%x\n", output.data, buf.data, field->offset ); + } + + free( fields ); + } + + free( classes ); + } + + FILE* f = fopen( "schema.txt", "w" ); + fwrite( output.data, 1, strlen(output.data), f ); + fclose( f ); + + free( scopes ); +} \ No newline at end of file diff --git a/src/cs2/sdk.h b/src/cs2/sdk.h new file mode 100644 index 0000000..0751f94 --- /dev/null +++ b/src/cs2/sdk.h @@ -0,0 +1,88 @@ +#pragma once +#include "../typedef.h" + +struct CS2_SCHEMA_FIELD { + U64 name; + U64 type; + U32 offset; + U32 size; + U64 metadata; +}; + +struct CS2_SCHEMA_CLASS { + U64 vft; + // const char* + U64 name; + // const char* + U64 module_name; + U32 size; + U16 num_fields; + +private: + U8 unk_01[2]; + +public: + U16 static_size; + U16 metadata_size; + +private: + U8 unk_02[4]; + +public: + // CS2_SCHEMA_FIELD + U64 fields; +}; + +struct CS2_SCHEMA_DECLARED_CLASS { + U64 vft; + // const char* + U64 name; + // const char* + U64 module_name; + // void* + U64 unk_ptr; + // CS2_SCHEMA_CLASS + U64 class_ptr; +}; + +struct CS2_SCHEMA_ENTRY { + U64 hash[2]; + // CS2_SCHEMA_DECLARED_CLASS + U64 declared_class; +}; + +struct CS2_SCHEMA_SCOPE { + U64 vft; + char name[256]; + +private: + U8 unk_01[0x338]; + +public: + // CS2_SCHEMA_ENTRY* + U64 declared_classes; + +private: + U8 unk_02[0xe]; + +public: + U16 num_classes; +}; + +struct CS2_SCHEMA { +private: + U8 unk_01[0x188]; +public: + U64 scope_size; + // CS2_SCHEMA_SCOPE[] + U64 scopes; +}; + +// fuck you, they will forever be netvars to me. +struct NETVAR_ENTRY { + STR<256> scope; + STR<256> clientclass; + STR<256> prop; + + I32 offset; +}; \ No newline at end of file diff --git a/src/heavens-gate.vcxproj b/src/heavens-gate.vcxproj index 23a1b96..0a41f0b 100644 --- a/src/heavens-gate.vcxproj +++ b/src/heavens-gate.vcxproj @@ -197,6 +197,7 @@ + @@ -209,6 +210,8 @@ + + diff --git a/src/heavens-gate.vcxproj.filters b/src/heavens-gate.vcxproj.filters index f6c97b7..643ec4f 100644 --- a/src/heavens-gate.vcxproj.filters +++ b/src/heavens-gate.vcxproj.filters @@ -17,6 +17,9 @@ Util + + Game + @@ -72,6 +75,12 @@ Game + + Game + + + Game + diff --git a/src/source.cpp b/src/source.cpp index dd08e9e..1ce0754 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -26,8 +26,6 @@ bool run() { } I32 __cdecl main() { - con_init(); - u_set_debug_privilege(); u_thread_create( &con_hook_handler ); u_thread_create( &con_handler ); -- cgit v1.2.3