Often times NOP
is used to align instruction addresses. This is usually encountered for example when writing Shellcode to exploit buffer overflow or format string vulnerability.
Say you have a relative jump to 100 bytes forwards, and make some modifications to the code. The chances are that your modifications mess up the jump target's address and as such you'd have to also change the aforementioned relative jump. Here, you can add NOP
s to push the target address forward. If you have multiple NOP
s between the target address and the jump instruction, you can remove the NOP
s to pull the target address backward.
This would not be a problem if you are working with an assembler which supports labels. You can simply do JXX someLabel
(where JXX is some conditional jump) and the assembler will replace the someLabel
with the address of that label. However, if you simply modify the assembled machine code(the actual opcodes) by hand(as it sometimes happens with writing shellcode), you also have to change the jump instruction manually. Either you modify it, or then move the target code address by using NOP
s.
Another use-case for NOP
instruction would be something called a NOP sled. In essence the idea is to create a large enough array of instructions which cause no side-effects(such as NOP
or incrementing and then decrementing a register) but increase the instruction pointer. This is useful for example when one wants to jump to a certain piece of code which address isn't known. The trick is to place the said NOP sled in front of the target code and then jumping somewhere to the said sled. What happens is that the execution continues hopefully from the array which has no side-effects and it traverses forwards instruction-per-instruction until it hits the desired piece of code. This technique is commonly used in aforementioned buffer overflow exploits and especially to counter security measures such as ASLR.
Yet another particular use for the NOP
instruction is when one is modifying code of some program. For example, you can replace parts of conditional jumps with NOP
s and as such circumvent the condition. This is a often used method when "cracking" copy protection of software. At simplest it's just about removing the assembly code construct for if(genuineCopy) ...
line of code and replacing the instructions with NOP
s and.. Voilà! No checks are made and non-genuine copy works!
Note that in essence both examples of shellcode and cracking do the same; modify existing code without updating the relative addresses of operations which rely on relative addressing.