EnumWindows
(참조 된 질문의 기능)이 데이터 매개 변수를 제공하므로 실제로 모든 작업을 수행 할 필요가 없습니다. 답안에서 보여준 객체 참조와 같이 원하는 값을 넣을 수 있습니다. Morris의 기법은 범용 데이터 매개 변수를 제공하지 않는 콜백 함수에 더 적합합니다.
모리스의 코드를 사용하여 답을 적용하려면 먼저 콜백 메소드의 서명이 API의 콜백 함수의 서명과 일치하는지 확인해야합니다. EnumWindows
을 호출하기 때문에 Bool을 반환하는 두 개의 인수를 갖는 함수가 필요합니다. 호출 규칙은 stdcall이어야합니다 (모리스의 코드에서 가정하기 때문에 다른 모든 호출 규칙을 사용하기가 어렵습니다).
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과 델파이 5, 7, 2007에서 작동하는 모든 코드입니다. XE는 그렇게 할 것입니다. 게시물을 수정해야합니다. – menjaraz