Code Patch를 통해서 API 후킹을 할 떄, 32bit 환경에서는 JMP Instruction 중 “E9 XXXXXXXX”를 사용하면 됬었다. 하지만 64bit 환경에서는 32bit 환경보다 가상메모리 공간이 훨씬더 커지면서 “E9 XXXXXXXX”을 이용해서는 안정적으로 후킹을 할 수가 없게 되었다. (32bit 가상메모리공간 -> 4GB, 64bit 가상메모리공간 -> 16TB)
따라서 64bit 환경에서는 32bit 환경에서 했던 것처럼 Code Patch를 하지 못한다. 다른 방법을 사용을 해야 한다. 64bit 환경에서 후킹 할 수 있는 방법을 찾는대로 계속 꾸준히 업데이트를 할 계획이다. 하지만 찾은 방법들이 안정적인지는 잘 모르겠다.
후킹 방법 목록
다음 항목들은 64bit에서 후킹할 수 있는 방법들이다.
1 | # 첫번째 방법 -> 14 바이트 |
1. JMP Instruction “FF 25”
1 | 0x00007FFF 00000001 'FF 25 00000000' JMP QWORD PTR ds:[7FFF00000007] # JMP QWORD PTR [RIP+addr0] |
JMP Instruction 중에서 “FF 25 XXXXXXXX”를 이용하는 방법이다. FF25로 시작하는 JMP 명령어는 레지스터 RIP + offset(XXXXXXXX)을 더한 주소로 이동한다. 이를 통해서 RIP+offset(XXXXXXXX) 주소에다가 후킹 함수 주소를 넣으면, 후킹 함수로 이동할 수 있는 기법이다.
테스트 코드
1 | #include "Windows.h" |
2. mov & jmp instruction
1 | mov rax, address # "48 b8 000000 000000" |
64bit 값을 가질 수 있는 레지스터를 이용해서 레지스터에 후킹 함수 주소값을 집어넣고, JMP 명령어를 통해서 후킹 함수쪽으로 실행흐름을 바꾸는 방법이다.
어떤 레지스터를 사용할 것인지에 따라서 machine code는 달라질 수 있다. mov 명령어를 통해 immu64 값을 rax의 집어 넣는 machine code 는 “48 b8 XXXXXXXX XXXXXXXX” 이고, rax 레지스터 값으로 이동하는 JMP의 machine code는 “ff e0” 이다.
테스트 코드
1 | #include "Windows.h" |
3. push & mov & ret instruction
1 | push 4byte_low_address |
64bit에서는 64bit 레지스터 값을 push할 수 있는 명령어는 있지만, immu64 값을 push 할수 있는 명령어가 없다. 따라서 스택에 후킹 함수를 주소를 집어 넣으러면 push 4byte_low_address를 넣고, mov dword ptr[rsp+4], 4byte_high_address를 통해서 rsp값에 후킹 함수 주소를 설정해야 한다. 그 이후 ret 명령어를 통해서 후킹 함수쪽으로 실행흐름을 바꾸는 기법이다.
테스트 코드
1 | #include "Windows.h" |
참고자료
Win32 API 후킹 - Trampoline API Hooking
Assembly Challenge : Jump to a non-relative address without using registers