Last active
June 25, 2019 14:50
-
-
Save rkr35/863f4331177d94df730a5e05abee3c7c to your computer and use it in GitHub Desktop.
Cheat Engine Damage + MessageBox
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <Windows.h> | |
| #include <chrono> | |
| #include <sstream> | |
| #include <thread> | |
| using Address = DWORD_PTR; | |
| class CeString { | |
| private: | |
| Address* buffer; | |
| auto get_size_for_msg(std::size_t msg_len) const { | |
| auto size = msg_len / double(sizeof Address); | |
| size = std::ceil(size); | |
| return std::size_t(size); | |
| } | |
| public: | |
| CeString(const char* message) { | |
| const auto msg_len = std::strlen(message) + 1; | |
| const auto size_for_msg = get_size_for_msg(msg_len); | |
| buffer = new Address[3 + size_for_msg]; | |
| // Header of 1's. | |
| buffer[0] = ~0; | |
| // Length of string. | |
| buffer[1] = msg_len; | |
| // The actual string placed in memory. | |
| std::memcpy(buffer + 2, message, msg_len); | |
| // The footer. Not sure what these bytes do, | |
| // but all strings in the tutorial seem to have this final piece. | |
| buffer[2 + size_for_msg] = 0x10000; | |
| } | |
| ~CeString() { | |
| delete[] buffer; | |
| buffer = nullptr; | |
| } | |
| Address get_string_address() const { | |
| return Address(&buffer[2]); | |
| } | |
| }; | |
| void ce_msg_box(const CeString& s) { | |
| using CeMsgBoxPrototype = void(Address); | |
| static const auto CeMsgBox = (CeMsgBoxPrototype*)0x1001596d0; | |
| CeMsgBox(s.get_string_address()); | |
| } | |
| void ce_msg_box(const char* s) { | |
| ce_msg_box(CeString(s)); | |
| } | |
| using MessageBuffer = std::ostringstream; | |
| void ce_msg_box(const MessageBuffer& body) { | |
| ce_msg_box(body.str().c_str()); | |
| } | |
| void sleep() { | |
| using namespace std::literals::chrono_literals; | |
| std::this_thread::sleep_for(100ms); | |
| } | |
| bool should_display_test_string() { | |
| return GetAsyncKeyState(VK_HOME); | |
| } | |
| void display_test_string() { | |
| CeString s("The quick brown fox jumps over the lazy dog."); | |
| { | |
| // Show the address of the string, | |
| // so we can examine in memory if everything is properly layed out. | |
| MessageBuffer b; | |
| b << std::hex << s.get_string_address(); | |
| ce_msg_box(b); | |
| } | |
| ce_msg_box(s); | |
| } | |
| bool should_detach_dll() { | |
| return GetAsyncKeyState(VK_END); | |
| } | |
| HANDLE g_MyThreadHandle = nullptr; | |
| bool should_damage() { | |
| return GetAsyncKeyState(VK_DELETE); | |
| } | |
| void damage() { | |
| using PlayerBase = Address; | |
| static const auto player_base = *(PlayerBase*)0x1002cb9e0; | |
| using DamageFuncPrototype = void(PlayerBase); | |
| static const auto DamageFunc = (DamageFuncPrototype*)0x10002b2b0; | |
| DamageFunc(player_base); | |
| } | |
| DWORD WINAPI MyThread(_In_ LPVOID lpParameter) { | |
| while (true) { | |
| if (should_damage()) { | |
| damage(); | |
| } | |
| if (should_display_test_string()) { | |
| display_test_string(); | |
| } | |
| if (should_detach_dll()) { | |
| ce_msg_box("detach"); | |
| CloseHandle(g_MyThreadHandle); | |
| FreeLibraryAndExitThread(HINSTANCE(lpParameter), 0); | |
| break; | |
| } | |
| sleep(); | |
| } | |
| return 0; | |
| } | |
| BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved) { | |
| if (fdwReason == DLL_PROCESS_ATTACH) { | |
| DisableThreadLibraryCalls(hinstDLL); | |
| g_MyThreadHandle = CreateThread(nullptr, 0, MyThread, hinstDLL, 0, nullptr); | |
| } | |
| return TRUE; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment