——————————
Table of Contents
——————————
I. Introduction
II. Registers
II.a 32 Bit Registers
II.b 16 Bit Registers
III. Commands
III.a JMP
III.b MOV
III.c Push/Pop + The Stack
III.d alloc/label/registersymbol
III.e Call and Ret
III.f Others
IV. Array of Bytes
V. Conclusion
VI. Credits/Acknowledgements
BONUS: Writing a Script
——————————
I. Introduction
——————————
‘Ello there, I assume one of two things because you’re reading this.
1) You’re trying to learn Auto Assembler (I won’t call you a noob, because everybody has to start somewhere, right? =) )
or
2) You want to test your Auto Assembler knowledge (to an extent).
Now, if the first of the two is correct, then take each part slowly, and make sure you understand a section before going on ahead.
Dark Byte wrote: |
Most people think that AA is hard, but in fact, it’s really quite easy. |
Words from the creator of Cheat Engine himself.
If the second of the two is true, then I don’t really have any advice for you, however I do have a favor to ask. If you find something incorrect, or vague, or something that you think I can redo better, PLEASE TELL ME. I am sitll in the process of learning myself! But wait, don’t even ask, I can read your mind…
You wrote: |
Why should I listen (or in this case, read) to/from someone who is still learning? |
Well, I’ll tell you, my good friend. Although I’m still learning, I do know about Auto Assembler, and I just thought it would be nice to share the knowledge that I have with you. =)
Edit: This was written a long time ago, but I’ve learned a lot, and I’ve rechecked it.
Now, off we go… into the amazing world of the computer…..
——————————
II. Registers
——————————
Now you have probably seen these before in scripts, as they are VERY commonly used. There are two types of Registers used, and I shall explain both in this guide.
—————
II.a 32 Bit
—————
First of all, I will explain how each register got its name, in order to possibly help you remember which is which. First of all, the E in front (if you notice below, all of the 32 Bit Registers have an E in front) tells you that the register is a 32 Bit Register. The A, B, C, and D, should become obvious after reading the description. As should SI, DI, BP, SP, and IP. The X after EAX, EBX, ECX, and EDX, is simply there to show that there are no more letters to put, kinda like a NOP command (which you will read about later on). If you notice, there are three letters in each of the 32 Bit Registers.
EAX: The Acculmulator register. It can also be used as storage.
EBX: Once upon a time, it was the base register, but now it’s just free storage.
ECX: The Counting register. Once again, can also be used as storage.
EDX: The Data register. As with the last three, it can be used as storage.
ESI: The Source Index register. It is used as a pointer variable in strings, but you shouldn’t worry about that part right now. Can be used for storage.
EDI: The Destiny Index register. Once again, can be used as storage, and is a pointer variable in strings, but don’t worry about it.
EBP: The Base Pointer register. It temporarily store ESP, but can also be used as general storage.
ESP: The Source Pointer register. It points to registers and addresses on the stack (more on that later).
EIP: The Instruction Pointer register. Using this incorrectly can lead to a crash in whatever program you’re trying to mess with.
—————
II.b 16 Bit
—————
The 16 Bit Registers are very similar to the 32 Bit Registers, save a couple things. One of the things is that, instead of three letters, as the 32 Bit registers have, they have two letters. There are also a couple more 16 Bit registers than 32 Bit registers, but don’t worry about them. 16 Bit registers probably won’t be used in our general purposes anyway.
AX: See EAX
BX: See EBX
CX: See ECX
DX: See EDX
SI: See ESI
DI: See EDI
BP: See EBP
SP: See ESP
IP: See EIP
—————
And that’s pretty much it on registers. If you want to learn more about registers, then just go Google it. For most learners, however, this should suffice.
——————————
III. Commands
——————————
Now, what is a language without its functions or commands? Comparing this to English, a command is like a word, and an opcode is like a sentence. For those that don’t know, an opcode is something simple, such as:
Code: |
jmp 00123EAA |
There are a couple things that you should know about Opcodes.
Firstly, there is always an address and/or a register involved in an opcode, as well as the obvious command. An address is in Hex, which is short for Hexadecimal. Hexadecimal is a numbering system with base 16. It’s like the Decimal numbering system, which has a base of ten.
Think about it this way. Our normal numbering system is decimal, which, as I said above, is base 10. This means that we can not have a “10” in one column, rather, it is placed in two. In Hexadecimal, you CAN have a 10 in one column–you can have all the way up to 15 in one column. But you may be wondering about that fact that 1 and 0 don’t fit in one column still.
Calm down, though. In hexadecimal, the decimal 10 is replaced by A, the decimal 11 is replaced by B, and so forth up to F, which stands for 16. After that, it becomes 10, then 11, up until 1F, and then it starts over at 20, and so forth. A way to translate between these two, is to click on “Start” at the bottom left corner of your screen, then click the “Run” button, and type in “calc”. Next, click on view, and click on “Scientific”, so that your calculator nearly doubles in size, with many new functions (unless of course, it was already in “Scientific” mode). Next, click on the numbering system that your original number is in. e.g Click on “Hex” if you want to put 6AF0 into Decimal. Next, type in your number, and then click on the system that you want to translate to. Voila, you have your number translated!
Also, every address has an opcode and a number of bytes. The number of bytes corresponds to what the opcode is, as every command takes up a certain number of bytes. I know how many bytes some of the very common functions take up, but if you want to know the number of bytes that each command takes up, you’ll have to rely on someone else… preferably Google! =)
Lastly, something very handy is to “comment” something. To comment, all you do is put “//” after a command, or a space, and then type whatever you would like. If you don’t type the “//” after a command or space, then the computer will think that you’re typing a command.
Now, on to what each command does…
—————
III.a JMP
—————
The JMP command is one of the most commonly used commands (around as common as the MOV command, which we will get to next). However, you don’t see “JMP” nearly as much as you see “MOV” in opcodes and scripts, because there are many variations to the JMP command. There are way too many to list, but some are listed below.
JMP: Always jump to
JE/JZ: Jump to if equal
JNE/JNZ: Jump to if not equal
JA: Jump to if Above
JG: Jump to if Greater
JNA: Jump to if not Above
JNG: Jump to if not Greater
JB: Jump to if Below
JL: Jump to if Lower
JNB: Jump to if not Below
JNL: Jump to if not Lower
JAE: Jump to if Above or Equal
JGE: Jump to if Greater or Equal
JNAE: Jump to if not Above or Equal (i.e. JB)
JNGE: Jump to if not greater than or Equal (i.e. JL)
And you get the picture. Now this must seem confusing. “Jump to if greater”, or JG is one of the Conditional Jumps. A conditional jump is as its name implies, it jumps when a certain condition is met. Usually, there is a “CMP” or compare function above it–more on that later. That’s pretty much it for JMP. On to…
—————
III.b MOV
—————
Now, as you read above, the MOV command is one of the most widely used commands, because it is one of the most versatile. An example of MOV is below.
Code: |
mov eax,ebx |
What this means is “move the address that is stored at ebx into eax”. Notice that there is a comma that seperates the two registers, but no space. It may seem a bit confusing at first, but it is really simple. Here is a better explanation.
“Mov” stands for “move”. A register by itself means “the address stored within that register”. So basically, “Move, the address stored in ebx, into the address of eax”, which will overwrite whatever was in eax before, and completely erase its existance. =D What you could relate this to is copying what is in ebx, and pasting it into eax.
Another form of mov is below.
Code: |
mov eax,[ebx] |
This means “move the VALUE of ebx into the address that is stored within eax”. Simply put, having the [brackets] around a register or address means the value of what is in the register or address.
However, something that will not work is below.
Code: |
mov [eax],[ebx] |
WILL NOT WORK. REPEAT: THE CODE ABOVE WILL NOT WORK. You can not, repeat CAN NOT move the value of one thing into the value of another thing. But don’t take this the wrong way–you can move the value of one thing indirectly into another thing. 😉 Refer to the code below.
Code: |
push eax //Push eax onto the stack–we’ll cover this later mov eax,[0100200A] //Move the value of 0100200A into eax mov [ebx],eax //Move eax (which is the value of 0100200A) into the value of ebx pop eax //Pop eax from the stack–once again, we’ll cover this later |
I believe that covers it for the MOV function. Onto…
—————
III.c Push and Pop + The Stack
—————
You saw above how I used the Push and Pop commands. But wait, I’m psychic… I can read your mind!
You wrote: |
What does push and pop do? And what is the stack? |
Ok, well as you saw above, after the “Push”, I commented:
Code: |
//Push eax onto the stack |
This is basically just putting eax onto the stack. The Pop eax is basically taking eax out of the stack. A very, VERY good explanation of the stack was written by Skyone, from CEF, and I just couldn’t live with myself if I didn’t allow you the pleasure of learning about it the way I did. 😉
Skyone wrote: |
The stack is used to give a variable a blank value, and use it for storage. This about it like this: You have a piece of paper that you are doing your homework on, but then your friend calls you to tell you that you need to call Phil, where his number is 555-6405. You panic, with nothing else to write on, you write it on your homework sheet. After you hang up from talking to your friend, you now have time to find your phone book so you can write down Phil’s number. After writing Phil’s number in the phone book, you erase it from your homework, call Phil, and continue on with the homework.
To push a value on to the stack is to “write down Phil’s number on the homework.” To pop it is to “transfer the number to a phone book, then erase it from the homework.” |
Next up…
—————
III.d Alloc/Label/RegisterSymbol
—————
I like to classify Auto Assembler scripts two ways.
1) The simple changing of an address
This is simply something like the code below.
Code: |
[enable] 00ABC123: mov eax,ebx [disable] 00ABC123: mov ebx,eax |
All it really is doing is changing the opcode of the address 00ABC123.
But then there are very complicated scripts, much like the scripts for dICE or pID00. (I’m not gonna put one here, because it isn’t really necessary to your learning.
In the very complicated scripts, at the top you will see things (note how I didn’t use usually–in a complicated script there will be the functions “alloc”, “label”, and sometimes “registersymbol”.
““““““
Label
““““““
I believe the “label” function is the most important of the three. What it does is allows the variable that you “label” to be used in your script, like below.
Code: |
label(Continue)
AutoAssembler: Continue: SayWhat: |
There are a few things to note in this script. First, this script is missing the “alloc” functions, which I’ll get into after this one.
Next, if you understand why I chose the label that corresponds to the “jne”, then you’re doing well.
Note that I use all of the labels that are defined in my script, otherwise it would not compile.
““““““
Alloc
““““““
Now, the “alloc” function. What it does is allocates (hence, alloc, allocate) X amount of memory to your purpose. Now, this memory isn’t just any old memory, this is unused memory that you can overwrite without running into problems. Now, as I said, it allocates X amount of memory. X is a variable that is a certain number of bytes. 1024 bytes, or one kb (kilobyte) is usually enough for what you’re trying to accomplish. Now that we know about the alloc function, let me demonstrate to you how to use it–and for now, let us just build upon what we have so far.
Code: |
alloc(AutoAssembler,1024) alloc(SayWhat,1024) label(Continue) AutoAssembler: Continue: SayWhat: |
Notice how I don’t do
Code: |
label(AutoAssembler) |
or
Code: |
label(SayWhat) |
because those are already defined in Cheat Engine’s “dictionary,” as we’ll call it.
““““““
RegisterSymbol
““““““
Lastly, the function “registersymbol”. What this does, is allows you to add the symbol that you register to your Cheat Table. Note, you still have to allocate memory for it. Let’s try this in our script.
Code: |
alloc(AutoAssembler,1024) alloc(SayWhat,1024) alloc(WooHoo,1024) label(Continue) registersymbol(WooHoo) AutoAssembler: Continue: SayWhat: |
““““““
Counterparts
““““““
Now, the last part of this mini-section: the counterparts.
There are two things that you can do with an Auto Assembler script. Firstly, you can inject something. Secondly, you can add it to your Cheat Table. If you decide that you want to add it to your cheat table (which is how most scripts are nowadays), then you need an enable and disable section of your code, like below.
Code: |
[ENABLE] alloc(AutoAssembler,1024) alloc(SayWhat,1024) alloc(WooHoo,1024) label(Continue) registersymbol(WooHoo) AutoAssembler: Continue: |
Now, as you noticed, there is nothing in the Disable section–but not for long! 😉
What you want to accomplish in the DISABLE section of your code, is to undo whatever you did in the ENABLE section.
How you do this is to undo the allocating, and the registering of symbols. Now, I feel a question coming on…
You wrote: |
How do you do that? |
Simple, my friend. Via the dealloc, and unregister symbol functions! Oh wait, another question,
“What about label?” you ask?
Well, there is nothing to undo label. =) That means that n the DISABLE section, you drop almost half of the code from the beginning section! =)
So why don’t we add what we’ve learned to the script?
Code: |
[ENABLE] alloc(AutoAssembler,1024) alloc(SayWhat,1024) alloc(WooHoo,1024) label(Continue) registersymbol(WooHoo) AutoAssembler: Continue: |
Oh hey there… another question.
You wrote: |
Why didn’t you put the “1024”? |
Well since the computer knows that you allocated 1024 bytes to AutoAssembler (let’s just use this as an example), you only need to dealloc AutoAssembler, and it knows to deallocate the whole 1024 bytes that were allocated to AutoAssembler. (Sorry if this is a bit vague)
—————
III.e Call and Ret
—————
The Call function is very similar to the JMP function. The only difference is that it has a counterpart to get back to where it was before. A simple script utilizing these two functions is below.
Code: |
mov [0100579C],10 //Move 10 into the value of the address cmp [0100579C],0 //Compare it to 0 call NameGoesHere //Call, or JMP to NameGoesHere jmp 01002FF5 NameGoesHere: |
—————
III.f Others
—————
Now, obviously, there are many, many other functions in Auto Assembler, or else it would be a VERY limited language.
I’ll go ahead and define as many as I can. (Oh boy…)
““`
Nop
““`
Nop: I mentioned this earlier. This means “No Operation”, and it basically cancels out what was there before it.
““`
Inc/Dec
““`
Inc: Increase by one. This increases the value of the register or addres by one. Used as below.
Code: |
inc eax |
Dec: Decrease by one. Virtually the same as Inc.
““`
Add/Sub
““`
Add: Addition. Used as the script below.
Code: |
add eax,02 //Add 2 to eax, and store the result in eax |
Sub: Subtraction. Used like add.
““`
Lea
““`
This is a bit confusing, but here goes. Look at the script below.
Code: |
mov eax,00123ABC lea ebx,[eax+DEF] |
If you couldn’t tell, [eax+DEF] is a pointer. LEA is taking the address that is being pointed at by [eax+DEF] and placing it (the address being pointed at) into ebx.
““`
And/Or/Xor
““`
Ok, I haven’t the slightest clue what “xor” means in English–many websites say something along the lines of…
Them wrote: |
I assume you understand how these logical operator behave. |
If someone could define XOR in English for me, I would be most indebted. However, I need no help explaining how they work in Assembly. 😉
First off, they all have the same syntax as the add, and sub commands–as in below.
Code: |
and eax,ebx |
In which eax and ebx can be anything. But no, it cannot be “my mom”. -.-;
Back to the script. To process this, (yes I know we’re not computers…) we have to first give the two registers values. How about we give eax the value of 12, and ebx the value of 27. Next, we change them to binary–the one’s and zero’s language. =O Is that a question?
You wrote: |
But I do I change it from decimal to binary? |
Simple my friend, just load up your good ol’ friend the calculator, select decimal and type in your number, then click the binary! Something to note, the calculator does not allow you to put decimals, it simply rounds then changes to binary.
I come up with:
Code: |
EAX = 1100 & EBX = 11011 |
Ok, now you remember back in Elementary school when we lined up our numbers to do arithmetic? Well let’s do that here.
Code: |
and eax,ebx
EAX = 1100 |
Now, the AND instruction will give a 1 if both of the numbers are 1, otherwise it will give a zero. So let’s check it out on this problem.
Code: |
and eax,ebx
EAX = 01100 (added the zero just to make it easier) |
And now we change 01000 to decimal, and we get 8, which is stored into EAX.
Next, the OR function. Let’s use our same scenario, just for the sake of ease.
Code: |
or eax,ebx
EAX = 01100 |
Now, what the OR function does is the oppositte of the AND function. If both digits are 0, then it will produce a 0, otherwise it will produce a one.
Code: |
or eax,ebx
EAX = 01100 |
We change 11111 to decimal, and we get 31, which is stored into EAX.
Lastly, the XOR function. Once again, let’s use the same scenario.
Code: |
xor eax,ebx
EAX = 01100 |
Ok, now the XOR function will return 0 if both digits have the same value, otherwise it will return a one.
Code: |
xor eax,ebx
EAX = 01100 |
We translate that to 23, and so 23 is stored into EAX. By the way, when writing a script/code/whavever, you don’t need to inclue the EAX = BlahBlahBlah, I was just using it to show you how it worked.
““`
Well that’s about all you need to know for commands! (Man that was long…) Onto the next section…
——————————
IV. Array of Bytes
——————————
Ok, picture this. You’ve gotten your script and your addresses and you start hacking. All’s well. until… OH NO! A PATCH! But don’t fret. Now you don’t have to worry about waiting for other people to post the new addresses!
You wrote: |
I did? I don’t recall doing that… |
You didn’t?!
Oh, you don’t know how.
Alrighty, then, I’ll tell you, my good friend.
1) Load up your Engine and attatch it to the game you are hacking.
2) Click on “Add Address Manually”, which is above the right side of your Cheat Table.
3) Click on the box next to what says “Address”, and type in the Addresses of whos AOB’s you want to get.
4) Click on the drop-down-arrow next to what says “Type” and choose Array of Byte.
5) Type in 8 as the number (or Nr.) of bytes.
6) Click ok. =)
Ok, now you have the Array of Bytes for your address. But how about after the patch?
1) Load up your Engine and attatch it to the game that you want to hack.
2) Around the top of the middle area of the Engine should be a section of scanning. Click on the drop-down-box by “Value Type” then choose Array of Bytes.
3) Now, type (or paste if you want, from a Notepad doccument), the Array of Bytes into the Value section.
4) Click first scan, and an address should pop up. If an address doesn’t pop up, take a few bytes (the two letter/number segments) off of the end, and then search again.
Ok, you’ve got the address… now what do you do with it? Take the script that you want to convert–let’s just use the v.38 Maplestory God Mode script.
Code: |
[ENABLE] 6803ec: je 0068133e [DISABLE] 6803ec: jne 0068133e |
So you have the new address. Delete the “6803EC” in the Enable and Disable sections, and then paste your address. MAKE SURE THAT YOU LEAVE THE COLON ( : ) THERE.
Well, that’s it for the Array of Bytes…
——————————
V. Conclusion
——————————
…and that’s pretty much it for the Auto Assembler tutorial! Hey wait, do I sense a question?
You wrote: |
Was it really that easy? That’s it? No more tricks or anything like that? |
Nope, that really was it! Once again, I shall quote the creator of Cheat Engine…
“Most people think that ASM is really hard, but in fact, it’s really quite simple.” ~Dark Byte himself
However, I have a mini-tut after this on writing a script, so stay tuned, folks! You don’t need to read the “Writing a Script” tutorial, as it is only Bonus, although I highly recommend it.
——————————
VI. Credits/Acknowledgements
——————————
There are a couple acknowledgements I would like to give, before giving the credits.
First, and foremost, Wizet, for creating Maplestory that I got so in to hacking. ; )
Second, Dark Byte, for creating the base of our hacking today, and for creating the Tutorial for Cheat Engine. Hey, we all have to start somewhere!
Third, Sponge and Labyrnth for helping me with my scripts.
and Fourth, the creators of all the guides that I got my information from.
Thank you!
“““““
Credits
“““““
Note, that these are not in any order.
Scrbly’s Tutorial on CodeInjection and AutoAssembler
Idogear’s post on Basic Assembly
TheSorc3r3r’s tutorial on Beginning Assembly Language
Skyone’s Tutorial on Basic Assembly
M3KillU’s tutorial on Array of Bytes
Renkokuken’s Post on Register Sets
Vrunk’s Tutorial on Allocated Memory
Dark Byte’s Guide on Basic Assembler
Dark Byte’s Guide on the registersymbol/unregistersymbol functions
Zhoul’s “There’s always more than 1 way to skin a cat”
Dark Byte’s “Auto assembler scripts in cheat tables”
——————————
Bonus. Writing a Script
——————————
So you’ve read the tutorial, and you understand it fully, but you still want more. I understand, as I felt like that once–unfortunately I don’t believe there were any tutorials on writing scripts when I needed them.
Code: |
[ENABLE] alloc(AutoAssembler,1024) alloc(SayWhat,1024) alloc(WooHoo,1024) label(Continue) registersymbol(WooHoo) AutoAssembler: Continue: SayWhat: |
Remember this script from before? Well let’s turn it into a full script, using a lot of what we’ve learned.
Code: |
[ENABLE] alloc(AutoAssembler,1024) alloc(SayWhat,1024) alloc(WooHoo,1024) label(Continue) registersymbol(WooHoo) AutoAssembler: Continue: SayWhat: [DISABLE] |
Something that you NEED for a script, is an address in the actual memory of the program that you’re hacking. However, this can’t be just any random address, or something could happen that you don’t want to happen (crash, maybe). This address has to be related to your cause.
But why do we need an address? Well as I said before, the alloc function allocates UNUSED MEMORY, in the program to your function. Because this is UNUSED, the program does nothing to access this, and therefore, you have to MAKE IT access this.
There are a couple crucial things when messing with addresses. First, you MUST use the same ammount of bytes as the original opcode used. How do we tell the number of bytes in an opcode? Simple. Look between the address and the opcode and there should be a bunch of segments of 2 letter/number combinations. These are called the Array of Bytes.
Something very helpful when meeting this need is the function “nop”. As I explained earlier, it means “no operation”. All it does is take up a byte. Meaning, if you don’t use up all of the bytes, then you can fill in the remaining bytes with ‘nop’s.
There are 3 scenarios you can encounter when filling in bytes. I have already described one, in which your code is smaller than the original code. Another of the last two scenarios is when you have exactly the same ammount of bytes as the original opcode, in which all is fine.
But the last of the scenarios is a bit confusing. This is the scenario in which your code has more bytes than the original opcode. Now, what you have to do has overwrite the NEXT address’s opcode with your code, and do so forth until you have enough bytes.
Why don’t we play with Minesweeper? I wrote a code a little while back while I was learning about writing scripts (I still am, but that was when I knew less).
Code: |
[enable] alloc(WhatNowMinesweeper,256) //Allocating… alloc(ChiliDog,4) label(ReturnHere) registersymbol(ChiliDog) //Registering… ChiliDog: 01002FF5: //This is the address that writes to the time on MineSweeper WhatNowMinesweeper: //My actual code [disable] 01002FF5: //The address that we modified to jmp to my code |
Now, first thing’s first. I told you that I would tell you about the “ReturnHere” thing, and so I shall. Just so you know, a program processes what it is told to do in one opcode, then moves on to the next opcode, and so on. It’s pretty much like a never ending cycle. However, if we make a dead end, i.e. if the code has no where else to go after the code, then the program will most likely crash. Therefore, we redirect it out back right after the end of the address that we changed, and therefore the code has a place to go–and we don’t crash! =D
And that’s pretty much it on writing a script. Please, feel free to ask questions, and to comment on whether you liked it or not. =)