2014-06-11 1 views
1

Matrox TripleHead2Go와 같은 플랫폼에서 3 중 모니터 윈도우 위치를 정정하기위한 전역 후크를 작성하고 있습니다. 32 비트 프로그램에서 지금까지 잘 작동하지만 지금은 64 비트 버전을 빌드해야합니다. 각 창 클래스에 설치 한 wndproc 썽크에 대한 x86 opcode를 번역 할 때 도움이 필요합니다.x86 opcode를 64bit 버전으로 변환

썽크는 원래의 wndproc 주소 인 wndproc 호출에 추가 인수를 추가합니다. 그러면 내 wndproc 처리기가 끝에 호출 할 수 있습니다.

#ifdef _WIN64 
    //TODO: figure out the WIN64 instructions 
#else 
    const unsigned char PatchTemplate[] = 
    { 
    0x90,       // nop, will become int3 if debug = true 
    0x58,       // pop eax (get the return address) 
    0x68, 0x00, 0x00, 0x00, 0x00, // push imm32, original wndproc address 
    0x50,       // push eax (restore the return address) 
    0x68, 0x00, 0x00, 0x00, 0x00, // push imm32, our wndproc address 
    0xC3       // retn 
    }; 

    #define PATCH_ORIG_OFFSET 3 
    #define PATCH_NEW_OFFSET 9 
#endif 

답변

4

64 비트 모드에서, 제 4 인자는 레지스터 rcx, rdx, r8r9에 전달된다. 그럼에도 불구하고 어쨌든 스택 공간이 할당됩니다.

추가 인수를 적절한 위치에 넣을 수 있도록 전달하는 인수의 개수를 알아야합니다. 표준 wndproc이라면 이미 4 개의 인수가 있습니다. 32 비트 코드는 처음에 새로운 인수를 삽입하므로 C 프로토 타입이라고 가정하므로 64 비트 모드에서도 동일한 작업을 수행해야합니다. 마지막에 새 인수를 추가하는 것이 더 쉽습니다.

또한 스택은 16 바이트 정렬로 유지되어야하며 호출 규칙에 따라 호출자는 인수를 해제해야합니다 (64 비트 모드에서는 더 이상 stdcall이 필요하지 않음). 물론 호출자는 추가 인수에 대해 알지 못하므로 스택을 올바르게 복원하지 않으므로 직접 처리해야합니다.

코드는 다음과 같습니다

00000000 90      nop       ; nop, will become int3 if debug = true 
00000001 4883EC28    sub rsp, 40     ; allocate space for arguments 
00000005 4C894C2420    mov [rsp + 32], r9   ; spill 4th arg to stack 
0000000A 4D89C1     mov r9, r8     ; move 3rd arg 
0000000D 4989D0     mov r8, rdx     ; move 2nd arg 
00000010 4889CA     mov rdx, rcx    ; move 1st arg 
00000013 48B988776655443322-  mov rcx, 0x1122334455667788 ; old wndproc 
0000001C 11 
0000001D 48B888776655443322-  mov rax, 0x1122334455667788 ; new wndproc 
00000026 11 
00000027 FFD0     call rax     ; call new wndproc 
00000029 4883C428    add rsp, 40     ; restore stack 
0000002D C3      ret 

업데이트을 :이 5 번째 인수로 기존의 WndProc를 추가 버전이어야합니다 :

00000000 90      nop       ; nop, will become int3 if debug = true 
00000001 4883EC28    sub rsp, 40     ; allocate space for arguments 
00000005 48B888776655443322-  mov rax, 0x1122334455667788 ; old wndproc 
0000000E 11 
0000000F 4889442420    mov [rsp + 32], rax   ; add as 5th argument 
00000014 48B888776655443322-  mov rax, 0x1122334455667788 ; new wndproc 
0000001D 11 
0000001E FFD0     call rax     ; call new wndproc 
00000020 4883C428    add rsp, 40     ; restore stack 
00000024 C3      ret 
+0

우수한 감사합니다! 올바른 인수를 가진 winproc 프로토 타입과 추가 인수가 하나만 있다고 가정했습니다. 인수를 x64 플랫폼의 끝으로 옮기는 것은 문제가되지 않습니다. 귀하의 답변을 기꺼이 받아 들일 수는 있지만 기꺼이 괜찮다면 대신 인수를 추가하는 코드를 제공해주십시오. – Geoffrey

+1

완료. 문제가있을 경우 알려 주시면 문제를 해결할 수 있습니다. – Jester

+0

감사합니다. 내가 가진 한 가지 질문은 스택에 40 바이트를 할당하는 이유입니다. 정렬 요구 사항을 이해하지만 40 바이트가 필요한 이유를 이해하지 못합니다. – Geoffrey