REPEATABLE INSTRUCTIONS!
| |
REP STOS - THE MEMORY PAINT BUCKET TOOL
REP STOS is a Repeat STore String. STOS is one of a number of instructions that can have the “rep” prefix added to it, which repeat a single instruction multiple times. All rep operations use the rcx/ecx/cx register as a counter to determine how many times to loop through the instruction. Each time it executes, it decrements the counter by 1. Once the counter == 0, it continues to the next instruction.
| |
What does it do?
Either stores 1, 2, 4, or 8 bytes at a time into memory pointed to by RDI:
- STOSB - Fill 1 byte at [RDI] with AL
- STOSW - Fill 2 bytes at [RDI] with AX
- STOSD - Fill 4 bytes at [RDI] with EAX
- STOSQ - Fill 8 bytes at [RDI] with RAX
After each store, RDI automatically increments to point to the next position!
Syntactically:
| |
Real example - Let’s break down this code:
| |
Step 1: Setup the stack
| |
Step 2: Get address and prepare to fill memory
| |
Step 3: THE REP STOS MAGIC HAPPENS HERE!
| |
What rep stosb does:
- Store AL (which is 0) at [RDI]
- RDI++ (move to next byte)
- ECX– (one less byte to fill)
- Repeat until ECX = 0
So this is basically doing: memset(buffer, 0, 128) in one instruction!
Step 4: Store a value at the beginning of the stack
| |
Memory now looks like:
[rsp] = 0x05EAF00D (4 bytes)
[rsp+0x10] = 0x00000000 (128 bytes of zeros from rep stosb)
Step 5: Copy a word (2 bytes) from rsp to buffer
| |
So now our buffer that was all zeros has 0xF00D stored at position 2:
buffer[0] = 0x00
buffer[1] = 0x00
buffer[2] = 0x0D (lower byte of 0xF00D)
buffer[3] = 0xF0 (upper byte of 0xF00D)
buffer[4] = 0x00
...
Step 6: Read that value back
| |
Step 7: Cleanup
| |
Why is REP STOS fast?
Instead of writing a loop like:
| |
REP STOS does it all in ONE instruction. The CPU handles the loop internally, which is way more efficient!
Common use cases:
- Zeroing memory - like
memset(buffer, 0, size) - Filling arrays - set everything to 0xFF or whatever value
- Initializing buffers - before you use them
Quick reference:
| |
Remember: RDI = destination, RAX/EAX/AX/AL = value to fill, RCX/ECX/CX = count!
REP MOVS - Repeat Move Data String to String
MOVS is one of a number of instructions that can also have the rep prefix added to it, which also repeats a single instruction multiple times. MOVS is its own instruction which can be called without the REP instruction prefix. Again, all rep operations use the cx register as a counter to determine how many times to loop through the instruction. Each time it executes, it decrements cx. Once cx == 0, it continues to the next instruction.
Unlike MOV, MOVS can move memory to memory but only between SI and DI, which is the source and destination.
Quick reference:
| |
Remember: RSI = source, RDI = destination, RCX/ECX/CX = count!
DF (Direction Flag)
The direction flag controls the direction of copies with a rep movs. This is a control flag, so based on the direction flag it could be incrementing RDI and RSI, or it could actually be decrementing, so it could kind of be copying backwards down towards lower addresses.
Why this matters for security: If an attacker can control DF and start it copying backwards when the programmer is expecting it to copy forward, that can lead to some memory corruption!
How to control DF:
| |
Always make sure you know which direction you’re going! Most of the time you want cld to copy forward.