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++ VirtualQueryEx

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
dm0000
Newbie cheater
Reputation: 0

Joined: 09 Nov 2014
Posts: 16

PostPosted: Tue Dec 16, 2014 5:02 pm    Post subject: C++ VirtualQueryEx Reply with quote

Hello, here we go again,

I'm trying to scan a process memory using VirtualQueryEx for a value.

I'm only getting strange address's, well, it's not even a address.

Maybe something about conversions, idk.

The value have a address of 4 bytes type.

Code:
void ScanAndWrite(LPVOID value){
   MyWnd.SetMyToken();

   //1 - process ID
   char buf[255];
   GetDlgItemText(MyWnd.hwnd, 100, buf, 255); // get text from a combobox
   //convert to string to parse (get number before a blank space)
   string id = string(buf);
   string strFinal = id.substr(0, id.find_first_of(" "));
   DWORD pIDparsed = strtoul(strFinal.c_str(), 0, 0); // convert the parsed string to DWORD

   //2 - Get process handle
   HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pIDparsed);
   if (pHandle == NULL) { MessageBox(NULL, "pHandle NULL", "OpenProcess", MB_OK | MB_ICONWARNING); TerminateThread(MyWnd.threadScan, 1); }
   
   //3- Start memory scan
   MEMORY_BASIC_INFORMATION mBI;
   UINT memoryRegionStart = 0x1FFFFF;
   UINT memoryRegionEnd = 0x7fffffffffffffff;   
   SendMessage(MyWnd.pB, PBM_SETRANGE, 0, MAKELPARAM(memoryRegionStart, memoryRegionEnd));   //progressbar
   do{
      SIZE_T vQe = VirtualQueryEx(pHandle, (void*)memoryRegionStart, &mBI, sizeof(MEMORY_BASIC_INFORMATION));
      if (vQe == 0) { MessageBox(NULL, "VirtualQueryEx fails", "VirtualQueryEx", MB_OK | MB_ICONWARNING); TerminateThread(MyWnd.threadScan, 1); }
      
      if ((mBI.State == MEM_COMMIT) && (mBI.Type == MEM_PRIVATE) && (mBI.Protect == PAGE_READWRITE)){
         UINT start, end;
         start = (UINT)mBI.BaseAddress;
         end = (UINT)mBI.BaseAddress + mBI.RegionSize;
         //ready memory
         LPVOID valueFound;
         SIZE_T byteToRead = 4;
         for (start; start < end; start = start +4){            
            if (ReadProcessMemory(pHandle, (LPCVOID)start, &valueFound, sizeof(valueFound), &byteToRead)){
               SendMessage(MyWnd.lB, LB_ADDSTRING, 0, (LPARAM)&start); // test to add all address
               if (&valueFound == value){
                  SendMessage(MyWnd.lB, LB_ADDSTRING, 0, (LPARAM)&start); // add address to a listbox                  
               }
            }
         }
      }   
      memoryRegionStart += mBI.RegionSize;      
      SendMessage(MyWnd.pB, PBM_SETPOS, (WPARAM)memoryRegionStart, 0);
   } while (memoryRegionStart < memoryRegionEnd);
   
   CloseHandle(pHandle);
   TerminateThread(MyWnd.threadScan, 0);
}


I call it in a button like this:

Code:
LPVOID tP = "45000";
DWORD tId;
MyWnd.threadScan = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ScanAndWrite, tP, 0, &tId);


Function is definide as:

Code:
void ScanAndWrite(LPVOID value);


Result:

Gif with the result: http://s29.postimg.org/sbd98md8n/scan_gif.gif

*forum says that i can't post links =(

I need tips about what i need to change here to make it work. I'm out of ideas.
I should have something like 20~25 address only (tested with cheat engine).

Ty!
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: Tue Dec 16, 2014 5:28 pm    Post subject: Reply with quote

You need to format the string you are trying to show in the list. You can't just toss the listbox the value and assume it will do it for you.

So this line:
SendMessage(MyWnd.lB, LB_ADDSTRING, 0, (LPARAM)&start);

Should be using a formatted string instead of the raw searched result address. You could do something like this:
Code:

char szBuffer[1024] = { 0 };
sprintf_s(szBuffer, 1024, "%d", start);
SendMessage(MyWnd.lB, LB_ADDSTRING, 0, (LPARAM)&szBuffer);


You should also consider dumping the whole region at once and scanning within it instead of constantly calling ReadProcessMemory.

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

Joined: 09 Nov 2014
Posts: 16

PostPosted: Tue Dec 16, 2014 10:44 pm    Post subject: Reply with quote

atom0s wrote:
You need to format the string you are trying to show in the list. You can't just toss the listbox the value and assume it will do it for you.

So this line:
SendMessage(MyWnd.lB, LB_ADDSTRING, 0, (LPARAM)&start);

Should be using a formatted string instead of the raw searched result address. You could do something like this:
Code:

char szBuffer[1024] = { 0 };
sprintf_s(szBuffer, 1024, "%d", start);
SendMessage(MyWnd.lB, LB_ADDSTRING, 0, (LPARAM)&szBuffer);


You should also consider dumping the whole region at once and scanning within it instead of constantly calling ReadProcessMemory.


Yes.

start need to be %p to show the pointer.

The problem is to get the value now and make it scan faster as cheat engine. holly shit, to much time to finish.

This is the CE settings that i'm trying to reproduce in my code: s16.postimg.org/5upuj3aj9/ce_settings.png
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 Dec 17, 2014 1:09 am    Post subject: Reply with quote

Like I said at the end of my post, you are constantly calling ReadProcessMemory, this is a very poor implementation of writing a scanner. You should dump the whole region of memory for the current block you iterated from VirtualQueryEx and scan locally within that block instead.

Here is a very basic thrown together example of searching for 4 byte values I threw together for you:
Code:

/**
 * Simple Memory Scanner Example
 * (c) 2014 atom0s [[email protected]]
 */

#include <Windows.h>
#include <string>
#include <TlHelp32.h>

/**
 * @brief The target process to scan within.
 */
#define TARGET_NAME "winmine.exe"

/**
 * @brief Obtains the process id of the given target.
 *
 * @return The process id if found, 0 otherwise.
 */
unsigned int getTargetProcessId()
{
    PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };

    // Obtain a snapshot of the current process list..
    auto handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (handle == INVALID_HANDLE_VALUE)
        return 0;

    // Obtain the first process..
    if (!::Process32First(handle, &pe32))
    {
        ::CloseHandle(handle);
        return 0;
    }

    // Loop each process looking for the target..
    do
    {
        if (!_stricmp(pe32.szExeFile, TARGET_NAME))
        {
            ::CloseHandle(handle);
            return pe32.th32ProcessID;
        }
    } while (::Process32Next(handle, &pe32));

    // Cleanup..
    ::CloseHandle(handle);
    return 0;
}

/**
 * @brief Entry point of this application.
 *
 * @param argc  The count of arguments passed to this application.
 * @param argv  The array of arguments passed to this application.
 *
 * @return Non-important return.
 */
int __cdecl main(int argc, char* argv[])
{
    // Obtain the target process id..
    auto processId = getTargetProcessId();
    if (processId == 0)
        return 0;

    // Open a handle to the target..
    auto handle = ::OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId);
    if (handle == INVALID_HANDLE_VALUE)
        return 0;

    // Obtain the current system information..
    SYSTEM_INFO sysInfo = { 0 };
    ::GetSystemInfo(&sysInfo);

    auto addr_min = (long)sysInfo.lpMinimumApplicationAddress;
    auto addr_max = (long)sysInfo.lpMaximumApplicationAddress;

    auto found = 0;

    // Loop the pages of memory of the application..
    while (addr_min < addr_max)
    {
        MEMORY_BASIC_INFORMATION mbi = { 0 };
        if (!::VirtualQueryEx(handle, (LPCVOID)addr_min, &mbi, sizeof(mbi)))
        {
            printf_s("Failed to query memory.\n");
            break;
        }

        // Determine if we have access to the page..
        if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_GUARD) == 0) && ((mbi.Protect & PAGE_NOACCESS) == 0))
        {
            //
            // Below are flags about the current region of memory. If you want to specifically scan for only
            // certain things like if the area is writable, executable, etc. you can use these flags to prevent
            // reading non-desired protection types.
            //

            auto isCopyOnWrite = ((mbi.Protect & PAGE_WRITECOPY) != 0 || (mbi.Protect & PAGE_EXECUTE_WRITECOPY) != 0);
            auto isExecutable = ((mbi.Protect & PAGE_EXECUTE) != 0 || (mbi.Protect & PAGE_EXECUTE_READ) != 0 || (mbi.Protect & PAGE_EXECUTE_READWRITE) != 0 || (mbi.Protect & PAGE_EXECUTE_WRITECOPY) != 0);
            auto isWritable = ((mbi.Protect & PAGE_READWRITE) != 0 || (mbi.Protect & PAGE_WRITECOPY) != 0 || (mbi.Protect & PAGE_EXECUTE_READWRITE) != 0 || (mbi.Protect & PAGE_EXECUTE_WRITECOPY) != 0);

            // Dump the region into a memory block..
            auto dump = new unsigned char[mbi.RegionSize + 1];
            memset(dump, 0x00, mbi.RegionSize + 1);
            if (!::ReadProcessMemory(handle, mbi.BaseAddress, dump, mbi.RegionSize, NULL))
            {
                printf_s("Failed to read memory of location: %08X\n", mbi.BaseAddress);
                break;
            }

            // Scan for 4 byte value of 1337..
            for (auto x = 0; x < mbi.RegionSize - 4; x += 4)
            {
                if (*(DWORD*)(dump + x) == 1337)
                    found++;
            }

            // Cleanup the memory dump..
            delete[] dump;
        }

        // Step the current address by this regions size..
        addr_min += mbi.RegionSize;
    }

    printf_s("Found %d results!\n", found);

    // Cleanup..
    ::CloseHandle(handle);
    return ERROR_SUCCESS;
}


This will dump the region once, and locally scan within it. Which is much faster then constantly calling ReadProcessMemory.

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

Joined: 09 Nov 2014
Posts: 16

PostPosted: Wed Dec 17, 2014 8:15 am    Post subject: Reply with quote

wow! Ty! I'm studying it. Since i don't like copy/paste.

Why are you not using PROCESS_ALL_ACCESS ?

I didn't know about "auto". I don't see why use "auto every time.

ow, you are using GetSystemInfo. nice.

VirtualQueryEx fails when return 0, no? it's not a bool.

My first try, and my code looks more complicated.

In my function to get the process i'm setting processentrry32 dwSize and not calling like you do.

Code:

bool Window::ListProcess(){
   PROCESSENTRY32 pEntry;
   HANDLE pSnap;
   int pos = 0;
   pSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   pEntry.dwSize = sizeof(PROCESSENTRY32);
   if (pSnap == INVALID_HANDLE_VALUE)   return false;
   if (!Process32First(pSnap, &pEntry)) {
      CloseHandle(pSnap);
      return false;
   }
   while (Process32Next(pSnap, &pEntry)){
      //parse strings
      string processExe = string(pEntry.szExeFile);
      char procID[10];      
      sprintf_s(procID, "%lu", pEntry.th32ProcessID);
      string finalText = string(procID) + " - " + processExe;      
      SendMessage(MyWnd.pB, PBM_SETRANGE, 0, MAKELPARAM(0, 100));

      if (processExe.find("chrome") != string::npos || processExe.find("plugin") != string::npos
         || processExe.find("Flash") != string::npos || processExe.find("iex") != string::npos){
         pos++;
         SendMessage(MyWnd.pB, PBM_SETPOS, (WPARAM)pos, 0);
         //get memory info                  
         HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pEntry.th32ProcessID);
         PROCESS_MEMORY_COUNTERS info = { 0 };
         info.cb = sizeof(info);
         GetProcessMemoryInfo(process, &info, sizeof(info));
         SIZE_T memorySize = (info.WorkingSetSize / 1024) / 1024; // bytes to mega
         char mU[255];
         sprintf_s(mU, "%lu", memorySize);         
         finalText = finalText + " : " + string(mU);
         SendMessage(cB, CB_ADDSTRING, 0, (LPARAM)(finalText.c_str()));         
      }
   }
   SendMessage(MyWnd.pB, PBM_SETPOS, (WPARAM)100, 0);
   CloseHandle(pSnap);
   return true;
}


BTW, the conversion of your "dump" is given wrong results:"

string test = to_string((int)dump);
string total = "Address: " + string(t1) + "- Value: " + test;

The address is missing characteris, i was trying to test your code to see how it work, using WPM to test the address.

And here:


for (auto x = 0; x < mbi.RegionSize - 4; x += 4)


i changed to

for (auto x = 0; x < (int)mbi.RegionSize - 4; x += 4)

To stop the warning: Warning 2 warning C4018: '<' : signed/unsigned mismatch

Ty! Very nice your code, i will rewrite my function i think. Rolling Eyes[/code] Embarassed


EDIT:

I did mine using your + mine:

Code:
I just re-write it:

But it is stuck in second IF ( "if 2" ):



bool scan(){
   //to write
   LPCVOID valueToWrite = 0;

   MyWnd.SetMyToken();

   //1 - process ID
   char buf[255];
   GetDlgItemText(MyWnd.hwnd, 100, buf, 255); // get text from a combobox
   //convert to string to parse (get number before a blank space)
   string id = string(buf);
   string strFinal = id.substr(0, id.find_first_of(" "));
   DWORD pIDparsed = strtoul(strFinal.c_str(), 0, 0); // convert the parsed string to DWORD

   HANDLE pHandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pIDparsed);
   if (pHandle == INVALID_HANDLE_VALUE){
      CloseHandle(pHandle); TerminateThread(MyWnd.threadScan, 1); return false; //not thread safe
   }

   SYSTEM_INFO sysInfo = { 0 };
   GetSystemInfo(&sysInfo);

   auto startAddress = (long)sysInfo.lpMinimumApplicationAddress;
   auto endAddress = (long)sysInfo.lpMaximumApplicationAddress;

   while (startAddress < endAddress){
      MEMORY_BASIC_INFORMATION mbi = { 0 };
      if (VirtualQueryEx(pHandle, (LPCVOID)startAddress, &mbi, sizeof(mbi)) != 0){ //if 1         
         if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_GUARD) == 0) && ((mbi.Protect & PAGE_NOACCESS) == 0)) {   //if 2      
            bool isWritable = ( mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_WRITECOPY || mbi.Protect == PAGE_EXECUTE_READWRITE || mbi.Protect == PAGE_EXECUTE_WRITECOPY);
            if (isWritable){ //if 3               
               auto dump = new unsigned char[mbi.RegionSize + 1];
               memset(dump, 0x00, mbi.RegionSize + 1);
               if (!ReadProcessMemory(pHandle, mbi.BaseAddress, dump, mbi.RegionSize, NULL)){ MessageBox(NULL, "Can't read memory", "ReadProcessMemory", MB_OK); }
               for (auto x = 0; x < mbi.RegionSize - 4; x += 4){ // 4 bytes                  
                  if (*(DWORD*)(dump + x) == (DWORD)"45000"){
                     char t1[255];
                     sprintf_s(t1, "%p", mbi.BaseAddress);
                     SendMessage(MyWnd.lB, LB_ADDSTRING, 0, (LPARAM)t1);
                     WriteProcessMemory(pHandle, mbi.BaseAddress, &valueToWrite, sizeof(valueToWrite), NULL);
                  }
               }
               delete[] dump;
            }else{ MessageBox(NULL, "No Writable memory.", "mbi", MB_OK | MB_ICONERROR); return false; } //if 1

            startAddress += mbi.RegionSize;

         }else{ MessageBox(NULL, "No access to the page.", "mbi", MB_OK | MB_ICONERROR); return false; } //if 2
      }else{ MessageBox(NULL, "VirtualQueryEx fails.", "VirtualQueryEx", MB_OK | MB_ICONERROR); return false; } // if 3
   }// while
   CloseHandle(pHandle);
   TerminateThread(MyWnd.threadScan, 1);
   return true;
}





I'm trying to understand why it is stuck in "if 2", never pass. NVM, it's working, but the results are so different from Cheat Engine.

s21.postimg.org/lc69ybyif/wrong_address.png



wrong_address.PNG
 Description:
Address differents / cheat engine
 Filesize:  23.48 KB
 Viewed:  25114 Time(s)

wrong_address.PNG


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 18, 2014 12:04 am    Post subject: Reply with quote

The return of VirtualQueryEx can be treated like a boolean. If it fails it returns 0. As a boolean, false is also equal to 0. So handling it the way I do is fine.

As for the auto keyword, it is used to automatically assume the variables type without having to manually define it. The compiler makes the assumption based on the right-hand value of the assignment.

Quote:
string test = to_string((int)dump);
string total = "Address: " + string(t1) + "- Value: " + test;

The address is missing characteris, i was trying to test your code to see how it work, using WPM to test the address.


to_string just converts the raw number to a string. This is not using hexadecimal. You need to enforce hex if you want to see it that way.

Inside your new code you have:
Code:
if (*(DWORD*)(dump + x) == (DWORD)"45000"){


This is not valid in C++, you can't cast a string to a DWORD like that. You will not get the value you want, instead you are going to get the address that holds the value 45000.

As for PROCESS_ALL_ACCESS, I do not use it because it is poor practice to be greedy with flags like that. Along with that, on newer systems (Windows Vista and higher) using that flag can fail if the application does not have proper permissions.

It is better to specify only what you need.

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

Joined: 09 Nov 2014
Posts: 16

PostPosted: Fri Dec 19, 2014 10:32 am    Post subject: Reply with quote

atom0s wrote:
The return of VirtualQueryEx can be treated like a boolean. If it fails it returns 0. As a boolean, false is also equal to 0. So handling it the way I do is fine.

As for the auto keyword, it is used to automatically assume the variables type without having to manually define it. The compiler makes the assumption based on the right-hand value of the assignment.

Quote:
string test = to_string((int)dump);
string total = "Address: " + string(t1) + "- Value: " + test;

The address is missing characteris, i was trying to test your code to see how it work, using WPM to test the address.


to_string just converts the raw number to a string. This is not using hexadecimal. You need to enforce hex if you want to see it that way.

Inside your new code you have:
Code:
if (*(DWORD*)(dump + x) == (DWORD)"45000"){


This is not valid in C++, you can't cast a string to a DWORD like that. You will not get the value you want, instead you are going to get the address that holds the value 45000.

As for PROCESS_ALL_ACCESS, I do not use it because it is poor practice to be greedy with flags like that. Along with that, on newer systems (Windows Vista and higher) using that flag can fail if the application does not have proper permissions.

It is better to specify only what you need.


Ty!

I'm studying your function do mine, and i was thinking, the address "dumped" is relative to my application no? beucase when i dump it, it will change the address. or i'm wrong?

I was trying to check it with cheat engine, and WPM with your code to see what happen, and the address is different. (added PROCESS_VM_WRITE).

I'm using this inside your code to check:

printf_s("Writed %#10.1x\n", mbi.BaseAddress);

or the real address in the target process would be mbi.baseAddress + mbi.RegionSize ?

baseAddress = where it start.
regionSize = bytes of the address that have the value.

So let's say i want to WPM, i would use the address: baseAddress + regionSize .
or even: process address + baseAddress + regionsize?

Maybe i need to use VirtualAllocEx ?

Sorry for ask, i'm just trying to understand.

*sometimes i take time to awser here because i need to work too. Razz
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: Fri Dec 19, 2014 3:27 pm    Post subject: Reply with quote

dm0000 wrote:
Ty!

I'm studying your function do mine, and i was thinking, the address "dumped" is relative to my application no? beucase when i dump it, it will change the address. or i'm wrong?

I was trying to check it with cheat engine, and WPM with your code to see what happen, and the address is different. (added PROCESS_VM_WRITE).

I'm using this inside your code to check:

printf_s("Writed %#10.1x\n", mbi.BaseAddress);

or the real address in the target process would be mbi.baseAddress + mbi.RegionSize ?

baseAddress = where it start.
regionSize = bytes of the address that have the value.

So let's say i want to WPM, i would use the address: baseAddress + regionSize .
or even: process address + baseAddress + regionsize?

Maybe i need to use VirtualAllocEx ?

Sorry for ask, i'm just trying to understand.

*sometimes i take time to awser here because i need to work too. Razz


Yes, when you dump the memory region you have to adjust it for your local memory. You would use the 'mbi.BaseAddress' and add the offset inside of the region the value was found out. While you are looping the region checking for the value, the value of say 'x' is the offset to where the value would be.

So taking my above code for example:
Code:

            // Scan for 4 byte value of 1337..
            for (auto x = 0; x < mbi.RegionSize - 4; x += 4)
            {
                if (*(DWORD*)(dump + x) == 1337)
                {
                    printf_s("Found 1337 at address: %08X", (DWORD)mbi.BaseAddress + x);
                    found++;
                }
            }

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

Joined: 09 Nov 2014
Posts: 16

PostPosted: Sat Dec 20, 2014 1:19 pm    Post subject: Reply with quote

atom0s wrote:
dm0000 wrote:
Ty!

I'm studying your function do mine, and i was thinking, the address "dumped" is relative to my application no? beucase when i dump it, it will change the address. or i'm wrong?

I was trying to check it with cheat engine, and WPM with your code to see what happen, and the address is different. (added PROCESS_VM_WRITE).

I'm using this inside your code to check:

printf_s("Writed %#10.1x\n", mbi.BaseAddress);

or the real address in the target process would be mbi.baseAddress + mbi.RegionSize ?

baseAddress = where it start.
regionSize = bytes of the address that have the value.

So let's say i want to WPM, i would use the address: baseAddress + regionSize .
or even: process address + baseAddress + regionsize?

Maybe i need to use VirtualAllocEx ?

Sorry for ask, i'm just trying to understand.

*sometimes i take time to awser here because i need to work too. Razz


Yes, when you dump the memory region you have to adjust it for your local memory. You would use the 'mbi.BaseAddress' and add the offset inside of the region the value was found out. While you are looping the region checking for the value, the value of say 'x' is the offset to where the value would be.

So taking my above code for example:
Code:

            // Scan for 4 byte value of 1337..
            for (auto x = 0; x < mbi.RegionSize - 4; x += 4)
            {
                if (*(DWORD*)(dump + x) == 1337)
                {
                    printf_s("Found 1337 at address: %08X", (DWORD)mbi.BaseAddress + x);
                    found++;
                }
            }


Ty for your attention! You are a very nice person for help me!

I just finished my program with your help.

Code:

BYTE data[] = { 0x0, 0x0, 0x0, 0x0 };
DWORD wAddr = (DWORD)mbi.BaseAddress + x;
if (WriteProcessMemory(Funcs.pHandle, (BYTE*)wAddr, &data, sizeof(data), NULL)){
   SendMessage(MyCtrl.lB, LB_ADDSTRING, 0, (LPARAM)"OK");
}
else{
   SendMessage(MyCtrl.lB, LB_ADDSTRING, 0, (LPARAM)"NOT OK");
}


Where i click to give rep for you? I don't have a button!

EDIT: i was searching in msdn about multiple access in memory with thread and i can't find this info, do you know if is safe to make 2 thread to read and write memory together? I will scan for more values and it is slow if i check for everything in the same thread i think.

EDIT2: i think i will use the same thread, do a vector list with the address for each value and write memory after. Laughing

EDIT3: Do you know if flash player pluging have a memory protection? With my code or CE it crash after sometime of WPM, or crash at start.
Back to top
View user's profile Send private message
eclessiastes
How do I cheat?
Reputation: 0

Joined: 03 Sep 2016
Posts: 4

PostPosted: Sat Sep 03, 2016 4:19 am    Post subject: Reply with quote

Hello atom0s
I studied your readprocessmemory function and i have a confusion regarding it.
auto addr_min = (long)sysInfo.lpMinimumApplicationAddress;
auto addr_max = (long)sysInfo.lpMaximumApplicationAddress;
Why you use (long) ? I ask because it doesn't work.
If i change to char * it will work
auto addr_min = (char *)sysInfo.lpMinimumApplicationAddress;
auto addr_max = (char *)sysInfo.lpMaximumApplicationAddress;
Thank you for your time!
Best regards
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