C++ DLL で使用される呼び出し規約をプログラムで推測できますか?
-
21-09-2019 - |
質問
C++ DLL ファイル内の関数をテストするプログラムを作成したいと想像してください。ユーザーが DLL を選択できるようにする必要があります (C++ DLL について話していると仮定します)。DLL によってエクスポートされたすべての関数のリストを取得できるはずです。次に、ユーザーはリストから関数名を選択し、引数のリストを手動で入力できる必要があります (引数はすべて、int、double、bool、char 配列などの基本型です (例:c-type strings) ) を選択し、指定された引数を使用して選択した関数の実行を試みます。彼は、指定された引数を使用して関数が実行されるかどうか、または指定された引数によって関数がクラッシュするのかどうか (たとえば、署名と一致しないため) を知りたいと考えています。
主な問題は、C++ は厳密に型指定された言語であるため、コンパイル時に関数呼び出しの引数の数と型を知っている必要があることです。そして私の場合、これらの引数が何であるかは、ユーザーは実行時にそれらを選択します。
私が思いついた唯一の解決策は、アセンブリを使用して手動で引数をコールスタックにプッシュすることでした。
ただし、アセンブリをいじりたい場合は、DLL 内の関数がどの呼び出し規約を使用しているかを確実に把握する必要があることがわかりました。
それで(最後に:)私の質問は次のとおりです。呼び出し規約をプログラムで推測することはできますか?dependency Walker は役に立ちませんし、PE 形式を手動で読み取る方法もわかりません。
解決
答えはのかもしれないの
は、関数名はC ++装飾されている場合は、あなたが名前の装飾からの引数の数と種類を決定することができ、これはあなたの最良のシナリオ、およびMSVCは、最初の場所でコードを書くために使用された場合は、かなり可能性があります。
エクスポートされた関数はstdcallの大会(Windows APIのためのデフォルト)を呼び出している場合は、、あなたがプッシュするバイト数ではなく、引数の型を決定することができます。
悪いニュースは、Cは規則を呼び出すため、シンボル名を見て、伝えるためにどのような方法がないということです。あなたは、ソースコードやデバッグ情報へのアクセスを持っている必要があります。
http://en.wikipedia.org/wiki/X86_calling_conventionsする
関数はエクスポートとして与えられている名前は、の必要なのことをリンカが見ている名前を持つ任意の関係を持っていますが、ほとんどの時間、エクスポートされた名前とシンボル名ではなく、リンカが同じで見てます。
他のヒント
あなたはここで32ビットまたは64ビットを話しているかどうかを指定していない、あなたや他のポスターで概説困難は主に32ビットコードに適用されます。 64ビット版Windowsでは、基本的に一つだけ呼び出し規約がありますあなたがことを意味し、(それがジョンKnoellerによってリンクWikipediaの記事にもしてあります)を行う誰を除いて、当然の呼び出し規約を(知っています)自分自身を調理します。
また、マイクロソフトのx64は、呼び出し規約で、呼び出される関数のパラメータの数を知らないと、ユーザーがしたい/あなたが望む限り多くのパラメータを提供し、それを呼び出してからあなたを停止しません。呼び出し側がスタック空間を確保し、その後、それをクリーンアップするので、これはあなたのためです。 - 。もちろん、まだあなたが無効な入力を提供しているので、愚かなことを行うと呼ばれる機能を有していてもよいパラメータ右[数]を提供するが、それはまた別の話だありません。
コンパイルされたコードは、単に「ここでは、この機能はfastcallであり、ここではこの1つはstdcallのある」残念ながら言いません。
IDAのようにも近代的な逆アセンブラは、デフォルトでコールタイプを推測しようとしない(どこかIDKのプラグインやオプションがあるかもしれません)。
あなたが人間であれば、は、基本的には、最初のいくつかの手順を見て、時間の90%を伝えるCNです。レジスタを介してその通過のparamsは(特にECX)場合、彼らはポップとプッシュ、そのSTDCALL、ある場合はそのCDECL。 Fastcallもレジスタを使用しますが、何か特別なことは...私の頭の上から知らないん。あなたのプログラムが明らかに人間ではありませんので、しかし、このすべての情報は無用です。
あなたがテストを行っている場合は、少なくともヘッダファイルを持っていけません?これは猫の皮を剥ぐためにとてもハードな方法です..
C++ 関数がどのような呼び出し規則を使用しているかを知りたい場合は、勉強するのが最善の方法です。
- その関数を宣言するヘッダー、および
- 特定の DLL をコンパイルしたコンパイラのドキュメント。
しかし、正直に言うと、この全体は少し混乱しているように思えます。あなたの友人はなぜこれをできるようにしたいのですか?また、なぜ関連する関数を宣言するヘッダーを解析することで必要な情報を取得できないのでしょうか?
このページでは、VC++6 がパラメーターと呼び出し規約情報をシンボル名にエンコードする方法について説明します。 http://www.bottledlight.com/docs/mangle.html
VC++ の新しいバージョンは互換性があると思われますが、これについては確認していません。
コンパイラに付属する、これを自動化するツールもいくつかあります。 http://msdn.microsoft.com/en-us/library/5x49w699.aspx
名前マングリングは C++ 関数にのみ適用されます。関数が「extern "C"」の場合、これは機能しません。