11
アアアアアアアアアアア slank( アアアア )

アセンブリ入門

Embed Size (px)

Citation preview

Page 1: アセンブリ入門

アセンブラを入門した話

slank( すらんく )

Page 2: アセンブリ入門

以下のアセンブラを読み解きます

seccamp2015 の問題です

Page 3: アセンブリ入門

コードをいくつかのブロックに分割関数に入る初期作業

関数を出る作業

for 文の作業

for 文の中身

Page 4: アセンブリ入門

関数に入る初期作業push %esipush %ebxmov 0x0c(%esp), %ebxmov 0x10(%esp), %ecx

push 命令はスタックにレジスタを格納して、スタックポインタの値を減らす。esi 、 ebx の順にスタックにプッシュしている。

mov 命令は、値をコピーする。( スタックポインタのアドレス値 +0x0c) の中身 (function 関数の第 1 引数 array) を ebx にコピー( スタックポインタのアドレス値 +ox10) の中身 ( 関数の第 2 引数 n) を ecx にコピー

move

move

初期状態のスタック 処理後のスタック

( スタック=関数スタック ) とする

n

&array

Page 5: アセンブリ入門

for 文の作業test %ecx, %ecxjle 26 <function+26>

test 命令で ecx の値を調べる、 ecx and ecx の結果をフラグレジスタに反映させる。jle 命令で、 ecx!=0x0 だったら for 文に入らずループ後にジャンプする。

for(i=0; i<n; i++){} の赤字部分をチェックしている。

C 言語に直訳 すると for(i=0; i<n; i++){}

Page 6: アセンブリ入門

for 文の作業mov %ecx, %esimov $0x00, %edxmov $0x00, %eax

mov 命令で、 ecx を esi に、 0x00 を edx,eax に代入。eax は C 言語のコードでの変数 i に相当。 ecx はnに相当。esi は n のコピーとして、 edx は配列に値を代入するときに使用される。

C 言語に直訳 すると for(i=0; i<n; i++){}

0x00

i=0x00

nn

&array

Page 7: アセンブリ入門

for 文の中身mov %edx, (%ebx, %eax, 4)

0x00

i=0x00

nn

&array

スタックとレジスタ array の示すメモリ領域

(ebx, eax, 4)=(ebx の示すアドレス )+4*(eax の値 )なので、 array[i] のことである。array[i] に edx の値を代入する。現在は edx=0x00 だが、 for ループが回るにつれてこの後 edx が変化していく。

C 言語の array[i]=i*n に相当している。

0x00

Page 8: アセンブリ入門

for 文の作業add $0x01, %eaxadd %esi, %edx

n

i=0x01

nn

&array

スタックとレジスタ array の示すメモリ領域

0x00

add 命令で、eax = eax + 1 ( for(i=0; i<n; i++) に相当 )edx = edx + esi  の処理をする。

edx には、 esi( n ) を追加する動作を行って、array[i] = edx にそなえる。

加算

Page 9: アセンブリ入門

for 文の作業

cmp %ecx, %eaxjne 1a <function+1a> 比べる

フラグレジスタcmp 命令で ecx と eax を比較して比較結果をフラグレジスタに入力jne 命令で、 ecx != eax (i != n) なら <function+1a> すなわち for 文内部の命令部にジャンプする。そうでない場合は、 for ループを抜けて次の命令に進む。

ni=0x01

Page 10: アセンブリ入門

関数を出る作業pop %ebxpop %esiret

pop 後のスタックpop 前のスタック

pop 命令で、スタックに格納されていたメモリ領域を解放します。

その後 ret 命令で、関数を抜け出します。ret 命令では、スタックに積まれたリターンアドレスを pop して、そのアドレスに jump をする。

push 命令にに対しての pop 命令のように、 ret 命令は、 call 命令と対になっている。

Page 11: アセンブリ入門

関数を呼び出すとき関数を呼び出すときに、 CPU は、関数スタックを用意して、関数実行前に引数、リターンアドレス、を格納する。という規約が存在するが、処理系によっては、関数の引数を直接レジスタに格納することもある。 (cdecl だったり、 Register だったり。。 )

関数の引数は、 call 命令の前に、レジスタに格納している。(どんな規則でレジスタを選んでいるかはわからなかった。)