├── GetAndAssignInstanciatedMaterial.h ├── GetComponentsInChildren.h ├── Helper.h ├── README.md ├── dumper.lua └── material scanner ├── mat_scan ├── dumper.cpp ├── json.hpp ├── mat_scan.vcxproj ├── mat_scan.vcxproj.filters ├── mat_scan.vcxproj.user ├── usermode.cpp └── usermode.h └── material_scan.sln /GetAndAssignInstanciatedMaterial.h: -------------------------------------------------------------------------------- 1 | struct dynamic_array 2 | { 3 | std::uint64_t base; 4 | std::uint64_t mem_id; 5 | std::uint64_t sz; 6 | std::uint64_t cap; 7 | }; 8 | 9 | // Loop through player list to apply chams to players. 10 | for (auto entityLoop : entities) 11 | { 12 | auto skinnedMultiMesh = threads::Read(playerModel + offsets::playermodel::multi_mesh); // _multiMesh 13 | auto SkinnedRenderersList = threads::Read(skinnedMultiMesh + 0x78); // List k__BackingField; 14 | auto SkinnedList = threads::Read(SkinnedRenderersList + 0x10); 15 | int materialsCount = threads::Read(SkinnedRenderersList + 0x18); 16 | 17 | for (std::uint32_t idx{ 0 }; idx < materialsCount; idx++) { 18 | const auto renderEntry = threads::Read(SkinnedList + 0x20 + (idx * 0x8)); 19 | if (!renderEntry) 20 | continue; 21 | 22 | const auto untity_object = threads::Read(renderEntry + 0x10); 23 | if (!untity_object) 24 | continue; 25 | 26 | const auto mat_list = threads::Read(untity_object + 0x148); 27 | if (mat_list.sz < 1 || mat_list.sz > 5) 28 | continue; 29 | 30 | for (std::uint32_t idx{ 0 }; idx < mat_list.sz; idx++) { 31 | threads::Write(mat_list.base + (idx * 0x4), globals::chamMaterial); 32 | 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /GetComponentsInChildren.h: -------------------------------------------------------------------------------- 1 | void GetComponentsInChildren(uintptr_t GameObject, std::vector& renderers) { 2 | if (GameObject == 0) return; // Rebuilt by Cjweb. 3 | 4 | auto componentList = threads::Read(GameObject + 0x30); 5 | int componentSize = threads::Read(GameObject + 0x40); 6 | 7 | for (int j = 0; j < componentSize; ++j) { 8 | uintptr_t component = threads::Read(componentList + (0x10 * j + 0x8)); 9 | if (component == 0) continue; 10 | 11 | auto componentInst = threads::Read(component + 0x28); 12 | if (componentInst == 0) continue; 13 | auto componentObject = threads::Read(componentInst + 0x0); 14 | if (componentObject == 0) continue; 15 | auto componentName = threads::Read(componentObject + 0x10); 16 | if (componentName == 0) continue; 17 | std::string Name = threads::ReadASCII(componentName); 18 | 19 | log_to_file("[Component]: " + Name);// + " [" + std::to_string(componentSize) + "]"); 20 | 21 | if (Name == "SkinnedMeshRenderer") { 22 | renderers.push_back(component); 23 | } 24 | if (Name == "Transform") { 25 | uintptr_t childList = threads::Read(component + 0x70); 26 | int childSize = threads::Read(component + 0x80); 27 | 28 | for (int i = 0; i < childSize; ++i) { 29 | uint64_t childTransform = threads::Read(childList + (0x8 * i)); 30 | if (childTransform == 0) continue; 31 | 32 | auto childGameObject = threads::Read(childTransform + 0x30); 33 | if (childGameObject == 0) continue; 34 | auto childGameObjectName = threads::Read(childGameObject + 0x60); 35 | if (childGameObject == 0) continue; 36 | std::string childName = threads::ReadASCII(childGameObjectName); 37 | 38 | log_to_file("[Child]: " + childName + " [" + std::to_string(childSize) + "]"); 39 | 40 | GetComponentsInChildren(childGameObject, renderers); 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Helper.h: -------------------------------------------------------------------------------- 1 | // Misc code that would be used with GetComponentsInChildren showing how to properly access viewModel and apply chams. 2 | 3 | void ProcessSkinnedMeshRenderer(uintptr_t renderer) { 4 | if (renderer == 0) return; 5 | 6 | // Requires size be least 2 if its 1 it wont work. 7 | for (std::uint32_t idx{ 0 }; idx < 2; idx++) { 8 | const auto renderEntry = threads::Read(renderer + 0x20 + (idx * 0x8)); 9 | if (!renderEntry) 10 | continue; 11 | 12 | const auto untity_object = threads::Read(renderEntry + 0x10); 13 | if (!untity_object) 14 | continue; 15 | 16 | const auto mat_list = threads::Read(untity_object + 0x148); 17 | if (mat_list.sz < 1 || mat_list.sz > 5) 18 | continue; 19 | 20 | for (std::uint32_t idx{ 0 }; idx < mat_list.sz; idx++) { 21 | threads::Write(mat_list.base + (idx * 0x4), globals::handChamMaterial); 22 | } 23 | } 24 | } 25 | 26 | // Example of using GetComponentsInChildren 27 | 28 | std::vector renderers; 29 | std::vector materials; 30 | std::lock_guard lock(mtx); 31 | GetComponentsInChildren(globals::viewModel, renderers); 32 | for (auto renderer : renderers) { 33 | ProcessSkinnedMeshRenderer(renderer); 34 | } 35 | 36 | // Getting viewModel for hand/weapon chams. 37 | 38 | auto get_view_model() -> uint64_t { 39 | auto held = threads::Read(reinterpret_cast(this) + offsets::item::held_entity); // 0xB0 40 | auto viewModel = threads::Read(held + offsets::heldentity::viewModel); 41 | auto viewModelInstance = threads::Read(viewModel + 0x30); 42 | auto baseViewModel = threads::Read(viewModelInstance + 0x10); 43 | 44 | // Required if not false will cause chams to apply to world and break camera movement. 45 | threads::Write(viewModelInstance + 0x40, false); // useViewModelCamera 46 | return threads::Read(baseViewModel + 0x30); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Rust External - Full Chams for Players and All Gear Types 3 | 4 | This repository provides a more complete tutorial on how to do full chams for players, including all gear types. Using `GetComponentsInChildren`, you can also apply chams to hands, weapons, and entities. Here is a brief tutorial on how to dump materials and use this feature. Note that the provided code can be further optimized, which will be up to you. 5 | 6 | ## Getting Material Addresses 7 | 8 | 1. **Start Rust without EAC:** 9 | - Open Steam. 10 | - Run `RustClient.exe`. 11 | - Host a server from your computer and connect to it. EAC will not be enabled in this setup, allowing you to use Cheat Engine safely. 12 | 13 | 2. **Using Cheat Engine:** 14 | - Once in the server, select `RustClient.exe` as the application for Cheat Engine. 15 | - Check "Hex" and type `DEADBEEFDEADBEEF` into the value field. 16 | - Set the value type to 8 bytes as shown in the image below: 17 | 18 | ![Searching DEADBEEFDEADBEEF](https://i.gyazo.com/9511221d994a25f27c58a5cea83f7b32.png) 19 | 20 | - You should find around 5000 addresses. Add every address you found to the address table by clicking the first one, scrolling to the bottom, holding shift, and clicking the last one to select them all. Then click the red arrow to add them to the table as shown in the image below: 21 | 22 | ![Adding All Addresses to Address Table](https://i.gyazo.com/d193b661833e521bb4adfded8e4f3fb4.png) 23 | 24 | - In the Cheat Engine navigation bar, click "Table" and then "Show cheat table lua script". Enter the provided Lua script, but first, ensure you edit the script to change the directory where it will save the `json.txt` file. This script will dump all addresses into `json.txt` as shown in the image below: 25 | 26 | ![Executing the Lua Script to Dump Addresses to json.txt](https://i.gyazo.com/561dcb1e6926906a2edebe7c3359c4f0.png) 27 | 28 | 3. **Building and Running the Material Scanner:** 29 | - Close Cheat Engine. 30 | - Build the material scanner source. Once built, place the executable file in the same directory as your `json.txt`. 31 | - Run the executable. You should get a file called `material_output.txt`, which will contain the names and IDs of available materials. 32 | - Note that some materials may cause your game to crash; this process involves trial and error. 33 | 34 | ## Credits 35 | 36 | - **Cjweb:** GetComponentsInChildren / Helper functions / dumper.lua script 37 | - **DarkEether:** GetAndAssignInstanciatedMaterial / Material scanner 38 | 39 | ## Preview Images 40 | 41 | ![Chams](https://i.gyazo.com/6c2321fcbe2d8826b016964957c0acc8.jpg) 42 | ![Chams through wall](https://i.gyazo.com/868eafa9c68b757fd9c496c7d465f90a.jpg) 43 | -------------------------------------------------------------------------------- /dumper.lua: -------------------------------------------------------------------------------- 1 | local jsonFile = io.open("C:\\Users\\YOURNAME\\json.txt", "w") -- Open a file to write JSON 2 | 3 | if jsonFile then 4 | local list = getAddressList() -- Get the list of addresses from Cheat Engine 5 | jsonFile:write('{"CheatTable":{"CheatEntries":{"CheatEntry":[') -- Start of JSON structure 6 | 7 | for i = 0, list.Count-1 do 8 | local addressItem = list[i] -- Get the address item at index i 9 | local address = tonumber(addressItem.Address, 16) -- Convert the address to a number, assuming it's in hexadecimal 10 | if address then 11 | -- Format the address as JSON and write to file, add commas between entries 12 | jsonFile:write(string.format('{"Address":"%X"}', address)) 13 | if i < list.Count - 1 then 14 | jsonFile:write(',') 15 | end 16 | else 17 | print("Error: Unable to convert address at index " .. i .. " to a number.") 18 | end 19 | end 20 | 21 | jsonFile:write(']}}}') -- Close the JSON structure 22 | jsonFile:close() -- Close the file 23 | print("Addresses have been saved in JSON format.") -- Confirmation message 24 | else 25 | print("Failed to open file for writing. - Made by Cjweb") -- Error message in case file opening fails 26 | end 27 | -------------------------------------------------------------------------------- /material scanner/mat_scan/dumper.cpp: -------------------------------------------------------------------------------- 1 | #include "usermode.h" 2 | #include "json.hpp" 3 | #include 4 | 5 | using nlohmann::json; 6 | 7 | int main( ) { 8 | mem::memory::setup( ); 9 | auto game_assembly = mem::memory::get_module( L"GameAssembly.dll" ); 10 | std::ifstream input( "json.txt" ); 11 | json swag; 12 | input >> swag; 13 | input.close( ); 14 | auto sneed = swag[ "CheatTable" ][ "CheatEntries" ][ "CheatEntry" ]; 15 | std::ofstream output( "material_output.txt" ); 16 | for ( auto& entry : sneed ) { 17 | std::string addr_s = entry[ "Address" ]; 18 | unsigned long long value; 19 | std::istringstream iss( addr_s ); 20 | iss >> std::hex >> value; 21 | value -= 0x88; 22 | char _name[ 255 ]; 23 | auto _addy = mem::memory::read( value + 0x30 ); 24 | mem::memory::read( _addy, _name, 255 ); 25 | _name[ 254 ] = 0; 26 | std::string name( _name ); 27 | auto key = mem::memory::read( value + 0x8 ); 28 | output << "material name" << name << "material address" << key << "\n"; 29 | } 30 | output.close( ); 31 | } 32 | -------------------------------------------------------------------------------- /material scanner/mat_scan/json.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LabX1/rust-external-chams/17a7c38ee53d15075d0cb0b708aa6ad72ff853eb/material scanner/mat_scan/json.hpp -------------------------------------------------------------------------------- /material scanner/mat_scan/mat_scan.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {9f36b7e0-412b-4d2a-a543-1fac59c093a7} 25 | matscan 26 | 10.0 27 | material_scan 28 | 29 | 30 | 31 | Application 32 | true 33 | v143 34 | Unicode 35 | 36 | 37 | Application 38 | false 39 | v143 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | true 46 | v143 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | v143 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Level3 77 | true 78 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 79 | true 80 | 81 | 82 | Console 83 | true 84 | 85 | 86 | 87 | 88 | Level3 89 | true 90 | true 91 | true 92 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 93 | true 94 | 95 | 96 | Console 97 | true 98 | true 99 | true 100 | 101 | 102 | 103 | 104 | Level3 105 | true 106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 107 | true 108 | stdcpp20 109 | 110 | 111 | Console 112 | true 113 | 114 | 115 | 116 | 117 | Level3 118 | true 119 | true 120 | true 121 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | true 123 | 124 | 125 | Console 126 | true 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /material scanner/mat_scan/mat_scan.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /material scanner/mat_scan/mat_scan.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /material scanner/mat_scan/usermode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #ifdef _DEBUG 5 | #include "usermode.h" 6 | 7 | bool mem::memory::setup( ) { 8 | HANDLE ss = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL ); 9 | if ( ss ) 10 | { 11 | HANDLE process = NULL; 12 | PROCESSENTRY32 pe; 13 | pe.dwSize = sizeof( PROCESSENTRY32 ); 14 | if ( Process32First( ss, &pe ) ) {do {if ( !wcscmp( pe.szExeFile, ( L"RustClient.exe" ) ) ) {process = OpenProcess( PROCESS_ALL_ACCESS, false, pe.th32ProcessID );}} while ( Process32Next( ss, &pe ) );} 15 | CloseHandle( ss ); 16 | process_handle = process; 17 | } 18 | return process_handle; 19 | } 20 | 21 | void mem::memory::read( uintptr_t address, void* buffer, size_t size ) { 22 | if ( process_handle ) 23 | ReadProcessMemory( process_handle, ( LPCVOID )address, buffer, size, 0 ); 24 | } 25 | 26 | void mem::memory::write( uintptr_t address, void* buffer, size_t size ) { 27 | if ( process_handle ) 28 | WriteProcessMemory( process_handle, ( LPVOID )address, &buffer, size, NULL ); 29 | } 30 | 31 | mem::memory::module_t mem::memory::get_module( const std::wstring& name ) { 32 | module_t mod = { 0 }; 33 | HANDLE ss = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, GetProcessId( process_handle ) ); 34 | if ( ss ) { 35 | MODULEENTRY32 me; 36 | me.dwSize = sizeof( MODULEENTRY32 ); 37 | if ( Module32First( ss, &me ) ) {do {if ( !wcscmp( me.szModule, name.data( ) ) ) {mod.base = ( uint64_t )me.modBaseAddr;mod.size = ( uint64_t )me.modBaseSize;break;}} while ( Module32Next( ss, &me ) );} 38 | CloseHandle( ss ); 39 | } 40 | return mod; 41 | } 42 | #endif // _DEBUG 43 | -------------------------------------------------------------------------------- /material scanner/mat_scan/usermode.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef _DEBUG 8 | namespace mem::memory { 9 | typedef struct _module {uint64_t base;uint64_t size;}module_t; 10 | inline HANDLE process_handle = 0; 11 | bool setup( ); 12 | void read( uintptr_t, void*, size_t ); 13 | template 14 | inline type read( uintptr_t address ) {type buffer{};read( address, &buffer, sizeof( type ) );return buffer;} 15 | void write( uintptr_t, void*, size_t ); 16 | template 17 | inline void write( uintptr_t address, type buffer ) {write( address, &buffer, sizeof( buffer ) );} 18 | module_t get_module( const std::wstring& name ); 19 | } 20 | #endif // _DEBUG 21 | -------------------------------------------------------------------------------- /material scanner/material_scan.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.9.34622.214 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mat_scan", "mat_scan\mat_scan.vcxproj", "{9F36B7E0-412B-4D2A-A543-1FAC59C093A7}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {9F36B7E0-412B-4D2A-A543-1FAC59C093A7}.Debug|x64.ActiveCfg = Debug|x64 17 | {9F36B7E0-412B-4D2A-A543-1FAC59C093A7}.Debug|x64.Build.0 = Debug|x64 18 | {9F36B7E0-412B-4D2A-A543-1FAC59C093A7}.Debug|x86.ActiveCfg = Debug|Win32 19 | {9F36B7E0-412B-4D2A-A543-1FAC59C093A7}.Debug|x86.Build.0 = Debug|Win32 20 | {9F36B7E0-412B-4D2A-A543-1FAC59C093A7}.Release|x64.ActiveCfg = Release|x64 21 | {9F36B7E0-412B-4D2A-A543-1FAC59C093A7}.Release|x64.Build.0 = Release|x64 22 | {9F36B7E0-412B-4D2A-A543-1FAC59C093A7}.Release|x86.ActiveCfg = Release|Win32 23 | {9F36B7E0-412B-4D2A-A543-1FAC59C093A7}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {D8FA90E8-F862-448C-902E-9DE3B02B2D65} 30 | EndGlobalSection 31 | EndGlobal 32 | --------------------------------------------------------------------------------