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 


c++ basic memory scanner

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

Joined: 19 Feb 2017
Posts: 3

PostPosted: Sun Feb 19, 2017 10:48 pm    Post subject: c++ basic memory scanner Reply with quote

I am trying to read the string in this process i made, bb = "stringstuff", with len of 11.

Code:

#include <iostream>
#include <windows.h>

struct stuff {
   int i = 0;
   int b = 1;   
   const char* bb = "stringstuff";
   stuff() { std::cout << "stuff created\n" << "i: " << i << "\nb: " << b << "\nbb: " << bb << "\n" << std::endl; }
};

int main() {
   stuff *stuffPtr = new stuff();//creates a stuff thing with its default values set
   while ((*stuffPtr).bb == "stringstuff") {
      std::cout << "i: " << stuffPtr->i << "\n";
      std::cout << "b: " << stuffPtr->b << "\n";
      std::cout << "bb: " << stuffPtr->bb << "\n\n";
      std::cout << &stuffPtr->bb << std::end;
      Sleep(10000);
      if (stuffPtr->bb != "stringstuff") {
         std::cout << "bb has been changed to: " << stuffPtr->bb << std::endl;
         Sleep(30000);         
      }
   }
   delete stuffPtr;
   return 1;
}



i am using this other process

[spoiler]
Code:

#include "windows.h"
#include "Tlhelp32.h"
#include <iostream>
#include <vector>

class Memory {

private:
   DWORD _processID = 0;
   DWORD _processAddress = 0;
   HANDLE _snapshot=0;
   HANDLE _handle=0;
   const char* _processName=0;

public:
   Memory(const char* processName);
   ~Memory();
   void getProcessID();
   void getModuleAddress();

   template<typename TYPE>
   TYPE read(DWORD address);

   char* query(const char *data, size_t len);
};

int main()
{
   Memory *Mem = new Memory("process1.exe");//processID Address and handle PROCESS_QUERY_INFORMATION.

   const char* hey = Mem->query("stringstuff",11);
   

   std::cout << hey << std::endl;


   system("PAUSE");
   delete Mem;
   return 0;   //Mem.read<int>(0x0);
}


Memory::Memory(const char* processName)
{
   _processName = processName;
   getProcessID();
   getModuleAddress();
   _handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, _processID);//PROCESS_QUERY_INFORMATION, PROCESS_VM_READ
   if (_handle == NULL) {
      std::cout << "handle error\n";
   }
}

Memory::~Memory()
{
   CloseHandle(_handle);
}

void Memory::getProcessID()
{
   PROCESSENTRY32 _processEntry;
   _snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   while (!_processID)
   {
      if (Process32First(_snapshot, &_processEntry))
      {
         do
         {
            if (!strcmp((const char*)_processEntry.szExeFile, _processName))
            {
               _processID = _processEntry.th32ProcessID;
               break;
            }   
         } while (Process32Next(_snapshot, &_processEntry));
      }
      if (!_processID)
      {
         std::cout << _processName << " not found.\n";
         break;
      }
   }
   CloseHandle(_snapshot);
}

void Memory::getModuleAddress()
{
   MODULEENTRY32 _moduleEntry;
   _snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, _processID);
   _moduleEntry.dwSize = sizeof(MODULEENTRY32);

   while (_processAddress == 0)
   {
      do
      {
         if (!strcmp((const char*)_moduleEntry.szModule, _processName))
         {
            _processAddress = (unsigned int)_moduleEntry.modBaseAddr;
            break;
         }

      } while (Module32Next(_snapshot, &_moduleEntry));


      if (_processAddress == 0)
      {
         std::cout << "Failed to find module " << _processName << std::endl;
         break;
      }
   }
      std::cout << "Base Address: " << std::hex << _processAddress << std::dec << std::endl;
      CloseHandle(_snapshot);
}

template<typename TYPE>
TYPE Memory::read(DWORD address)
{
   TYPE _buffer = -1;
   ReadProcessMemory(_handle, (void*)address, &_int, sizeof(_buffer), 0);
   return _buffer;
}

char* Memory::query(const char *data,size_t len)
{
   _handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, _processID);//PROCESS_QUERY_INFORMATION, PROCESS_VM_READ
   DWORD dwProtectionMask = PAGE_READONLY | PAGE_EXECUTE_WRITECOPY | PAGE_READWRITE | PAGE_WRITECOMBINE;
   SYSTEM_INFO si;
   GetSystemInfo(&si);

   MEMORY_BASIC_INFORMATION memoryInfo;

   char* p = 0;
   int page = 0;

   while (p < si.lpMaximumApplicationAddress)
   {
      if (VirtualQueryEx(_handle, p, &memoryInfo, sizeof(memoryInfo)) == sizeof(memoryInfo))
      {
         p = (char*)memoryInfo.BaseAddress;
         char *buffer = new char[memoryInfo.RegionSize];

         SIZE_T bytesRead;
         if (ReadProcessMemory(_handle, p, &buffer[0], memoryInfo.RegionSize, &bytesRead))
         {
            for (size_t i = 0; i < (bytesRead - len); ++i)
            {
               if (memcmp(data, &buffer[i], len) == 0)
               {
                  std::cout << page << " end\n";
                  return (char*)p + i;
               }
            }
         }
         p += memoryInfo.RegionSize;
         delete[] buffer;
      }
      page++;
      std::cout << page << ":pages read.\n";
      
      Sleep(50);
      
   }
   return "no find";
}

[/spoiler]

specifically

Code:


int main()
{
   Memory *Mem = new Memory("process1.exe");//processID Address and handle PROCESS_QUERY_INFORMATION.

   const char* hey = Mem->query("stringstuff",11);
   

   std::cout << hey << std::endl;


   system("PAUSE");
   delete Mem;
   return 0;   //Mem.read<int>(0x0);
}

char* Memory::query(const char *data,size_t len)
{
   _handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, _processID);//PROCESS_QUERY_INFORMATION, PROCESS_VM_READ
   DWORD dwProtectionMask = PAGE_READONLY | PAGE_EXECUTE_WRITECOPY | PAGE_READWRITE | PAGE_WRITECOMBINE;
   SYSTEM_INFO si;
   GetSystemInfo(&si);

   MEMORY_BASIC_INFORMATION memoryInfo;

   char* p = 0;
   int page = 0;

   while (p < si.lpMaximumApplicationAddress)
   {
      if (VirtualQueryEx(_handle, p, &memoryInfo, sizeof(memoryInfo)) == sizeof(memoryInfo))
      {
         p = (char*)memoryInfo.BaseAddress;
         char *buffer = new char[memoryInfo.RegionSize];

         SIZE_T bytesRead;
         if (ReadProcessMemory(_handle, p, &buffer[0], memoryInfo.RegionSize, &bytesRead))
         {
            for (size_t i = 0; i < (bytesRead - len); ++i)
            {
               if (memcmp(data, &buffer[i], len) == 0)
               {
                  std::cout << page << " end\n";
                  return (char*)p + i;
               }
            }
         }
         p += memoryInfo.RegionSize;
         delete[] buffer;
      }
      page++;
      std::cout << page << ":pages read.\n";
      
      Sleep(50);
      
   }
   return "no find";
}



the program finds process1 gets the handle and searches its virtualqueryex (3 pages) it must find a match because "end" is cout, but it throws a read access violation and will not return (char*)p + i, then has a bunch of errors about

e.g. Hack.exe' (Win32): Loaded 'C:\Windows\SysWOW64\ntdll.dll'. Cannot find or open the PDB file.

anyone else have similar experience or can help? thank.

[spoiler]
another problem i had was when reading 30-50 pages of virtual memory a bad memory allocation exception would be thrown but hopefully i never have to read that much...
[/spoiler]
Back to top
View user's profile Send private message
Viloresi
Expert Cheater
Reputation: 0

Joined: 02 Feb 2017
Posts: 149

PostPosted: Mon Feb 20, 2017 9:47 am    Post subject: Reply with quote

You must get an access violation becausw you aren't checking if the pages you are reading are accesible... You've declared thedwProtectionMask but you are not using it... You are just checking if the virtualqueryex function fails or not, so you have to add an if condition to see if the "returned" (it's not actually returned since it's stored into you memorybasicinformation) values are matching the dw protection mask, also you should start from a very simple program tha reads just the numbers inside the addresses so you can understand this better
Back to top
View user's profile Send private message
Harambe132
How do I cheat?
Reputation: 0

Joined: 19 Feb 2017
Posts: 3

PostPosted: Mon Feb 20, 2017 3:19 pm    Post subject: Reply with quote

edit: i changed the query function to DWORD and return (DWORD)p+i, now the program returns an address.

just got to figure out why my write is failing and if it works ill get back.

Code:

DWORD Memory::query(const char *data, size_t len)
{
   DWORD dwProtectionMask = PAGE_READONLY | PAGE_EXECUTE_WRITECOPY | PAGE_READWRITE | PAGE_WRITECOMBINE;
   SYSTEM_INFO si;
   GetSystemInfo(&si);
   
   MEMORY_BASIC_INFORMATION memoryInfo;
   
   unsigned char* p = (unsigned char*)_processAddress;
   int page = 0;
   
   while (p < si.lpMaximumApplicationAddress)
   {
      if (VirtualQueryEx(_handle, p, &memoryInfo, sizeof(memoryInfo)) == sizeof(memoryInfo))
      {
         if ((memoryInfo.AllocationProtect & dwProtectionMask) && (memoryInfo.State & MEM_COMMIT))
         {
            //p = (char*)memoryInfo.BaseAddress;
            unsigned char *buffer = new unsigned char[memoryInfo.RegionSize];
   
            SIZE_T bytesRead;
            if (ReadProcessMemory(_handle, p, &buffer[0], memoryInfo.RegionSize, &bytesRead))
            {
               for (size_t i = 0; i < (bytesRead - len); ++i)
               {
                  if (memcmp(data, &buffer[i], len) == 0)
                  {
                     std::cout << page << " end\n";
                     const char* writeValue = "stringNew";
                     LPVOID writeAddress = p + i;
                     if (WriteProcessMemory(_handle, writeAddress, &writeValue, sizeof(writeValue), 0)!=0) {
                        std::cout << "write success!\n";
                     }
                     else {
                        std::cout << "write failure\n";
                     }
                     return (DWORD)writeAddress;
                  }
               }
            }
            p += memoryInfo.RegionSize;
            delete[] buffer;
         }      
      }
      page++;
      std::cout << page << ":pages read.\n";
      Sleep(50);
   }
   return 0;
}
Back to top
View user's profile Send private message
Viloresi
Expert Cheater
Reputation: 0

Joined: 02 Feb 2017
Posts: 149

PostPosted: Mon Feb 20, 2017 4:22 pm    Post subject: Reply with quote

Edit: sorry I've messed with your variables before, since I didn't see you've called the structure as memoryInfo...

You're doing it wrong, if you are not sure just put a cout just next to the virtualqueryex and see what values are stored inside tje memorybasicinformation structure...
Aniway you have to change tha allocationprotect to (memoryInfo.Protect & dwProtectionMask) .
Maybe this code will help you (the first one, bevause the others have some errors)
http://www.cplusplus.com/forum/general/202725/


And take a look how that structure is (i guess you already did, but who knows)
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366775(v=vs.85).aspx
Back to top
View user's profile Send private message
Harambe132
How do I cheat?
Reputation: 0

Joined: 19 Feb 2017
Posts: 3

PostPosted: Mon Feb 20, 2017 10:24 pm    Post subject: Reply with quote

i converted the query function to search for an int (69) in process1, figured out the address to be (base address += regionSize) + i*sizeof(int).

read the address to confirm this, and my process1 struct on the heap will not allow me access to write. feelsbadman.

_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE, TRUE, _processID);

Code:

#include <iostream>
#include <windows.h>


struct stuff {
   int i = 69;
};


int main() {

   int temp = 0;

   stuff *stuffPtr = new stuff();//creates a stuff thing with its default values set
   while (1) {
      std::cout << "i: " << stuffPtr->i << "\n";
      Sleep(5000);
   }
   delete stuffPtr;
   return 1;
}
Back to top
View user's profile Send private message
ulysse31
Master Cheater
Reputation: 2

Joined: 19 Mar 2015
Posts: 324
Location: Paris

PostPosted: Tue Feb 21, 2017 10:13 am    Post subject: Reply with quote

Any reason you don't open process with all access?
Code:
DebuggedProc.hwnd = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID);

Or even better, dbug privileges ?
Code:
BOOL SetPrivilege(
   HANDLE hToken,          // access token handle
   LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
   BOOL bEnablePrivilege   // to enable or disable privilege
)
{
   TOKEN_PRIVILEGES tp;
   LUID luid;

   if (!LookupPrivilegeValue(
      NULL,            // lookup privilege on local system
      lpszPrivilege,   // privilege to lookup
      &luid))        // receives LUID of privilege
   {
      printf("LookupPrivilegeValue error: %u\n", GetLastError());
      return FALSE;
   }

   tp.PrivilegeCount = 1;
   tp.Privileges[0].Luid = luid;
   if (bEnablePrivilege)
      tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
   else
      tp.Privileges[0].Attributes = 0;

   // Enable the privilege or disable all privileges.

   if (!AdjustTokenPrivileges(
      hToken,
      FALSE,
      &tp,
      sizeof(TOKEN_PRIVILEGES),   
      (PTOKEN_PRIVILEGES)NULL,
      (PDWORD)NULL))
   {
      printf("AdjustTokenPrivileges error: %u\n", GetLastError());
      return FALSE;
   }

   if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)

   {
      printf("The token does not have the specified privilege. \n");
      return FALSE;
   }

   return TRUE;
}
int ProcessPriv()
{
   // get process handle
   HANDLE hProc = GetCurrentProcess();

   // get access token of process
   HANDLE hToken = NULL;
   if (!OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES, &hToken))
      fout << "Failed to open access token" << endl;

   // set token privileges to SE_DEBUG_NAME to able to access OpenProcess() with PROCESS_ALL_ACCESS
   if (!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE))
      fout <<"Failed to set debug privilege" << endl;

   return 0;
}


Why are you doing a monologue ? It appears to me that Viloresi makes valid points.
Quote:
process1 struct on the heap will not allow me access to write

See if you can write with Cheat Engine but considering you do not even check the memory page rights, there is not much to say. Obviously someone already told you to check for those rights but then again.


Code:
MEMBLOCK * QueryMemoryAddrress(int64_t addr)
{
   MEMORY_BASIC_INFORMATION meminfo;
   MEMBLOCK *mb = nullptr;
   DWORD error = GetLastError();
   if (DebuggedProc.hwnd)
   {
         if (VirtualQueryEx(DebuggedProc.hwnd, (LPCVOID)addr, &meminfo, sizeof(meminfo)) == 0)
         {
            fout << "Virtual Query failed" << endl;
         }
#define WRITABLE (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE | PAGE_EXECUTE_READ)
         if ((meminfo.State & MEM_COMMIT))// && (meminfo.Protect & WRITABLE))
         {
            fout << "Memory pages are writable and commited" << endl;
            mb = create_memblockInsertDisas(DebuggedProc.hwnd, &meminfo, 1);
            fout << "base add : " << hex << meminfo.BaseAddress << endl;
            fout << "wanted add : " << hex << addr << endl;
            fout << "regionsize : " << meminfo.RegionSize << endl;
            addr += meminfo.RegionSize;
         }
         else
         {
            fout << "Memory pages are not writable and/or not MEM comit" << endl;
         }
   }
   else
      fout << "no process handle" << endl;
   DebuggedProc.basePageAddress =(int64_t) meminfo.BaseAddress;
   fillEachMemblock(mb);
   return mb;
}


1/ Your protection masks DWORD dwProtectionMask = PAGE_READONLY |..
So if the protection is readonly you'll still try to write to it.
2/You check the allocation with the member allocation state instead of state (because current memory page state is not necessarily the same state as when it was allocated), that's a mistake
Quote:
memoryInfo.AllocationProtect
instead of
meminfo.Protect
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