2010-12-02 7 views
1

이것은 EasyHook에 대한 특정 기능이 아니라 일반적으로 후킹에 관한 기능입니다. 나는이 서명 기능을 훅하고 싶은 :관리되지 않는 함수 후킹, 호출 규칙에 스택/레지스터 문제가 있습니까?

public: int __thiscall Connection_t::Send(unsigned int,unsigned int,void const *) 

이 명확하게 관리되지 않는 코드와 내 관리 C# 코드가 EasyHook.But를 사용하여 함께 후크하기 위해 노력하고있어 내가 여기에 문제를 일으키는 EasyHook하지만 내 knowlegde을하지 생각 - 더 큰 놀라움을

public static int Send_Hooked(uint connection, uint size, IntPtr pDataBlock) 
    { 
     return Send(connection, size, pDataBlock); 
    } 

    [DllImport("Connection.dll", EntryPoint = "[email protected][email protected]@[email protected]", CallingConvention = CallingConvention.ThisCall)] 
    static extern int Send(uint connection, uint size, IntPtr pDataBlock); 

    [UnmanagedFunctionPointer(CallingConvention.ThisCall, CharSet = CharSet.Unicode, SetLastError = true)] 
    delegate int DSend(uint connection, uint size, IntPtr pDataBlock); 

을하지만 후크을 programm가 최대한 빨리 후크를 주입으로 충돌하지 계속해서 : 내가 같이 DllImport를 정의하고 삭제하는 방법 등 규칙을 호출에 ...
이다. 나는 이것이 호출 규칙의 문제라고 생각하고 hooking 함수가 hooked 함수의 스택을 어떻게 든 방해한다.

Func = (int (__stdcall *)(unsigned int, unsigned short, void const))::GetProcAddress(::GetModuleHandle("Connection.dll"), "[email protected][email protected]@[email protected]"); 
PVOID DetourPtr; 
PVOID TargetPtr; 
DetourTransactionBegin(); 
DetourAttachEx(&Func, SendConnectionHook, &Trampoline, &TargetPtr, &DetourPtr); 
DetourTransactionCommit(); 

그리고 호출 된 함수 :

__declspec(naked) void SendConnectionHook (CPU_CONTEXT saved_regs, void * ret_addr, WORD arg1, DWORD arg2, DWORD arg3) 
{ 
    DWORD edi_value; 
    DWORD old_last_error; 

    __asm 
    { 
     pushad; /* first "argument", which is also used to store registers */ 
     push ecx; /* padding so that ebp+8 refers to the first "argument" */ 

     /* set up standard prologue */ 
     push ebp; 
     mov ebp, esp; 
     sub esp, __LOCAL_SIZE; 
    } 

    edi_value = saved_regs.edi; 
    old_last_error = GetLastError(); 
    OnConnectionSend((void *) saved_regs.ecx, (unsigned char *) arg3, arg2); 
    SetLastError(old_last_error); 

    __asm 
    { 
     /* standard epilogue */ 
     mov esp, ebp; 
     pop ebp; 

     pop ecx; /* clear padding */ 
     popad; /* clear first "argument" */ 
     jmp [Trampoline]; 
    } 
} 

(대상

그래서 나는 ++ 있지만 C에서 우회와 동일한 기능을 훅 않는 다른 프로젝트에서보세요 (후킹 부분)했다 어셈블리 및 C++ 예제는 모두 Visual C++로 컴파일됩니다. 원래 함수를 호출하기 전에 일부 레지스터를 저장하고 스택을 복구해야 할 것 같습니까? 아니면 내가 여기서 잘못하고있는 어떤 다른 생각?

답변

7

C++ 클래스 인스턴스 메서드를 연결하려고합니다. 숨겨진 인수가 있습니다. 입니다. 이 인수는 일반적으로이 호출 규칙에 ECX 레지스터를 통해 전달됩니다. 그것이 우회적 인 버전의 Detours 버전입니다.

이 작업을하는 것은 매우 중요합니다. 특히 CPU 레지스터 값을 일찍, 특히 ECX로 보존해야합니다. 그것은 기계 코드를 사용하는 스텁을 필요로하며 관리 스텁에는 기계 코드가 필요하지 않습니다. EasyHook이이 기능을 지원하지 않는다고 확신합니다. 기능 목록에서 확실히 약속하지 않았습니다.

+0

passant : Thanks. EXC를 첫 번째 인수로 보는 것은 해결책이었습니다. – Fge

0

내가 알아 낸 것 같습니다. @ 한자 Passant 맞았 어 : 나는 숨겨진 this 인수를 저장해야합니다. EasyHook은 실제로 모든 것을 처리하지만 (.net 항목을 정리하는 것처럼). this는 첫 번째 인자이기 때문에 단순히 (connectionthis 참조입니다) 내 기능에 추가 않았다 :이 작업을 수행하는 이유

public static int Send_Hooked(IntPtr connection, uint unknown, uint size, IntPtr pDataBlock) 
    { 
     return Send(connection, unknown, size, pDataBlock); 
    } 

    [DllImport("Connection.dll", EntryPoint = "[email protected][email protected]@[email protected]", CallingConvention = CallingConvention.ThisCall)] 
    static extern int Send(IntPtr connection, uint unknown, uint size, IntPtr pDataBlock); 

    [UnmanagedFunctionPointer(CallingConvention.ThisCall, CharSet = CharSet.Unicode, SetLastError = true)] 
    delegate int DSend(IntPtr connection, uint unknown, uint size, IntPtr pDataBlock); 

정말 설명 할 수 없다 (또한 나는 그것의 대부분을 이해 않았다고 생각 :) 나는 정말로 돌아가서 좀 더 많은 어셈블러/컴파일 이론을 배워야한다.

+0

해결책으로 자신의 답을 표시하는 것이 좋을 것입니다. –

관련 문제