IA32 チートシート
Intel構文は<ニーモニック> <Destination>, <Source>
となっている。
代表的なデータ型
型名 | サイズ |
---|---|
Byte | 1バイト |
WORD | 2バイト |
DWORD | 4バイト |
QWORD | 8バイト |
レジスタ
汎用レジスタ
レジスタ | 概要 | 下位16bit | 下位16bitのうち上位8bit | 下位16bitのうち下位8bit |
---|---|---|---|---|
EAX | 算術計算の結果や戻り値が格納される | AX | AH | AL |
EBX | 他のレジスタでは足りない時に利用される | BX | BH | BL |
ECX | ループ操作などのカウンタが格納される | CX | CH | CL |
EDX | 汎用計算に使用される | DX | DH | DL |
EBP | スタックのベースポインタが格納される | BP | - | - |
ESP | スタックポインタが格納される | SP | - | - |
ESI / EDI | オペランドの Source / Destination に利用される | - | - | - |
EFLAGレジスタ
算術結果の状態を格納するためのレジスタ。代表的なものを以下に記載する。
名称 | 概要 |
---|---|
CF / Carry Flag | 桁上がりもしくは桁借りした場合に1
|
PF / Parity Flag | 結果の最下位バイトに値1のビットが偶数個含まれている場合は1 、奇数個の場合は0
|
ZF / Zero Flag | 操作の結果が0になった場合に1
|
SF / Sign Flag | 操作の結果がマイナスになった場合に1
|
OF / Overflow Flag | 符号付き算術演算でオーバーフローが発生した場合に1
|
アドレッシングモード
モード | サンプル | 概要 |
---|---|---|
レジスタアドレッシング | mov eax, ebx |
レジスタの値をそのまま入れる |
イミディエイト | mov eax, 0Ah |
値自体を入れる(0Ah = 10) |
直接アドレッシング | mov eax, [1234h] |
eaxにメモリアドレス1234h にある値を入れる |
ベースポインタ相対アドレッシング | mov eax, [1234h + 2] |
eaxにメモリアドレス1234h に2を加えたメモリ領域の値を入れる |
間接アドレッシング | mov eax, [edi] |
eaxにediレジスタに入っているアドレスのメモリ領域の値を入れる |
ベース - インデックス | mov eax, [ebx + edi] |
eaxにebxに入っているメモリアドレスにediを足した結果のメモリ領域の値を入れる |
代表的な命令一覧
ニーモニック | 命令 | 概要 |
---|---|---|
mov | mov A, B |
AにBの値を格納 |
add | add A, B |
A = A + B |
sub | sub A, B |
A = A - B |
mul | mul A |
EAXの値とオペランドAの掛け算の結果(符号なし)を EDX(上位ビット)とEAX(下位ビット)に格納 |
div | div A |
EDX:EAXの値をオペランドAで割った結果(符号なし)を EAX(商)とEDX(余り)に格納 |
inc | inc A |
A = A + 1 |
dec | dec A |
A = A - 1 |
imul | imul A |
EAXの値とオペランドAの掛け算の結果(符号あり)を EDX(上位ビット)とEAX(下位ビット)に格納 |
idiv | idiv A |
EDX:EAXの値をオペランドAで割った結果(符号あり)を EAX(商)とEDX(余り)に格納 |
and | and A, B |
AにAとBの論理積を入れる |
or | or A, B |
AにAとBの論理和を入れる |
xor | xor A, B |
AにAとBの排他的論理和を入れるxor eax, eax と記載して初期化する(0になる) |
not | not A |
Aの否定(1の補数)をAに入れる |
sal | sal A, B |
AをBだけ算術左シフトした結果をAに入れるA*(2^n) となる |
sar | sar A, B |
AをBだけ算術右シフトした結果をAに入れるA/(2^n) となる |
shl | shl A, B |
AをBだけ論理左シフトした結果をAに入れるA*(2^n) となる |
shr | shr A, B |
AをBだけ論理右シフトした結果をAに入れるA/(2^n) となる |
rol | rol A, B |
Aを左にB回だけ回転させる |
ror | ror A, B |
Aを右にB回だけ回転させる |
rcl | rcl A, B |
A(+CF)を左にB回だけ回転させる |
rcr | rcr A, B |
(CF+)Aを右にB回だけ回転させる |
push | push A |
ESPを-4バイトしてAの値をスタックに入れる |
pop | pop A |
スタックから値を取り出しAに入れ、ESPを+4バイトする |
pusha | pusha |
ESPを-16バイトして16バイトレジスタの値をスタックに入れる レジスタ:AX, CX, DX, BX, SP, BP, SI, DI |
pushad | pushad |
ESPを-32バイトして32バイトレジスタの値をスタックに入れる レジスタ:EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI |
popa | popa |
スタックから値を取り出し16バイトレジスタに格納し、ESPを+16バイトする レジスタ:AX, CX, DX, BX, SP, BP, SI, DI |
popad | popad |
スタックから値を取り出し32バイトレジスタに格納し、ESPを+32バイトする レジスタ:EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI |
call | call A |
戻り先をスタックにプッシュし、EIPにAを入れる |
ret | ret (A) |
ESPが示しているデータをEIPに入れる Aがある場合、AバイトだけESPをマイナスする |
test | test A, B |
AとBの論理積で比較し結果をEFLAGSにセット |
cmp | cmp A, B |
AとBを比較(A-Bをする) |
jmp | jmp A |
Aにジャンプ |
je / jz | je(jz) A |
結果が等しいか0 のときにAへジャンプ |
jne / jnz | jne(jnz) A |
演算結果が0 でないときAへジャンプ |
jg | jg A |
大きいときAにジャンプ |
jge | jge A |
大きいか等しいときにAにジャンプ |
ja | ja A |
大きいとき(符号なし)Aにジャンプ |
jae | jae A |
大きいか等しいとき(符号なし)にAにジャンプ |
jl | jl A |
小さいときAにジャンプ |
jle | jle A |
小さいか等しいときAにジャンプ |
jb | jb A |
小さいとき(符号なし)Aにジャンプ |
jbe | jbe A |
小さいか等しいとき(符号なし)Aにジャンプ |
lea | lea A, B |
BのアドレスをAに入れる |
nop | nop |
何もしない |
int3 | int 3 |
ソフトウェアブレークポイント用 |
loop | loop A |
ECXのカウンタをデクリメントして0 以外ならAにジャンプ、0 なら次の命令を実行 |
cld | cld |
DFをクリア |
std | std |
DFをセット |
scasb | scasb |
ALとEDIを比較しFLAGSを設定 DFが0:EDIをインクリメント DFが1:EDIをデクリメント |
repne | repne scasb |
ECXをデクリメントし0になるかZFが1になるまでscasb 命令をループ |
代表的な処理の特徴
配列へのアクセス
mov ecx, [ebp+<var>] ; hoge[0]
add ecx, [ebp+<counter>] ; hoge[0]からcounterバイト分アドレス加算
; -> hoge[counter]
mov [ecx], <value>
j = j + S[i] + K[i % 128]
のパターン
mov ecx, [ebp + <var_4>] ; var_4[0]
add ecx, [ebp + <counter>] ; var_4[0+i]
add ecx, [ebp + <var_14>] ; var[i] + j
mov eax, [ebp + <counter>] ; i
idiv [ebp + <key_length>] ; i % key_length
mov eax, [ebp + <arg_0>] ; 符号拡張
movsx edx, byte ptr [eax+edx] ; j + s[i] + K[ i % 128 ]
add ecx, edx
and ecx, 800000FFh
配列の初期化
xor ebx, ebx ; ebx = 0
xor eax, eax ; eax = 0
push 1Fh ; 1Fh = 31
lea edi, [ebp+var_93] ; edi = var_93のアドレス
pop ecx ; ecx = 31
mov [ebp+var_94], bl ; var_94 = 0
rep stosd
; rep:ecxが0になるまで繰り返す(ecxの回数分繰り返す)
; stosdの挙動は以下の通り
; 1. ediが示すメモリアドレスにeaxの値を設定する
; 2. ediのアドレスを4バイト(dword分)加算する
; 3. ecxの値を1減らす
stosw
; 1. ediが示すメモリアドレスにeaxの下位2バイトを設定する
; 2. ediのアドレスを2バイト(word分)加算する
stosb
; 1. ediが示すメモリアドレスにeaxの下位1バイトを設定する
; 2. ediのアドレスを1バイト(byte分)加算する
アセンブリ | 説明 |
---|---|
xor ebx, ebx |
ebxレジスタを0で初期化する(eaxレジスタの値を同じ値でxorすると0となるため) |
xor eax, eax |
eaxレジスタを0で初期化する |
push 1Fh |
スタック領域に1Fh(16進数:0x1F, 10進数:31)を格納する |
lea edi, [ebp+var_93] |
ediレジスタに変数var_93 のメモリアドレスを格納する |
pop ecx |
・スタックの一番上に積まれている値を取り出しecxレジスタに格納する ・今回は1Fh(16進数:0x1F, 10進数:31)がレジスタに格納される |
mov [ebp+var_94], bl |
・var_94 にebxの下位8ビットの値を格納する・ebxは0であるため32bitすべて0であり、下位8ビットも0であるため、0を var_94 に格納している |
rep stosd |
・rep はstosd をecxが0になるまで繰り返す(ecxの回数分繰り返す)・ stosd は以下の処理を行う1. ediが示すメモリアドレスにeaxの値を設定する 2. ediのアドレスを4バイト(dword分)加算する 3. ecxの値を1減らす |
stosw |
1. ediが示すメモリアドレスにeaxの下位2バイトを設定する 2. ediのアドレスを2バイト(word分)加算する |
stosb |
1. ediが示すメモリアドレスにeaxの下位1バイトを設定する 2. ediのアドレスを1バイト(byte分)加算する |
インクリメント
mov eax, [ebp+<var>]
add eax, 1
mov [ebp+<var>], eax
swap関数呼び出し
swap(s[i], s[j])
の場合
mov eax, [ebp+s]
add eax, [ebp+j]
push eax
mov eax, [ebp+s]
add eax, [epb+i]
push eax
call _func
関数
ポイントのサマリは以下の通り
-
[]
はその中に記載されたメモリアドレスが示すメモリ領域を示している - メモリアドレス(ポインタ)を渡す場合は
lea
ニーモニックが利用される - 値渡しの場合、引数はそのままスタックにプッシュされ、サブルーチン内で直接使用される
- ポインタ渡しの場合、引数としてメモリアドレスが渡され、サブルーチン内でそのアドレスが指す値にアクセスする
値渡しの場合
サブルーチン呼出し直前の処理
mov [esp + var_4], 2 ; 変数var_4に0x2を格納する
push [esp + var_4] ; スタックに変数var_4の値(0x2)を格納する
mov eax, 1 ; eaxに0x1を格納する
push eax ; スタックにeaxの値(0x1)を格納する
サブルーチン呼出し直後のサブルーチン側での処理
mov eax, [esp+arg_0] ; eaxに第1引数(0x1)を格納する
mov ebx, [esp+arg_4] ; ebxに第2引数(0x2)を格納する
ポインタ渡しの場合
サブルーチン呼出し直前の処理
lea eax, [esp + var_4] ; eaxにvar_4のメモリアドレスを格納する
push eax ; スタックにvar_4のメモリアドレスを格納する
call sub_1234E5 ; サブルーチンを実行する
サブルーチン呼出し直後のサブルーチン側での処理
mov eax, [esp + arg_0] ; eaxに第1引数であるメモリアドレスを格納する
mov ebx, [eax] ; ebxにeaxに格納されているメモリアドレスが示す先の値を格納する
IDA 操作テクニック
IDA Pythonによるcall
命令のカラーコーディング
for head in Heads():
op = print_insn_mnem(head)
if op == "call" or op == "jmp":
set_color(head, CIC_ITEM, 0xe0f0e0)
アセンブリコードに情報を追加
各行のメモリアドレスと値など自動的にコメントを付与する
-
Options > General > Disassembly > Display disassembly line parts
- ☑ Line prefixes(graph)
- ☑ Auto comments
ショートカットキー
ショートカットキー | 名称 | 概要 |
---|---|---|
F4 |
カーソル行まで実行 | 選択している行まで実行する |
F7 |
ステップイン | 1行ずつ実行する。call の場合は関数へ入る。 |
F8 |
ステップアウト | 1行ずつ実行する。call の場合は関数へ入らず実行後の状態で次の行へ移る。 |
F9 |
続行 | 次のブレークポイントまで実行する |
Ctrl + n |
EIP書き換え | EIPのアドレスを選択している行のアドレスに書き換える |
n |
rename | 選択している変数の名前を変換する |
: |
Enter comments | コメントを追加する |
x |
Jump to xref to operand | 選択している関数を呼び出している場所を逆参照する |
u |
undefine | IDAが自動的に識別し設定した内容を解除する |
h |
hex to decimal, decimal to hex | 選択した値を16進数↔10進数の相互変換を行う |
a |
hex to ascii, ascii to hex | 選択した値を16進数↔ASCII文字の相互変換を行う |
その他ショートカットは公式サイトを確認する。
Shortcuts | Hex-Rays Docs
実行命令の強制変更
-
右クリックしてSet IP
をクリックすると、設定したところから命令が開始される
構造体情報設定、追加
- 該当の値が特定のキーの数値だった場合、特定のキーの名称に逆変換することが可能である
- 該当の値を右クリックして
Symbolic constant
->Use standard symbolic constant
- 該当の値を右クリックして
- 動的ロードの場合は構造体情報が
Structures
に入らないため、自身で追加する必要あり- 追加後、数値を右クリックして定義すればメンバーアクセス状況を文字化することができる
- コード例
mov ecx, [eax+edx+8] ; 修正前 mov ecx, [eax+edx+_WTS_PROCESS_INFOA.pProcessName] ; 修正後