71

I see this instruction in the beginning of several Windows programs. It's copying a register to itself, so basically, this acts as a nop. What's the purpose of this instruction?

greatwolf
  • 203
  • 1
  • 8
Mellowcandle
  • 4,795
  • 6
  • 34
  • 47
  • 4
    The Essence: It is a two-byte NOP. So you can patch two bytes atomically without having the processor load an incomplete/incorrect instruction when he tries to execute this part of the code while you are changing it. – Michael Anderson Mar 25 '13 at 16:40
  • 13
    In x86-64 mov edi,edi is not a NOP. In x86-64 it zeroes the top 32 bits of rdi. In 32-bit code mov edi,edi can used as a NOP. – nrz Apr 08 '13 at 18:18

3 Answers3

81

Raymond Chen (Microsoft) has a blog post discussing this in detail:

https://devblogs.microsoft.com/oldnewthing/20110921-00/?p=9583

In short, it's a compile time addition applied in order to support run time hot patching, so the function can have the first two bytes overwritten with a JMP instruction to redirect execution to another piece of code.

Ben Schwehn
  • 103
  • 2
QAZ
  • 2,571
  • 22
  • 22
  • 4
    You should probably add a note about the 5 empty bytes preceding the mov edi, edi instruction. – tmr232 Oct 03 '15 at 09:59
  • Why not a real 2-byte NOP like 66 90? That would be more efficient: no back-end uop needed, no extra latency for EDI (in case that matters), no physical register needed to rename the output. Perhaps it's supposed to be a "signature" that tools can recognize as not naturally occurring except in hotpatch code? – Peter Cordes Dec 08 '19 at 16:52
  • 1
    @PeterCordes: Raymond Chen discusses that also https://devblogs.microsoft.com/oldnewthing/20130102-00/?p=5663 "the decision to use MOV EDI, EDI as the two-byte NOP instruction came after consulting with CPU manufacturers for their recommendations for the best two-byte NOP" – Ben Schwehn Aug 26 '20 at 20:45
  • 1
    @BenSchwehn: Huh, probably that decision dates back to P5 Pentium days, where a 66 prefix made the instruction take an extra cycle to decode. It's unfortunate for later CPUs from P6 and onward. It's also unfortunate that it has to be a NOP, rather than optionally being a useful instruction like a 2-byte encoding of push ebp for functions that use a frame pointer. (Using the push r/m32 form with a modrm byte, not the 1-byte short form.) But that's somewhat less simple to handle, and need an alternative to not pessimize functions that don't want to push anything. – Peter Cordes Aug 26 '20 at 21:02
19

It's intended to jump to a specific location, 5 bytes before the mov instruction. From there, you have 5 bytes which are intended to be modified to a long jump to somewhere else in 32-bit memory space. Note that when hot-patching, that 5 bytes jump should be placed first, and then the mov can be replaced. Going the other way, you risk the replaced mov-jmp running first, and jumping to the 5 bytes of whatever happens to be there (it's all nops by default, but you never know).

[addition follows]

Regarding writing the 5 bytes jump - there's also the problem of there is only one instruction that will let you write more than 4 bytes atomically - cmpxchg8b, and that's not an ideal instruction for the purpose. If you write the 0xe9 first and then a dword, then you have a race condition if the 0xe9 is executed before you place the dword. Yet another reason to write the long jump first.

peter ferrie
  • 4,709
  • 4
  • 19
  • 33
  • It's NOPs or INT3's, generally. – mrduclaw Mar 30 '13 at 02:06
  • Right, but in the case of INT3s, you definitely don't want to be running that by accident. – peter ferrie Apr 05 '13 at 20:41
  • And in case the function is already detoured, writing the 4-byte jump target address first will atomically replace whatever rel32 the previous jmp had. (Assuming that the dword is 4-byte aligned, which it will be if functions are 8 or 16-byte aligned. It ends at the start of a function.) – Peter Cordes Dec 08 '19 at 17:07
8

courtsey Hotpatching and the Rise of Third-Party Patches presentation at BlackHat USA 2006 by Alexander Sotirov

What Is Hotpatching? Hotpatching is a method for modifying the behavior of an application by modifying its binary code at runtime. It is a common technique with many uses:

• debugging (software breakpoints)

• runtime instrumentation

• hooking Windows API functions

• modifying the execution or adding new functionality to closed-source applications

• deploying software updates without rebooting

• fixing security vulnerabilities

Hotpatches are generated by an automated tool that compares the original and patched binaries. The functions that have changed are included in a file with a .hp.dll extension. When the hotpatch DLL is loaded in a running process, the first instruction of the vulnerable function is replaced with a jump to the hotpatch.

The /hotpatch compiler option ensures that the first instruction of every function is a mov edi, edi instruction that can be safely overwritten by the hotpatch. Older versions of Windows are not compiled with this option and cannot be hotpatched.

rebel87
  • 391
  • 1
  • 3
  • 11