In the code you are patching, namely
movzx eax, byte ptr word_F3BB4A
and eax, 2
jz short loc_62300F
there are two instructions that reference memory: the movzx
and the jz
.
Of the twos only the latter is position independent (it's destination is encoded as a relative offset), the former use an absolute address.
Absolute addresses are fixed up (relocated) by the loader based on the metadata the linker have generated. These metadata works by instruction address.
For example if we patch this program
012C1000 | A1 00 20 2C 01 | mov eax,dword ptr ds:[12C2000] |
012C1005 | 90 | nop |
012C1006 | 90 | nop |
012C1007 | 90 | nop |
012C1008 | 90 | nop |
012C1009 | 90 | nop |
012C100A | 90 | nop |
012C100B | 90 | nop |
012C100C | 90 | nop |
012C100D | 90 | nop |
012C100E | C3 | ret |
by moving the move down 8 bytes (that's the reason of all the nop
I used) and step again through the executable we have:
010C1000 | 90 | nop |
010C1001 | 90 | nop |
010C1002 | 90 | nop |
010C1003 | 5C | pop esp |
010C1004 | 91 | xchg eax,ecx |
010C1005 | 90 | nop |
010C1006 | 90 | nop |
010C1007 | 90 | nop |
010C1008 | A1 00 20 40 00 | mov eax,dword ptr ds:[402000] |
010C100D | 90 | nop |
010C100E | C3 | ret |
where we see:
- The move instruction use the address 402000h and so it will eventually fail at runtime. It has not been relocated, as expected.
- The
nop
in place of the original move has been changed by the loader when performing the relocation of the, now non existent, original move.
If you want to patch the original code so that it overwrites the location of the move with a zero before doing its original work, then replace
0F B6 05 XX XX XX XX | movzx eax,byte ptr ds:[XXXXXXXXh]
83 E0 02 | and eax,2
with
90 | nop
C6 05 XX XX XX XX 00 | mov byte ptr ds:[XXXXXXXXh], 0
31 C0 | xor eax,eax
Note how the immediates of both moves have the same address and how at the end eax
is zero as expected.