1、無条件ジャンプ命令 JMP#
EIP(ポインタレジスタ)
は次に実行される命令を指し、実行が完了すると EIP は次の命令を指します。EIP(ポインタレジスタ)内の値は、各命令の実行後に自動的に更新され、次に実行される命令のアドレスを指します。アセンブリ言語のいくつかのジャンプ命令(例えば JMP、JE、JNE など)は EIP の値を修正し、指定されたアドレスにジャンプして実行することができます。
JMP A
命令の中で、A はプログラム作成者が期待する無条件のジャンプ先のメモリアドレスです。
jmp short 命令
JMP SHORT
命令は 2 バイトの短距離ジャンプ命令で、前方または後方にしかジャンプできません。最初のバイト EB はジャンプオペコード(OPCODE)です。ジャンプの方向は 2 番目のバイトの値によって決まります。このジャンプには距離制限があります。
jmp short 命令の機械コードを表示
上の図では、EB は jmp のオペコードであり、この命令は命令の終了後の 5 バイトに前方ジャンプします。ターゲットアドレスの計算は下の図の方法を使用できます。命令の開始アドレス➕命令自体の長さ(2 バイト)➕2 番目のバイトのジャンプ距離(5 バイト)。
ジャンプ位置の計算
short のジャンプ距離:最大の前方ジャンプ距離は 0x7f です。
注:ida は機械コードを表示します
メニューバーの Options-General 設定で、Number of opcode bytes (graph) の値を 12(10)に変更します。デフォルトは 0 です。
注:データベーススナップショット機能
逆アセンブル中にプログラムにいくつかの変更を加えると、既に認識された関数が中断されます。データベーススナップショットを使用すると、以前の状態に戻すことができ、問題が発生した場合に修正方法がわからないときにこの機能を使用できます。
スナップショットに名前を付ける
スナップショットをロードする、View-Database snapshot manager
すべてのスナップショットリストと作成日を確認できます
実験 2 ジャンプの 2 番目のバイトを 05 から 7f に変更
ida の patch byte 機能を使用して 05 を 7f に変更します
実験2 05を7fに変更
実験2 変更後のアセンブリビュー 上の図から左側の矢印が見え、プログラムはここで0x4013a5に前方ジャンプします。
次に 0x7f を 0x80 に変更します。
0x80 に変更すると、プログラムは後方にジャンプし、以前の 0x7f は最も遠い前方ジャンプであり、したがって 0x80 は最も遠い後方ジャンプです。
python は数値から前方または後方のジャンプを判断しないため、-0x80 を表す dword を入力する必要があります。つまり、0xffffff80
です。計算結果は0xffffffff
とのビット AND 演算を行い、32 ビットを超えるビットはクリアされるため、0x4012a6
という値が得られます。
もし 0xff を 2 番目のバイトのジャンプ距離として使用すると、これは最小のジャンプ距離 - 1 であり、上の図からわかるように最終的に 0x401325 にジャンプし、つまり 1 バイトジャンプします。
さらに 1 バイト後方にジャンプすると、命令の 2 番目のバイトを fe に変更し、最終的に起点位置に戻り、無限ループを形成します。
もし 2 番目のバイトを fd に変更すると、命令の終わりから 3 バイト後方にジャンプし、最終的に 0x401323 にジャンプします。
短距離ジャンプを使用すると、現在のアドレスの近くでしかジャンプできず、すべてのアドレスにジャンプすることはできません。したがって、プログラムは長距離ジャンプを使用します。
上の図にはいくつかの長距離ジャンプが表示されており、図中の loc はその命令が一般的な命令であることを示しています。
上の図は長距離ジャンプであり、0x4026ae から 0x4029b3 までの距離は短距離ジャンプの作用範囲を超えています。
ジャンプ範囲計算公式は:終点命令開始アドレス - 開始命令開始アドレス - 5
5 はジャンプ命令の長さで、結果は 0x300、つまり長距離ジャンプ命令オペコード E9 の後の dword です。
2、条件付きジャンプ命令#
CMP A,B # AとBを比較し、比較結果に基づいて異なる操作を実行
条件付きジャンプ命令
上の図では、CMP は eax と ebx を比較します(レジスタの減算)。もしそれらが等しい場合、結果は 0 になり、フラグレジスタ(EFLAGS)の Z フラグまたはゼロフラグがトリガーされ、JZ 命令がこのフラグを検出してジャンプします。Z フラグがトリガーされると、上の図の緑色
の矢印のパスが実行され、トリガーされない場合は青色
の矢印のパスが実行されます。
16 進数 | ASM | 説明 | |
---|---|---|---|
74 or 0F84 | JE | 等しい場合はジャンプ | |
75 or 0F85 | JNE | 等しくない場合はジャンプ | |
77 or 0F87 | JA | 大きい場合はジャンプ | |
7C | JL | 小さい場合はジャンプ | |
7D | JGE | 小さくない場合はジャンプ | |
7E | JLE | 小さいか等しい場合はジャンプ | |
7F | JG | 大きいか等しい場合はジャンプ | |
80 | JO | オーバーフローの場合はジャンプ | |
81 | JNO | オーバーフローでない場合はジャンプ | |
82 | JB/JNAE | 小さい場合はジャンプ | |
83 | JNB/JAE | 小さくない場合はジャンプ | |
86 | JNA/JBE | 大きくないか等しい場合はジャンプ | |
88 | JS | 符号が負の場合はジャンプ | |
89 | JNS | 符号が正の場合はジャンプ | |
8C | JL/JNGE | 小さい場合はジャンプ | |
8D | JGE/JNL | 小さくない場合はジャンプ | |
8E | JLE/JNG | 小さいか等しい場合はジャンプ | |
8F | JG/JNLE | 大きいか等しい場合はジャンプ |
JMP と NOP を除いて、残りはすべて比較結果に基づいて実行される条件付きジャンプ命令です。
3、CALL と RET 命令#
- CALL 命令は関数を呼び出すために使用されます。
- RET 命令はこの関数を呼び出した命令の次の命令に戻るために使用されます。
下の図には CALL 呼び出し命令があり、プログラムは0x4013d8
にジャンプしてこの関数を実行します。(0x4013d8
のアドレスの前のsub_
はここが関数であることを示します)CALL 命令は戻りアドレス0x40123d
をスタックに保存します。
call 命令の例
この関数をダブルクリックすると、次の位置にジャンプし、関数の具体的な内容は以下の通りです:
0x4013d8 関数の具体的な内容
上の図のように、関数が完了すると ret 命令が実行され、スタックに保存された戻りアドレス 0x4012d にジャンプします。これはこの関数を呼び出した命令の次の命令です。
戻りアドレス