5

文書化されていない関数の使用方法を学ぶために、OllyDbgでアセンブラーとデバッグのスキルを学んでいます。今、私は次の問題を抱えています:

私は次のコード部分を持っています(OllyDbgから):

MOV EDI,EDI
PUSH EBP
MOV EBP,ESP
MOV EAX, DWORD PTR SS:[EBP+8]
XOR EDX,EDX
LEA ECX, DWORD PTR DS:[EAX+4]
MOV DWORD PTR DS:[EAX], EDX
MOV DWORD PTR DS:[ECX+4],ECX
MOV DWORD PTR DS:[ECX],ECX
MOV DWORD PTR DS:[EAX+C],ECX
MOV ECX, DWORD PTR SS:[EBP+C]

これが関数の始まりであり、目標はデータ構造を見つけることです。そのため、最初にEBPをスタックにプッシュし、次にESP(現在のスタックポインター)をEBPに移動して、関数のスタックフレームを定義していることがわかりました。チュートリアルでは、一般的なレイアウトでは、最初の引数は[EBP + 8]に配置され、2番目の引数は[EBP+C]に配置されると書かれています。

これは私が理解していないことです。最初のパラメーターがEBP+8に配置されていることをどのように知ることができますか?

誰かが私を助けてくれることを願っています!ありがとう!

4

1 に答える 1

9

「文書化されていない機能」とはどういう意味ですか?ほとんどの場合、アセンブリは高水準コードをコンパイルするだけです。それについて「文書化されていない」ものはほとんどありません。

EBP関数のスタックフレームポインタとして最も頻繁に使用されます。特にC呼び出し規約(名前でも知られていますcdecl)で使用されます。この規則では、パラメーターは逆の順序でスタックに渡され(たとえば、最後のパラメーターが最初にプッシュされます)、呼び出された関数はEBPそれらにアクセスするために使用します。あなたが投稿したコードに基づいて、データ構造は最初のパラメーターによって示されているのではないかと思います。見てください:

MOV EAX, DWORD PTR SS:[EBP+8]
LEA ECX, DWORD PTR DS:[EAX+4]
MOV DWORD PTR DS:[EAX], EDX
MOV DWORD PTR DS:[ECX+4],ECX
MOV DWORD PTR DS:[ECX],ECX
MOV DWORD PTR DS:[EAX+C],ECX
MOV ECX, DWORD PTR SS:[EBP+C]

最初の命令は、最初の引数をに移動しEAXます。次に、オフセット4がその引数に追加され、に移動されECXます。LEAこれは、「LoadEffectiveAddress」の省略形である命令によって行われることに注意してください。これは符号なし演算に使用され、コンパイラはポインタ演算を実行してオフセットを追加するときに使用するのが好きです。したがって、この命令が表示されるたびに、操作対象が構造体へのポインタである可能性があることに注意する必要があります。もちろん、確実に知る方法はありません。MOV後で、そのアドレスとの間でいくつかのsを取得します。ここで、ECXはメモリへのアクセスに使用されます。構造が存在する場合、Cでは次のようになります。

struct a { /* pointed to by EAX / [EBP+8] */
    int memb1; /* MOV DWORD PTR DS:[EAX], EDX */
    struct b* memb2; /* LEA ECX, DWORD PTR DS:[EAX+4] */
    int memb3; /* unused? */
    int memb4; /* MOV DWORD PTR DS:[EAX+C],ECX */
};

struct b {
    int memb1; /* MOV DWORD PTR DS:[ECX],ECX */
    int memb2; /* MOV DWORD PTR DS:[ECX+4],ECX */
};

これがどういうわけか物事をクリアすることを願っています。アセンブリコードのリバースエンジニアリングは、特にアプリケーションで使用される引数のタイプを示すAPI呼び出しがない場合は、非常に困難で時間のかかる作業です。

于 2012-06-02T10:31:32.390 に答える