Difference between revisions of "Tutorial:Stack"
Line 3: | Line 3: | ||
[[Category:Auto Assembler]] | [[Category:Auto Assembler]] | ||
{{DISPLAYTITLE:Tutorial - The Stack}} | {{DISPLAYTITLE:Tutorial - The Stack}} | ||
− | + | If you're unfamiliar with registries please start here: [[Assembler#Registers|Registers]] | |
So what is ''the stack''? | So what is ''the stack''? | ||
Line 13: | Line 13: | ||
:Removes the most recently added element that was not yet removed. | :Removes the most recently added element that was not yet removed. | ||
− | It uses a '''LIFO''' (last in, first out) behavior. So if we | + | The stack is primarily used to store values for a process. It uses a '''LIFO''' (last in, first out) behavior. So if we [[Assembler:Commands:PUSH|PUSH]] value A onto the stack and then [[Assembler:Commands:PUSH|PUSH]] value B, when we [[Assembler:Commands:POP|POP]] it will be value B first then value A with the second [[Assembler:Commands:POP|POP]].[https://wikipedia.org/wiki/Stack_(abstract_data_type)] |
[[File:Lifo_stack.png||LIFO|border]] | [[File:Lifo_stack.png||LIFO|border]] | ||
− | + | <br> | |
== Working with the Stack == | == Working with the Stack == | ||
So let's just dig in, if we have some code like this. | So let's just dig in, if we have some code like this. | ||
Line 24: | Line 24: | ||
push 00DEAD | push 00DEAD | ||
push 00BEEF | push 00BEEF | ||
+ | |||
pop dword ptr [TestVals] | pop dword ptr [TestVals] | ||
pop dword ptr [TestVals+4] | pop dword ptr [TestVals+4] | ||
Line 33: | Line 34: | ||
So let's set a breakpoint and watch the stack as we step though the opcode. | So let's set a breakpoint and watch the stack as we step though the opcode. | ||
+ | :Note: You can select a line of opcode in the memory view form and press ''F5'' to set a breakpoint. | ||
+ | :Note: Step though opcode in the memory view form by pressing ''F7'', after a breakpoint has been hit. | ||
:Note: to view the stack you may need to select it for viewing. | :Note: to view the stack you may need to select it for viewing. | ||
[[File:StackView.01.png||stack view|border]] | [[File:StackView.01.png||stack view|border]] | ||
− | + | <br> | |
=== Code step 1 === | === Code step 1 === | ||
[[File:TutorialStack.02.png||step 1|border]] | [[File:TutorialStack.02.png||step 1|border]] | ||
Line 66: | Line 69: | ||
The thing to remember is that if you push in some injected code then you will need to pop in order to clean (or sanitize) the stack. | The thing to remember is that if you push in some injected code then you will need to pop in order to clean (or sanitize) the stack. | ||
+ | <br> | ||
+ | == Working with the registries == | ||
+ | We can [[Assembler:Commands:PUSH|PUSH]] and [[Assembler:Commands:POP|POP]] most registries, this is useful for saving and restoring stuff in injected code. The x86 architecture has 8 General-Purpose Registers (GPR), 6 Segment Registers, 1 Flags Register and an Instruction Pointer. 64-bit x86 has additional registers.[https://wikibooks.org/wiki/X86_Assembly/X86_Architecture] | ||
+ | <pre> | ||
+ | push eax | ||
+ | push ebx | ||
+ | push ecx | ||
+ | push edx | ||
+ | push esi | ||
+ | push edi | ||
+ | push ebp | ||
+ | push esp | ||
+ | |||
+ | pop esp | ||
+ | pop ebp | ||
+ | pop edi | ||
+ | pop esi | ||
+ | pop edx | ||
+ | pop ecx | ||
+ | pop ebx | ||
+ | pop eax | ||
+ | </pre> | ||
+ | |||
+ | There is the [[Assembler:Commands:PUSHAD|PUSHAD]] and [[Assembler:Commands:POPAD|POPAD]] to save and restore all the generic registries. So the above code could just be written like this. | ||
+ | <pre> | ||
+ | pushad | ||
+ | |||
+ | popad | ||
+ | </pre> | ||
+ | :Note: [[Assembler:Commands:PUSHAD|PUSHAD]] and [[Assembler:Commands:POPAD|POPAD]] are not available in 64 bit mode. | ||
+ | |||
+ | <br> | ||
+ | == Working with the Flags registry == | ||
+ | We can even [[Assembler:Commands:PUSH|PUSH]] and [[Assembler:Commands:POP|POP]] the Flags registry, using [[Assembler:Commands:PUSHF|PUSHF]] and [[Assembler:Commands:POPF|POPF]] (for 16 bit registry). This allows us to save and restore the Flags when doing compares (conditional opcodes). The FLAGS register is the status register in Intel x86 microprocessors that contains the current state of the processor. This register is 16 bits wide. Its successors, the EFLAGS and RFLAGS registers, are 32 bits and 64 bits wide, respectively. The wider registers retain compatibility with their smaller predecessors.[https://wikipedia.org/wiki/FLAGS_register] | ||
+ | :Note: when in 32 bit mode you should use [[Assembler:Commands:PUSHFD|PUSHFD]] and [[Assembler:Commands:POPFD|POPFD]] to manipulate the full 32 bits of the EFlags registry. | ||
+ | :Note: when in 64 bit mode you should use [[Assembler:Commands:PUSHFQ|PUSHFQ]] and [[Assembler:Commands:POPFQ|POPFQ]] to manipulate the full 32 bits of the EFlags registry. | ||
+ | <pre> | ||
+ | pushfd | ||
+ | cmp eax,ebx | ||
+ | movcc eax,ecx | ||
+ | popfd | ||
+ | </pre> | ||
<br> | <br> | ||
== See Also == | == See Also == | ||
− | {{ | + | {{TutorialsAA}} |
== Sources == | == Sources == | ||
# [https://wikipedia.org/wiki/Stack_(abstract_data_type) wikipedia.org/wiki/Stack_(abstract_data_type)] | # [https://wikipedia.org/wiki/Stack_(abstract_data_type) wikipedia.org/wiki/Stack_(abstract_data_type)] | ||
+ | # [https://wikibooks.org/wiki/X86_Assembly/X86_Architecture wikibooks.org/wiki/X86_Assembly/X86_Architecture] | ||
+ | # [https://wikipedia.org/wiki/FLAGS_register wikipedia.org/wiki/FLAGS_register] |
Revision as of 17:15, 12 May 2018
If you're unfamiliar with registries please start here: Registers
So what is the stack?
Well I hate to use the word in the definition, but it's just a metaphorical stack of bytes; or an abstract data type that serves as a collection of elements, with two principal operations.
- PUSH
- Adds an element to the collection.
- POP
- Removes the most recently added element that was not yet removed.
The stack is primarily used to store values for a process. It uses a LIFO (last in, first out) behavior. So if we PUSH value A onto the stack and then PUSH value B, when we POP it will be value B first then value A with the second POP.[1]
Contents
Working with the Stack
So let's just dig in, if we have some code like this.
push 123ABC push 00DEAD push 00BEEF pop dword ptr [TestVals] pop dword ptr [TestVals+4] pop dword ptr [TestVals+8]
And if we assemble this in some memory.
So let's set a breakpoint and watch the stack as we step though the opcode.
- Note: You can select a line of opcode in the memory view form and press F5 to set a breakpoint.
- Note: Step though opcode in the memory view form by pressing F7, after a breakpoint has been hit.
- Note: to view the stack you may need to select it for viewing.
Code step 1
Code step 2
So it's here that we start to see the values on the stack.
Code step 3
Code step 4
Code step 5
And here we can start to see the values being popped in the reverse order that they were pushed.
Code step 6
Code step 7
And that's really all there is to the basics of the stack.
The thing to remember is that if you push in some injected code then you will need to pop in order to clean (or sanitize) the stack.
Working with the registries
We can PUSH and POP most registries, this is useful for saving and restoring stuff in injected code. The x86 architecture has 8 General-Purpose Registers (GPR), 6 Segment Registers, 1 Flags Register and an Instruction Pointer. 64-bit x86 has additional registers.[2]
push eax push ebx push ecx push edx push esi push edi push ebp push esp pop esp pop ebp pop edi pop esi pop edx pop ecx pop ebx pop eax
There is the PUSHAD and POPAD to save and restore all the generic registries. So the above code could just be written like this.
pushad popad
Working with the Flags registry
We can even PUSH and POP the Flags registry, using PUSHF and POPF (for 16 bit registry). This allows us to save and restore the Flags when doing compares (conditional opcodes). The FLAGS register is the status register in Intel x86 microprocessors that contains the current state of the processor. This register is 16 bits wide. Its successors, the EFLAGS and RFLAGS registers, are 32 bits and 64 bits wide, respectively. The wider registers retain compatibility with their smaller predecessors.[3]
- Note: when in 32 bit mode you should use PUSHFD and POPFD to manipulate the full 32 bits of the EFlags registry.
- Note: when in 64 bit mode you should use PUSHFQ and POPFQ to manipulate the full 32 bits of the EFlags registry.
pushfd cmp eax,ebx movcc eax,ecx popfd
See Also
- Auto Assembler Basics
- Auto Assembler Templates
- Code Injection - Basic injection
- Code Injection - Full injection
- Code Injection - Adding Editable Values
- Code Injection - Working with Integers
- Code Injection - Working with Floats