Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Calling the Tutorial's Message Box function.

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
syj
How do I cheat?
Reputation: 0

Joined: 21 Mar 2019
Posts: 2

PostPosted: Thu Mar 21, 2019 1:35 pm    Post subject: Calling the Tutorial's Message Box function. Reply with quote

Hello,

I would like to call the Message Box function in Cheat Engine's tutorial through a DLL that I inject. This Message Box shows up whenever you skip a stage of the tutorial or when your health reaches 0.

I am able to call the damage function for Step 2 as follows:

Code:

void damage() {
   using PlayerBase = DWORD_PTR;
   static const auto player_base = *(PlayerBase*)0x1002cb9e0;

   using DamageFuncPrototype = void(PlayerBase);
   static const auto DamageFunc = (DamageFuncPrototype*)0x10002b2b0;

   DamageFunc(player_base);
}


Calling damage() then decreases the player's health as if they clicked on the "Hit me" button in Step 2.

Looking at how the tutorial calls the Message Box function—which is at 0x1001596d0—I'm guessing the signature of the function is something like:

Code:
void MessageBox(const char* string)


at least based on observing that the pointer of the string that the Message Box displays is moved into register RCX before the call:
Code:
Tutorial-x86_64.exe+2B305 - mov rcx,[Tutorial-x86_64.exe+19F628] { (1001F8FE8) }
Tutorial-x86_64.exe+2B30C - call Tutorial-x86_64.exe+1596D0


When I call the following, however, the tutorial crashes:
Code:
void ce_msg_box() {
   using MsgBoxPrototype = void(const char*);
   static const auto MsgBoxFunc = (MsgBoxPrototype*)0x1001596d0;
   MsgBoxFunc("Test string.");
}


I am not sure where to go from here, as I have just begun reverse engineering.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25791
Location: The netherlands

PostPosted: Fri Mar 22, 2019 1:23 am    Post subject: Reply with quote

Perhaps it needs a pointer to a string instance and not a raw string. strings in fpc start with a byte specifying the length following the string, and no idea how longer strings are handled, perhaps a full blown class object
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
syj
How do I cheat?
Reputation: 0

Joined: 21 Mar 2019
Posts: 2

PostPosted: Fri Mar 22, 2019 8:43 am    Post subject: Reply with quote

I looked at some of the functions that the Message Box calls, and you're right: there's a structure to the string in addition to the raw characters. Although we pass to the Message Box function a pointer to the raw string, other calls within this function will examine the memory 16 bytes before this pointer.

Specifically, as far as I can tell, strings in the tutorial are laid out as:

8 byte header of 1's.
8 byte value containing the string length.
The raw string bytes, aligned to the nearest 8 byte multiple.
8 byte footer with the value 0x10000.

Final code for anyone interested:
Code:
#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);
      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. I'm 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;

DWORD WINAPI MyThread(_In_ LPVOID lpParameter) {
   while (true) {
      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;
}



ce_strings.png
 Description:
 Filesize:  62.29 KB
 Viewed:  1843 Time(s)

ce_strings.png



ce_msg_box_short_string.PNG
 Description:
 Filesize:  17 KB
 Viewed:  1843 Time(s)

ce_msg_box_short_string.PNG


Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites