#include "pch.h"
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
#include <cstdint>
#include <set>
#include <thread>
using namespace std;
//Функция нажатия клавиши
void PressKey(WORD virtualKeyCode, DWORD dwDelayAfterPressMs) { // dwDelayAfterPressMs - небольшая задержка после нажатия
INPUT inputs[2] = {};
// Событие "клавиша нажата"
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = virtualKeyCode;
inputs[0].ki.dwFlags = 0; // 0 для KEYEVENTF_KEYDOWN
// Событие "клавиша отпущена"
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wVk = virtualKeyCode;
inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
UINT uSent = SendInput(2, inputs, sizeof(INPUT));
if (uSent != 2) {
cout << "Failed to send input " << GetLastError() << endl;
}
if (dwDelayAfterPressMs > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(dwDelayAfterPressMs));
}
}
bool fuzzy_memcmp(const std::uint8_t* lhs, const std::uint8_t* rhs, std::size_t size, const char* masks) noexcept {
constexpr auto wildcard = '?';
const auto end = lhs + size;
for (; lhs < end; ++lhs, ++rhs, ++masks) {
if (*masks != wildcard && *lhs != *rhs)
return false;
}
return true;
}
const std::uint8_t* sigscan_naive(const std::uint8_t* base, std::size_t input_size, const uint8_t* pattern,
std::size_t pattern_size, const char* masks) noexcept {
if (pattern_size && (input_size >= pattern_size) && base && pattern && masks) {
const auto alignmentCount = (input_size - pattern_size) + 1;
const auto end = base + alignmentCount;
for (auto current = base; current < end; ++current) {
if (fuzzy_memcmp(current, pattern, pattern_size, masks))
return current;
}
}
return nullptr;
}
BOOL IsPointer(uintptr_t address) {
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery((LPCVOID)address, &mbi, sizeof(mbi))) {
return (mbi.State == MEM_COMMIT && (mbi.Protect & PAGE_READWRITE || mbi.Protect & PAGE_READONLY));
}
return false;
}
// ==================================================
// КОНСТАНТЫ ДЛЯ ТИПОВ ПРИКАЗОВ
// ==================================================
const int DOTA_UNIT_ORDER_NONE = 0;
const int DOTA_UNIT_ORDER_MOVE_TO_POSITION = 1;
const int DOTA_UNIT_ORDER_MOVE_TO_TARGET = 2;
const int DOTA_UNIT_ORDER_ATTACK_MOVE = 3;
const int DOTA_UNIT_ORDER_ATTACK_TARGET = 4;
const int DOTA_UNIT_ORDER_CAST_POSITION = 5;
const int DOTA_UNIT_ORDER_CAST_TARGET = 6;
const int DOTA_UNIT_ORDER_CAST_TARGET_TREE = 7;
const int DOTA_UNIT_ORDER_CAST_NO_TARGET = 8;
const int DOTA_UNIT_ORDER_CAST_TOGGLE = 9;
const int DOTA_UNIT_ORDER_HOLD_POSITION = 10;
const int DOTA_UNIT_ORDER_TRAIN_ABILITY = 11;
const int DOTA_UNIT_ORDER_DROP_ITEM = 12;
const int DOTA_UNIT_ORDER_GIVE_ITEM = 13;
const int DOTA_UNIT_ORDER_PICKUP_ITEM = 14;
const int DOTA_UNIT_ORDER_PICKUP_RUNE = 15;
const int DOTA_UNIT_ORDER_PURCHASE_ITEM = 16;
const int DOTA_UNIT_ORDER_SELL_ITEM = 17;
const int DOTA_UNIT_ORDER_DISASSEMBLE_ITEM = 18;
const int DOTA_UNIT_ORDER_MOVE_ITEM = 19;
const int DOTA_UNIT_ORDER_CAST_TOGGLE_AUTO = 20;
const int DOTA_UNIT_ORDER_STOP = 21;
const int DOTA_UNIT_ORDER_TAUNT = 22;
const int DOTA_UNIT_ORDER_BUYBACK = 23;
const int DOTA_UNIT_ORDER_GLYPH = 24;
const int DOTA_UNIT_ORDER_EJECT_ITEM_FROM_STASH = 25;
const int DOTA_UNIT_ORDER_CAST_RUNE = 26;
const int DOTA_UNIT_ORDER_PING_ABILITY = 27;
const int DOTA_UNIT_ORDER_MOVE_TO_DIRECTION = 28;
const int DOTA_UNIT_ORDER_PATROL = 29;
const int DOTA_UNIT_ORDER_VECTOR_TARGET_POSITION = 30;
const int DOTA_UNIT_ORDER_RADAR = 31;
const int DOTA_UNIT_ORDER_SET_ITEM_COMBINE_LOCK = 32;
const int DOTA_UNIT_ORDER_CONTINUE = 33;
const int DOTA_UNIT_ORDER_VECTOR_TARGET_CANCELED = 34;
const int DOTA_UNIT_ORDER_CAST_RIVER_PAINT = 35;
const int DOTA_UNIT_ORDER_PREGAME_ADJUST_ITEM_ASSIGNMENT = 36;
// ==================================================
// КОНСТАНТЫ ДЛЯ ИСТОЧНИКОВ ПРИКАЗА
// ==================================================
const int DOTA_ORDER_ISSUER_SELECTED_UNITS = 0;
const int DOTA_ORDER_ISSUER_CURRENT_UNIT_ONLY = 1;
const int DOTA_ORDER_ISSUER_HERO_ONLY = 2;
const int DOTA_ORDER_ISSUER_PASSED_UNIT_ONLY = 3;
DWORD WINAPI EntityScan(LPVOID lpParam) {
HMODULE hModule = (HMODULE)lpParam;
//main func
AllocConsole();
FILE* stream;
freopen_s(&stream, "CONOUT$", "w", stdout);
HMODULE client = GetModuleHandleA("client.dll");
if (client == NULL) {
cout << "client.dll not found" << endl;
return FALSE;
}
HMODULE engine2 = GetModuleHandleA("engine2.dll");
if (engine2 == NULL) {
cout << "engine2.dll not found" << endl;
return FALSE;
}
cout << "client 0x" << hex << client << endl;
cout << "engine2 0x" << hex << engine2 << endl;
MODULEINFO out_modinfo{};
if (!K32GetModuleInformation(GetCurrentProcess(), client, &out_modinfo, sizeof(out_modinfo))) {
cout << "K32GetModuleInformation failed: " << GetLastError() << endl;
return FALSE;
}
const char masks[]{ "xxx????xx????xxx????xxx" };
const auto entitysystem_xref = sigscan_naive((const std::uint8_t*)client, out_modinfo.SizeOfImage,
(const std::uint8_t*)"\x48\x8d\x0d????\xff\x15????\x48\x8b\x0d????\x33\xd2\xe8",
std::size(masks) - 1,
masks);
if (!entitysystem_xref) {
cout << "entitysystem_xref not found!" << endl;
return FALSE;
}
const auto mov_insn_ptr = entitysystem_xref + 0xD;
const auto rel32 = *(std::int32_t*)(mov_insn_ptr + 0x3);
const auto entity_system_ptr = (void**)(mov_insn_ptr + 0x7 + rel32);
// EntityScan
while (1) {
system("cls");
const auto entitysystem = *entity_system_ptr;
if (!entitysystem) {
cout << "entitysystem not created yet" << endl;
continue;
}
cout << "entitysystem: 0x" << hex << entitysystem << endl;
int heroCount = 0;
std::set<uintptr_t> NPC;
int index = 1;
int illusion = 0;
for (int i = 0; i < 64; i++) {
uintptr_t entitylistAddress = uintptr_t(entitysystem) + 0x10 + (i * 0x8); // размер ентлиста
void** entitylist = *(void***)(entitylistAddress);
if (entitylist && IsPointer(uintptr_t(entitylist))) {
for (int j = 0; j < 512; j++) {
uintptr_t entAddr = uintptr_t(entitylist) + (j * 0x78); // 0x78 размер сущности
void* entPtr = *(void**)entAddr;
if (IsPointer((uintptr_t)entPtr)) {
int index = i * 512 + j;
unsigned char isnpc = *(unsigned char*)(uintptr_t(entPtr) + 0x4f4); // isnpc
if (index >= 1 && index <= 64) {
bool islocal = *(bool*)(uintptr_t(entPtr) + 0x690); // Смотрим у каждого контроллера локальный ли он игрок? islocalhero = 0x690
if (islocal == 1 && islocal == TRUE) {
cout << "11111111111111111111111111111" << endl << endl;
cout << "Local player find at 0x" << entPtr << endl << endl;
uint32_t rawheroindex = *(uint32_t*)(uintptr_t(entPtr) + 0x80c);
uint32_t heroindex = rawheroindex & 0x7FFF;
uint32_t listindex = heroindex / 512;
uint32_t entindex = heroindex % 512;
uintptr_t chunkadr = uintptr_t(entitysystem) + 0x10 + (listindex * 0x8);
void** chunk_ptr = *reinterpret_cast<void***>(chunkadr);
uintptr_t localheroadr = uintptr_t(chunk_ptr) + (entindex * 0x78);
void* localheroptr = *reinterpret_cast<void**>(localheroadr);
cout << "Localhero found at 0x" << localheroptr << " him hp is: " << dec << *(int*)(uintptr_t(localheroptr) + 0x34c) << endl;
cout << "Adress vecabl 0x" << hex << uintptr_t(localheroptr) + 0xad8 << endl;
cout << "11111111111111111111111111111" << endl << endl;
}
}
if (isnpc == 3) {
if (NPC.insert(reinterpret_cast<uintptr_t>(entPtr)).second) {
uintptr_t unttypeadr = uintptr_t(entPtr) + 0xa44; // 0xa44 = isnpc(bool) npc == 3
uint32_t unttype = *(uint32_t*)(unttypeadr); //read
if ((unttype & 1) != 0) {
heroCount++;
bool isIllusion(*(uint32_t*)(uintptr_t(entPtr) + 0x1870) != 0xFFFFFFFF);
if (isIllusion == TRUE) {
illusion++;
cout << "Illusion #" << dec << heroCount << " found at address: 0x" << hex << entPtr << " him hp is: " << dec << *(int*)(uintptr_t(entPtr) + 0x34c) << endl; // hp = 0x34
}
else {
heroCount++;
cout << "Hero #" << dec << illusion << " found at address: 0x" << hex << entPtr << " him hp is: " << dec << *(int*)(uintptr_t(entPtr) + 0x34c) << endl; // hp = 0x34c
}
}
}
}
}
}
}
}
cout << "Total players:: " << index << endl;
cout << "Total heroes:: " << heroCount << endl;
cout << "Total ilussions:: " << illusion << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hModule);
HANDLE hThread = CreateThread(
nullptr,
0,
EntityScan,
hModule,
0,
nullptr
);
if (hThread) {
CloseHandle(hThread);
}
else {
cout << "Thread not created" << endl;
return FALSE;
}
return TRUE;
}
return TRUE;
}