1

クライアントから、次の厄介な問題を解決するように依頼されました。彼らは、明らかな理由もなく「左右」にメッセージボックスを表示する傾向があるカスタムソフトウェアを持っています。たとえば、ソフトウェア自体が会計プログラムであり、顧客の支払いを受け取ると、メッセージ ボックスが 3 ~ 4 回連続して表示されることがあります。各メッセージ ボックスは、Windows の既定のサウンドを再生します。残念ながら、このソフトウェアがプログラムされた方法、それが再生するサウンドのタイプは完全に間違っています。たとえば、メッセージ自体が単なる情報である場合、警告メッセージ ボックスを表示し、警告システム サウンドを再生することがあります。これはすべて、ソフトウェアを使用するスタッフにとって非常に煩わしいものです。

ソフトウェアを配布しているベンダーに連絡を取ろうとしましたが、行き詰まりました。だから今、私はこの問題を軽減する方法を探しています。

私の最も簡単な解決策は、スピーカーをミュートすることを提案することでしたが、残念ながら、受信メールを聞くことができるようにするために、そして最も重要なことに、後でボイスメールを再生できるようにするために、スピーカーが存在する必要があります. したがって、私の解決策は、単一のプロセスだけでメッセージボックスの音をミュートすることでした。

私の経験から、これらの音を生成している可能性のある 2 つの API があることを知っています: MessageBeepと古いBeepです。

AppInit_DLLs を使用してシステム API にフックする方法を説明しているこの記事も見つけました。著者が示唆するように、カーネル32.dllではなくUser32.dllからフックする必要があるAPIの両方を除いて、それはうまく機能します。

質問セクションには、User32.dll から API にフックするためのおおよその手順を示すこの投稿もありますが、それらを実装しようとすると、十分な情報がありません (私の知識ではそれを実行するための情報がありません)。

私の質問は、User32.dll モジュールの API にフックする方法を知っている人はいますか?

編集:追伸。言及するのを忘れました。このソフトウェアは、UAC と互換性がないため、UAC を無効にして Windows 7 Professional にインストールされます :)

4

4 に答える 4

2

別の方法として、アプリケーションにパッチを適用できます。への呼び出しを見つけてMessageBeep、 で上書きしますnop

于 2013-06-12T09:43:12.000 に答える
1

これは難しい方法です。アプリが Vista より前の Windows で管理者として実行されている場合、 を介して API のアドレスを取得し、::GetProcAddress()そのメモリ ページに書き込む権限を自分に付与し、先頭を上書きすることができます。jmpオーバーライド関数のアドレスにジャンプする " " アセンブリ命令を含む API のコード。上書き関数が同じ引数を取り、 として宣言されていることを確認してください__cdecl

拡大された答えは次のとおりです。

API フックの「標準」手法には、次の手順が含まれます。

1: DLL をターゲット プロセスに挿入する

これは通常、最初にターゲット プロセス内で DLL の名前/パスを含む文字列 ("MyHook.dll" など) にメモリを割り当て、次にターゲット プロセス内にリモート スレッドを作成し、そのエントリ ポイントkernel32::LoadLibraryA()があなたのDLLを引数として。このページには、この手法の実装があります。特権と少し格闘する必要がありますが、Windows XP およびそれ以前の OS で 100% 動作することが保証されています。Vista とそれ以降のバージョンについてはわかりませんが、アドレス空間レイアウトのランダム化がこれを難しくしている可能性があります。

2. API をフックする

DLL がターゲット プロセスにロードされると、DLL がDllMain()自動的に実行され、ターゲット プロセスで必要なものを実行できるようになります。内からDllMain、 を使用::LoadLibraryA()して、HMODULEフックする API を含むライブラリ (例: "user32.dll")::GetProcAddress()を取得し、それをフックする API の名前 (例: "MessageBeep") と共に に渡します。 API 自体のアドレス。最終的には、そのアドレスのページに書き込む権限を自分に付与し、API の先頭を、jmp回り道 (つまり、フックする API の「バージョン」) にジャンプする命令で上書きします。_cdecl回り道には、フックする APIと同じ署名と呼び出し規則 (通常は ) が必要であることに注意してください。そうしないと、モンスターが目覚めてしまいます。

here で説明されているように、この手法はやや破壊的です。元の API は自分の API にジャンプするように変更されているため、回り道から元の API にコールバックすることはできず、非常にタイトで素敵な無限ループになってしまいます。元の API を保持したり、元の API にコールバックしたりできるさまざまな手法があります。そのうちの 1 つは...A()、API のバージョンをフックしてから、バージョンを呼び出すこと...W()です (すべてではないにしてもほとんどの...A()Windows API の ASCII 文字列をUNICODE 文字列であり、...W()対応する文字列を呼び出すことになります)。

于 2013-06-11T20:35:42.793 に答える
0

これを行うためにカスタム プログラムに時間を費やす必要はありません。

実行中の特定のアプリケーションをミュートすることができ、次回アプリケーションを開いたときにその設定が記憶されます。https://superuser.com/questions/37281/how-to-disable-sound-of-certain-applicationsを参照してください。

ほとんどのシステム サウンドをオフにする Windows Sound Sentry もありますが、Sound Sentry のアプリケーションごとの設定については知りません。

于 2013-06-11T20:53:40.377 に答える
0

Deviare API フックを使用して、いくつかの C# 行でフックを解決できます。または、もう少し難しく安定性の低い EasyHook を使用することもできます。

于 2013-06-13T18:15:05.543 に答える