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 


[HELP - C++] Failed using PAGE_READWRITE on Memory Scanner

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

Joined: 30 Sep 2010
Posts: 1

PostPosted: Thu Sep 30, 2010 10:56 pm    Post subject: [HELP - C++] Failed using PAGE_READWRITE on Memory Scanner Reply with quote

I try to using a HadFuny Memory Scanner source code, worked like a charms when I compile to be an executable. But, when I modify and compile to be a DLL (injection), the process that has been injected using RAM resource so high (any program windows is not responding, but the cursor still moveable).

here the source:

memscan.h
Code:

// Filename: MemoryScan.cpp
// Author: HadFuny
// Date: 28-05-2010
// Copyright HadFuny 2010

/*
#include <windows.h>
#include <stdio.h>
*/

#define IS_IN_SEARCH(mb,offset) (mb->searchmask[(offset) / 8] & ( 1 << ((offset) % 8)))
#define REMOVE_FROM_SEARCH(mb,offset) mb->searchmask[(offset) / 8] &= ~(1<<((offset) % 8));

typedef struct _MEMBLOCK
{
    HANDLE hProc;
    unsigned char *addr;
    int size;
    unsigned char *buffer;

    unsigned char *searchmask;
    int matches;
    int data_size;

    struct _MEMBLOCK *next;
} MEMBLOCK;

typedef enum
{
    COND_UNCONDITIONAL,
    COND_EQUALS,

    COND_INCREASED,
    COND_DECREASED,
} SEARCH_CONDITION;

// added for debugging
void __cdecl odprintf(const char *format, ...)
{
   char    buf[4096], *p = buf;
   va_list args;
   int     n;

    va_start(args, format);
    n = _vsnprintf(p, sizeof buf - 3, format, args); // buf-3 is room for CR/LF/NUL
    va_end(args);

    p += (n < 0) ? sizeof buf - 3 : n;

    while ( p > buf  &&  isspace(p[-1]) )
            *--p = '\0';

    *p++ = '\r';
    *p++ = '\n';
    *p   = '\0';

    OutputDebugString(buf);
}
// added for debugging

MEMBLOCK* create_memblock (HANDLE hProc, MEMORY_BASIC_INFORMATION *meminfo, int data_size)
{
    MEMBLOCK *mb = (MEMBLOCK*)malloc(sizeof(MEMBLOCK));

    if (mb)
    {
        mb->hProc = hProc;
        mb->addr = (unsigned char*)meminfo->BaseAddress;
        mb->size = meminfo->RegionSize;
        mb->buffer = (unsigned char*)malloc (meminfo->RegionSize);
        mb->searchmask = (unsigned char*)malloc (meminfo->RegionSize/8);
        memset (mb->searchmask, 0xff, meminfo->RegionSize/8);
        mb->matches = meminfo->RegionSize;
        mb->data_size = data_size;
        mb->next = NULL;
    }

    return mb;
}

void free_memblock (MEMBLOCK *mb)
{
    if (mb)
    {
        if (mb->buffer)
        {
            free (mb->buffer);
        }

        if (mb->searchmask)
        {
            free (mb->searchmask);
        }

        free (mb);
    }
}


void update_memblock (MEMBLOCK *mb, SEARCH_CONDITION condition, unsigned int val)
{
    static unsigned char tempbuf[128*1024];
    unsigned int bytes_left;
    unsigned int total_read;
    unsigned int bytes_to_read;
    unsigned int bytes_read;

    if (mb->matches > 0)
    {
        bytes_left = mb->size;
        total_read = 0;
        mb->matches = 0;
   
        while (bytes_left)
        {
            bytes_to_read = (bytes_left > sizeof(tempbuf)) ? sizeof(tempbuf) : bytes_left;
            ReadProcessMemory (mb->hProc, mb->addr + total_read, tempbuf, bytes_to_read, (DWORD*)&bytes_read);
            if (bytes_read != bytes_to_read) break;
   
            if (condition == COND_UNCONDITIONAL)
            {
                memset (mb->searchmask + (total_read/8), 0xff, bytes_read/8);
                mb->matches += bytes_read;
            }
            else
            {
                unsigned int offset;
   
                for (offset = 0; offset < bytes_read; offset += mb->data_size)
                {
                    if (IS_IN_SEARCH(mb,(total_read+offset)))
                    {
                        BOOL is_match = FALSE;
                        unsigned int temp_val;
                        unsigned int prev_val = 0;
   
                        switch (mb->data_size)
                        {
                            case 1:
                                temp_val = tempbuf[offset];
                                prev_val = *((unsigned char*)&mb->buffer[total_read+offset]);
                                break;
                            case 2:
                                temp_val = *((unsigned short*)&tempbuf[offset]);
                                prev_val = *((unsigned short*)&mb->buffer[total_read+offset]);
                                break;
                            case 4:
                            default:
                                temp_val = *((unsigned int*)&tempbuf[offset]);
                                prev_val = *((unsigned int*)&mb->buffer[total_read+offset]);
                                break;
                        }
   
                        switch (condition)
                        {
                            case COND_EQUALS:
                                is_match = (temp_val == val);
                                break;
                            case COND_INCREASED:
                                is_match = (temp_val > prev_val);
                                break;
                            case COND_DECREASED:
                                is_match = (temp_val < prev_val);
                                break;
                            default:
                                break;
                        }
   
                        if (is_match)
                        {
                            mb->matches++;
                        }
                        else
                        {
                            REMOVE_FROM_SEARCH(mb,(total_read+offset));
                        }
                    }
                }
            }
   
            memcpy (mb->buffer + total_read, tempbuf, bytes_read);
   
            bytes_left -= bytes_read;
            total_read += bytes_read;
        }
   
        mb->size = total_read;
    }
}



MEMBLOCK* create_scan (unsigned int pid, int data_size)
{
    MEMBLOCK *mb_list = NULL;
    MEMORY_BASIC_INFORMATION meminfo;
    unsigned char *addr = 0;

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);

    if (hProc)
    {
        while (1)
        {
            if (VirtualQueryEx(hProc, addr, &meminfo, sizeof(meminfo)) == 0)
            {
                break;
            }
         
         #define WRITABLE (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
           
         if ((meminfo.State & MEM_COMMIT) && (meminfo.Protect & WRITABLE))
            {
                MEMBLOCK *mb = create_memblock (hProc, &meminfo, data_size);
                if (mb)
                {
                    mb->next = mb_list;
                    mb_list = mb;
                }
            }
            addr = (unsigned char*)meminfo.BaseAddress + meminfo.RegionSize;
        }
    }

    return mb_list;
}


void free_scan(MEMBLOCK *mb_list)
{
    CloseHandle (mb_list->hProc);

    while (mb_list)
    {
        MEMBLOCK *mb = mb_list;
        mb_list = mb_list->next;
        free_memblock (mb);
    }
}

void update_scan (MEMBLOCK *mb_list, SEARCH_CONDITION condition, unsigned int val)
{
    MEMBLOCK *mb = mb_list;
    while (mb)
    {
        update_memblock (mb, condition, val);
        mb = mb->next;
    }
}


void dump_scan_info(MEMBLOCK *mb_list)
{
    MEMBLOCK *mb = mb_list;

    while (mb)
    {
        int i;
        odprintf("0x%08x %d", mb->addr, mb->size);

        for (i = 0; i < mb->size; i++)
        {
            printf ("%02x", mb->buffer[i]);
        }

        mb = mb->next;
    }
}


void poke (HANDLE hProc, int data_size, unsigned int addr, unsigned int val)
{
    if (WriteProcessMemory (hProc, (void*)addr, &val, data_size, NULL) == 0)
    {
        odprintf("poke failed");
    }
}

unsigned int peek(HANDLE hProc, int data_size, unsigned int addr)
{
    unsigned int val = 0;

    if (ReadProcessMemory (hProc, (void*)addr, &val, data_size, NULL) == 0)
    {
        odprintf("peek failed");
    }

    return val;
}


void print_matches (MEMBLOCK *mb_list)
{
    unsigned int offset;
    MEMBLOCK *mb = mb_list;

    while (mb)
    {
        for (offset = 0; offset < mb->size; offset += mb->data_size)
        {
            if (IS_IN_SEARCH(mb,offset))
            {
                unsigned int val = peek (mb->hProc, mb->data_size, (unsigned int)mb->addr + offset);
                odprintf("0x%08x: 0x%08x (%d)", mb->addr + offset, val, val);
            }
        }

        mb = mb->next;
    }
}


int get_match_count (MEMBLOCK *mb_list)
{
    MEMBLOCK *mb = mb_list;
    int count = 0;

    while (mb)
    {
        count += mb->matches;
        mb = mb->next;
    }

    return count;
}

unsigned int str2int (char *s)
{
    int base = 10;

    if (s[0] == '0' && s[1] == 'x')
    {
        base = 16;
        s += 2;
    }

    return strtoul (s, NULL, base);
}


dllmain.cpp
Code:

#include <windows.h>
#include <stdio.h>
#include "memscan.h"

#define SCAN_VALUE_SIZE      4      // 4 bytes
#define   SCAN_VALUE_START   100      // the value

MEMBLOCK *StartNewScan(void)
{
   DWORD dwProcessID = GetCurrentProcessId();

   MEMBLOCK *scan = NULL;
   scan = create_scan(dwProcessID, SCAN_VALUE_SIZE);

   if(!scan)
   {
      odprintf("[StartNewScan()] SCAN: FALSE | Breaking...");
      return FALSE;
   }

   odprintf("[StartNewScan()] SCAN: TRUE | Continue...");

   update_scan(scan, COND_EQUALS, SCAN_VALUE_START);

   odprintf("[StartNewScan()] %d matches found!", get_match_count(scan));

   return scan;
}

void DoScanning(void)
{
   MEMBLOCK *scan;

   scan = StartNewScan();

   if(scan)
   {
      odprintf("[DoScanning()] SCAN: TRUE | Continue to search...");
      while(true)
      {
         if(GetAsyncKeyState(VK_F10)&1)
         {
            update_scan(scan, COND_DECREASED, 0);
            odprintf("[DoScanning()] Decreased value: %d matches found!", get_match_count(scan));
         }

         if(GetAsyncKeyState(VK_F11)&1)
         {
            odprintf("[DoScanning()] Print matched output:");
            print_matches(scan);
         }

         if(GetAsyncKeyState(VK_F12)&1)
         {
            odprintf("[DoScanning()] Dumping scan info:");
            dump_scan_info(scan);
         }

         Sleep(10);
      }
   }
   else
   {
      odprintf("[DoScanning()] SCAN: FALSE | Leaving...");
   }

}

BOOL WINAPI Loop(LPVOID lpParam)
{
   while(true)
   {
      if(GetAsyncKeyState(VK_F9)&1) DoScanning();
     
      Sleep(1);
   }

   return TRUE;
}

BOOL WINAPI DllMain(HMODULE hDll, DWORD dwReason, LPVOID lpReserved)
{
   DisableThreadLibraryCalls(hDll);
   
   if(dwReason == DLL_PROCESS_ATTACH)
   {
      odprintf("[DllMain()] DLL_PROCESS_ATTACH");
      CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)Loop, NULL, NULL, NULL);
   }
   else if(dwReason == DLL_PROCESS_DETACH)
   {
      odprintf("[DllMain()] DLL_PROCESS_DETACH");
   }

   return TRUE;
}


please look at this line: memscan.h (create_scan())
Code:

#define WRITABLE (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)


if I use PAGE_READWRITE argument, the program that has been injected not responding (high RAM).

but if without PAGE_READWRITE argument, then show some results, but not the actual search result.

What's wrong with that? I hope there is someone who can help me.

Thanks in advance!

PS: I try to injecting Cheat Engine Tutorial (Tutorial.exe) part I for the sample (looking for a value of 100, and will be decreased)
Back to top
View user's profile Send private message
justa_dude
Grandmaster Cheater
Reputation: 23

Joined: 29 Jun 2010
Posts: 893

PostPosted: Fri Oct 01, 2010 12:01 pm    Post subject: Reply with quote

A few suggestions for you.

1) If you post 5 lines of code that don't work, someone will find the error. If you post 20 lines of code that don't work, someone might find the error. If you post three pages of code that don't work, most folks won't bother.

2) You should try to understand what the code does before altering it. This code uses a lot of functionality for interacting with /other/ processes. When you inject a dll, you can manipulate memory/etc directly.

3) You can attach a debugger and/or profiler to your code to see exactly what's going on.

4) Creating a thread from inside DLLMain is probably a bad idea. It would be better to have the injecting process initiate the thread.
Back to top
View user's profile Send private message
tombana
Master Cheater
Reputation: 2

Joined: 14 Jun 2007
Posts: 456
Location: The Netherlands

PostPosted: Fri Oct 01, 2010 1:30 pm    Post subject: Reply with quote

justa_dude wrote:
4) Creating a thread from inside DLLMain is probably a bad idea. It would be better to have the injecting process initiate the thread.

That's not a problem. That's what most injected dlls do.
Back to top
View user's profile Send private message
justa_dude
Grandmaster Cheater
Reputation: 23

Joined: 29 Jun 2010
Posts: 893

PostPosted: Fri Oct 01, 2010 1:59 pm    Post subject: Reply with quote

tombana wrote:
justa_dude wrote:
4) Creating a thread from inside DLLMain is probably a bad idea. It would be better to have the injecting process initiate the thread.

That's not a problem. That's what most injected dlls do.


He's calling functions from STDIO inside that thread. AFAIK, any blocking action (which STDIO does a lot of) could cause deadlock. Using functions from anywhere but kernel32 is documented as bad practice, and this code has obviously not been studied to an extent that would qualify it as only doing "safe" things. Not to mention the fact that it confuses the fact that being loaded is not the same thing in Windows parlance as being told to "go." DLLs get loaded without ever doing any real work all the time.

Cheers,
adude
Back to top
View user's profile Send private message
Jesper
Grandmaster Cheater Supreme
Reputation: 9

Joined: 21 Feb 2007
Posts: 1156

PostPosted: Fri Oct 01, 2010 7:17 pm    Post subject: Reply with quote

The source looks a lot like if not exactly like the one in http://www.youtube.com/watch?v=YRPMdb1YMS8. Maybe you should ask the maker of the tutorial for help?
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