2017-05-21 6 views
0

私はアセンブリが新しく、現在教育目的で調査中の実行可能ファイルを持っています。私はIDAプロを使用して実行可能ファイルの目的を理解していますが、質問はほとんどありません。私のコードは以下の通りです:アセンブリ:2つのアドレスを追加する

1.text:00401525     call ebp ; MapViewOfFile 
2.text:00401527     mov  ebp, eax 
3.text:00401529     test ebp, ebp 
4.text:0040152B     mov  [esp+54h+argv], ebp ; argv-shi ari chemi dll gadmotanili 
5.text:0040152F     jnz  short loc_401538 
6.text:00401531     push eax    ; Code 
7.text:00401532     call ds:exit 
8.text:00401538 ; --------------------------------------------------------------------------- 
9.text:00401538 
10.text:00401538 loc_401538:        ; CODE XREF: _main+EFj 
11.text:0040154C     mov  esi, [ebp+3Ch] 
12.text:0040154F     push ebp 
13.text:00401550     add  esi, ebp 
14.text:00401552     mov  ebx, eax 
15.text:00401554     push esi 
16.text:00401555     mov  [esp+68h+var_30], ebx 
17.text:00401559     mov  ecx, [esi+78h] 
18.text:0040155C     push ecx 
19.text:0040155D     call sub_401040 

私の質問を単純化するために列挙しました。

1行目に表示されているように、戻り値はebpに格納され、次にargvに格納されます(kernel32.dllがマップされただけです)。その後11行目(私が理解するように)では、いくつかの関数ポインタがesiに移動しました。 3chの小数点は60で、各関数は4バイトです。kernel32.dllからエクスポートされたすべての関数がリストされ、15番目の関数がAddSecureMemoryCacheCallbackであることがわかりました。その後、ebpがスタックにプッシュされ、13行目で私は完全に混乱しました。私が理解しているように、AddSecureMemoryCacheCallbackを指すポインターに始まるkernel32.dllのポインターを追加するのはナンセンスですが、これができることは何も考えられませんでしたが、これの目的は何ですか?申し訳ありませんが、私の質問がばかげて聞こえる場合、私はアセンブリで新しく、それは大きすぎるので、コード全体を貼り付けることができませんでした。ありがとう。

+0

エクスポートリストを見ている理由がわかりません。 'kernel32.dll'が最初からマッピングされていた場合、' ebp'はそのMZヘッダを指しています。オフセット60には、PEヘッダーへのオフセットである 'e_lfanew'があります。 –

+0

本当にありがとうございました:)私が言ったように、私はアセンブリで新しく、何が見えるのか分かりませんでしたが、私にはまだ分かりません。説明していただけますか? – Rasty

答えて

2

関数は、関数が成功した場合、戻り値はマップされたビューの開始アドレスであるMapViewOfFile

戻り値
呼び出します。
この関数が失敗すると、戻り値はNULLになります。拡張エラー情報を取得するには、GetLastErrorを呼び出します。

これは、ebpが基本ポインタとしてではなく、汎用レジスタとして使用されるように最適化されたコードです。

1 call ebp ; MapViewOfFile 
2 mov  ebp, eax   //EBP = start address of mapped view. 
3 test ebp, ebp   //Success or failure? 
4 mov  [esp+54h+argv], ebp //save mapped address in a variable 
5 jnz  short loc_401538 //Success -> jump to loc_401538 
6 push eax     //failure -> clean up and exit. 
7 call ds:exit 
8 --------------------------------------------------------------------------- 
9 
10 loc_401538:        ; CODE XREF: _main+EFj 
11 mov  esi, [ebp+3Ch]  //esi = MappedFile.SomeOffset at addr 60 in the mapped file 
12 push ebp     //Param3 = Addr(MappedFile)    
13 add  esi, ebp    //esi = pointer(MappedFile.SomeOffset) 
14 mov  ebx, eax    //ebx = start of mapped file 
15 push esi     //Param2 = pointer(MappedFile.SomeOffset) 
16 mov  [esp+68h+var_30], ebx //store start of mapped file in some var 
17 mov  ecx, [esi+78h]  //ecx = MappedFile.SomeOffset-> = 120 
18 push ecx     //Param1 = MappedFile.SomeOffset[120] 
19 call sub_401040   //call subroutine(Param1, Param2, Param3) 

サブルーチンは、cdecl calling conventionを使用する3つのパラメータを持つ関数です。 Param2とParam3はマップされたファイルへのポインタであり、param1は未知のデータです。
マップされているファイルのファイル名を知っている場合は、ヘキサエディタを使用してデータを調べ、Offset 60に格納されているオフセットを(おそらく)確認してから、offset:[0+offset[60]][120]に格納されているデータを計算できます。

eaxが利用可能になるため、呼び出されたサブルーチンは値を返す可能性が高いことに注意してください。あなたのコメントについて

このスニペットはKernel32.dll内の関数を呼び出すこと
あなたの仮定が間違っています。すべてのポインタは、MapViewOfFileによって返されたバッファを指しています。コードが何をしているのかを理解するには、その特定のファイルの内容を調べなければなりません。

レジスタをプッシュすることは、単に仕事中の呼び出し規約であるcdeclです。これはcコードなので、内部ではcdecl呼び出し規約を使用するため、スタックを使用してすべてのパラメータを転送する必要があります。
外部では、最初の3つのパラメータをレジスタに転送するstdcallを使用します。

stdcallcdeclの両方がEAXに戻ります。

+0

ありがとうございます:)しかし、13行目で 'add esi、ebp'は' MappedFile.SomeOffset'のポインタをesiに移動する 'lea esi、ebp'ではないでしょうか? – Rasty

+0

あなたは 'lea esi、[ebp + esi]'を意味すると確信しています。はい、それは動作しますが、 'add reg、reg'は2バイトで、' lea reg、[reg + reg] 'は3バイトなので、addはより効率的です。最後のオフセット@ 120は、ポインタへのポインタを使用して逆参照されます。だからそこに着くには2つのステップが必要です。 – Johan

+0

私はちょっと混乱しています。レジスタに格納された値を 'add'命令で加算してはいけませんか?なぜ1つのレジスタのポインタを別のレジスタに格納するのですか? – Rasty

関連する問題