 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
iPromise Grandmaster Cheater
Reputation: -1
Joined: 27 Jun 2009 Posts: 529 Location: Canada
|
Posted: Fri Dec 25, 2009 1:58 pm Post subject: [C++] Help. |
|
|
2 Questions.
My first question is can I find the base address of the process i'm injected to by using VirtualQuery() with MEMORY_BASIC_INFORMATION?
Like so:
| Code: |
MEMORY_BASIC_INFORMATION MBI;
VirtualQuery(0, &MBI, sizeof(MBI));
return MBI.BaseAddress;
|
My second question is on my previous thread, I asked a faster method to scan through addresses, see what I usually do is:
| Code: |
DWORD Start = 0x00400000;
DWORD Stop = 0x04FFFFFF;
do
{
bool Read = ReadByte(Start, Value);
if (Read == true)
{
SendMessageX(ListBox1, LB_ADDSTRING, 0, (LPARAM) ConvertAddress((LPVOID) Start).c_str());
}
++Start;
} while (Start <= Stop);
|
Dark Byte and other members suggested I use VirtualQuery() to scan faster, but I dont see how it could scan faster by using it.
If you really do need VirtualQuery() to scan through the regions, etc, to find the allocated addresses, can you give an example code and show me how to do it?
P.S. I am finished my Memory Engine, but its slow in scanning, so i'm trying to find a faster method to scan through the addresses. To anyone that helps, get a free copy of it, its semi - private so theres a less chance of it getting detected, I just tested it on the game: GunBound and it works but again, slow.
Thanks
Some pictures for proof:
 |
|
| Back to top |
|
 |
lurc Grandmaster Cheater Supreme
Reputation: 2
Joined: 13 Nov 2006 Posts: 1900
|
Posted: Fri Dec 25, 2009 4:59 pm Post subject: |
|
|
Well you said your injected right? Why not use ImageNtHeader then and just retrieve the base/size of the .CODE section (or whatever header you want to scan) so that you aren't scanning memory that isn't even in the region?
Another thing, as a precaution, is that you should check for the bit-wise masks: PAGE_NOACCESS and PAGE_GUARD through VirtualQuery of the .CODE section or whatever section you're scanning because if these flags are marked, then you the system will raise access violations exceptions.
P.S. doesn't really look like an "engine". Just looks like a program that just searches byte signatures. _________________
|
|
| Back to top |
|
 |
iPromise Grandmaster Cheater
Reputation: -1
Joined: 27 Jun 2009 Posts: 529 Location: Canada
|
Posted: Fri Dec 25, 2009 5:25 pm Post subject: |
|
|
@lurc I protect all my addresses I encounter with PAGE_EXECUTE_READWRITE so theirs no need for VirtualQuery(). ImageNtHeader, i'm considering to use.
Also, it is a engine, it doesn't only scan for byte signatures, it scans for more. You'll get first dip when you get a copy. |
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 475
Joined: 09 May 2003 Posts: 25986 Location: The netherlands
|
Posted: Fri Dec 25, 2009 5:58 pm Post subject: |
|
|
| Code: |
SendMessageX(ListBox1, LB_ADDSTRING, 0, (LPARAM) ConvertAddress((LPVOID) Start).c_str());
|
waits till the message has been written to the listbox and then returns, you could probably improve that by going multithreaded and using postmessage (of course, keep track of the allocated strings)
also, make sure the routine "ReadByte" does not contain one single windows API call, if it does, it'll be slow
if you HAVE to call windows api's then limit them to the least possible times called. So if you are going to read a 4MB region, only call the api's once and then check the 4MB buffer _________________
Tools give you results. Knowledge gives you control.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
hcavolsdsadgadsg I'm a spammer
Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Fri Dec 25, 2009 6:12 pm Post subject: |
|
|
| holy cow, please don't write all your code into 1 giant cluster |
|
| Back to top |
|
 |
Anden100 Grandmaster Cheater
Reputation: 0
Joined: 20 Apr 2007 Posts: 668
|
Posted: Sat Dec 26, 2009 10:55 am Post subject: |
|
|
| Dark Byte wrote: | | Code: |
SendMessageX(ListBox1, LB_ADDSTRING, 0, (LPARAM) ConvertAddress((LPVOID) Start).c_str());
|
waits till the message has been written to the listbox and then returns, you could probably improve that by going multithreaded and using postmessage (of course, keep track of the allocated strings)
also, make sure the routine "ReadByte" does not contain one single windows API call, if it does, it'll be slow
if you HAVE to call windows api's then limit them to the least possible times called. So if you are going to read a 4MB region, only call the api's once and then check the 4MB buffer |
Is it possible to do multiple LB_ADDSTRING's in just one PostMessage call, to display all addresses in one call to PostMessage? |
|
| Back to top |
|
 |
iPromise Grandmaster Cheater
Reputation: -1
Joined: 27 Jun 2009 Posts: 529 Location: Canada
|
Posted: Sat Dec 26, 2009 1:43 pm Post subject: |
|
|
@Anden100 I dont think so.
@slovach Lol..
@Dark Byte Thanks.
What i'm doing now to scan faster is making multiple threads that reads a certain amount of addresses, until they fnally reach to the target stop region. |
|
| Back to top |
|
 |
Flyte Peanuts!!!!
Reputation: 6
Joined: 19 Apr 2006 Posts: 1887 Location: Canada
|
Posted: Sat Dec 26, 2009 2:54 pm Post subject: |
|
|
| iPromise wrote: | | What i'm doing now to scan faster is making multiple threads that reads a certain amount of addresses, until they fnally reach to the target stop region. |
Read: http://iso-9899.info/wiki/Why_not_threads |
|
| Back to top |
|
 |
Anden100 Grandmaster Cheater
Reputation: 0
Joined: 20 Apr 2007 Posts: 668
|
Posted: Sat Dec 26, 2009 3:20 pm Post subject: |
|
|
Multiple Threads... thats what i never got to...
And, making a memory scanner is not that big, i did it without too much trouble, and even with a basic (bad looking) GUI, never got to release the source though... |
|
| Back to top |
|
 |
iPromise Grandmaster Cheater
Reputation: -1
Joined: 27 Jun 2009 Posts: 529 Location: Canada
|
Posted: Sat Dec 26, 2009 4:09 pm Post subject: |
|
|
@Flyte Then what can I use that wont be so time consuming?
EDIT: Scanning fast is a bitch, multithreading wont do much either.. |
|
| Back to top |
|
 |
iPromise Grandmaster Cheater
Reputation: -1
Joined: 27 Jun 2009 Posts: 529 Location: Canada
|
Posted: Sun Dec 27, 2009 12:17 am Post subject: |
|
|
This is what i'm doing now.
| Code: |
SYSTEM_INFO si;
MEMORY_BASIC_INFORMATION mbi;
GetSystemInfo(&si);
DWORD MinimumSystemAddress = (DWORD) si.lpMinimumApplicationAddress;
do
{
mbi.RegionSize = 0;
SIZE_T ret = VirtualQuery((LPCVOID) MinimumSystemAddress, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
if (ret == sizeof(MEMORY_BASIC_INFORMATION))
{
if (mbi.Type == MEM_PRIVATE)
{
if (mbi.State = MEM_COMMIT)
{
if (mbi.RegionSize > 0)
{
bool Read = ReadByte(MinimumSystemAddress, atoi(GetValue));
if (Read == true)
{
SendMessageX(ListBox1, LB_ADDSTRING, 0, (LPARAM) ConvertAddress((LPVOID) MinimumSystemAddress).c_str());
}
}
}
}
}
++MinimumSystemAddress;
} while (MinimumSystemAddress <= (DWORD) 0x7FFFFFFF);
GetResults();
|
|
|
| Back to top |
|
 |
lurc Grandmaster Cheater Supreme
Reputation: 2
Joined: 13 Nov 2006 Posts: 1900
|
Posted: Sun Dec 27, 2009 1:10 am Post subject: |
|
|
1. You're initializing a new variable every single time it loops (which is a lot of times.)
Solution: Place variable definitions outside of loop.
SIZE_T ret;
bool Read;
do { ... } while ( ... );
2. Your calling VirtualQuery on EVERY-SINGLE-ADDRESS. I mean that's good for catching exceptions and all, but usually an entire page is going to be protected the same way.
3. Your sending a message every single time you read a correct byte, Why not just store all the address's as they are (DWORD) and just convert them all to strings and add them to the list box AFTER your done searching?
4. Like i said before, your searching far passed the region of game memory. Find out the end of the region your searching instead, then you won't need to worry about wasting time searching a place where you have no interest in.
Edit:
Forgot to add this
| Code: | | if (mbi.State = MEM_COMMIT) |
Your assigning the state MEM_COMMIT, when you should be comparing.
Switch that = to == _________________
|
|
| Back to top |
|
 |
hcavolsdsadgadsg I'm a spammer
Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Sun Dec 27, 2009 3:03 am Post subject: |
|
|
| lurc wrote: | 1. You're initializing a new variable every single time it loops (which is a lot of times.)
Solution: Place variable definitions outside of loop.
SIZE_T ret;
bool Read;
do { ... } while ( ... );
|
no, you don't need to worry about this.
this is not what is happening in actuality. |
|
| Back to top |
|
 |
Slugsnack Grandmaster Cheater Supreme
Reputation: 71
Joined: 24 Jan 2007 Posts: 1857
|
Posted: Sun Dec 27, 2009 6:35 am Post subject: |
|
|
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;
}
}
}
}
}
|
|
|
| Back to top |
|
 |
Anden100 Grandmaster Cheater
Reputation: 0
Joined: 20 Apr 2007 Posts: 668
|
Posted: Sun Dec 27, 2009 7:29 am Post subject: |
|
|
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
and Slugsnack, tyvm for the DOS header thing , very useful for my Disassembler project (omg a lot of coding it takes...) |
|
| 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
|
|