 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
tanjiajun_34 Grandmaster Cheater
Reputation: 0
Joined: 16 Feb 2006 Posts: 786 Location: Singapore
|
Posted: Wed Jan 20, 2010 5:37 am Post subject: Scan Memory |
|
|
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 |
|
 |
tombana Master Cheater
Reputation: 2
Joined: 14 Jun 2007 Posts: 456 Location: The Netherlands
|
Posted: Wed Jan 20, 2010 6:53 am Post subject: |
|
|
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 |
|
 |
tanjiajun_34 Grandmaster Cheater
Reputation: 0
Joined: 16 Feb 2006 Posts: 786 Location: Singapore
|
Posted: Wed Jan 20, 2010 8:57 am Post subject: |
|
|
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 |
|
 |
tombana Master Cheater
Reputation: 2
Joined: 14 Jun 2007 Posts: 456 Location: The Netherlands
|
Posted: Wed Jan 20, 2010 9:40 am Post subject: |
|
|
| 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 |
|
 |
tanjiajun_34 Grandmaster Cheater
Reputation: 0
Joined: 16 Feb 2006 Posts: 786 Location: Singapore
|
Posted: Wed Jan 20, 2010 11:12 am Post subject: |
|
|
| That where VirtualQueryEx comes in? To find out which memory can be read.
|
|
| Back to top |
|
 |
tombana Master Cheater
Reputation: 2
Joined: 14 Jun 2007 Posts: 456 Location: The Netherlands
|
Posted: Wed Jan 20, 2010 1:10 pm Post subject: |
|
|
| 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 |
|
 |
tanjiajun_34 Grandmaster Cheater
Reputation: 0
Joined: 16 Feb 2006 Posts: 786 Location: Singapore
|
Posted: Wed Jan 20, 2010 7:32 pm Post subject: |
|
|
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 |
|
 |
iPromise Grandmaster Cheater
Reputation: -1
Joined: 27 Jun 2009 Posts: 529 Location: Canada
|
Posted: Sat Jan 23, 2010 2:51 pm Post subject: |
|
|
| Don't scan addresses 1 by 1, use VirtualQuery() to find a list of readable memory pages that you read from.
|
|
| Back to top |
|
 |
KryziK Expert Cheater
Reputation: 3
Joined: 16 Aug 2009 Posts: 199
|
Posted: Sat Jan 23, 2010 8:01 pm Post subject: |
|
|
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 |
|
 |
Anden100 Grandmaster Cheater
Reputation: 0
Joined: 20 Apr 2007 Posts: 668
|
Posted: Sun Jan 24, 2010 5:33 am Post subject: |
|
|
I love how you keep giving out advices that you wouldn't understand any part of yourself iPromise , 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 , (of curse, DB's Memory Scan is faster, but this works properly  |
|
|
| Back to top |
|
 |
iPromise Grandmaster Cheater
Reputation: -1
Joined: 27 Jun 2009 Posts: 529 Location: Canada
|
Posted: Thu Jan 28, 2010 7:10 pm Post subject: |
|
|
@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 |
|
 |
tanjiajun_34 Grandmaster Cheater
Reputation: 0
Joined: 16 Feb 2006 Posts: 786 Location: Singapore
|
Posted: Sun May 09, 2010 2:34 am Post subject: |
|
|
| 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 |
|
 |
Slugsnack Grandmaster Cheater Supreme
Reputation: 71
Joined: 24 Jan 2007 Posts: 1857
|
Posted: Sun May 09, 2010 5:18 am Post subject: |
|
|
| 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 |
|
 |
iPromise Grandmaster Cheater
Reputation: -1
Joined: 27 Jun 2009 Posts: 529 Location: Canada
|
Posted: Sun May 09, 2010 10:25 pm Post subject: |
|
|
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 |
|
 |
Slugsnack Grandmaster Cheater Supreme
Reputation: 71
Joined: 24 Jan 2007 Posts: 1857
|
Posted: Mon May 10, 2010 2:31 am Post subject: |
|
|
| 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 |
|
 |
|
|
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
|
|