I don't know where the problem lies, whether it's a permission modification issue or
// troveaim.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#pragma warning(disable: 4067) // 忽略警告
#pragma clang diagnostic ignored "-Wc++17-extensions"
#define _HAS_CXX17 1
#define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WAR NING
#include <iostream>
#include <windows.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <cstdint>
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <cfloat>
#include <array>
#include <cstdint>
// Define localPlayer offset
const uintptr_t localPlayerOffset = 0x1098438;
// Blacklist keywords
const std::vector<std::string> blacklist_keywords = {
"pet", "portal", "abilities", "placeable", "cornerstone",
"services", "client", "karma", "outpost", "minion", "custom"
};
// Offsets for positions, camera, and silent aim
const std::vector<uintptr_t> positionOffsets = { localPlayerOffset, 0x8, 0x28, 0xC4, 0x4, 0x80 };
const std::vector<uintptr_t> camOffsets = { localPlayerOffset, 0x20, 0x70 };
const std::array<uintptr_t, 3> silentAimOffsets = {
0x3FAEB3, // F3 0F 10 82 DC 00 00 00
0x3FAEE9, // F3 0F 10 82 E0 00 00 00
0x3FAF1F // F3 0F 10 82 E4 00 00 00
};
// Max range for targeting entities
const float MAX_RANGE = 40.0f;
struct Entity {
std::string name;
float x, y, z;
float scale;
int level;
int death;
double health;
};
uintptr_t GetAddress(HANDLE hProcess, uintptr_t base, const std::vector<uintptr_t>& offsets) {
uintptr_t address = base;
for (size_t i = 0; i + 1 < offsets.size(); ++i) {
uint32_t tmp = 0;
if (!ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(address + offsets[i]), &tmp, sizeof(tmp), nullptr) || tmp == 0) {
return 0;
}
address = tmp;
}
return offsets.empty() ? address : (address + offsets.back());
}
float ReadFloat(HANDLE hProcess, uintptr_t address) {
float value = 0.0f;
ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(address), &value, sizeof(value), nullptr);
return value;
}
bool WriteFloat(HANDLE hProcess, uintptr_t address, float value) {
SIZE_T bytesWritten;
bool result = WriteProcessMemory(hProcess, reinterpret_cast<LPVOID>(address), &value, sizeof(value), &bytesWritten);
return result && bytesWritten == sizeof(value);
}
std::string ReadString(HANDLE hProcess, uintptr_t address, size_t maxLen) {
std::vector<char> buffer(maxLen);
SIZE_T bytesRead;
if (!ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(address), buffer.data(), maxLen, &bytesRead)) {
return {};
}
size_t len = 0;
while (len < bytesRead && buffer[len] != '\0') ++len;
return std::string(buffer.data(), len);
}
bool ReadValue(HANDLE hProcess, uintptr_t address, const std::string& type, void* out) {
SIZE_T bytesRead;
if (type == "float") {
return ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(address), out, sizeof(float), &bytesRead) && bytesRead == sizeof(float);
}
else if (type == "uint") {
return ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(address), out, sizeof(uint32_t), &bytesRead) && bytesRead == sizeof(uint32_t);
}
else if (type == "double") {
return ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(address), out, sizeof(double), &bytesRead) && bytesRead == sizeof(double);
}
else if (type == "int") {
return ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(address), out, sizeof(int32_t), &bytesRead) && bytesRead == sizeof(int32_t);
}
return false;
}
std::vector<Entity> GetAllEntities(HANDLE hProcess, uintptr_t world) {
std::vector<Entity> entities;
if (!world) return entities;
uintptr_t nodeInfo = GetAddress(hProcess, world, { 0x7C });
if (!nodeInfo) return entities;
uint32_t baseAddr = 0;
ReadValue(hProcess, nodeInfo, "uint", &baseAddr);
if (!baseAddr) return entities;
uint32_t size = 0, step = 0;
uintptr_t sizeAddr = GetAddress(hProcess, nodeInfo, { 0x8 });
ReadValue(hProcess, sizeAddr, "uint", &size);
uintptr_t stepAddr = GetAddress(hProcess, nodeInfo, { 0x4 });
ReadValue(hProcess, stepAddr, "uint", &step);
std::vector<uintptr_t> nodes;
for (uint32_t i = 0; i < size; ++i) {
uintptr_t addr = baseAddr + i * step;
while (addr) {
uint32_t next = 0;
if (!ReadValue(hProcess, addr, "uint", &next)) break;
if (next != 1) nodes.push_back(addr);
addr = next & ~1u;
}
}
for (auto node : nodes) {
uintptr_t ent = GetAddress(hProcess, node, { 0x10, 0xC4, 0x4, 0x0 });
if (!ent) continue;
uintptr_t nameAddr = GetAddress(hProcess, ent, { 0x58, 0x64, 0x0 });
auto name = ReadString(hProcess, nameAddr, 96);
if (name.empty()) continue;
uintptr_t posAddr = GetAddress(hProcess, ent, { 0x58, 0xC4, 0x4, 0x80 });
float x = 0, y = 0, z = 0;
ReadValue(hProcess, posAddr, "float", &x);
ReadValue(hProcess, posAddr + 4, "float", &y);
ReadValue(hProcess, posAddr + 8, "float", &z);
float scale = 0;
ReadValue(hProcess, posAddr + 0x74, "float", &scale);
int level = 0;
uintptr_t lvlAddr = GetAddress(hProcess, ent, { 0x58, 0xC4, 0x54, 0x120 });
ReadValue(hProcess, lvlAddr, "int", &level);
int death = 0;
uintptr_t deathAddr = GetAddress(hProcess, ent, { 0x58, 0x0 });
ReadValue(hProcess, deathAddr, "int", &death);
double health = 0;
uintptr_t healthAddr = GetAddress(hProcess, ent, { 0x58, 0xC4, 0x84, 0x80 });
ReadValue(hProcess, healthAddr, "double", &health);
entities.push_back({ name, x, y, z, scale, level, death, health });
}
std::cout << "\n[Info] Base: 0x" << std::hex << baseAddr << " Size: " << std::dec << size << " Step: " << step << std::endl;
std::cout << "[Info] Total entities found: " << entities.size() << std::endl;
return entities;
}
DWORD GetPID(const std::wstring& name) {
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W e{ sizeof(e) };
if (Process32FirstW(snap, &e)) do {} while (Process32NextW(snap, &e) && name != e.szExeFile);
CloseHandle(snap);
return name == e.szExeFile ? e.th32ProcessID : 0;
}
std::tuple<float, float, float> GetForwardVector(float sx, float sy, float sz, float dx, float dy, float dz) {
float vx = dx - sx;
float vy = dy - sy;
float vz = dz - sz;
float length = sqrt(vx * vx + vy * vy + vz * vz);
if (length == 0) return { 0.0f, 0.0f, 0.0f };
return { vx / length, vy / length, vz / length };
}
bool ContainsKeyword(const std::string& str, const std::vector<std::string>& keywords) {
for (const auto& kw : keywords) {
if (str.find(kw) != std::string::npos) return true;
}
return false;
}
// Silent Aim variables
std::array<uintptr_t, 3> allocatedSilentAimAddresses = { 0, 0, 0 };
std::array<std::vector<BYTE>, 3> originalInstructions;
std::array<uintptr_t, 3> instructionAddresses;
bool AllocateRemoteFloats(HANDLE hProcess) {
for (int i = 0; i < 3; i++) {
void* addr = VirtualAllocEx(hProcess, nullptr, sizeof(float), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!addr) {
std::cerr << "索引处分配失败 " << i << std::endl;
return false;
}
allocatedSilentAimAddresses[i] = reinterpret_cast<uintptr_t>(addr);
std::cout << "分配的内存在: 0x" << std::hex << allocatedSilentAimAddresses[i] << std::endl;
}
return true;
}
bool ReadBytes(HANDLE hProcess, uintptr_t address, BYTE* buffer, SIZE_T size) {
SIZE_T bytesRead;
return ReadProcessMemory(hProcess, (LPCVOID)address, buffer, size, &bytesRead) && bytesRead == size;
}
bool WriteBytes(HANDLE hProcess, uintptr_t address, BYTE* buffer, SIZE_T size) {
SIZE_T bytesWritten;
return WriteProcessMemory(hProcess, (LPVOID)address, buffer, size, &bytesWritten) && bytesWritten == size;
}
bool PatchMovssInstruction(HANDLE hProcess, int index, uintptr_t baseAddress) {
uintptr_t instrAddr = baseAddress + silentAimOffsets[index];
instructionAddresses[index] = instrAddr;
std::vector<BYTE> orig(8);
if (!ReadBytes(hProcess, instrAddr, orig.data(), 8)) {
std::cerr << "无法读取原始指令 " << std::hex << instrAddr << std::endl;
return false;
}
originalInstructions[index] = orig;
// Patch bytes f3 0f 10 05 + 4 bytes relative address
BYTE patch[8] = { 0xF3, 0x0F, 0x10, 0x05 }; // movss instruction
uint32_t absAddr = static_cast<uint32_t>(allocatedSilentAimAddresses[index]); // Absolute address
memcpy(patch + 4, &absAddr, sizeof(absAddr)); // Write absolute address in bytes
if (!WriteBytes(hProcess, instrAddr, patch, 8)) {
std::cerr << "未能在此处写补丁 " << std::hex << instrAddr << std::endl;
return false;
}
std::cout << "修补的 movss 在 0x" << std::hex << instrAddr << " 指向 0x" << allocatedSilentAimAddresses[index] << std::endl;
return true;
}
void RestoreOriginalInstructions(HANDLE hProcess) {
for (int i = 0; i < 3; i++) {
if (!originalInstructions[i].empty() && instructionAddresses[i] != 0) {
WriteBytes(hProcess, instructionAddresses[i], originalInstructions[i].data(), originalInstructions[i].size());
std::cout << "恢复原始指令于 0x" << std::hex << instructionAddresses[i] << std::endl;
}
}
}
void FreeAllocatedMemory(HANDLE hProcess) {
for (int i = 0; i < 3; i++) {
if (allocatedSilentAimAddresses[i]) {
VirtualFreeEx(hProcess, (LPVOID)allocatedSilentAimAddresses[i], 0, MEM_RELEASE);
std::cout << "释放的内存在 0x" << std::hex << allocatedSilentAimAddresses[i] << std::endl;
allocatedSilentAimAddresses[i] = 0;
}
}
}
void WriteSilentAimVector(HANDLE hProcess, float fx, float fy, float fz) {
if (!allocatedSilentAimAddresses[0] || !allocatedSilentAimAddresses[1] || !allocatedSilentAimAddresses[2]) {
std::cerr << "静默瞄准地址未分配" << std::endl;
return;
}
std::cout << "将静默目标向量写入地址: "
<< std::hex
<< "X: 0x" << allocatedSilentAimAddresses[0] << " "
<< "Y: 0x" << allocatedSilentAimAddresses[1] << " "
<< "Z: 0x" << allocatedSilentAimAddresses[2] << std::dec << std::endl;
if (!WriteFloat(hProcess, allocatedSilentAimAddresses[0], -fx) ||
!WriteFloat(hProcess, allocatedSilentAimAddresses[1], -fy) ||
!WriteFloat(hProcess, allocatedSilentAimAddresses[2], -fz)) {
std::cerr << "无法写入静默瞄准向量值" << std::endl;
}
}
int main() {
int world = 0x10984B0;
DWORD pid = GetPID(L"Trove.exe");
if (!pid) {
std::cerr << "没找到宝藏世界进程." << std::endl;
return 1;
}
HANDLE proc = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION, FALSE, pid);
if (!proc) {
std::cerr << "无法打开宝藏世界进程." << std::endl;
return 1;
}
HMODULE mods[1024]; DWORD needed;
EnumProcessModules(proc, mods, sizeof(mods), &needed);
uintptr_t base = reinterpret_cast<uintptr_t>(mods[0]);
if (!AllocateRemoteFloats(proc)) {
std::cerr << "分配内存以进行静默瞄准失败" << std::endl;
CloseHandle(proc);
return 1;
}
for (int i = 0; i < 3; i++) {
if (!PatchMovssInstruction(proc, i, base)) {
std::cerr << "无法修补movss指令" << std::endl;
RestoreOriginalInstructions(proc);
FreeAllocatedMemory(proc);
CloseHandle(proc);
return 1;
}
}
std::cout << "静默瞄准成功初始化" << std::endl;
while (true) {
uintptr_t localPlayer = GetAddress(proc, base, { localPlayerOffset });
uintptr_t playerPosPtr = GetAddress(proc, base, positionOffsets);
uintptr_t camPtr = GetAddress(proc, base, camOffsets);
uintptr_t world = GetAddress(proc, base, { 0x10984B0, 0x0 });//世界指针
auto allEntities = GetAllEntities(proc, world);
std::vector<Entity> filteredEntities;
for (const auto& e : allEntities) {
if (!ContainsKeyword(e.name, blacklist_keywords)) {
filteredEntities.push_back(e);
}
}
float px = ReadFloat(proc, playerPosPtr);
float py = ReadFloat(proc, playerPosPtr + 4);
float pz = ReadFloat(proc, playerPosPtr + 8);
float cx = ReadFloat(proc, camPtr);
float cy = ReadFloat(proc, camPtr + 4);
float cz = ReadFloat(proc, camPtr + 8);
// Print player and camera coordinates
std::cout << "[PlayerPos] x: " << px << ", y: " << py << ", z: " << pz << std::endl;
std::cout << "[CamPos] x: " << cx << ", y: " << cy << ", z: " << cz << std::endl;
float closestDist = FLT_MAX;
Entity closestEntity = { "", 0, 0, 0, 0, 0, 0, 0.0 };
bool found = false;
for (const auto& e : filteredEntities) {
float dx = e.x - px;
float dy = e.y - py;
float dz = e.z - pz;
float dist = sqrt(dx * dx + dy * dy + dz * dz);
if (dist < closestDist && dist <= MAX_RANGE) {
closestDist = dist;
closestEntity = e;
found = true;
}
}
if (found) {
auto [fx, fy, fz] = GetForwardVector(cx, cy, cz, closestEntity.x, closestEntity.y, closestEntity.z);
WriteSilentAimVector(proc, fx, fy, fz);
std::cout << "[SilentAim] 目标: " << closestEntity.name << " 向量: (" << fx << ", " << fy << ", " << fz << ") 距离: " << closestDist << std::endl;
}
else {
std::cout << "在范围内未找到有效的静音瞄准实体" << MAX_RANGE << ".\n";
}
Sleep(10);
}
RestoreOriginalInstructions(proc);
FreeAllocatedMemory(proc);
CloseHandle(proc);
return 0;
}