I've been trying to learn reverse-engineering for fun, cracking my own dummy games and whatnot and I just learned ASLR is a thing. I'm now trying to re-conceptualize everything I've read so far keeping ASLR in mind.
In the screenshot below, for example, we can see a call, a jmp and a
push a.84167B (the executable is named a.exe for quicker typing)
008410D4 | 50 | push eax | 008410D5 | 68 __28318400__ | push a.843128 | 843128:"Your chance to miss: %i%%. 008410DA | E8 31FFFFFF | call <a._printf> | 008410DF | 83C4 0C | add esp,C | 008410E2 | 395F 18 | cmp dword ptr ds:[edi+18],ebx | DummyConsoleGame.cpp:98 008410E5 | 0F8E 90050000 | jle a.84167B |
As far as I know, most call and jump statements use relative addressing, right? They use RVA and something like that, and I'm guessing the debugger (x64dbg in this case) is lending me a helping hand and resolving the address for me, right?
Those instructions don't have an underline under their binary equivalent, and when I've tried to copy those instructions and paste them at another address -- even though I'm pasting something like
call 0x00841010, I can see that, despite the ASLR being enabled -- on the next restart, the address that I just pasted does change and resolves to the correct address (but the bytes don't change).
Now, when it comes to the
push a.84167B instruction, I can see that the bytes for the operand are actually underlined in the binary representation. And, if I try copying the instruction and pasting it in another address (which results in me pasting
push 0x843128) -- on the next restart, the bytes for the original
push a.84167B instruction that I copied do change (and point to yet again the correct address (not
0x843128)), but they don't change for the instruction that I've copied (thus the instruction I just patched points at the same old address
0x843128, which isn't even in the virtual address space of the program after the restart).
Have I understood correctly that the jump and call instructions actually get translated by the debugger and they actually use relative addressing (and thus the bytes don't change despite of ASLR), but most of the other instructions (including that
push) do use absolute addresses (and the bytes for those addresses get updated in reference to the reloc table or something like that)
Is that the reason why copying a jump/call instruction doesn't break on a restart, but copying a mov/push/anything like that with an absolute address breaks on restart? And because the patched address is not in the reloc table or something the bytes don't get updated?
Am I right that the underline under the bytes with the absolute address essentially mean the bytes are not "hard-coded" and get updated during runtime in reference to the reloc table or something?
If I were to patch a new string to the end of the .rdata section, how would I
pushthat specific address without it breaking on a restart? If it's debugger specific -- how would I do it in Ghidra, or x64dbg, or Ollydbg, or even IDA? Do I have to manually update the reloc table, or am I completely mistaken about how all of this works? I'm guessing I need to use a RVA, but I can't figure out how to do it:
call a:0x843128, none of these seems to work.