EnumWindows
(参照された質問の関数)は、データパラメータを提供するので、実際にすべての作業を行う必要はありません。答えに示されているオブジェクト参照など、必要な値を置くことができます。 Morrisの手法は、汎用データパラメータを提供しないコールバック関数に適しています。
モリスのコードを使用するように回答するには、まずコールバックメソッドのシグネチャがAPIのコールバック関数のシグネチャと一致することを確認する必要があります。 EnumWindows
を呼び出しているので、Boolを返す2つの引数の関数が必要です。コーリング規約は標準である必要があります(Morrisのコードはそれを前提としており、他の呼び出し規約を犠牲にするのは困難です)。
function TAutoClickOKThread.cbEnumWindowsClickOK(
Wnd: HWnd; Param: LParam): Bool; stdcall;
begin
// ...
end;
次に、我々は、すべてのマシンコードにTCallbackThunk
データ構造を設定し、ジャンプが意図したコールバックメソッドを参照するオフセット。
しかし、私たちはMorrisの記述方法を使用していません。彼のコードはデータ構造をスタックに置きます。つまり、実行可能コードをスタックに入れています。現代のプロセッサとオペレーティングシステムはこれをもう許しません - OSはあなたのプログラムを停止させます。 VirtualProtect
を呼び出して、現在のスタックページのアクセス許可を変更して実行させることができますが、これによってページ全体が実行可能になり、攻撃のためにプログラムを開いたままにしたくない場合があります。代わりに、私たちはスタックから離れたサンクレコードのために特にメモリのブロックを割り当てます。
procedure TAutoClickOKThread.Execute;
var
Callback: PCallbackThunk;
begin
Callback := VirtualAlloc(nil, SizeOf(Callback^),
Mem_Commit, Page_Execute_ReadWrite);
try
Callback.POPEDX := $5A;
Callback.MOVEAX := $B8;
Callback.SelfPtr := Self;
Callback.PUSHEAX := $50;
Callback.PUSHEDX := $52;
Callback.JMP := $E9;
Callback.JmpOffset := Integer(@TAutoClickOKThread.cbEnumWindowsClickOK)
- Integer(@Callback.JMP) - 5;
EnumWindows(Callback, 0);
finally
VirtualFree(Callback);
end;
end;
これらは、そのレコードの32ビットx86命令です。対応するx86_64命令が何であるかわかりません。
私は、いくつかのAPIコールバックがlParamの回避策を許可しているものを追加しますが、いくつかはそうではありません(例:図のWinNLS)。また、これはStdcallThunkなどと呼ばれるべきです。 – OnTheFly
生成されたコードが実行可能ページに存在しないため、これは機能しません。あなたはその問題を解決することができます。しかし、あなたはx86上でしか動作できず、x64で失敗するコードを持っています。 –
@David Heffernan:ありがとう。私のボックスはx86で、Delphi 5,7、2007で動作するコードはすべてXEで動作します。私は投稿を編集する必要があります。 – menjaraz