Questions about this topic? Sign up to ask in the talk tab.

Difference between revisions of "Out of Order Code Execution"

From NetSec
Jump to: navigation, search
Line 47: Line 47:
 
! [[Machine_code|Machine Code]]
 
! [[Machine_code|Machine Code]]
 
|-
 
|-
| <source lang="asm">jmp 0x00000004</source>
+
| <source lang="asm">
| <source lang="asm">\xeb\x01</source>
+
jmp 0x00000004
|-
+
push 0x3458686a
|<source lang="asm"> push 0x3458686a</source>
+
push 0x0975003c
|<source lang="asm"> \x68\x6a\x68\x58\x34</source>
+
 
|-
+
</source>
|<source lang="asm">push 0x0975003c</source>
+
| <source lang="asm">
|<source lang="asm">\x68\x3c\x00\x75\x09</source>
+
\xeb\x01
 +
\x68\x6a\x68\x58\x34
 +
\x68\x3c\x00\x75\x09
 +
</source>
 
|}
 
|}
  

Revision as of 20:10, 13 May 2012

Out of Order Execution occurs when an in-line assembler interprets the instructions as if they are right next to each other when in fact the instructions may never be executed to begin with.

This concept cannot be described in assembly, however only in machine code. There are several ways to preform OOE, however this article contains an eight-byte solution that will not only jump through breakpoints laid within a debugger but also detect if breakpoints were present.


c3el4.png 8 bytes was the smallest that this code would function inside, if readers can get it even shorter then please do so and let us know

Remember that short Byte example in ascii of xor eax, eax with the push 58, pop eax, xor al, 58 ? Now we're going to put it to good use. Our shellcode will be:

\xeb\x01\x68\x6a\x58\x58 \x34\x58


ooochart0.JPG

In those 8 bytes we have jumped past the \x68, or the push instruction, into our actual code. Our actual code is the data for the push instruction, not the push instruction itself. By jumping past the push instruction into 0x04, we are able to execute these four [bytes], which is a DWORD. And as it so happens, the \x58 at the end is used in an xor, not to pop eax. However, apon review in a debugger, you will find the code looks like :

 
jmp 0x01
 
push 0x3458586a
 
pop eax
 

if one didn't know any better wouldn't it seem that the code made eax equal to 0x3458586a ?

Its a neat obfuscation technique, however it can also be used as an Anti-heuristics. When putting breakpoints over the push or pop instructions, of course since the breakpoints are around other bytes that we're not executing we're not going to stop execution for the breakpoints. And for some reason, these breakpoints cause the low 8 bits of eax to hang during the xor. In other words, with a small

cmp eax, 0

We can detect if there were breakpoints during execution, or not. Now we can erase ourselves if we want to be intelligent, or we can attempt a debugger exploit. A better way to cmp eax, 0 would be to cmp al with 0x00, only two more bytes: \x3c\x00

So lets turn it up one more notch in stead of just leaving it at that. Say we want to wrap our code so that it looks entirely like another set of instructions and the code will continue to execute out-of-order. We want to compare eax to 0, if eax is not zero, we want to jump 9 bytes forward - for whatever reason. The purpose of this is to learn out-of-order code execution, not debugger exploitation. So what instructions are needed?

We will need push DWORD; pop eax; xor al, [byte]; cmp eax, and jne. So, we'll construct our code like so, with the fake execution stack so that the wrapped code can be seen:

ooochart1.JPG

So in a debugger, the code will display as:

Assembly Machine Code
 
jmp 0x00000004
push 0x3458686a
push 0x0975003c
 
 
 
\xeb\x01
\x68\x6a\x68\x58\x34
\x68\x3c\x00\x75\x09
 



The [bytecode] we are actually executing is:

Assembly Machine Code
 
push 0x68
pop eax
xor al, 0x68
cmp eax, 0x00
jne 0x09
 
 
\x6a\x68
\x58
\x34\x68
\x3c\x00
\x75\x09
 


Notice the machine code being executed is the same machine code following the first push DWORD or \x68 instruction. The jump to 0x04 and the push DWORD are simply \xeb\x01\x68, and the instructions following that are multiwrapped. Now, the value that xor al or \x34 takes at address 0x00000008 must also be an instruction that supports a DWORD parameter. For one last example, we'll show off one more type of out-of-order Byte wrapping. But keep in mind, in 12 bytes you have now not only obfuscated your code but detected if breakpoints were present, and done a conditional jump 9 bytes ahead if there in fact WERE any breakpoints around. So for our last example of obfuscation, we'll use code that does the exact same thing, however looks different on the inside of a debugger: Assembly Machine Code jmp 0x00000004 \xeb\x01 xor eax, 0x3458356a \x35\x6a\x35\x58\x34 xor eax, 0x0975003c \x35\x3c\x00\x75\x09

Not too much different than the last set of code, now is it? Obviously, some instructions have changed, however this code will do the same thing:

ooochart2.JPG

This time we have hidden our instructions behind xor instructions in stead of the push DWORD instruction. The code we actually execute : Assembly Machine Code push 0x35 \x6a\x35 pop eax \x58 xor al, 0x35 \x34\x35 cmp eax, 0x00 \x3c\x00 jne 0x09 \x75\x09

Notice that this time we push 0x35 in stead of 0x68, then xor al with 0x35 in stead of 0x68. That is because 0x68 represents the push DWORD instruction, while 0x35 represents the xor eax, DWORD instruction. Play around with that a bit, push your knowledge further! After all, its still only 12 bytes ;)

Out of Order Code Execution is part of a series on programming.
<center>
</center>