Ok I've seen a few people stugeling with nopping and most of you guys know nothing about what you're actually doing when you guys shove those 0x90's to an address.
So that's what I'm going to explain to you guys today. I'm also going to include some theory on the stack and the inner workings of the processor. Feel free to leave this thread after you see that it is only theory. Know however that what I'm explaining here can lift you to a whole new level of understanding how hacks, and programs in general work.
So of we go.
Noping
I'm sure you've all done it, shooting 0x90's at addresses with memcpy() or memmove() or another memory mover. I'm also sure however that over 90% of you guys don't have any idea why nopping does what it does. I mean why the fuck would sending "\x90" to an address stop it from execution?
That's very easy to explain, you see NOP (short for No Operation or No Operation Performed) does just as the name applies: nothing.
On encountering a nop the processor does nothing, it increments the instruction pointer (see stack & inner workings of a processor) so it can execute the next execution found.
That's all, so if you have a piece of code like this:
And this is the piece of code that's responsible for the recoil, and you change it to:
Now the processor will go like:
Code:
Instruction >> do nothing
Next instruction
Instruction >> do nothing
Next instruction
Instruction >> do nothing
next instruction
Instruction >> do nothing
next instruction
And that's how nopping works.
Now the stack & the internal workings of a processor
I'm sure you guys have all wondered at some point why the computer does what it does, and how a bunch of symbols inside .exe file translate to a full blown game. Well your explanation is here:
Ok first off, the stack
The stack is easy to understand and to work with. The stack as the name implies is like a pile of junk, the only thing you have to remember is the 'first in last out' principle, or 'last in first out'. This simply means that the last thing you throw on your pile of junk, is the first thing you're going to take off again. Let me illustrate that.
The computer's stack works exactly like this, the programs on your computer throw (push) data on the stack and then take it back again later on (pop)
This is called pushing and popping.
Code:
pushing = saving data on the stack
popping = loading data from the stack
Push and pop are instructions, just like nop is, on finding a push or pop instruction the processor will handle accordingly.
Now onto the inner workings of a processor:
Ok this'll be the toughest part of this little lecture, I'll handle a few aspect on how an processor works in general.
First off, instructions
As you probably have noticed by now an processor acts on instructions. These are literally hardcoded into the processor and there are a lot of instructions. When an processor encounters an instruction it will simply do what the instruction tells the processor to do and move on. Here's a list of basic instructions:
Code:
mov moves a piece of data from one place to another, eg. from an memory address into an register (see registers)
pop loads data from the stack into an register of variable (see registers)
push saves date on the stack
sub subtracts a value from an register or variable (see registers)
add adds a value from an register or variable (see registers)
So when a processor encounters one of these instructions it will handle appropriately. There are a lot more instructions than the 6 mentioned by me. Some of these instructions also take operands like the move instruction, it needs an destination and a source. Like this:
Code:
mov variable1, register1
The instructions have different lengths and sizes, the mov instruction for example is 2 bytes long, while the push & pop instructions are both 1 byte in length. Another funny thing is that a mov instruction is actually a push and a pop combined.
Code:
mov operand1, operand2
can be replaced by (or actually translates to)
Code:
push operand1
pop operand2
So just remember: instructions are the things where the processor acts (mov) or does not act upon (nop)
Now Registers
Registers are what makes programs tick, every thing you can do with your compiler and what programs can do in general translates back to registers.
There are many types of registers inside a processor, here's a little list:
Code:
# User-accessible Registers
# Data registers
# Address registers
# Conditional registers
# General purpose registers (GPRs)
# Floating point registers (FPRs)
# Constant registers
# Vector registers
# Special purpose registers ( SPR )
# Control and status registers
All these registers have a small piece of memory inside the processor, and the processor uses these registers to do everything your programs do. I'll now tell you what every of these register types do:
General purpose registers & User-accessible registers
The User-accessible registers and the General purpose registers are one and the same. they're used to preform various tasks like moving data around and preforming calculations. You can pass GPRs into processor functions.
Since most of the processor's registers cannot be used by the outside, GRPs also serve as an output place for instructions that require math with floating points integers, or arrays of data. For example:
the processor can do this by storing the 1 into the eax register, and the remainder ( 0.9) in ebx. So you can still access floating points and doubles.
A list of General purpose registers (GPRs)
Code:
eax
ebx
ecx
edx
esi
edi
ebp
esp
These registers had special names in the past, but since 32 bit systems came around and made it possible to use all these registers for all kinds of things, the names and their original functions became obsolete.
So know you know what it means when I do this:
This command (again an offspring of the mov command, and thus a push/pop combination) simply moves 1 to what is in eax.
here's how it (can) look in C++
Data registers & Address registers
These are easy to explain, Data registers hold as their names imply: data. There registers hold data that is to be moved to the RAM (random access memory) or they act as a buffer for data to be moved from the RAM to the processor. So these are simply the registers that receive data from the memory for the processor to use.
Address registers are a bit more tricky. There are three types address registers:
I won't go into the MAR types because the DMAR and SMAR will suffice.
DMAR stands for Destination Memory Address Register, SMAR is the same but instead of Destination it's Source Memory Address Register.
Say you have a mov instruction, the mov instruction takes two operands, a source and an destination. So when the processor sees a mov command it'll load the destination operand into a DMAR and the source operand into an SMAR register, than it jumps to a processor function that'll load the contents at SMAR to DMAR.
Conditional registers, Floating point registers & Constant registers
These are all registers that are crafted to hold values and data. As the name implies the Floating point registers hold floats or doubles:
Code:
float i = 0.9;
or
double i = 0.9;
This value will be dealt with in the floating point register. Conditional registers are almost the same, only they handle booleans, or true/false conditions.
Constant registers are read-only they never change. They hold values like PI and other constant and never changing values.
Vector registers
These are registers (and instructions alike) to work with arrays and vectors of data. If you have an array in your program, it will be handled by an vector register (if you have one, but that's probably the case)
Code:
char name[] = "SCHiM";
name is an character array, and will be handled by a vector register.
Special purpose registers
These are registers that programs use to control their flow. Here's a list of SPRs:
Code:
EIP
EFLAGS
CS
DS
ES
SS
ES
SP
GS
If you're still with me you can see that the SP or ESP register is also mentioned in the GPRs group, I'm also posting it here because unlike the others this register has kept it's original function: Pointing to the stack
See stack
The ESP short for Extended Stack Pointer, is used to keep track of where the stack is, and points to the highest (last) item that was put into the stack. There is no pointer to keep track of how deep the stack is. This so the designers of microprocessors thought is the responsibility of the caller. You as programmer (or your compiler) must keep track of how deep the stack goes, so you don't try to pop data from below the stack.
The EIP register or Extended Instruction Register keeps track of the next instruction to be executed by the processor. You cannot access this register.
EFLAGS or just FLAGS
Are used to keep track of states inside the processor, they are read only registers and are part of the Conditional registers (see Conditional registers)
They either hold true or false a few examples:
You have the Zero flag for example, this flag is set when the remainder of a calculation is Zero (0). This flag is used when comparing values. Take a look at this example:
Code:
if (i == i){
//do something
}
This piece of code checks if i == i, this could translate to:
The processor subtracts i from i, if the remainder is 0 the zero flag is set, now the program can read the zero flag to see if i = i.
Control and status registers
These registers are like the SPRs they keep track of the statues inside the processor but more internal than the SPRs group. they aren't to any meaning to us.
I hope at least a few people have read this little lecture, I've spend over an hour of writing this, and it'll make you much more competent if you actually understand what it is you're doing when programming
-SCHiM
Happy hacking
I've kept this article as simple as possible, explaining the inner workings of processors in-dept would take ages, there are also a few errors inside this article especially at the register part, this is because this article is here to illustrate what all these things do, not to tell you about all the exceptions rules and special cases