ugh typo on my end
should be byte* buffer indeed
now it's scanning 4 bytes at a time, yet only moving them 1 byte everytime (so you find stuff 4x times)
Originally Posted by Davidm44
He is indeed, but like I said, I was almost 100% sure I would run into another problem, and I did.
I scanned using cheat engine and found about 400 addresses and when I used this method i got over 1600.
Was there a reason you changed byte to dword? I have no idea if this even affects the scan at all. But I don't think i'm getting the results i'm looking for with this scanner.
If you knew for sure everything is stored as a DWORD you could keep it as a DWORD and move bSize * 4 every iteration
So, depends on the type of buffer, that's how many bytes it scans? Either way, i got 63,000 addresses this time.
You said it scans 4 bytes, so when it's checking if buffer[i] = 10 it's checking 4 bytes aswell? Correct me if i'm wrong.
Ok let's do a little example;
Say we're at offset 0x1000 and we have the following bytes:
A3 39 83 93 0A 00 00 00 03 34 0A 00 8C 0A 2B 5F
A Dword is 4 bytes, so when we say:
DWORD *Buffer = new Buffer[bSize] we're making an array of DWORDs
Looking at how this would fill up we'd get (Remember it's Little-Endian so the bytes are reverse in memory)
Buffer[0] = 0x938339A3;
Buffer[1] = 0x0000000A; //oh there's 10!
Buffer[2] = 0x000A3403;
Buffer[3] = 0x5F2B0A8C;
Now say we were to make a Short *Buffer;
Short[0] = 0x39A3;
Short[1] = 0x9383;
Short[2] = 0x000A; //Here's 10!
Short[3] = 0x0000;
short[4] = 0x3403;
Short[5] = 0x000A; //Here's Another!
Short[6] = 0x0A8C;
Short[7] = 0x5F2B;
Ok now let's go down to the Byte level and say we have a Byte* Buffer;
Byte[0] = 0xA3;
Byte[1] = 0x39;
Byte[2] = 0x83;
Byte[3] = 0x93;
Byte[4] = 0x0A; //Here's 10!
Byte[5] = 0x00;
Byte[6] = 0x00;
Byte[7] = 0x00;
Byte[8] = 0x03;
BYte[9] = 0x34;
Byte[10] = 0x0A; //Here's another!
Byte[11] = 0x00;
Byte[12] = 0x8C;
Byte[13] = 0x0A; //here's another!
Byte[14] = 0x2B;
Byte[15] = 0x5F;
The problem we're facing is that we don't really know what's being used to store the variable you're looking for without resorting to debugging the actual winmine.exe (and at that point you'd also be able to figure out at which offset what is stored)
If you look at the above it 16 bytes it could very well be:
Byte,Byte,Short,Long,Byte,Short,Long,Byte or
Short,Short,Long,Byte,Byte,Byte,Byte,Long etc etc
So Scanning at the byte level gives you the most info, but then you'll have to go through it to figure out what it is you're looking for.
One way is If you know the value has changed simply keep a list of the first addresses in memory and then the second time around scan only those for the 'new' value.
I sort of get what you're saying. But the most confusing thing is that when I change the buffer size from 0xFFFF and 0xFFFFF, my results are completely different.
It's confusing me so much. I hardly understand what's going on anymore. T.T
That shouldn't happen unless the part that moves your pointer in memory is wrong. If you want to post your latest code i'll give it a once over
Here's the latest.
Code:
#include <windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
DWORD pid;
HWND hwnd;
HANDLE handle;
int n = 0;
DWORD bSize = 0xFFFF;
byte* buffer = new byte[bSize];
DWORD base = 0x0000000;
DWORD end = 0x7FFFFFFF;
DWORD re;
int value = 10;
int main()
{
hwnd = FindWindow(0,"Minesweeper");
if(!hwnd)
{
cout << "Window not found!";
getch();
return 0;
}
GetWindowThreadProcessId(hwnd,&pid);
handle = OpenProcess(PROCESS_ALL_ACCESS,0,pid);
if(!handle)
{
cout << "Could not get window handle!";
getch();
return 0;
}
while ( base != end)
{
ULONG bytesRead = 0;
if(ReadProcessMemory(handle,(LPVOID)base,buffer,bSize,&bytesRead) != 0)
{
for(DWORD i = 0; i < bytesRead; i++ )
{
if(buffer[i] == value)
{
cout << hex << base + i << endl;
n++;
}
}
}
if( (end-base) >= bSize)
{
base += bSize;
} else if( (end-base) <= bSize)
{
base += (end-base);
}
}
delete[] buffer;
cout << dec << n << endl;
cout << "Done";
getch();
}
Thanks for helping me on this.
Here's whats happening..
The ReadProcessMemory function will Fail with 'partial read' error (#299) meaning it can't read certain bytes in the address range you're trying to read.. Even it it can't read 1 or 2 bytes, the entire read fill wait which basically skips the entire block from being processed. (which is the size of your buffer).
So if you set your buffer large to an imaginary amount where it will take 4 passes but it only succeeds on the last one you will only find the items in that part of memory. As you make the buffer smaller it will skip less parts of memory if it does fail.
You might want to do something with the privilege level for your app so it doesn't crap out there (most likely cause).
I used DebugActiveProcess right after getting the window handle and the results didn't change at all. I don't think this has anything to do with access rights, rather, reading the wrong regions in memory.
Once again i'm not sure at all, so correct me if i'm wrong.
Certain areas of a programs memory are 'protected' thus you do not have access to read from there without changing permissions or reading around them.
VirtualQueryEx is helpful for this
Also you may want to start at 0x00400000 instead of 0x00000000 since most apps don't store their vars below that
Or if you have a sense what you're looking for, debug/disassembly the target app and find the offset there
I'm finding this whole conversation really interesting. Please keep on, don't mind me... Im just lurking. xD