Assembly is Too High Level: Repetition of REP Instructions That Don’t Repeat Anything 2


The REP (Repeat String Operation) is a pretty cool prefix; It modifies a single string instruction to repeat until the ECX register reaches zero. As this only applies to one instruction (as apposed to a block of code), ECX needs a way to decrement, REP automatically decrements ECX by 1 each execute of the string operation instruction. So the idea is to set ECX to the amount of times you want the string operation to execute and the run the string operation with the REP prefix. The instructions that REP is supposed to be appropriate for are: INS, MOVS, OUTS, LODS, STOS, CMPS, and SCAS.

Now that I described the coloring book, lets color outside the lines. What happens when we try to REP prefix an instruction not in this list. For example:

Screen Shot 2016-02-13 at 3.27.53 PM

And this is in a debugger after executing the last INC.

Screen Shot 2016-02-13 at 3.28.10 PM

You’ll notice that ECX didn’t decrement at all, and EAX is only up to ‘2’; as there were only 2 INC instructions. In other words, the REP prefix was completely ignored. I like this, because gratuitous prefixes can be abused…

Consistent Instruction Sizes:

Revisiting the concept discussed in the Consistent Instruction Sizes blog post, this can be done with an ironic repetition of REP instructions that don’t repeat anything (best phrase ever):

Screen Shot 2016-02-13 at 3.45.08 PM

Just like the previous blog post PoC, this one launches a /bin/sh shell as well. The thing I love so much more about this one is that the 0xF3 prefix (REP) doesn’t really change the original meaning of the code (unless it is one of the very few string instructions). In comparison, the 0x66 and 0x67 override prefixes will change the register sizes all over the place and has to be treated carefully. And with the REP prefix, even if it was a string instruction, all you have to do is just make sure to set ECX to 1 before the instruction and it will work like a non-REP as well. But don’t just do a normal ‘XOR ECX, ECX’ with machine code 0x31c9, you should do the full REP version of 0xf3f3f3f3f3f3f3f3f3f3f3f3f331c9

Repeating a NOP to “pause”:

Screen Shot 2016-02-13 at 3.52.16 PM

The above source file produces the below results in most debuggers/disassemblers.

Screen Shot 2016-02-13 at 3.52.28 PM

So we take a normal NOP instruction:

Screen Shot 2016-02-13 at 3.54.11 PM

And put the REP prefix in front of it and get a pause:

Screen Shot 2016-02-13 at 3.54.26 PM

It’s really just a cool backwards compatibility hack on Intel’s part. PAUSE was introduced with the Pentium 4. But if you used this instruction on an older Intel processor, what would it do. Well like we discovered with using a useless (non-string based) REP prefix, it wouldn’t modify the instruction after it, in this case machine code for a NOP. In other words, machine code for a PAUSE on a pre Pentium 4 process would just be a glorified NOP.


Leave a comment

Your email address will not be published. Required fields are marked *

2 thoughts on “Assembly is Too High Level: Repetition of REP Instructions That Don’t Repeat Anything

  • Robert Clausecker

    Note that the rep prefix is used in some new instructions as a part of the encoding and does make a pretty huge difference. For example, popcount is F3 0F B8 or REP JMPE where JMPE is the instruction to change to Itanium mode on Itanium processors. Similarly, TZCNT is F3 0F BC or just REP BSF which kinda makes sense (same for LZCNT which is REP BSR). Lastly, F3 is used in SSE instructions as a prefix to change from packed to scalar instructions. Randomly adding F3 prefixes to your own code is a certain way to make sure that the code stops working on future architectures.