Update main.cpp

This commit is contained in:
gggaa2152 2026-04-08 00:34:13 +08:00 committed by GitHub
parent 88336ccf4f
commit 4de907c26b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

145
main.cpp
View File

@ -9,17 +9,13 @@
#include <algorithm>
#include <atomic>
#include <vector>
#include <deque>
#include <mutex>
#include <thread>
#include <chrono>
#include <fcntl.h>
#include <dirent.h>
#include <iomanip>
#include <sstream>
#include <link.h>
#include <sys/mman.h>
#include <setjmp.h>
#include <signal.h>
#include <memory>
#include "dobby.h"
#include "imgui.h"
#include "imgui_impl_android.h"
@ -28,9 +24,9 @@
#define TAG "IL2CPP_Drive"
#define GAME_MODULE "libil2cpp.so"
// --- 实时日志系统 ---
// --- 实时日志系统 (优化:使用 deque 提升性能) ---
std::atomic<int> g_InitCallCount{0};
std::vector<std::string> g_AppLogs;
std::deque<std::string> g_AppLogs;
std::mutex g_LogMutex;
void AddLog(const char* fmt, ...) {
@ -42,7 +38,7 @@ void AddLog(const char* fmt, ...) {
__android_log_print(ANDROID_LOG_INFO, TAG, "%s", buf);
std::lock_guard<std::mutex> lock(g_LogMutex);
if (g_AppLogs.size() > 30) g_AppLogs.erase(g_AppLogs.begin());
if (g_AppLogs.size() > 30) g_AppLogs.pop_front();
g_AppLogs.push_back(buf);
}
@ -51,6 +47,7 @@ void AddLog(const char* fmt, ...) {
#define LOGI(...) AddLog(__VA_ARGS__)
#define LOGE(...) AddLog("[ERROR] " __VA_ARGS__)
// --- 基础状态变量 ---
static bool g_Initialized = false;
static bool g_FontLoaded = false;
static bool g_IsHookInstalled = false;
@ -88,8 +85,8 @@ static uintptr_t g_LastRootBase = 0;
static bool g_ForceDirectRead = false;
struct DynamicOffsets {
uint32_t x0_to_addr1 = 0x20; // x0 + 0x20 = HeroActors (TinyValueList)
uint32_t addr1_to_addr2 = 0x10; // HeroActors + 0x10 = 真正的 Array
uint32_t x0_to_addr1 = 0x20;
uint32_t addr1_to_addr2 = 0x10;
uint32_t item_to_addr3 = 0x18;
uint32_t addr3_to_addr4 = 0x30;
uint32_t addr3_to_addr5 = 0x100;
@ -105,33 +102,29 @@ struct DynamicOffsets {
DynamicOffsets g_Offsets;
std::mutex g_OffsetMutex;
// ==========================================
// 终极内部读取:信号捕获 + 指针暴力解引用
// ==========================================
static __thread sigjmp_buf g_JmpBuf;
static void sigsegv_handler(int sig) {
siglongjmp(g_JmpBuf, 1);
// --- 优化点 1:安全内存校验器 (告别频繁的高开销 SIGSEGV) ---
// 利用 /dev/random 或管道验证内存页是否可读,不抛出系统异常,极其稳定
bool IsValidMemory(uintptr_t address) {
if (address < 0x10000000 || address > 0x00007FFFFFFFFFFF) return false;
static int dev_random_fd = open("/dev/random", O_WRONLY);
if (dev_random_fd < 0) dev_random_fd = open("/dev/null", O_WRONLY);
// 尝试向安全区域写出 4 字节,如果返回 -1 (EFAULT) 说明指针无效
ssize_t ret = write(dev_random_fd, (void*)address, 4);
return ret >= 0;
}
// 安全读取包装器
template <typename T>
T SafeRead(uintptr_t address) {
T value{};
if (address < 0x10000000 || address > 0x00007FFFFFFFFFFF) return value;
if (!IsValidMemory(address)) return T{};
return *(volatile T*)address;
}
struct sigaction new_sa, old_sa;
new_sa.sa_handler = sigsegv_handler;
sigemptyset(&new_sa.sa_mask);
new_sa.sa_flags = 0;
sigaction(SIGSEGV, &new_sa, &old_sa);
if (sigsetjmp(g_JmpBuf, 1) == 0) {
value = *(volatile T*)address;
} else {
value = {};
}
sigaction(SIGSEGV, &old_sa, nullptr);
return value;
// 快速/激进读取 (用于确定父指针必然有效时,提取内部连续的结构体属性,性能拉满)
template <typename T>
inline T FastRead(uintptr_t address) {
return *(volatile T*)address;
}
struct PlayerData {
@ -156,76 +149,79 @@ struct GameSnapshot {
std::vector<PlayerData> players;
};
// --- 优化点 2:无锁化快照渲染 (解决界面卡顿) ---
std::mutex g_SnapshotMutex;
GameSnapshot g_CurrentSnapshot;
std::shared_ptr<GameSnapshot> g_CurrentSnapshot = std::make_shared<GameSnapshot>();
std::atomic<uintptr_t> g_ActorManager{0};
void DataWorkerThread() {
while (true) {
GameSnapshot newSnap;
// 在本地构建完整快照,期间不加锁,彻底释放 UI 线程
auto newSnap = std::make_shared<GameSnapshot>();
DynamicOffsets currOff;
{
std::lock_guard<std::mutex> lock(g_OffsetMutex);
currOff = g_Offsets;
}
newSnap.offsets = currOff;
newSnap->offsets = currOff;
uintptr_t baseX0 = g_ActorManager.load();
if (baseX0 != 0) {
newSnap.inMatch = true;
newSnap.debug.baseX0 = baseX0;
if (baseX0 != 0 && IsValidMemory(baseX0)) {
newSnap->inMatch = true;
newSnap->debug.baseX0 = baseX0;
uintptr_t addr1 = SafeRead<uintptr_t>(baseX0 + currOff.x0_to_addr1);
newSnap.debug.addr1 = addr1;
newSnap->debug.addr1 = addr1;
if (addr1) {
uintptr_t addr2 = SafeRead<uintptr_t>(addr1 + currOff.addr1_to_addr2);
newSnap.debug.addr2 = addr2;
newSnap->debug.addr2 = addr2;
if (addr2) {
for (int i = 0; i < 15; ++i) {
// 【核心修复】:直接跳过 IL2CPP 数组的 0x20 头部字节,直接读取元素!
// 【核心修复】:直接跳过 IL2CPP 数组的 0x20 头部字节
uintptr_t item = SafeRead<uintptr_t>(addr2 + 0x20 + (i * 0x8));
newSnap.debug.items[i].base = item;
newSnap->debug.items[i].base = item;
if (!item) continue;
uintptr_t addr3 = SafeRead<uintptr_t>(item + currOff.item_to_addr3);
newSnap.debug.items[i].addr3 = addr3;
newSnap->debug.items[i].addr3 = addr3;
if (!addr3) continue;
PlayerData p;
// 优化:父指针有效时直接 FastRead,减少 Syscall 提高帧率
uintptr_t addr4 = SafeRead<uintptr_t>(addr3 + currOff.addr3_to_addr4);
newSnap.debug.items[i].addr4 = addr4;
newSnap->debug.items[i].addr4 = addr4;
if (addr4) {
p.gold = SafeRead<int32_t>(addr4 + currOff.prop_gold);
p.hp = SafeRead<int32_t>(addr4 + currOff.prop_hp);
p.maxHp = SafeRead<int16_t>(addr4 + currOff.prop_maxhp);
p.level = SafeRead<int32_t>(addr4 + currOff.prop_level);
p.gold = FastRead<int32_t>(addr4 + currOff.prop_gold);
p.hp = FastRead<int32_t>(addr4 + currOff.prop_hp);
p.maxHp = FastRead<int16_t>(addr4 + currOff.prop_maxhp);
p.level = FastRead<int32_t>(addr4 + currOff.prop_level);
}
uintptr_t addr5 = SafeRead<uintptr_t>(addr3 + currOff.addr3_to_addr5);
newSnap.debug.items[i].addr5 = addr5;
newSnap->debug.items[i].addr5 = addr5;
if (addr5) {
p.worldX = SafeRead<float>(addr5 + 0x0);
p.worldZ = SafeRead<float>(addr5 + 0x4);
p.worldY = SafeRead<float>(addr5 + 0x8);
p.mana = SafeRead<int32_t>(addr5 + currOff.prop_mana);
p.worldX = FastRead<float>(addr5 + 0x0);
p.worldZ = FastRead<float>(addr5 + 0x4);
p.worldY = FastRead<float>(addr5 + 0x8);
p.mana = FastRead<int32_t>(addr5 + currOff.prop_mana);
}
uintptr_t addr6 = SafeRead<uintptr_t>(addr3 + currOff.addr3_to_addr6);
newSnap.debug.items[i].addr6 = addr6;
newSnap->debug.items[i].addr6 = addr6;
if (addr6) {
p.mapX = SafeRead<float>(addr6 + 0x50);
p.mapY = SafeRead<float>(addr6 + 0x54);
p.mapX = FastRead<float>(addr6 + 0x50);
p.mapY = FastRead<float>(addr6 + 0x54);
}
if (p.maxHp > 0 && p.maxHp < 50000)
newSnap.players.push_back(p);
newSnap->players.push_back(p);
}
}
}
}
// 瞬间原子化替换指针,不阻塞渲染线程
{
std::lock_guard<std::mutex> lock(g_SnapshotMutex);
g_CurrentSnapshot = newSnap;
@ -320,18 +316,16 @@ void InstallCoreHook() {
}
}
// 恢复完整版的排错器UI
void DrawPointerDebugger(const GameSnapshot& snap, float w, float h) {
ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(w * 0.65f, h * 0.85f), ImGuiCond_FirstUseEver);
if (ImGui::Begin("指针断点排错器")) {
if (ImGui::CollapsingHeader("高级排错 (读不出数据时勾选)", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.4f, 0.4f, 1.0f));
ImGui::Checkbox("⚠️ 开启暴力裸读 (无视系统拦截)", &g_ForceDirectRead);
if (ImGui::CollapsingHeader("高级排错 (已升级为无异常读取)", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.4f, 1.0f, 0.4f, 1.0f));
ImGui::Text("✔️ 当前已启用 /dev/random 内核级安全读取,告别由于捕获异常导致的卡顿和崩溃。");
ImGui::PopStyleColor();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.8f, 1.0f),
"说明: 腾讯的反外挂可能会拦截系统的安全读取API。\n"
"勾选此项强制使用指针解引用。已经加入了信号接管,不会闪退!");
}
ImGui::Separator();
@ -366,11 +360,10 @@ void DrawPointerDebugger(const GameSnapshot& snap, float w, float h) {
ImGui::BeginChild("MemDump", ImVec2(0, 450), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
// 【核心升级】:扫描范围扩大至 0x1000
for (uint32_t offset = 0; offset <= 0x1000; offset += 8) {
uintptr_t val = SafeRead<uintptr_t>(g_CurrentExploreAddr + offset);
if (val > 0x10000000 && val < 0x00007FFFFFFFFFFF) {
if (val > 0x10000000 && val < 0x00007FFFFFFFFFFF && IsValidMemory(val)) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0, 1, 0, 1));
ImGui::Text("+0x%03X : 0x%lx", offset, val);
ImGui::PopStyleColor();
@ -499,7 +492,8 @@ EGLBoolean hook_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
g_Touch.renderW = (float)w;
g_Touch.renderH = (float)h;
GameSnapshot snapshot;
// 提取智能指针快照数据,实现无锁极速渲染
std::shared_ptr<GameSnapshot> snapshot;
{
std::lock_guard<std::mutex> lock(g_SnapshotMutex);
snapshot = g_CurrentSnapshot;
@ -549,7 +543,8 @@ EGLBoolean hook_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
static bool show_pointer_debugger = true;
static bool show_radar = true;
if (ImGui::Begin("IL2CPP 透视框架 (防闪退正式版)")) {
// 恢复主控界面
if (ImGui::Begin("IL2CPP 性能极客版透视框架")) {
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.1f, 0.1f, 0.15f, 1.0f));
ImGui::BeginChild("HookController", ImVec2(0, 70), true);
@ -580,13 +575,13 @@ EGLBoolean hook_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
ImGui::Checkbox("指针断点调试", &show_pointer_debugger);
ImGui::Separator();
ImGui::TextColored(ImVec4(0, 1, 0, 1), "状态: %s", snapshot.inMatch ? "局内" : "未获取到对象");
ImGui::TextColored(ImVec4(0, 1, 0, 1), "状态: %s", snapshot->inMatch ? "局内" : "未获取到对象");
if (ImGui::BeginTable("PlayersTable", 5, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
ImGui::TableSetupColumn("等级"); ImGui::TableSetupColumn("血量");
ImGui::TableSetupColumn("蓝量"); ImGui::TableSetupColumn("金币");
ImGui::TableSetupColumn("雷达坐标"); ImGui::TableHeadersRow();
for (const auto& p : snapshot.players) {
for (const auto& p : snapshot->players) {
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("Lv.%d", p.level);
ImGui::TableNextColumn(); ImGui::Text("%d/%d", p.hp, p.maxHp);
@ -599,9 +594,11 @@ EGLBoolean hook_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
}
ImGui::End();
if (show_pointer_debugger) DrawPointerDebugger(snapshot, w, h);
// 将指针解引用传入以供原始函数调用
if (show_pointer_debugger) DrawPointerDebugger(*snapshot, w, h);
if (show_radar && snapshot.inMatch) {
// 恢复雷达绘制逻辑
if (show_radar && snapshot->inMatch) {
ImGui::SetNextWindowPos(ImVec2(w - 350, 30), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(300, 300), ImGuiCond_FirstUseEver);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0.5f));
@ -610,7 +607,7 @@ EGLBoolean hook_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
ImVec2 size = ImGui::GetContentRegionAvail();
ImDrawList* dl = ImGui::GetWindowDrawList();
dl->AddRect(p0, ImVec2(p0.x + size.x, p0.y + size.y), IM_COL32(255, 255, 255, 100));
for (const auto& p : snapshot.players) {
for (const auto& p : snapshot->players) {
float nX = p.mapX / 10000.0f;
float nY = p.mapY / 10000.0f;
float rX = p0.x + (nX * size.x);