diff --git a/BattlefieldChat/BattlefieldChat.cpp b/BattlefieldChat/BattlefieldChat.cpp index 7b2ec08..a86ea51 100644 --- a/BattlefieldChat/BattlefieldChat.cpp +++ b/BattlefieldChat/BattlefieldChat.cpp @@ -41,66 +41,99 @@ int main() { cout.flags(f); hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - cout << " [*] 正在预分配内存..." << endl; - // This memory should not be freed, otherwise the game will crash (I'm too lazy to restore the pointer LOL) - // Possible memory leaks, but the size is small and therefore not a big problem + cout << " [*] 正在初始化..." << endl; messageCaveAddr = (uintptr_t)VirtualAllocEx(hProcess, NULL, sizeof(char) * 91, MEM_COMMIT, PAGE_READWRITE); - cout << " [+] 申请内存成功: 0x" << hex << messageCaveAddr << endl; + cout << " [+] 预分配内存成功: 0x" << hex << messageCaveAddr << endl; cout.flags(f); + Pointer messageCavePtr(hProcess, moduleBaseAddr); + messageCavePtr.pointer = messageCaveAddr; + ChatOpenPointer chatOpenPtr; + ChatLengthPointer chatLengthPtr; + ChatMessagePointer chatMessagePtr; + cout << " [+] Done! 在游戏中打开聊天即可自动呼出输入框" << endl; InputDialog dialog; bool lastState = false; while (IsWindow(gameWindow)) { - bool state = isBattlefieldChatOpen(); - if (!isFullscreenWindow(gameWindow) && !lastState && state) { - cout << endl << " [+] 检测到聊天框打开" << endl; - wstring str = dialog.showInputDialog(L"", gameWindow, isBorderlessWindow(gameWindow) ? 2 : 1); - - SetForegroundWindow(gameWindow); - if (str.length() == 0) { - press(VK_ESCAPE, 20); - cout << " [-] 取消输入操作" << endl; - goto outer; - } - // Convert Simplified Chinese std::wstring to Traditional Chinese std::string - wstring trad = CHS2CHT(str); - string converted = WStrToStr(trad); + if (chatOpenPtr.refreshPointer()) { + bool state = chatOpenPtr.readBoolean(); + if (!isFullscreenWindow(gameWindow) && !lastState && state) { + cout << endl << " [+] 检测到聊天框打开" << endl; + wstring str = dialog.showInputDialog(L"", gameWindow, isBorderlessWindow(gameWindow) ? 2 : 1); - int length = (converted.size() / sizeof(char)); + SetForegroundWindow(gameWindow); + if (str.length() == 0) { + press(VK_ESCAPE, 20); + cout << " [-] 取消输入操作" << endl; + goto outer; + } + // Convert Simplified Chinese std::wstring to Traditional Chinese std::string + wstring trad = CHS2CHT(str); + string converted = WStrToStr(trad); - if (length > 90) { - press(VK_ESCAPE, 20); - MessageBox(NULL, L"聊天消息长度不能超过90字节", L"错误", 0); - cout << " [-] 聊天消息长度超过90字节" << endl; - goto outer; - } + int length = (converted.size() / sizeof(char)); - if (!writeBattlefieldChatMessage(converted)) { - cout << " [-] 写入消息数据失败" << endl; - goto outer; - } + if (length > 90) { + press(VK_ESCAPE, 20); + MessageBox(NULL, L"聊天消息长度不能超过90字节", L"错误", 0); + cout << " [-] 聊天消息长度超过90字节" << endl; + goto outer; + } - if (!writeBattlefieldChatPointer()) { - cout << " [-] 重定向消息指针失败" << endl; - goto outer; - } + if (!chatLengthPtr.refreshPointer()) { + cout << " [-] 错误: 刷新指针失败 [ChatLength]" << endl; + goto outer; + } - // It may be possible to exceed the chat message length limit? But shouldn't do so, at risk of being banned - if (!writeBattlefieldChatLength(length)) { - cout << " [-] 写入消息长度失败" << endl; - goto outer; - } + if (!chatMessagePtr.refreshPointer()) { + cout << " [-] 错误: 刷新指针失败 [ChatMessage]" << endl; + goto outer; + } + + uintptr_t oldAddr = chatMessagePtr.readAddress(); + if (oldAddr == 0) { + cout << " [-] 错误: 读取指针失败 [ChatMessage]" << endl; + goto outer; + } - cout << " [+] 写入消息数据成功" << endl; - press(VK_RETURN, 20); - cout << " [+] 模拟发送完成" << endl; + + if (!messageCavePtr.writeString(converted)) { + cout << " [-] 错误: 写入数据失败 [ChatMessage]" << endl; + goto resume; + } + + if (!chatMessagePtr.writeAddress(messageCaveAddr)) { + cout << " [-] 错误: 写入指针失败 [ChatMessage]" << endl; + goto resume; + } + + // It may be possible to exceed the chat message length limit? But shouldn't do so, at risk of being banned + if (!chatLengthPtr.writeAddress(messageCaveAddr + length)) { + cout << " [-] 错误: 写入数据失败 [ChatLength]" << endl; + goto resume; + } + + cout << " [+] 写入消息数据成功" << endl; + press(VK_RETURN, 20); + cout << " [+] 模拟发送完成" << endl; + + + resume: + if (!chatMessagePtr.writeAddress(oldAddr)) { + cout << " [-] 错误: 恢复指针失败 [ChatMessage]" << endl; + } + if (!chatLengthPtr.writeAddress(oldAddr)) { + cout << " [-] 错误: 恢复指针失败 [ChatLength]" << endl; + } + } + lastState = state; } outer: - lastState = state; Sleep(200); } + VirtualFreeEx(hProcess, (LPVOID)messageCaveAddr, 0, MEM_RELEASE); CloseHandle(hProcess); cout << endl << " [*] 游戏已退出, Thanks for using!" << endl; Sleep(3000); diff --git a/BattlefieldChat/Offsets.cpp b/BattlefieldChat/Offsets.cpp index 834246c..25bffa5 100644 --- a/BattlefieldChat/Offsets.cpp +++ b/BattlefieldChat/Offsets.cpp @@ -1,83 +1,49 @@ #include "Offsets.h" -#include "Utils.h" HANDLE hProcess; uintptr_t moduleBaseAddr; uintptr_t messageCaveAddr; -bool isBattlefieldChatOpen() { - uintptr_t ptr = readPointer(hProcess, moduleBaseAddr, 0x39f1e50); - if (ptr == 0) return false; - - ptr = readPointer(hProcess, ptr, 0x8); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x28); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x0); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x20); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x18); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x28); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x38); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x40); - if (ptr == 0) return false; - unsigned char value = readByte(hProcess, ptr, 0x30); - return value == 1; -} - - -bool writeBattlefieldChatLength(int length) { - uintptr_t ptr = readPointer(hProcess, moduleBaseAddr, 0x3A2CA60); - if (ptr == 0) return false; - - ptr = readPointer(hProcess, ptr, 0x20); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x38); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x18); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x10); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x30); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x20); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0xB8); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x10); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x10); - if (ptr == 0) return false; - return writeLong(hProcess, ptr, 0x188, messageCaveAddr + length); +bool ChatOpenPointer::refreshPointer() { + pointer = baseModuleAddress; + if (!offset(0x39f1e50)) return false; + if (!offset(0x8)) return false; + if (!offset(0x28)) return false; + if (!offset(0x0)) return false; + if (!offset(0x20)) return false; + if (!offset(0x18)) return false; + if (!offset(0x28)) return false; + if (!offset(0x38)) return false; + if (!offset(0x40)) return false; + pointer += 0x30; + return true; } - -bool writeBattlefieldChatPointer() { - uintptr_t ptr = readPointer(hProcess, moduleBaseAddr, 0x3a327e0); - if (ptr == 0) return false; - - ptr = readPointer(hProcess, ptr, 0x20); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x18); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x38); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x8); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x68); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0xb8); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x10); - if (ptr == 0) return false; - ptr = readPointer(hProcess, ptr, 0x10); - if (ptr == 0) return false; - return writePointer(hProcess, ptr, 0x180, messageCaveAddr); +bool ChatLengthPointer::refreshPointer() { + pointer = baseModuleAddress; + if (!offset(0x3a327e0)) return false; + if (!offset(0x20)) return false; + if (!offset(0x18)) return false; + if (!offset(0x38)) return false; + if (!offset(0x8)) return false; + if (!offset(0x68)) return false; + if (!offset(0xB8)) return false; + if (!offset(0x10)) return false; + if (!offset(0x10)) return false; + pointer += 0x188; + return true; } -bool writeBattlefieldChatMessage(std::string str) { - return writeString(hProcess, messageCaveAddr, str.c_str(), str.size()); -} +bool ChatMessagePointer::refreshPointer() { + pointer = baseModuleAddress; + if (!offset(0x3a327e0)) return false; + if (!offset(0x20)) return false; + if (!offset(0x18)) return false; + if (!offset(0x38)) return false; + if (!offset(0x8)) return false; + if (!offset(0x68)) return false; + if (!offset(0xB8)) return false; + if (!offset(0x10)) return false; + if (!offset(0x10)) return false; + pointer += 0x180; + return true; +} \ No newline at end of file diff --git a/BattlefieldChat/Offsets.h b/BattlefieldChat/Offsets.h index bd11ebe..0eff901 100644 --- a/BattlefieldChat/Offsets.h +++ b/BattlefieldChat/Offsets.h @@ -1,12 +1,24 @@ #pragma once -#include -#include +#include "Pointer.h" extern HANDLE hProcess; extern uintptr_t moduleBaseAddr; extern uintptr_t messageCaveAddr; -bool isBattlefieldChatOpen(); -bool writeBattlefieldChatLength(int length); -bool writeBattlefieldChatMessage(std::string str); -bool writeBattlefieldChatPointer(); \ No newline at end of file +class ChatOpenPointer : public Pointer { +public: + ChatOpenPointer() : Pointer(hProcess, moduleBaseAddr) {} + bool refreshPointer(); +}; + +class ChatLengthPointer : public Pointer { +public: + ChatLengthPointer() : Pointer(hProcess, moduleBaseAddr) {} + bool refreshPointer(); +}; + +class ChatMessagePointer : public Pointer { +public: + ChatMessagePointer() : Pointer(hProcess, moduleBaseAddr) {} + bool refreshPointer(); +}; \ No newline at end of file diff --git a/BattlefieldChat/Pointer.cpp b/BattlefieldChat/Pointer.cpp new file mode 100644 index 0000000..c9576f7 --- /dev/null +++ b/BattlefieldChat/Pointer.cpp @@ -0,0 +1,66 @@ +#include "Pointer.h" + +bool Pointer::refreshPointer() { + return false; +} + +bool Pointer::readBoolean() { + bool value; + if (ReadProcessMemory(hProcess, (LPCVOID)pointer, &value, sizeof(value), 0)) + return value; + return false; +} + +uintptr_t Pointer::readAddress() { + uintptr_t value; + if (ReadProcessMemory(hProcess, (LPCVOID)pointer, &value, sizeof(value), 0)) + return value; + return 0; +} +bool Pointer::writeAddress(uintptr_t address) { + SIZE_T size = sizeof(address); + DWORD oldprotect; + if (!VirtualProtectEx(hProcess, (LPVOID)pointer, size, PAGE_EXECUTE_READWRITE, &oldprotect)) + return false; + if (!WriteProcessMemory(hProcess, (LPVOID)pointer, (LPCVOID)&address, size, nullptr)) + return false; + if (!VirtualProtectEx(hProcess, (LPVOID)pointer, size, oldprotect, &oldprotect)) + return false; + return true; +} + +bool Pointer::writeStringPtr(std::string data) { + uintptr_t address = readAddress(); + if (address == 0) throw 1; + SIZE_T size = data.size(); + DWORD oldprotect; + if (!VirtualProtectEx(hProcess, (LPVOID)address, size, PAGE_EXECUTE_READWRITE, &oldprotect)) + return false; + if (!WriteProcessMemory(hProcess, (LPVOID)address, data.c_str(), size, nullptr)) + return false; + if (!VirtualProtectEx(hProcess, (LPVOID)address, size, oldprotect, &oldprotect)) + return false; + return true; +} + +bool Pointer::writeString(std::string data) { + SIZE_T size = data.size(); + DWORD oldprotect; + if (!VirtualProtectEx(hProcess, (LPVOID)pointer, size, PAGE_EXECUTE_READWRITE, &oldprotect)) + return false; + if (!WriteProcessMemory(hProcess, (LPVOID)pointer, data.c_str(), size, nullptr)) + return false; + if (!VirtualProtectEx(hProcess, (LPVOID)pointer, size, oldprotect, &oldprotect)) + return false; + return true; +} + +Pointer::Pointer(HANDLE pProcessHandle, uintptr_t pBaseModuleAddress) { + hProcess = pProcessHandle; + baseModuleAddress = pBaseModuleAddress; +} + +bool Pointer::offset(uintptr_t offset) { + pointer += offset; + return (pointer = readAddress()) != 0; +} \ No newline at end of file diff --git a/BattlefieldChat/Pointer.h b/BattlefieldChat/Pointer.h new file mode 100644 index 0000000..0936b94 --- /dev/null +++ b/BattlefieldChat/Pointer.h @@ -0,0 +1,27 @@ +#pragma once +#include +#include +#include + +class Pointer { +public: + uintptr_t pointer = 0; + + bool refreshPointer(); + + bool readBoolean(); + + uintptr_t readAddress(); + bool writeAddress(uintptr_t address); + + bool writeStringPtr(std::string data); + bool writeString(std::string data); + + Pointer(HANDLE pProcessHandle, uintptr_t pBaseModuleAddress); +protected: + HANDLE hProcess; + uintptr_t baseModuleAddress; + + bool offset(uintptr_t offset); +}; +