64位下JMP遠跳地址的計算方法

highbuyer發表於2020-12-02

如果你分配的記憶體地址是64位的話。如: 504BEA0000, 你可以這樣
方法一:

48 B8 0000EA4B50000000 - mov rax,000000504BEA0000
FF E0 - jmp rax

指令和機器碼:
mov rax, 64位地址 的機器碼就是 “48 B8 64位地址的little-endian(需要64位即8個位元組)”
jmp rax 的機器碼 FF E0
這個方法會佔用12個位元組。如果你還要儲存rax暫存器內容和還原暫存器,你還需要額外的2兩個位元組,即14個位元組。

方法二:
如果跳轉前後的地址都是32位的,那麼地址的換算和32位沒有什麼區別,都是用的相對偏移。

方法三:

504BEA0006 - FF 25 00000000 - jmp qword ptr [504BEA000C]
504BEA000C - 00 00 - add [rax],al
504BEA000E - EA 4B500000 0000 - jmp 0000:0000504B
把64位的跳轉地址000000504BEA0000作為資料直接寫到跳轉語句504BEA0006的下面504BEA000C處。那麼跳轉語句永遠都是FF 25 00000000, 它會讀取接下來的8個位元組作為跳轉地址來使用的。而這個地址就是你申請到的記憶體地址。可以看到這種方法需要14個連續位元組,且不改變暫存器的內容。
當然也可以把跳轉地址的資料寫到其他的地方如: 04BEA000D處。 那麼跳轉語句的FF 25 00000000就變成FF 25 01000000, 其中01000000 little-endian讀下來就是00000001=1 即關於504BEA000C的相對地址是1。這後面4個位元組其實就是資料地址關於504BEA000C的偏移量。和32位的原理是相同的。

總之,以上三種方法各有特色也各有利弊。方法一和三對於32和64位地址是通用的。方法二適用當地址是32位的情況下。而對於第一種方法需要修改暫存器,但是不需要計算跳轉地址,而且定址範圍包括整個64位可用地址空間。第三種方法不修改暫存器,但需要計算偏移地址,而且和32位一樣定址空間限制在32位即前後2GB的範圍內。所以根據需要自己取捨吧。

相關文章