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 


Question about scanning...

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

Joined: 21 Sep 2004
Posts: 8

PostPosted: Tue Dec 14, 2004 9:56 pm    Post subject: Question about scanning... Reply with quote

Kinda new to C++ and was just making a test for reading memory stuff and i'm probably do this completly wrong but I tried doing a loop from 0x0000000 to 0xFFFFFFFF reading in each as an int with ReadProcessMemory(,,,)... and it's terribly slow...

How'd you get it so fast?
Or am I doing this completly wrong with a loop of 4294967295 (FFFFFFFF) Confused
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

Joined: 09 May 2003
Posts: 25287
Location: The netherlands

PostPosted: Wed Dec 15, 2004 2:39 am    Post subject: Reply with quote

Use a bigger buffer. Instead of reading 1 byte read 2048 or more at once.
Also, take a look at QueryVirtualMemoryEx

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Darimus
How do I cheat?
Reputation: 0

Joined: 21 Sep 2004
Posts: 8

PostPosted: Wed Dec 15, 2004 4:49 pm    Post subject: Reply with quote

Reading 2048 bytes each time worked.

I don't mean to bother you but I can't figure out how you get the 4 bytes value...

I figured out that 2 bytes follows this equation (by trial and error Shocked ): address+1's value *256, + address's value

but I cannot seem to figure out the equation for 4 bytes


--- edit ---

nvm I figured out how to get 4 bytes (once again on my own by trial and error -_-) : get the 2-byte value of the last 2 bytes of the 4, multiply that by 65535, then add the last 2-byte value and the first 2-byte value to get the final result of 4-byte int. :)

--- edit ---

Mine only yielded 172 results while yours had 4547353 :/
(searched for 5120 as byte)

my error is probably in this line to convert 4 seperate bytes to one 4-byte int:

r=long(((v[i+3]*256+v[i+2])*65535)+(v[i+3]*256+v[i+2])+(v[i+1]*256+v[i]));

:(

---edit---

my conversion formula is correct...
Address: 0x001ffffc Value: 4129714564
and the value of 0x001ffffc as a 4-byte int was: 4129714564, according to CE

So it must be something else...

(my prog's output
Scan finished

Results:
Scanned for integer of: 5120
Blocks Scanned: 1024
Total Memory Scanned: 0x00000000 to 0xfff00000
Unreadable memory blocks: 604
Readable memory blocks: 420
Matches: 294

Press any key to continue . . .
)
CE got (on Byte scan for 5120, scanning 0x0, to 0xFFFFFFFF: 5980799 matches...)
Back to top
View user's profile Send private message
falcotron
How do I cheat?
Reputation: 0

Joined: 02 Mar 2005
Posts: 1

PostPosted: Wed Mar 02, 2005 3:26 am    Post subject: Try casting instead Reply with quote

Even though this topic is very old, it's probably worth answering for future readers.

There's a much better way. Instead of this:

r=long(((v[i+3]*256+v[i+2])*65535)+(v[i+3]*256+v[i+2])+(v[i+1]*256+v[i]));

Try using a cast:

r = *(long *)(&(v[i]));

This has a number of advantages besides being shorter.

1. It's harder to screw up. Your algorithm is wrong; instead of giving you the correct value V, it gives you V + int(V / 65536). Anything that complicated is easy to get wrong. The cast is harder to get wrong, and if you do, it generally won't compile, making it easier to find the error.

2. It's much faster. Your code (after correcting it) compiles to something like 4 one-byte reads, 10 additions, and 3 multiplications. The cast version compiles to a single four-byte read (which, btw, is not 4 times slower than a one-byte read; in fact, it's generally significantly faster).

3. It's portable to big-endian architectures like PowerPC, as well as to any system where long is 2 or 8 bytes, with no changes.

4. Understanding it is a great way to understand C at a much deeper level. Within a short time, you'll be a talented low-level C hacker before you're a decent general-purpose programmer, and you'll scare away most employers....

5. If you're not writing code like this, there's really no good reason to be using C in the first place. The fact that this works is essentially the entire point of C. (In fact, I'd suggest trying python or ruby first anyway. A couple years ago, I rewrote a similar tool for linux from C++ to python with a couple of compiled C extensions for the critical chunks, and it was not only much easier to code and maintain, but slightly faster!)

Anyway, read as much of this as you can handle, and then stop. If you read the whole thing and it seems like exactly the level at which you like to think about things, go get a good C (not C++) book that includes all the machine-level stuff. (Suggestions, anyone?)

First, you have to understand how memory is laid out. Let's say v is an array of 12 chars at 00600000 (I'm going to use hex without the 0x prefix; hopefully nobody will get confused), holding the values 00 00 06 00 17 00 00 00 01 02 03 04. So v[0] is whatever char is at 00600000 (NUL), v[1] is whatever char is at 00600001 (also NUL), etc.

What we want to know is if, anywhere within this range, there's a 4-byte int with the value 23 (0x17 hex) hiding. Well, how are integers stored? As a contiguous chunk of (2, 4, or 8) bytes. So the 4-byte integer 23 looks like this in memory: 17 00 00 00.

Of course those are exactly the four bytes starting at 00600004, or &v[4]. But how do we get the compiler to interpret those bytes as a 4-byte integer? By using a cast. A cast takes a value of one type and converts it to another type. Different types are conveted in different ways by a cast, but for pointers, you end up with a pointer to the new type at the exact same memory location. So, if p is a pointer to a char at 00600004, then (long *)p is a pointer to a long at 00600004.

The & operator takes any expression and gives you the address of that expression. So &(v[i]) gives you the address v + i. Put this all together, and (long *)(&v[i]) gives you a long pointer, pointing at wherever v[i] is stored. If you dereference this long pointer with the * operator, you get whatever long is stored at the same location as v[i]. Tada!

Quick quiz: What's *(long *)(&v[11])?

Strictly speaking, it's an error, and if you're unlucky you'll get an access violation. More likely, though, you'll get unpredictable garbage. Why? Because &v[11] points to the last byte in v, plus whatever the next three bytes in memory happen to be. This could be some completely different variable, or uninitialized memory, or unpaged memory. This means you can't do this:

for (int i = 0; i <= len - 1; ++i) {
r = *(long *)(&v[i]);
// ...

Instead, do this:

for (int i = 0; i <= len - sizeof(long); ++i) { // ...

Now, you may have heard that casts are evil and should be avoided whenever possible. This is good advice. But "whenever possible" means there are exceptions, and this is the prime example. You're doing real down-to-the-metal programming, trying to read arbitrary memory and see what it holds. This is inherently dangerous, and using a cast doesn't make it any more so.

Still, you can make things marginally safer. As I mentioned above, what a cast does is different for different types. To avoid confusion, C++ allows you to make things more explicit by using one of four special cast operators, including one called reinterpret_cast, that always does exactly what you want here (reinterpret the exact same bytes as a different type). So, you may prefer this:

r = *reinterpret_cast<long *>(&(v[i]));

Another way to make this safer is with const. If you don't plan on changing the values, const can make sure you don't _accidentally_ change them. (It also may allow the optimizer to speed things up in some cases, but probably not this one.) If v is an array of const chars, then the cast would be:

r = *reinterpret_cast<const long *>(&(v[i]));

One nice thing about reinterpret cast is that, unlike the C-style cast, if v is const and you forget the const here, you'll get a syntax error.

Another way of doing the same thing is to use a union. Look up unions in a reference or tutorial; the idea is that it's a type which consists of two or more types sitting on top of each other.

If you really want to do this in a type-safe, C++ way, what you want to do is wrap a binary iostream around v and extra longs out of it. But that's a whole other story.

Finally, if you want to really understand how C works, or you just have carpal tunnel syndrome, you can compress things a bit:

r = *(long *)(v + i);

Why does this work? Well, under the covers, an array variable is like a pointer to the start of the array's memory. When you add a pointer to type T and an integer, you get a new pointer to v + i. In fact, v[i] is just shorthard for *(v + i), so &v[i] just means &*(v + i), which just means v + i. As far as the compiler's concerned, they're identical ways of writing the same thing. (This isn't true in C++ if you start defining your own operator overloads, by the way.) In fact, you can even use (i + v) instead of (v + i) if you really want to.

One quick note: "v + i" doesn't mean "i bytes after whatever v points to," but "i [elements of v] after whatever v points to." When v is an array of chars, each of which is 1 bytes, there's no different, but if v were an array of longs at 00600000, then v + 1 would be not 00600001 but 00600004. Usually this is what you want, but if you're not expecting it, it can throw you.

I've still never seen a better explanation of this than the (otherwise-dated) original C tutorial by C author Brian Kernighan (at http://www.lysator.liu.se/c/bwk-tutor.html#pointers). Almost everything else is now dated (25 years before the C99 specification), but this part is still worth reading.

The final mystery here is my third point. I said above that a long holding 23 is stored as 17 00 00 00. This is true using any current compiler on your Wintel box. However, there are two assumptions that could bite you later.

First, a long is however big the compiler says. Most modern compilers happen to say that a long is 32 bits, which is nice, but as far as the language is concerned, that's just a coincidence. A long could by 64 bits, or 36 (this was actually pretty common in the early days of C).

Second, there's no law saying that a 4-byte int with the value 23 has to be stored as 17 00 00 00. Why not 00 00 00 17, so the most significant part of the value comes first. This was one of the first flamewars among computer geeks, but both possibilities are alive today. Intel uses the first option ("little-endian") while IBM uses the second ("big-endian"), and historically a few chips used other orders as well (like "vax-endian"). So your arithmetic that works great on an Intel PC will fail miserably on a Mac.

The cast won't have this problem: It just says "interpret the bits starting here as a long, whatever that means," so on a PC it reads a little-endian long, and on a Mac it reads a big-endian long.

In some cases, you really do care. Let's say you took a save file from a game on your Mac, and you're trying to search through it on your PC. If you just cast each 4 bytes to a PC's long, you'll never find what you're looking for; you have to explicitly do the arithmetic Mac-style (or use a function like ntoh_l that does it for you...). More realistically, let's say you're writing a networked game where Mac and PC clients both talk to each other: one of them is going to have to convert ints back and forth to make the other happy. But when you don't have to worry about endianness, don't.

Now it's time to find that book. You'll still need to learn some low-level Win32 stuff to write your own competitor to Cheat Engine, but you should be able to handle it.
Back to top
View user's profile Send private message
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Tue Apr 26, 2005 10:55 am    Post subject: Reply with quote

Can't you just:

Code:
int bytesRead=0;
char* bytes = new char[2048];
short* words = (short*) bytes;
long* dwords = (long*) bytes;

ReadProcessMemory(process, (void*)address, (void *)bytes, 2048, &bytesRead);


Then scan bytes, words and dwords as required?

I looked up QueryVirtualMemoryEx on msdn and nothing showed up. Is this something that provides info on which reigons are used by the game?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

Joined: 09 May 2003
Posts: 25287
Location: The netherlands

PostPosted: Sat Apr 30, 2005 3:19 am    Post subject: Reply with quote

Thats kinda what ce's hyuperscan does. (Inject the scandll in all processes and new processes and only affect the process that was targeted)
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Source 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