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 


Scan Memory
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
tanjiajun_34
Grandmaster Cheater
Reputation: 0

Joined: 16 Feb 2006
Posts: 786
Location: Singapore

PostPosted: Wed Jan 20, 2010 5:37 am    Post subject: Scan Memory Reply with quote

I am typing to code to something like ce, but just to search 4 bytes memory.
But it is lagging like hell and takes forever.

Code:
procedure TForm1.Button1Click(Sender: TObject);
var
address,data,temp:dword;
begin
if GetProcessID(ProgramName,PidID) then
begin
PidHandle  :=  OpenProcess(PROCESS_ALL_ACCESS,False,PidId);
repeat
address:=($00400000);
ReadProcessMemory(PidHandle, Pointer(address), @data, 4, temp);
if data=strtoint(Edit1.Text) then
begin
  Listbox1.AddItem(inttostr(address), TObject(data));
end;
//Label1.Caption:=inttostr(address);
address:=address+$1;
until (address=$7FFFFFFF);
end;
end;


Edit1.text contains the value I am looking for.
Can anyone make it faster.

Another thing too, the result show in the Listbox1. is not the address. I think inttostr is not the correct way?Can someone help too?
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: Wed Jan 20, 2010 6:53 am    Post subject: Reply with quote

To make it faster, you have to read a whole chunk (like 0x1000) of bytes with one ReadProcessMemory call and then search in those bytes (and then repeat for the next chunk).
The result that is in Listbox1 is probably the address but in decimal notation instead of hexadecimal.
Back to top
View user's profile Send private message
tanjiajun_34
Grandmaster Cheater
Reputation: 0

Joined: 16 Feb 2006
Posts: 786
Location: Singapore

PostPosted: Wed Jan 20, 2010 8:57 am    Post subject: Reply with quote

By changing the 4 bytes
ReadProcessMemory(PidHandle, Pointer(address), @data, 4, temp);

To
100000 bytes?
ReadProcessMemory(PidHandle, Pointer(address), @data, 100000, temp);

Do we have to do anything to @data?

My current code is...

Code:
procedure TForm1.Button1Click(Sender: TObject);
var
address,temp:dword;
data:Array[0..100000] of dword;
begin
ProgressBar1.Max:=$7FFFFFFFF-$00400000;
if GetProcessID(ProgramName,PidID) then
begin
PidHandle  :=  OpenProcess(PROCESS_ALL_ACCESS,False,PidId);
repeat
address:=($00400000);
ReadProcessMemory(PidHandle, Pointer(address),@data,100000,temp);
ProgressBar1.Min:=0;
ProgressBar1.Position:=address-$00400000;
address:=address+$100000;
until (address=$7FFFFFFFF);
end;
end;


Ignore the ProgressBar1 for now. Is it correct? Since it load 100000, we need 100000 data? And once it loads 100000 addresses, we +100000 to the first address to reload the repeat no. of numbers? If yes, can you tell me how to check all the values in the data if it matched Edit1.text?
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: Wed Jan 20, 2010 9:40 am    Post subject: Reply with quote

tanjiajun_34 wrote:
Is it correct? Since it load 100000, we need 100000 data? And once it loads 100000 addresses, we +100000 to the first address to reload the repeat no. of numbers? If yes, can you tell me how to check all the values in the data if it matched Edit1.text?

Well almost correct. The problem is that if you for example read from 0x00400000 until 0x00600000 then not every byte in that region is always valid. Maybe the memory is valid from 0x00400000 till 0x00404000 and then there's no memory until 0x00502000 (Just using random numbers here).
So usually 0x1000 is a good size because that is the size of a page.
And then after you have scanned through the 0x1000 bytes of data you add 0x1000 to the first address and repeat. I don't know delphi so I can't help you with looping through the values once you have read them.
Back to top
View user's profile Send private message
tanjiajun_34
Grandmaster Cheater
Reputation: 0

Joined: 16 Feb 2006
Posts: 786
Location: Singapore

PostPosted: Wed Jan 20, 2010 11:12 am    Post subject: Reply with quote

That where VirtualQueryEx comes in? To find out which memory can be read.
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: Wed Jan 20, 2010 1:10 pm    Post subject: Reply with quote

tanjiajun_34 wrote:
That where VirtualQueryEx comes in? To find out which memory can be read.

Yes. There are other threads here with examples of that (in C, but converting to delphi shouldn't be too hard)
Back to top
View user's profile Send private message
tanjiajun_34
Grandmaster Cheater
Reputation: 0

Joined: 16 Feb 2006
Posts: 786
Location: Singapore

PostPosted: Wed Jan 20, 2010 7:32 pm    Post subject: Reply with quote

Can some delphi coder check if this is right?
Code:
procedure TForm1.Button2Click(Sender: TObject);
var
  address,stopaddress,resultaddress,addresstoread,temp:dword;
  canberead:MEMORY_BASIC_INFORMATION;
  data:Array[0..1000] of dword;
  scanning:integer;
begin
  if GetProcessID(ProgramName,PidID) then
  begin
    address:=($00400000);
    stopaddress:=address+1000;
    PidHandle  :=  OpenProcess(PROCESS_ALL_ACCESS,False,PidId);
    repeat
      ReadProcessMemory(PidHandle, Pointer(address),@data,1000,temp);
      if temp<>1000 then
      begin
        Virtualqueryex(PidHandle,pointer(address),canberead,1000);
        ReadProcessMemory(PidHandle, Pointer(canberead.BaseAddress),@data,canberead.RegionSize,temp);
      end;
      //ReadProcessMemory(PidHandle, Pointer(canberead.BaseAddress),@data,canberead.RegionSize,temp);
      address:=address+1000;
    until address=$7FFFFFFFF;

    closehandle(PidHandle);
  end;
end;



or this?
Code:
procedure TForm1.Button1Click(Sender: TObject);
var
canberead:MEMORY_BASIC_INFORMATION;
SystemInfo: SYSTEM_INFO;
startaddress,endaddress,eaddress:dword;
PageSize:cardinal;
temp:dword;
data:Array[0..1000] of dword;
scan:integer;
begin
if GetProcessID(ProgramName,PidID) then
begin
startaddress:=($00400000);
endaddress:=($7FFFFFFF);
eaddress:=startaddress;
GetSystemInfo(SystemInfo);
PageSize:=Systeminfo.dwPageSize;
scan:=0;
PidHandle  :=  OpenProcess(PROCESS_ALL_ACCESS,False,PidId);
    repeat
      if ReadProcessMemory(PidHandle, Pointer(eaddress),@data,PageSize,temp)=false then
      begin
      Virtualqueryex(PidHandle,pointer(eaddress),canberead,PageSize);
      ReadProcessMemory(PidHandle, Pointer(canberead.BaseAddress),@data,canberead.RegionSize,temp);
      end;
      repeat
      if data[scan]=strtoint(Edit1.Text) then
      begin
        ValueListEditor1.InsertRow(inttostr(scan+eaddress),Edit1.Text,true);
      end;
      scan:=scan+1;
      until scan=PageSize+1;
    until eaddress=endaddress+1;
end;
end;


Can someone explains how the chuck of value i got from readprocessmemory is stored and how to read all single value?
Back to top
View user's profile Send private message
iPromise
Grandmaster Cheater
Reputation: -1

Joined: 27 Jun 2009
Posts: 529
Location: Canada

PostPosted: Sat Jan 23, 2010 2:51 pm    Post subject: Reply with quote

Don't scan addresses 1 by 1, use VirtualQuery() to find a list of readable memory pages that you read from.
Back to top
View user's profile Send private message MSN Messenger
KryziK
Expert Cheater
Reputation: 3

Joined: 16 Aug 2009
Posts: 199

PostPosted: Sat Jan 23, 2010 8:01 pm    Post subject: Reply with quote

I would also like help with this. I am not using Delphi though.

I will continue trying things but any help (such as the answer to tanjiajun's questions) would help greatly.

I tried to use an array for ReadProcessMemory but it was blank. Can anyone post an example in c++ of using an array for a page/size 1000?

Thanks.
Back to top
View user's profile Send private message
Anden100
Grandmaster Cheater
Reputation: 0

Joined: 20 Apr 2007
Posts: 668

PostPosted: Sun Jan 24, 2010 5:33 am    Post subject: Reply with quote

I love how you keep giving out advices that you wouldn't understand any part of yourself iPromise Razz, look at how much you got feeded in your own thread before you understood it

Slugsnack wrote:
Base, EP, etc.

Code:
#include <windows.h>
#include <stdio.h>
#include <conio.h>

int main()
{
  IMAGE_DOS_HEADER* pIDH = (IMAGE_DOS_HEADER*)GetModuleHandle( NULL );
  IMAGE_NT_HEADERS* pINH = (IMAGE_NT_HEADERS*)((BYTE*)pIDH + (pIDH -> e_lfanew));
  IMAGE_OPTIONAL_HEADER IOH = pINH -> OptionalHeader;

  printf( "Magic number is : %u\n", pIDH -> e_magic );
  printf( "Address of entry point is : %#x", IOH.AddressOfEntryPoint );

  while( !_kbhit() )
    Sleep(100);

  return 0;
}


And you are using VirtualQuery completely wrong. You're not supposed to use VirtualProtect to make all memory readable either that's retarded.

Here is the code for my 'first scan' function in one of my first C projects. Yes, don't expect the code to be particularly good.

Code:
void FirstScan( unsigned int nValue, HWND hwndList )
{
  MEMORY_BASIC_INFORMATION mbi = {0};
  DWORD dwEndAddr;
  int iIndex;
  LVITEM lvi = {0};

  lvi.mask = LVIF_TEXT;
  lvi.iItem = 1;
  lvi.iSubItem = 0;
  TCHAR szAddress[9] = {0};
  TCHAR szValue[11] = {0};

  swprintf_s( szValue, _countof( szValue ), _T("%d"), nValue );

  while ( VirtualQuery( ( VOID * )( ( int )mbi.BaseAddress + mbi.RegionSize ), &mbi, sizeof( MEMORY_BASIC_INFORMATION ) ) )
  {
    if( mbi.Protect == PAGE_READWRITE )
    {
      dwEndAddr = ( DWORD )mbi.BaseAddress + mbi.RegionSize - 1 - ( !nScanType ? 0 : nScanType * 2 );

      for( DWORD i = ( DWORD )mbi.BaseAddress; i <= dwEndAddr; i++ )
      {
        __try
        {
          if( ( !nScanType && *( BYTE * )i == ( BYTE )nValue )
              || ( nScanType == 1 && *( WORD * )i == ( WORD )nValue )
              || ( nScanType == 2 && *( DWORD* )i == ( DWORD )nValue ) )
          {
            swprintf_s( szAddress, _countof( szAddress ), _T("%08X"), i );
            iIndex = ListView_InsertItem( hwndList, &lvi );
            ListView_SetItemText( hwndList, iIndex, 0, szAddress );
            ListView_SetItemText( hwndList, iIndex, 1, szValue );
            lvi.iItem++;
          }
        }
        __except( true )
        {
          i = dwEndAddr;
        }
      }
    }
  }
}


Anden100 wrote:
This is what i did in my MemoryScanner (removed some functions -.-), saves all results to a file, which can then be read later to print it in a different loop

Code:
#define SAVE_COUNT 100 //could be any number, how often values will be saved to a file

struct addr{
   int address;
   int value;
};

HANDLE hProcess;

BOOL scan(int value){
   std::fstream save(ADDRFILE, std::ios::binary | std::ios::out | std::ios::app);
   int pos = 0;
   addr address[50];
   MEMORY_BASIC_INFORMATION mbi;
   SYSTEM_INFO si;
   char bufstr[MAX_PATH];
   GetSystemInfo(&si);
   int min = (int)si.lpMinimumApplicationAddress;
   int max = (int)si.lpMaximumApplicationAddress;
   size_t s;
   if(hProcess == INVALID_HANDLE_VALUE){
      MessageBox(NULL, "Please choose a process!", "Notice", NULL);
      return FALSE;
   }
   for(int i = min; i < max;){
      s = VirtualQueryEx(hProcess, (LPVOID)i, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
      if(s == sizeof(MEMORY_BASIC_INFORMATION) && mbi.Type == MEM_PRIVATE && mbi.State == MEM_COMMIT && mbi.RegionSize > 0){
         size_t reg = mbi.RegionSize;
         void *buffer = malloc(reg);
         ReadProcessMemory(hProcess, (LPVOID)mbi.BaseAddress, buffer, reg, NULL);
         for(unsigned int j = 0; j < reg; j++){
            int *val = (int*)((DWORD)buffer + j);
            if(*val == value){
               if(pos <= SAVE_COUNT+1){
                  save.write(reinterpret_cast<char*>(&address), sizeof(addr)*pos);
                  pos = 0;
               }
               address[pos].address = (int)mbi.BaseAddress+j;
               address[pos].value = value;
               pos++;
               resultcount++;
            }
         }
      }
      if(s == 0){
         DWORD err = GetLastError();
         if(err == 6)
            sprintf_s(bufstr, sizeof(bufstr), "Please select a process");
         else
            sprintf_s(bufstr, sizeof(bufstr), "VirtualQueryEx failed with error code: %d", err);
         MessageBox(NULL, bufstr, "Error!", 0);
         return FALSE;
      }
      DWORD prog = (DWORD)mbi.BaseAddress + (DWORD)mbi.RegionSize;
      i = prog;
   }
   save.write(reinterpret_cast<char*>(&address), sizeof(addr)*pos);
   save.close();
   return TRUE;
}


This little piece of code is quite fast Razz, (of curse, DB's Memory Scan is faster, but this works properly Razz
Back to top
View user's profile Send private message
iPromise
Grandmaster Cheater
Reputation: -1

Joined: 27 Jun 2009
Posts: 529
Location: Canada

PostPosted: Thu Jan 28, 2010 7:10 pm    Post subject: Reply with quote

@Anden100

So what, I needed some explanations.

Heres an example of my 'first scan':

Code:

bool Read;                  
                  int Value = atoi(GetValue);
                  MEMORY_BASIC_INFORMATION pInfo = {0};
                  SYSTEM_INFO sInfo;
                  GetSystemInfo(&sInfo);                  
                  SIZE_T s;
                  
                  DWORD min = (DWORD) 0x00400000;
                  DWORD max = (DWORD) sInfo.lpMaximumApplicationAddress;

                  for (DWORD i = min; i < max; i++)
                  {
                     s = VirtualQueryX((LPCVOID) i, &pInfo, sizeof(MEMORY_BASIC_INFORMATION));
                     
                     if (s == sizeof(MEMORY_BASIC_INFORMATION) && pInfo.Type == MEM_PRIVATE && pInfo.State == MEM_COMMIT && pInfo.RegionSize > 0)
                     {                     
                        Read = ReadByte((DWORD) i, Value);
                           
                        if (Read == true)
                        {            
                           cout << (LPVOID) i << endl;
                           SendMessageX(ListBox1, LB_ADDSTRING, 0, (LPARAM) ConvertAddress((LPVOID) i).c_str());   
                        }                        
                     }   
                     else
                     {
                        i = (DWORD) pInfo.BaseAddress + (DWORD) pInfo.RegionSize;
                     }
                  }               

                  GetResults();
               }


This code is pretty fast, try to figure out what my "ReadByte" function does, i'm not going to spoonfeed you.
Back to top
View user's profile Send private message MSN Messenger
tanjiajun_34
Grandmaster Cheater
Reputation: 0

Joined: 16 Feb 2006
Posts: 786
Location: Singapore

PostPosted: Sun May 09, 2010 2:34 am    Post subject: Reply with quote

If the hs or gameguard blocked read and write processmemory, will VirtualQueryX works? I wanted to code in a dll and inject it into the game process. Since it is in the game process will it still be blocked?
Back to top
View user's profile Send private message
Slugsnack
Grandmaster Cheater Supreme
Reputation: 71

Joined: 24 Jan 2007
Posts: 1857

PostPosted: Sun May 09, 2010 5:18 am    Post subject: Reply with quote

virtualquery was not hooked last time i checked. at most if it was it was definitely only a usermode hook which can be bypassed easily
Back to top
View user's profile Send private message
iPromise
Grandmaster Cheater
Reputation: -1

Joined: 27 Jun 2009
Posts: 529
Location: Canada

PostPosted: Sun May 09, 2010 10:25 pm    Post subject: Reply with quote

Not as easy as you think Slugsnack, GameGuard / Hackshield scans for signatures like:

Code:

MOV EDI, EDI
PUSH EBP
MOV EBP, ESP


and if it finds such signatures, it closes the game, or that is how it was for me.
Back to top
View user's profile Send private message MSN Messenger
Slugsnack
Grandmaster Cheater Supreme
Reputation: 71

Joined: 24 Jan 2007
Posts: 1857

PostPosted: Mon May 10, 2010 2:31 am    Post subject: Reply with quote

i see. so it scans for the stack frame and if it detects it it closes the game. that's odd because a stack frame is used in probably 95% of functions
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
Goto page 1, 2  Next
Page 1 of 2

 
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