web-dev-qa-db-ja.com

x86で相対短いjmpをエンコードする方法

次のオペコードを使用して短いジャンプを実行したいとします。

[〜#〜] eb [〜#〜][〜#〜] cb [〜#〜]またはJMP rel8

「ジャンプショート、RIP = RIP + 8ビットの変位符号を64ビットに拡張」

(ここで、CBはバイトです符号付き値[〜#〜] eip [〜#〜]レジスタの方向に関連する相対オフセットを表します)

多分常にオフセットはoffset + 2になるでしょう。この短いジャンプの実行時間(基準方向)のEIPは2バイト命令のベースですが、加数 常に発生

eb 30 = jmp 0x00000032(+30)

eb e2 = jmp 0xffffffe4(-30)

次に、fe + 2がまたは[〜#〜] eip [〜#〜]であるため、EIPは意図的に同じ方向にすることができます。

eb fe = jmp 0x00000000

overoffsetが負の数であるにもかかわらず、分岐していたのは驚くべきことです。しかしIntelには言及がない(多分3000ページのため)。

Intel®64 and IA-32 Architectures Software Developer’s Manual:Vol。 2A 3-42

ジャンプ範囲が–128〜+127に制限されているニアジャンプ現在から EIP値。

次に、3つの可能性について考えます。

  1. 実行時のEIPのafter/future値であるため、+ 2です
  2. コード化された値は、2sコンポーネントでエンコードされた符号付き数値ではありません。
  3. これはマニュアルに記載されていますが、私は愚かなので私は見ていません
16
user1629569

rel8は、次の命令のメモリアドレスを基準にしています。2つの実行可能ファイルを作成して逆アセンブルすることで簡単に確認できます。

@label:
    jmp @label
    nop

これは次のように逆アセンブルされます(ndisasmを使用すると、16ビット、32ビット、64ビットのコードで同じです)。

EBFE jmp short 0x0
90   nop

次に、別の実行可能ファイル:

    jmp @label
@label:
    nop

EB00 jmp short 0x2
90   nop

したがって、rel8は常にjmpの後の次の命令に関連してエンコードされます。ただし、逆アセンブラー(少なくともndisasmおよびudcli)は、jmp命令自体に対して相対的に表示します。これにより、混乱が生じる可能性があります。

16
nrz

ショートジャンプかどうかにかかわらず、常にdestination - (source + sizeof(instruction))です。

つまり、_dst - end_of_jmp_

あなたの場合(ショートジャンプ)、sizeof(instruction)は2です。

この追加の背後にある理由は、CPUが命令フェッチステージを実行すると、命令ポインタが分岐の後に来る命令をすでに指しているという事実によるものです。 rel8またはrel32ブランチの変位は、そのEIP/RIP値を基準にしています。

18
JosephH

ジャンプショートは、ジャンプ命令(長さ2バイト)のendに相対的なEIPを取り、符号拡張されてEIPに追加される1バイトのオペランドを取ります。

5
SecurityMatt