You do not have to go through all this work, since EnumWindows (the function in the question asked) provides a data parameter. You can put any value you want there, for example, a link to the object shown in the answer. The Morris method is better suited for callback functions that do not provide any general-purpose data parameter.
To adapt the response to use Morris code, you first need to make sure that the signature of the callback method matches the signature of the API callback function. Since we call EnumWindows , we need a two-argument function that returns Bool. The calling convention should be stdcall (because the Morris code suggests this, and itβs hard to ban any other agreement).
function TAutoClickOKThread.cbEnumWindowsClickOK( Wnd: HWnd; Param: LParam): Bool; stdcall; begin
Then we create a TCallbackThunk data TCallbackThunk with all the machine code and the transition offset, referring to the intended callback method.
However, we do not use the method described by Morris. Its code pushes the data structure onto the stack. This means that we push the executable code onto the stack. Modern processors and operating systems no longer allow this - the OS will stop your program. We could get around this by calling VirtualProtect to change the permissions of the current stack page, allowing it to execute, but this makes the whole page executable, and we donβt want to leave the program open for attack. Instead, we allocate a block of memory, especially for thunk, separately from the stack.
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;
Please note that these are 32-bit x86 instructions in this entry. I have no idea what the corresponding x86_64 instructions will be.
source share