diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2024-03-27 04:15:22 +0100 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2024-03-27 04:15:22 +0100 |
commit | 8f7dfd4ff8ca94f6df375154524f774ea5444009 (patch) | |
tree | 0530c515fa13f34140b0644002ea66502148ae96 | |
parent | 056e59808b9c06fd34286ea208af9854f6a29096 (diff) |
Finished EFT "hack".
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | tarkov.cpp | 258 |
1 files changed, 188 insertions, 70 deletions
@@ -1,10 +1,13 @@ #include <ntddk.h> #include <EASTL/array.h> +#include <EASTL/unordered_map.h> +#include <eastl_compat.hpp> #include <DriverThread.hpp> #include <obfuscate.hpp> #include "memory.hpp" +#include "stringify.hpp" using namespace DriverThread; @@ -32,44 +35,124 @@ struct GameObjectManager struct UnityList { - char pad[16]; // 0x00->0x10; + uint8_t pad[16]; uint64_t pointer; uint32_t size; }; -static uint64_t GetObjectFromList(Memory& memory, uint64_t listPtr, uint64_t lastObjectPtr, const char * const objectName) +template<size_t N> +struct UnityString { - char name[128]; - uint64_t classNamePtr = 0x0; + uint8_t pad[16]; + uint32_t length; + wchar_t value[N]; +}; - BaseObject activeObject = memory.Read<BaseObject>(listPtr); - BaseObject lastObject = memory.Read<BaseObject>(lastObjectPtr); +template<typename T> +struct Vector3 +{ + T x; + T y; + T z; +}; - if (activeObject.object != 0x0) - { - while (activeObject.object != 0 && activeObject.object != lastObject.object) - { - classNamePtr = memory.Read<uint64_t>(activeObject.object + 0x60); - memory.ReadBuffer<char, sizeof(name)>(classNamePtr, name); +struct Player +{ + enum Side { + BEAR = 1, USEC = 2, SCAV = 4 + } side; + eastl::string nickname; + Vector3<float> position; +}; - if (strncmp(name, objectName, sizeof(name)) == 0) - return activeObject.object; +static const eastl::unordered_map<wchar_t, eastl::string> cyrillic_to_latin{ + {L'А', "A"}, {L'Б', "B"}, {L'В', "V"}, {L'Г', "G"}, {L'Д', "D"}, + {L'Е', "E"}, {L'Ё', "E"}, {L'Ж', "Zh"}, {L'З', "Z"}, {L'И', "I"}, + {L'Й', "Y"}, {L'К', "K"}, {L'Л', "L"}, {L'М', "M"}, {L'Н', "N"}, + {L'О', "O"}, {L'П', "P"}, {L'Р', "R"}, {L'С', "S"}, {L'Т', "T"}, + {L'У', "U"}, {L'Ф', "F"}, {L'Х', "Kh"}, {L'Ц', "Ts"}, {L'Ч', "Ch"}, + {L'Ш', "Sh"}, {L'Щ', "Shch"}, {L'Ъ', ""}, {L'Ы', "Y"}, {L'Ь', ""}, + {L'Э', "E"}, {L'Ю', "Yu"}, {L'Я', "Ya"}, + {L'а', "a"}, {L'б', "b"}, {L'в', "v"}, {L'г', "g"}, {L'д', "d"}, + {L'е', "e"}, {L'ё', "e"}, {L'ж', "zh"}, {L'з', "z"}, {L'и', "i"}, + {L'й', "y"}, {L'к', "k"}, {L'л', "l"}, {L'м', "m"}, {L'н', "n"}, + {L'о', "o"}, {L'п', "p"}, {L'р', "r"}, {L'с', "s"}, {L'т', "t"}, + {L'у', "u"}, {L'ф', "f"}, {L'х', "kh"}, {L'ц', "ts"}, {L'ч', "ch"}, + {L'ш', "sh"}, {L'щ', "shch"}, {L'ъ', ""}, {L'ы', "y"}, {L'ь', ""}, + {L'э', "e"}, {L'ю', "yu"}, {L'я', "ya"} +}; - activeObject = memory.Read<BaseObject>(activeObject.nextObjectLink); - } +static eastl::string transliterate_cyrillic(wchar_t* input, size_t length) +{ + eastl::string retval; + + for (size_t i = 0; i < length; ++i) { + const auto& got = cyrillic_to_latin.find(input[i]); + if (got == cyrillic_to_latin.end()) { + retval += *reinterpret_cast<char*>(&input[i]); + } else { + retval += got->second; } - if (lastObject.object != 0x0) + } + + return retval; +} + +double square_root(const double number) { + constexpr double ACCURACY = 0.001; + double lower, upper, guess; + + if (number < 1) { + lower = number; + upper = 1; + } else { + lower = 1; + upper = number; + } + + while ((upper-lower) > ACCURACY) { + guess = (lower + upper)/2; + if (guess*guess > number) + upper =guess; + else + lower = guess; + } + return (lower + upper)/2; +} + +static uint64_t GetObjectFromList(Memory& memory, uint64_t listPtr, uint64_t lastObjectPtr, const char * const objectName) +{ + char name[128]; + uint64_t classNamePtr = 0x0; + + BaseObject activeObject = memory.Read<BaseObject>(listPtr); + BaseObject lastObject = memory.Read<BaseObject>(lastObjectPtr); + + if (activeObject.object != 0x0) + { + while (activeObject.object != 0 && activeObject.object != lastObject.object) { - classNamePtr = memory.Read<uint64_t>(lastObject.object + 0x60); - memory.ReadBuffer<char, sizeof(name)>(classNamePtr, name); + classNamePtr = memory.Read<uint64_t>(activeObject.object + 0x60); + memory.ReadBuffer<char, sizeof(name)>(classNamePtr, name); + + if (strncmp(name, objectName, sizeof(name)) == 0) + return activeObject.object; - if (strncmp(name, objectName, sizeof(name)) == 0) - return lastObject.object; + activeObject = memory.Read<BaseObject>(activeObject.nextObjectLink); } + } + if (lastObject.object != 0x0) + { + classNamePtr = memory.Read<uint64_t>(lastObject.object + 0x60); + memory.ReadBuffer<char, sizeof(name)>(classNamePtr, name); - memset(name, 0, sizeof(name)); + if (strncmp(name, objectName, sizeof(name)) == 0) + return lastObject.object; + } - return 0; + memset(name, 0, sizeof(name)); + + return 0; } static uint64_t SearchTarkovProcess(void) { @@ -116,7 +199,7 @@ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject, if (tarkov_pid == NULL) { continue; } - DbgPrint("pid: %p\n", tarkov_pid); + DbgPrint(skCrypt("pid: %p\n"), tarkov_pid); if (!NT_SUCCESS(::OpenProcess(tarkov_pid, &pep, &obj))) { tarkov_pid = NULL; @@ -129,7 +212,7 @@ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject, KeDelayExecutionThread(KernelMode, TRUE, &wait); const auto mods = ::GetModules(pep, FALSE); - DbgPrint("mods: %zu\n", mods.size()); + DbgPrint(skCrypt("mods: %zu\n"), mods.size()); for (const auto &mod : mods) { if (mod.BaseDllName == targetModule) { DbgPrint("%s\n", "found"); @@ -142,17 +225,20 @@ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject, } if (!tarkov_pid) { + LARGE_INTEGER wait = {.QuadPart = (-1LL) * 10LL * 1000LL * 5000LL}; + KeDelayExecutionThread(KernelMode, TRUE, &wait); ::CloseProcess(&pep, &obj); continue; } - - //wait_timeout = (-1LL) * 10LL * 1000LL * 50LL; } + // Offsets stolen from: https://github.com/HuiTeab/EFT-DMA-Radar-Only-Code/blob/main/Source/Misc/Offsets.cs Memory memory(pep); auto gom_ptr = memory.Read<uint64_t>(base + 0x17FFD28); auto gom = memory.Read<GameObjectManager>(gom_ptr); if (!gom_ptr) { + LARGE_INTEGER wait = {.QuadPart = (-1LL) * 10LL * 1000LL * 5000LL}; + KeDelayExecutionThread(KernelMode, TRUE, &wait); ::CloseProcess(&pep, &obj); tarkov_pid = NULL; continue; @@ -160,35 +246,80 @@ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject, uint64_t activeNodes = memory.Read<uint64_t>(gom.ActiveNodes); uint64_t lastActiveNode = memory.Read<uint64_t>(gom.LastActiveNode); - auto game_world = GetObjectFromList(memory, activeNodes, lastActiveNode, "GameWorld"); + auto game_world = GetObjectFromList(memory, activeNodes, lastActiveNode, skCrypt("GameWorld")); auto local_game_world = memory.ReadChain<uint64_t>(game_world, { 0x30, 0x18, 0x28 }); - auto local_player = memory.Read<uint64_t>(local_game_world + 0x118); - auto player_list_ptr = memory.Read<uint64_t>(local_game_world + 0xC0); - auto player_list = memory.Read<UnityList>(player_list_ptr); - auto count = memory.Read<uint32_t>(player_list_ptr + 0x40); - - //auto registered_players = memory.Read<uint64_t>(local_game_world + 0xC0); - //auto player_count = memory.Read<uint32_t>(registered_players + 0x18); - DbgPrint("%p,%p,%p,%p,%p,%u,%u\n", game_world, local_game_world, local_player, player_list_ptr, player_list.pointer, player_list.size, count); -#if 0 - auto lgw = memory.ReadChain<uint64_t>(gom, { 0x30, 0x18, 0x28 }); - if (!lgw) - continue; - - auto registered_players = memory.Read<uint64_t>(lgw + 0xC0); - auto player_count = memory.Read<uint64_t>(registered_players + 0x18); - uint64_t i; - for (i = 0; i < player_count; ++i) { - auto player_ptr = memory.Read<uint64_t>(registered_players + 0x20 + i * 0x8); - auto class_name_ptr = memory.ReadChain<uint64_t>(player_ptr, { 0x0, 0x0, 0x48 }); - //if (!class_name_ptr) - // break; - char buf[64]; - memory.ReadBuffer<char, 64>(class_name_ptr, buf); - DbgPrint("++%.*s++\n", (int)memory.LastSize(), buf); + auto local_player = memory.Read<uint64_t>(local_game_world + 0x148); + auto local_player_class = memory.ReadChain<uint64_t>(local_player, { 0x0, 0x0, 0x48 }); + char local_player_class_name[64] = {}; + memory.ReadString<sizeof(local_player_class_name)>(local_player_class, local_player_class_name); + auto registered_players = memory.Read<uint64_t>(local_game_world + 0xF0); + auto registered_players_list = memory.Read<UnityList>(registered_players); + + Player me; + eastl::vector<Player> players; + size_t player_count = 0, scav_count = 0; + for (uint32_t i = 0; i < registered_players_list.size; ++i) { + auto player_base = memory.Read<uint64_t>(registered_players_list.pointer + 0x20 + (i * 0x8)); + auto player_class = memory.ReadChain<uint64_t>(player_base, { 0x0, 0x0, 0x48 }); + char player_class_name[64] = {}; + memory.ReadString<sizeof(player_class_name)>(player_class, player_class_name); + auto player_info = memory.ReadChain<uint64_t>(player_base, { 0x588 /* EFT Profile */, + 0x28 /* Player Info */ }); + const auto player_class_name_str = eastl::string(player_class_name); + if (player_class_name_str == skCrypt("ObservedPlayerView")) { + auto player_is_ai = memory.Read<unsigned char>(player_base + 0x109); + if (!player_is_ai) + player_count++; + auto player_side = memory.Read<uint32_t>(player_base + 0xF0); + if (player_side == 4 /* scav */) + scav_count++; + if (player_is_ai) + continue; + auto pos = memory.ReadChain<Vector3<float>>(player_base, { 0x10, 0x30, 0x30, 0x8, 0x38, 0x90 }); + auto player_nickname = memory.Read<uint64_t>(player_base + 0x48); + auto player_nickname_unity = memory.Read<UnityString<64>>(player_nickname); + const auto& player_trans_nickname = transliterate_cyrillic(player_nickname_unity.value, + player_nickname_unity.length); + players.emplace_back(Player{ .side = static_cast<Player::Side>(player_side), + .nickname = player_trans_nickname, .position = pos }); + } else if (player_class_name_str == skCrypt("ClientPlayer") || + player_class_name_str == skCrypt("LocalPlayer") || + player_class_name_str == skCrypt("HideoutPlayer")) + { + auto player_side = memory.Read<uint32_t>(player_info + 0x70); + if (player_side == 4 /* scav */) + scav_count++; + auto pos = memory.ReadChain<Vector3<float>>(player_base, { 0x10, 0x30, 0x30, 0x8, 0x38, 0x90 }); + me = Player{ .side = static_cast<Player::Side>(player_side), + .nickname = "", .position = pos }; + } } - DbgPrint("__%llu,%llu__\n", i, player_count); -#endif + DbgPrint(skCrypt("Players/Scavs: %u/%u\n"), player_count, scav_count); + for (const auto& player : players) { + eastl::string pside; + switch (player.side) { + case Player::Side::BEAR: + pside = "BEAR"; break; + case Player::Side::USEC: + pside = "USEC"; break; + case Player::Side::SCAV: + pside = "SCAV"; break; + default: + pside = "UNKN"; break; + } + auto xd = me.position.x - player.position.x; + xd *= xd; + auto yd = me.position.y - player.position.y; + yd *= yd; + auto zd = me.position.z - player.position.z; + zd *= zd; + auto pdist = square_root(xd + yd + zd); + DbgPrint(skCrypt("Player %s: [%s] %s [%s %s %s]\n"), pside.c_str(), ::to_string(pdist), player.nickname, + ::to_string(player.position.x).c_str(), ::to_string(player.position.y).c_str(), + ::to_string(player.position.z).c_str()); + } + +// You'll figure that out.. #if 0 auto camera_address = memory.Read<uint64_t>(base + 0x0179F500); if (!camera_address) @@ -207,25 +338,12 @@ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject, break; auto camera_name_ptr = memory.Read<uint64_t>(camera_obj + 0x60); - char buf[64]; - memory.ReadBuffer<char, 64>(camera_name_ptr, buf); + char buf[64] = {}; + memory.ReadString<sizeof(buf)>(camera_name_ptr, buf); if (memory.LastSize() > 0 && strncmp(buf, skCrypt("BaseOpticCamera(Clone)"), sizeof(buf)) == 0) optic_camera = camera_name_ptr; } - DbgPrint("--%p,%p--\n", lgw, optic_camera); - - if (!optic_camera) - continue; - auto component_list = memory.Read<uint64_t>(optic_camera + 0x30); - if (!component_list) - continue; - uint64_t i; - for (i = 0; i < 64; ++i) { - auto field = memory.ReadChain<uint64_t>(component_list, { 0x8 + (i * 0x10), 0x28 }); - if (!field) - break; - } - DbgPrint("++%llu++\n", i); + DbgPrint(skCrypt("Optic: %p\n"), optic_camera); #endif } |