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 


The aobscan instruction

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Tutorials
View previous topic :: View next topic  
Author Message
Geri
Moderator
Reputation: 111

Joined: 05 Feb 2010
Posts: 5636

PostPosted: Wed Jan 16, 2013 10:14 am    Post subject: The aobscan instruction Reply with quote

The original article can be found here.
http://www.szemelyesintegracio.hu/cheats/41-game-hacking-articles/507-aobscan-instruction

At the moment it is the same as this one, unless I make some changes.

Many people were asking for an aobscan tutorial so here I make a short description for using aobscan.

Why are we using aobscan frequently?
In many cases, the address of the code that we want to change is not static. This may happen in many games
where the codes are loaded only when they are used and it also happens if you are not using the same
game version. If the code itself did not change, only the address of the code, you can use aobscan to find the code's address.


First I will start with an example where I show how can you change a simple script into an aobscan script,
then I will explain it in more details for those who want to know how is it working. At the end I will write
some more advanced hints for specific problems that you may encounter when you are using aobscan.


The target process is the Tutorial program for CE 6.2. Here is a normal script that will solve Step 2
of the tutorial (at this point I assume that you can make cheats with static code addresses).

Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
mov [ebx+00000464],(int)1000

originalcode:
mov eax,[ebx+00000464]

exit:
jmp returnhere

"Tutorial-i386.exe"+22988:
jmp newmem
nop
returnhere:

 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"Tutorial-i386.exe"+22988:
mov eax,[ebx+00000464]
//Alt: db 8B 83 64 04 00 00


To change this into a script with aobscan, you have to make a few modifications only (look at the comments):

Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(returnhere)
label(originalcode)
label(exit)
label(whatever)                      //make a label that you can use for your aobscan
registersymbol(whatever)             //also register it as a symbol
aobscan(aob1,8B 83 64 04 00 00 3D)   //use aobscan to search for the code, more explanation later


newmem: //this is allocated memory, you have read,write,execute access
mov [ebx+00000464],(int)1000

originalcode:
mov eax,[ebx+00000464]

exit:
jmp returnhere

aob1:             //replace the static address with your aobscan, which is called aob1 in my case
whatever:         //store aob1 on the whatever label
jmp newmem
nop
returnhere:

 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
whatever:                    //replace the static address with the whatever label
db 8B 83 64 04 00 00         //restore the original byte pattern
unregistersymbol(whatever)   //we don't need this symbol anymore so unregister it


If you copy-paste this script into CE, it will scan for the code that I have changed in the original script
and do the same code injection. Now I should explain a few things in more details, though it is not really
neccessary to understand everything in order to use aobscan.



The aobscan Instruction
This instruction is used to find a byte pattern in the memory and store the address of the first result. Important
to remember that if there are more results for the scan, the first result will be used. Make sure to have only one
result for your scan or at least the first one should be the correct address that you want to find.

The code that we have changed in the original script was this:

Code:
Tutorial-i386.exe+22988 - 8B 83 64040000        - mov eax,[ebx+00000464]
Tutorial-i386.exe+2298E - 3D E8030000           - cmp eax,000003E8


If you look at it in the disassembler, you can see how is this instruction stored in the memory.
8B 83 64 04 00 00
3D E8 03 00 00

You have to come up with a pattern that will identify this code. Let's do this:
Switch value type to "Array of byte", make sure that the "Writable" box is just "optional" and it doesn't have
a checkmark in it, as the code we are looking for is NOT writable, only executable. Now scan for this byte pattern

8B 83 64 04 00 00

You will probably have 8 results, which is not a good start and if you check the first result, it is not the
correct code we are looking for. Thus we can see that we can't use this byte pattern. Now we have to come up with a new pattern that will filter out the 7 wrong results. As we can see, the first byte of the next instruction
starts with 3D. Try to scan for this byte pattern:

8B 83 64 04 00 00 3D

Now you will have one result, or at least the first one will be the code that you are looking for. This byte
pattern can be used to find our code's address. The syntax is very simple

Code:
aobscan(name,byte pattern)
aobscan(aob1,8B 83 64 04 00 00 3D)


The name of the aobscans and symbols can be anything, it's up to you. After this instruction is executed,
aob1 is equal to "Tutorial-i386.exe"+22988 address. You can use aob1 to refer to this address.

NOTE: The * character is a joker character. If you put * in your byte pattern, it can be anything.
Eg
"* 83 64 04 00 00 3D" could be anything from "00 83 64 04 00 00 3D" to "FF 83 64 04 00 00 3D"
When you are not sure that a byte will be the same in other game versions, use *.




Making The Script
As you see it was neccessary to make a few modifications in the original script to use aobscan. You can just
copy-paste these changes into your script without ever asking why are they needed, but if you are curious, here
are the reasons.


Code:
label(whatever)
registersymbol(whatever)


You are not able to use your aobscan result in the disable section and you can't scan for the code either, because you have changed it with your code injection. This is why the address has to be saved somewhere for later use.


Code:
aob1:             //replace the static address with your aobscan, which is called aob1 in my case
whatever:         //store aob1 on the whatever label


This is the part where we store aob1 on the "whatever" symbol so we can use it in the disable section too.


Disable section

Code:
whatever:                    //replace the static address with the whatever label


This is why we have saved the address on "whatever", we need to restore the original code in the disable section.


Code:
db 8B 83 64 04 00 00         //restore the original byte pattern


Yes. I have replaced

Code:
mov eax,[ebx+00000464]
//Alt: db 8B 83 64 04 00 00


with the original byte pattern. The reason is that the instruction may be compiled differently by CE and we have to be 100% sure to restore the instruction exactly as it was.

Example:
mov eax,[ebx+ecx++00000464]
and
mov eax,[ecx+ebx++00000464]
has the same results, but they are not the same instruction. We have to make sure that we restore the same instruction that has exactly the same byte pattern as the original. If we fail to do that, the original byte pattern will be lost and your aobscan will not find it if you try to enable the cheat again. Always be 100% sure that you have restored the original byte pattern, or the users will not be able to turn the script on/off.


Code:
unregistersymbol(whatever)   //we don't need this symbol anymore so unregister it


Simple clean-up. Remove the symbol that we are not using anymore.


Advanced tips and solutions to various problems that you may encounter when you are using aobscan:


The most common mistakes with aobscan are using the same symbol names when you have more than one script and not restoring the original code correctly. You should always use separate symbol/label/aobscan names in different scripts and as I have said above, be 100% sure that you have restored the original byte pattern. If your scripts are working correctly, they can be turned on/off anytime independently, without interfering with each other. It is easy to make mistakes and the users often blame CE for some bug, but if you have followed the instructions properly, it should work. The error is in your script, somewhere something is screwed up. Double-check everything, look at the changes in the disassembler when you turn the cheats on/off, check the original code and the restored code that they are really matching etc.


Make sure that your byte pattern is not containing static addresses or other codes that will most likely change
in other versions of the game. Eg a code like

Code:
call 00908070


will be different in another version of the game, because 00908070 is a static address. Replace static addresses with * character. Every * is a byte. So replace the address with * * * * in the pattern.



How to make a code injection at an address if you do not find a byte pattern for that particular address?


Let's assume that we want to change this code

Code:
Tutorial-i386.exe+22988 - 8B 83 64040000        - mov eax,[ebx+00000464]
Tutorial-i386.exe+2298E - 3D E8030000           - cmp eax,000003E8
Tutorial-i386.exe+22993 - 75 2C                 - jne Tutorial-i386.exe+229C1


and we have a byte pattern that gives us "Tutorial-i386.exe+22988" but we want to make the code injection at this address:

Code:
Tutorial-i386.exe+2298E - 3D E8030000           - cmp eax,000003E8


If we do not find any working byte pattern that will find Tutorial-i386.exe+2298E, we can use the previously discovered byte pattern that gives us Tutorial-i386.exe+22988 as the result. The original code would look like this:

Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
mov [ebx+00000464],(int)1000

originalcode:
cmp eax,000003E8

exit:
jmp returnhere

"Tutorial-i386.exe"+2298E:
jmp newmem
returnhere:


 
 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"Tutorial-i386.exe"+2298E:
cmp eax,000003E8
//Alt: db 3D E8 03 00 00


The aobscan version will be this:


Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(returnhere)
label(originalcode)
label(exit)
label(whatever)                     
registersymbol(whatever)           
aobscan(aob1,8B 83 64 04 00 00 3D) 

newmem: //this is allocated memory, you have read,write,execute access
mov [ebx+00000464],(int)1000

originalcode:
cmp eax,000003E8

exit:
jmp returnhere

aob1+6:             //22988+6 = 2298E so we are making our code injection on 2298E address instead of 22988
whatever:       
jmp newmem
returnhere:


 
 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
whatever:
db 3D E8 03 00 00
unregistersymbol(whatever)



As you can see, we have used the byte pattern that gives us Tutorial-i386.exe+22988 as a result but since we want to make the code injection at 2298E, we have simply used aob1+6 instead of aob1. 22988 + 6 = 2298E and since aob1 = 22988, aob1+6 is also equal to 2298E.



Jumps in your script:

Jump instructions in the original code will cause problems for you if you don't handle them properly. The source of the problem is this:

Code:
Tutorial-i386.exe+22988 - 8B 83 64040000        - mov eax,[ebx+00000464]
Tutorial-i386.exe+2298E - 3D E8030000           - cmp eax,000003E8
Tutorial-i386.exe+22993 - 75 2C                 - jne Tutorial-i386.exe+229C1
Tutorial-i386.exe+22995 - 8B 83 4C040000        - mov eax,[ebx+0000044C]



CE will show you that conditional jump as jne Tutorial-i386.exe+229C1 to make things easier, but in reality, that instruction is jne +2C. It will jump forward 2C bytes.

What happens if you use this code?

Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
//place your code here

originalcode:
jne Tutorial-i386.exe+229C1
mov eax,[ebx+0000044C]

exit:
jmp returnhere

"Tutorial-i386.exe"+22993:
jmp newmem
nop
nop
nop
returnhere:


 
 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"Tutorial-i386.exe"+22993:
jne Tutorial-i386.exe+229C1
mov eax,[ebx+0000044C]
//Alt: db 75 2C 8B 83 4C 04 00 00



Will it work? Absolutely. The problem is, Tutorial-i386.exe+229C1 is a static address and you can't jump to a static address, because it will be different in other game versions. This jump will work when you are making a normal script, but you can't use it with aobscan.

So let's replace it with the original instruction, jne +2C.


Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
//place your code here

originalcode:
jne +2C
mov eax,[ebx+0000044C]

exit:
jmp returnhere

"Tutorial-i386.exe"+22993:
jmp newmem
nop
nop
nop
returnhere:




[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"Tutorial-i386.exe"+22993:
jne +2C
mov eax,[ebx+0000044C]
//Alt: db 75 2C 8B 83 4C 04 00 00



What will happen if you enable this? If you are lucky, your program will not crash. But it will not work either. Because if you jump forward 2C bytes in the allocated memory that you have created, you end up at the middle of nowhere. Don't forget that this jump is calculating the destination from the current address so when you make a code injection, it is calculating the jump from the allocated memory.

Ok how to fix this? First we need a byte pattern for this code.

75 2C 8B 83 4C 04 00 00

Now calculate the difference between "Tutorial-i386.exe"+22993 and the destination of the jump, Tutorial-i386.exe+229C1. The difference is 2E bytes, which means that aob1+2E = Tutorial-i386.exe+229C1.

Why not 2C? We have jne +2C and now we have 2E. The answer is that the relative jump will calculate the destination from the end of the instruction and we are calculating it from the first byte of the instruction. Our instruction takes up 2 bytes, this is why the difference is 2 bytes higher.
Now that we know how should we change the jump, we can make a script that will jump to aob1+2E, wherever it is found by the aobscan.


Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(returnhere)
label(originalcode)
label(exit)
label(whatever)
registersymbol(whatever)
aobscan(aob1,75 2C 8B 83 4C 04 00 00)

newmem: //this is allocated memory, you have read,write,execute access
//place your code here

originalcode:
jne aob1+2E
mov eax,[ebx+0000044C]

exit:
jmp returnhere

aob1:
whatever:
jmp newmem
nop
nop
nop
returnhere:


 
 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
whatever:
db 75 2C 8B 83 4C 04 00 00
unregistersymbol(whatever)



Tada, we have made a magnificent script that is absolutely not making anything useful, but at least it is jumping at the right location, despite the fact that the jump instruction itself is far away from the destination. Now let's do something useful and replace jne with je. This will solve Step 2 of the tutorial and you can proceed to step 3.


In this moment, nothing more comes to my mind about this topic. This should be enough to deal with most of the problems that you will face when you are using aobscan.


Peace!
Geri

_________________
My trainers can be found here: http://www.szemelyesintegracio.hu/cheats

If you are interested in any of my crappy articles/tutorials about CE and game hacking, you can find them here:
http://www.szemelyesintegracio.hu/cheats/41-game-hacking-articles

Don't request cheats or updates.
Back to top
View user's profile Send private message
HowdyEngine
How do I cheat?
Reputation: 0

Joined: 21 Feb 2013
Posts: 2

PostPosted: Thu Feb 21, 2013 5:00 pm    Post subject: Reply with quote

Really appreciate your "tutorial" on this. I haven't gone through and tested all steps myself but I think I understood the overall points. It addresses code injection though, which I'm not quite after in this case.

I would like to ask you regarding AoB if it's possible to not just use it in injection/alteration purposes but also find variables or values of variables. I'm having trouble with a flash game where I can easily find the values and addresses but not any static base address, assuming because it's inside FlashPlugin file which also contains a lot of other things and changes every reload. I tried getting pointers but even a lvl 7 scan didn't seem to give anything static for next reload.

So I'm trying to obtain a way to find the variables using AoB. Is it possible, and can you give an example where you use AoB to locate and read the value of an variable? Preferably using the FlashPlugin for Firefox.
Back to top
View user's profile Send private message
Geri
Moderator
Reputation: 111

Joined: 05 Feb 2010
Posts: 5636

PostPosted: Sun Feb 24, 2013 5:11 pm    Post subject: Reply with quote

It doesn't matter that you use aobscan to find values for your game or find a code. You are searching for a byte pattern in both cases.

If you just want to make a manual scan, you don't need aobscan. An "array of bytes" scan in CE should help you finding the value if you know what are you looking for. This will work only if you have a working byte pattern for finding the address. Some of those values have to be static or you can't do this.

_________________
My trainers can be found here: http://www.szemelyesintegracio.hu/cheats

If you are interested in any of my crappy articles/tutorials about CE and game hacking, you can find them here:
http://www.szemelyesintegracio.hu/cheats/41-game-hacking-articles

Don't request cheats or updates.
Back to top
View user's profile Send private message
DaSpamer
Grandmaster Cheater Supreme
Reputation: 52

Joined: 13 Sep 2011
Posts: 1578

PostPosted: Sun Feb 24, 2013 5:34 pm    Post subject: Reply with quote

*most of the bytes should be static, else you'll end up with no results or with too m any results.
Codes are usually static (for the long it jmp or call stuff)

_________________
HEY Hitler
Do you get lazy when making trainers?
Well no more!
My CETrainer will generate it for you in seconds, so you won't get lazy! Very Happy

http://forum.cheatengine.org/viewtopic.php?t=564919
Back to top
View user's profile Send private message
chiyoko10
Cheater
Reputation: 0

Joined: 30 Mar 2013
Posts: 35
Location: Philippines

PostPosted: Mon Apr 15, 2013 7:50 am    Post subject: Reply with quote

Good instruction! Really helps me! Smile
_________________
Hi ! Smile
Back to top
View user's profile Send private message Yahoo Messenger
jungletek
Advanced Cheater
Reputation: 0

Joined: 02 Oct 2011
Posts: 72

PostPosted: Thu May 16, 2013 10:41 pm    Post subject: Reply with quote

Great tutorial Geri... was really helpful when I needed to refresh my knowledge of a few things.

Thanks, and more like this is always appreciated. I've bookmarked your game hacking articles for future reference, as I find them particularly easy to read. The only 'complaint' is that it's sort of hard to differentiate the code from the article text, as there's not specific formatting going on for the code like you get with a /code tag, for example.

Thanks again!
Back to top
View user's profile Send private message
Geri
Moderator
Reputation: 111

Joined: 05 Feb 2010
Posts: 5636

PostPosted: Fri May 17, 2013 10:59 am    Post subject: Reply with quote

I am very lazy if it comes to formatting, design, etc. Maybe I will use some other color or something for the codes in the future.
_________________
My trainers can be found here: http://www.szemelyesintegracio.hu/cheats

If you are interested in any of my crappy articles/tutorials about CE and game hacking, you can find them here:
http://www.szemelyesintegracio.hu/cheats/41-game-hacking-articles

Don't request cheats or updates.
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8516
Location: 127.0.0.1

PostPosted: Fri May 17, 2013 11:17 am    Post subject: Reply with quote

Geri wrote:
I am very lazy if it comes to formatting, design, etc. Maybe I will use some other color or something for the codes in the future.


Got bored and added some common formatting for you Geri, hope you don't mind. Razz

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Geri
Moderator
Reputation: 111

Joined: 05 Feb 2010
Posts: 5636

PostPosted: Fri May 17, 2013 8:20 pm    Post subject: Reply with quote

Wiccaan wrote:
Geri wrote:
I am very lazy if it comes to formatting, design, etc. Maybe I will use some other color or something for the codes in the future.


Got bored and added some common formatting for you Geri, hope you don't mind. Razz


Lol, sure I don't mind it at all. It looks better now. Basically everything looks better compared to what I do. As if ugliness would be my "signature". Laughing

_________________
My trainers can be found here: http://www.szemelyesintegracio.hu/cheats

If you are interested in any of my crappy articles/tutorials about CE and game hacking, you can find them here:
http://www.szemelyesintegracio.hu/cheats/41-game-hacking-articles

Don't request cheats or updates.
Back to top
View user's profile Send private message
KnightosMaster
How do I cheat?
Reputation: 0

Joined: 08 Jun 2013
Posts: 1
Location: Hungary

PostPosted: Sat Jun 08, 2013 8:06 am    Post subject: Reply with quote

Awesome tutorial, helped me a lot.
But my question is, how do I know that "Tutorial-i386.exe"+22988 is the memory region? When I tried what writes/acessess this adress, I got like 3 or 4 of them but none of them was 22988, and none fo them had the cmp command after them (which was needed for the 3D part).
Sorry if I missed something, but I couldn't figure that one out.
Back to top
View user's profile Send private message
Geri
Moderator
Reputation: 111

Joined: 05 Feb 2010
Posts: 5636

PostPosted: Sat Jun 08, 2013 5:14 pm    Post subject: Reply with quote

Make sure that everything matches:

1. Tutorial that comes with CE 6.2.
2. The 32-bit tutorial.
3. You should be at Step 2, the first scanning tutorial, scan for known value that starts at 100.

_________________
My trainers can be found here: http://www.szemelyesintegracio.hu/cheats

If you are interested in any of my crappy articles/tutorials about CE and game hacking, you can find them here:
http://www.szemelyesintegracio.hu/cheats/41-game-hacking-articles

Don't request cheats or updates.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Tutorials 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