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 


CE's scanning mechanics?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Source
View previous topic :: View next topic  
Author Message
Paprikaskrumpli
Cheater
Reputation: 0

Joined: 19 Dec 2020
Posts: 29

PostPosted: Thu Dec 31, 2020 8:00 am    Post subject: CE's scanning mechanics? Reply with quote

I wrote a simple c++ program to scan the game's memory (Read Process Memory). It works great, and is very fast, but causes to crash - black screen the game. (It usually takes a minute or so).

I'm very interested how CE does the "same", and manages not to crash the game. How does scanning for byte array work? - (I'm searching for an array of bytes)

I don't modify any of the game's values (at least no that I know of). I'm just simply reading blocks of memory.
In general I can use read process memory on this game without any problems. I feel like reading such big chunks of memory from the game doesn't seem like a good practice, and my program is no sneaky or smart by any means, but I don't see the problem. Please enlighten me!

Here are the most important parts of my code:

Code:

UINT64 placeJmpHere = 0;
   UINT64 start = moduleBase + 0xE00000;
   UINT64 end = moduleBase + 0xA00000;
   UINT64 pageNum = 0;
   BYTE page[4096];
   
   for (UINT64 i = start; i > end; i-=0x1000)
   {
      
      
      ReadProcessMemory(qtHandle, (void*)i, &page, sizeof(page), &bytesRead);
      
      placeJmpHere = findCode(page, pageNum);
      if (placeJmpHere != 0) {
         placeJmpHere += start - 11;
         break;
      }

      
      pageNum++;

   }
......
functions:

UINT64 findCode(BYTE* pg, UINT64 pageNum) {
   for (size_t i = 0; i < 4096; i++)
   {
      if (findPattern(asm2, pg, i)) {
         return (pageNum * 4096 + i);
      }
   }
   return 0;
}
bool findPattern(BYTE* pattern, BYTE* page, size_t index) {
   for (size_t i = 0; i < sizeof(pattern); i++)
   {
      if (page[index + i] != pattern[i]) {
         return false;
      }
   }
   return true;
}

Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 457

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

PostPosted: Thu Dec 31, 2020 11:00 am    Post subject: Reply with quote

don't read memory flagged as no_cache
_________________
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
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8516
Location: 127.0.0.1

PostPosted: Thu Dec 31, 2020 12:33 pm    Post subject: Reply with quote

You should be querying for the memory pages that are valid and readable rather than just attempting to read everything within a certain address range as you are showing in your test code.

- VirtualQuery (if in local process)
- VirtualQueryEx (if in external process)

Or the Nt/Zw equivalents if you need to bypass the forward-facing usermode calls.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Paprikaskrumpli
Cheater
Reputation: 0

Joined: 19 Dec 2020
Posts: 29

PostPosted: Thu Dec 31, 2020 2:00 pm    Post subject: Reply with quote

atom0s wrote:
You should be querying for the memory pages that are valid and readable rather than just attempting to read everything within a certain address range as you are showing in your test code.

- VirtualQuery (if in local process)
- VirtualQueryEx (if in external process)

Or the Nt/Zw equivalents if you need to bypass the forward-facing usermode calls.


All right, I'll give it a shot, thank you.

Dark Byte wrote:
don't read memory flagged as no_cache


Could you elaborate on this further, please?
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: Thu Dec 31, 2020 7:47 pm    Post subject: Reply with quote

As you iterate over the memory pages with VirtualQuery, it returns information about each page including the page flags. You can read more about it here:

https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualquery
https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-memory_basic_information
https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Paprikaskrumpli
Cheater
Reputation: 0

Joined: 19 Dec 2020
Posts: 29

PostPosted: Fri Jan 01, 2021 3:44 am    Post subject: Reply with quote

I queried the memory as you suggested, but this code also crashes (black screens) the game.

What conclusions should I derive from this? I think the game doesn't have anti-cheat, but I might be wrong. (Although I doubt it, because I use Read / Write Process Memory in the same game, read and modify single values without a problem.)

This code queries every page from the allocation base, and prints information about it.

Code:

   UINT64 ogBase = moduleBase;
   MEMORY_BASIC_INFORMATION mi = { 0 };
   do {
      mi = { 0 };
      VirtualQueryEx(qtHandle, (void*)moduleBase, &mi, sizeof(mi));

      std::cout <<"Page address: "<<hex<< mi.BaseAddress << endl;
      std::cout << "State: " << hex << mi.State << endl;
      std::cout << "Protect: "<< hex << mi.Protect << endl;
      std::cout << "---------------------------------\n\n";

      moduleBase += 0x1000;
   } while ((UINT64)mi.AllocationBase == (UINT64)ogBase);
Back to top
View user's profile Send private message
OldCheatEngineUser
Whateven rank
Reputation: 20

Joined: 01 Feb 2016
Posts: 1586

PostPosted: Fri Jan 01, 2021 7:07 am    Post subject: Reply with quote

this is not a good way to loop thru pages of your interest, besides that if you have real slow PC then it might cause blackscreen otherwise its probably RAM issues; having low ram can make Windows use page files heavily and swap critical contents or possibly your game did not tell Windows not to put its memory pages into page file.
_________________
About Me;
I Use CE Since Version 1.X, And Still Learning How To Use It Well!
Jul 26, 2020
STN wrote:
i am a sweetheart.
Back to top
View user's profile Send private message Visit poster's website
Paprikaskrumpli
Cheater
Reputation: 0

Joined: 19 Dec 2020
Posts: 29

PostPosted: Fri Jan 01, 2021 8:20 am    Post subject: Reply with quote

Okay I'm baffled. I tried NtQueryVirtualMemory, but the game still blackscreens like with the other functions.

What direction should I head next? I'm kinda lost, but I'm very interested how/why this happens, and understand it better.

(The function works, and returns correct values, and doesn't fail. Here I no longer try to read any addresses whatsoever. The code you see here is (basically) all I'm running.)
Code:

MEMORY_BASIC_INFORMATION mi = { 0 };
   _MEMORY_INFORMATION_CLASS mic = MemoryBasicInformation;
   size_t readBytes = 0;

   HMODULE nt = LoadLibraryA("ntdll.dll");
   if (nt != 0) {
      FARPROC vquery = GetProcAddress(nt, "NtQueryVirtualMemory");
      if (vquery != NULL) {

         NtQueryVirtualMemory _NtQVM = (NtQueryVirtualMemory)vquery;
         NTSTATUS ret;
         UINT64 ogBase = moduleBase;

         do {
            mi = { 0 };
            ret = _NtQVM(qtHandle, (void*)moduleBase, mic, &mi, sizeof(mi), &readBytes);

            cout << "Bytes read: " << readBytes << endl;
            cout << "Protect: " << mi.Protect << endl;
            cout << "Alloc Base: " << mi.AllocationBase << endl;
            cout << "Base Address: " << mi.BaseAddress << endl;
            cout << "State: " << mi.State << endl << endl;
            cout << "Status: ";
            if (ret == 0) {
               cout << "Success\n";
            }
            else {
               cout << "Unsuccesful?\n";
            }

            moduleBase += 0x1000;
         } while ((UINT64)mi.AllocationBase == (UINT64)ogBase);
      }
   }


Last edited by Paprikaskrumpli on Sat Jan 02, 2021 7:15 am; edited 1 time in total
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: Sat Jan 02, 2021 2:41 am    Post subject: Reply with quote

You need to check the queried pages information, validate it is safe to read and then use that data within your reads/scans. What you've shown us so far is just you calling the API and doing nothing with its return data.
_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Paprikaskrumpli
Cheater
Reputation: 0

Joined: 19 Dec 2020
Posts: 29

PostPosted: Sat Jan 02, 2021 4:33 am    Post subject: Reply with quote

Okay this is dumb, funny and weird. Please explain this to me.

So I want to modify code for code injection that seems to be dynamically allocated. It is not on an offset like asd.exe + 0x123, that is why I have to do this memory lookup.

There is a lot of memory to scan, so I started to look for ways to select region(s) that are potential. I found out after a while that CE show the allocation base for memory regions. I thought how cool would it be if I found pointers to this allocation base. I actually did. I scanned for the allocation base in hex and got some results, so I ran a pointer scan and got some reliable pointer paths. Cool stuff, I read the path with RPM() and started searching for code. As I said, it worked but resulted in a crash after a while.

I got the idea that what if the problem roots in something different. What part of my code did I not modify yet? It was the pointer path...
I used VirtualProtectEx() to modify access rights throughout the pointer path. This probably messed something up in the game that resulted in a crash. I removed this function from my code, and it ran like a champ, no crashes.

So please explain this:

I set the access rights back to the original after the modification from VirtualProtectEx() (Old Protect). What could have gone wrong? Actually, please share any other thoughts as well, if you have some on this topic.

Code:

moduleBase += 0x01C82818;

   
   VirtualProtectEx(qtHandle, (void*)moduleBase, sizeof(UINT64), PAGE_EXECUTE_READWRITE , &oldp);
   ReadProcessMemory(qtHandle, (void*)moduleBase, &moduleBase, sizeof(UINT64), &bytesRead);
   VirtualProtectEx(qtHandle, (void*)moduleBase, sizeof(UINT64), oldp, &oldp);

   moduleBase += 0x1c0;
   VirtualProtectEx(qtHandle, (void*)moduleBase, sizeof(UINT64), PAGE_EXECUTE_READWRITE, &oldp);
   ReadProcessMemory(qtHandle, (void*)moduleBase, &moduleBase, sizeof(UINT64), &bytesRead);
   VirtualProtectEx(qtHandle, (void*)moduleBase, sizeof(UINT64), oldp, &oldp);
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 Source 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