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 


How to find addresses an instruction accesses in C++?

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

Joined: 01 Jun 2021
Posts: 2

PostPosted: Tue Jun 01, 2021 7:17 pm    Post subject: How to find addresses an instruction accesses in C++? Reply with quote

Hello, I am trying to grab all addresses an instruction access from C++. My idea was to add a hardware breakpoint on the instruction, and collect the addresses over a short period of time. The problem is that my program grabs only one address over and over. When I use 'Find out what addresses this instruction accesses' within the memory viewer, Cheat Engine does pick up all addresses.

Below is the comparison of my program and Cheat Engine as well as my code. Has anyone a clue why my code only picks up 1 address? Or an alternative solution on how I might grab all addresses?

Thanks in advance

Instruction

movsd [edx+03],xmm1

Code

The code is a bit messy, apologies for that.

Code:
if (!DebugActiveProcess(processId))
{
   std::cout << "Debugger attachment failed...\n";
   CloseHandle(hProcess);
   return 1;
}
std::cout << "Debugger attached...\n";

HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, threads.at(0));
if (!hThread)
{
   std::cout << "Failed to open thread\n";
   CloseHandle(hProcess);
   return 1;
}

std::cout << "Thread 0x" << std::hex << threads.at(0) << std::endl;

DWORD address = matches.at(0);

CONTEXT ctx = { 0 };
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS | CONTEXT_INTEGER;
ctx.Dr0 = address;
ctx.Dr7 = 0x1;

SuspendThread(hThread);
SetThreadContext(hThread, &ctx);
ResumeThread(hThread);

std::vector<DWORD> addrs;
addrs.reserve(100);

DEBUG_EVENT dbgEvent;
int counter = 0;
while (counter < 100)
{
   if (WaitForDebugEvent(&dbgEvent, INFINITE) == 0)
      continue;

   if (dbgEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
   {
      if (dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)address)
      {
         
         GetThreadContext(hThread, &ctx);

         addrs.push_back(ctx.Edx);
         
         ctx.EFlags |= 1 << 16; // resume flag   
         
         ++counter;
         if (counter == 100)
         {
            ctx.Dr7 &= ~1; // disable Dr0
         }
         
         SetThreadContext(hThread, &ctx);
      }
   }

   ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE);
}

CloseHandle(hThread);

if (DebugActiveProcessStop(processId))
{
   std::cout << "Debugger detached...\n";
}

for (auto addr : addrs)
{
   std::cout << "0x" << std::hex << addr << '\n';
}
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8516
Location: 127.0.0.1

PostPosted: Wed Jun 02, 2021 8:58 pm    Post subject: Reply with quote

Quick glance looks ok assuming the process is 32bit. The only two things that stand out as a potential problem would be:

- You are only setting Dr7 to 1, this may be the cause of your issue in general as it is a bit field value for different 'when' conditions and register data. You can see what the bits mean here:
https://en.wikipedia.org/wiki/X86_debug_register#DR7_-_Debug_control
https://www.sandpile.org/x86/drx.htm

- You are only allowing it to try 100 times to find something, perhaps the other address access is happening after that?

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Stepfish
How do I cheat?
Reputation: 0

Joined: 01 Jun 2021
Posts: 2

PostPosted: Thu Jun 03, 2021 2:33 am    Post subject: Reply with quote

atom0s wrote:
Quick glance looks ok assuming the process is 32bit. The only two things that stand out as a potential problem would be:

- You are only setting Dr7 to 1, this may be the cause of your issue in general as it is a bit field value for different 'when' conditions and register data. You can see what the bits mean here:
-- URL --
-- URL --

- You are only allowing it to try 100 times to find something, perhaps the other address access is happening after that?


I ended up replacing the way I set Dr7 with an OR, but this was not the problem.

The problem was the way I initialized my CONTEXT. In order to let the thread continue after the breakpoint I have to set the Resume Flag (bit 16) in the EFlags. Setting the EFlags required me to use CONTEXT_ALL as ContextFlags for the CONTEXT. (It's really called like this...) Because I didn't have this access, my changes to the EFlags were ignored, and the thread never stepped over the breakpoint. Thus the same exception was thrown over and over.

This is an example of accessing the registers every time the address in Dr0 gets executed. In chapter 17 of Volume 3 of the Intel Software Developer's Manual there's more information on how to setup the debug registers. I hope this helps someone in the future, because it was a bit of a pain to figure all this out, while the final code is quite simple.

Code:
void DebugLoop(const LPDEBUG_EVENT debugEvent, const HANDLE hThread, DWORD address)
    {
        CONTEXT ctx;
        ctx.ContextFlags = CONTEXT_ALL;

        SuspendThread(hThread);
        GetThreadContext(hThread, &ctx);
        ctx.Dr0 = address;
        ctx.Dr7 |= 0x1;
        SetThreadContext(hThread, &ctx);
        ResumeThread(hThread);

        bool bDebug = true;
        while (bDebug)
        {
            if (!WaitForDebugEvent(debugEvent, 1))
            {
                continue;
            }

           DWORD dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;

            switch (debugEvent->dwDebugEventCode)
            {
            case EXCEPTION_DEBUG_EVENT:
           {
            auto exception = debugEvent->u.Exception.ExceptionRecord.ExceptionCode;
            auto exceptionAddress = debugEvent->u.Exception.ExceptionRecord.ExceptionAddress;
                  
               if (exception == EXCEPTION_SINGLE_STEP && exceptionAddress == (LPVOID)address)
               {
               GetThreadContext(hThread, &ctx);
                  
               // Access the registers etc. here
               std::cout << ctx.Eax << std::endl;

               ctx.EFlags |= (1 << 16);

               SetThreadContext(hThread, &ctx);
               dwContinueStatus = DBG_CONTINUE;
               }

               break;
           }
            case EXIT_PROCESS_DEBUG_EVENT:
            {
                bDebug = false;
                break;
            }
            default:
           {
            break;
           }
            }

            ContinueDebugEvent(debugEvent->dwProcessId,
                debugEvent->dwThreadId,
                dwContinueStatus);
        }
   }
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming 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