아이고. 이 글을 이제야 쓰게 되었습니다. 죄송합니다. 그동안 이 주제에 대해 개인적으로 물어보시는 분들에게는 메일로 답변 드렸는데, 답변 내용을 여기에도 올립니다.

 

가상함수 후킹과 COM 후킹은 근본적으로 동일하니 같은 방식을 사용하시면 됩니다.

 

Detours로 후킹 할 때 가장 중요한 것은 후킹의 대상이 되는 Function의 주소를 찾는 것입니다. 그런데 아시다시피 가상함수의 주소는 일반적인 방법으로 알 수 없습니다.

 

직접 프로그램을 만들어 디버깅 한 후 가상함수와 Object간의 Offset을 알아내야 해당 가상 함수의 Real주소를 알게 됩니다.

 

Real주소를 알았다면 Detours로 후킹하는 것은 간단하지요.

 

 

아래에서 큰 글자로 표시된 부분을 살펴보시기 바랍니다. Pvtbl 은 가상함수 테이블의 주소이고, -25888 값은Offset입니다.

 

 Offset을 확인하려면 한번 가상함수를 디버깅해 해당 주소를 알아 낸 후 해당 주소 – pvtbl 을 계산하면 됩니다.

 

COM Object또는 가상 함수를 가지는 객체가 변경되지 않았다면 이 Offset값은 항상 고정입니다.

 

#include <stdio.h>

#include <Windows.h>

#include <detours.h>

static PDETOUR_TRAMPOLINE Trampoline;

 

 

class CMember{

public:

           void Target(void);

};

 

void CMember::Target(void){

           printf("Cmember :: Target! (this:%p)\n"this);

 

}

 

class CDetour{

public :

           void WINAPI Mine_Target(CHAR* string);

           static void (CDetour::*Real_Target)(void);

};

 

void CDetour::Mine_Target(CHAR* string){

           printf("  CDetour::Mine_Target! (this:%p)\n"this);

           //__asm push edx;

           __asm mov eax, [esp];

           __asm push eax;

           __asm push eax;

           __asm call [Trampoline];

           //void (WINAPI *OriginalTarget)(CHAR* ) = (void (WINAPI *)(CHAR*))((PBYTE)Trampoline);

           //OriginalTarget(string);

}

 

void (CDetour::*CDetour::Real_Target)(void) = (void (CDetour::*)(void))&CMember::Target;

 

void WINAPI testMethod(CHAR* test){

           printf("general method %s\n",test);

}

 


 

class IInterface{

public :

           virtual void WINAPI test(CHAR* string)=0;

};

 

class ImplementClass : public IInterface{

public :

           void WINAPI test(CHAR* string){

                     printf("test test");

           }

};

 

 

 

int main(intchar**){

           LONG error;

           IInterface* inter;

           ImplementClass imple;

           inter = &imple;

       void* pvtbl;

       memcpy(&pvtbl, inter, sizeof(pvtbl));

    DetourTransactionBegin();

    DetourUpdateThread(GetCurrentThread());

       PBYTE tmp = (PBYTE)pvtbl - 25888;

           PVOID DetourPtr;

           PVOID TargetPtr;

       

           testMethod("asdfadsf");

         

           inter->test("test -- before detourAttach");

          

           DetourAttachEx(&(PVOID&)(tmp),(PVOID)(&(PVOID&)CDetour::Mine_Target), &Trampoline, &TargetPtr, &DetourPtr);

           error = DetourTransactionCommit();

          

 

           inter->test("test----inner virtual function");

 

    if (error == NO_ERROR) {

        printf("\n");

    }

           else{

                     printf("fail to attach\n");

           }


 

 

           getchar();

           return 0;

}

저작자 표시
신고


 

티스토리 툴바