2013-07-20 1 views
3

몇 가지 인터넷 검색 후 클래스의 VTable을 수정하는 방법을 찾았지만 제 경우에는 클래스를 가리키는 포인터와 함께 캐스팅 할 인터페이스가 있습니다. DLL (소스 코드 없음)에서 이러한 함수 중 하나를 내 함수 중 하나로 리디렉션해야합니다. 문제는 어떤 인덱스에 함수가 있는지 모르기 때문에 그것을 찾으려면 VTable에서 해당 함수에 대한 포인터를 검색해 보았습니다.외부 클래스의 VTable 변경

이렇게 할 방법이 있습니까? 이 질문을보고 정말 지금 작업을 수행하는 방법을 모르는 모든 그래서

typedef DWORD (__thiscall *CW_FUNC)(); 

class ClassWriter 
{ 
public: 
    PVOID m_hObj; 
    PVOID *__vfptr; 
    PVOID m_old[256]; 
    void SetObj(PVOID hObj) 
    { 
     m_hObj = hObj; 
     __vfptr = *(PVOID **)hObj; 
    } 
    void AddOverride(int offset, PVOID newfunc) 
    { 
     DWORD dwNull; 
     m_old[offset] = __vfptr[offset]; 
     VirtualProtect(__vfptr + offset * 4, 4, PAGE_EXECUTE_READWRITE, &dwNull); 
     __vfptr[offset] = newfunc; 
    } 
    int GetOffset(PVOID func) 
    { 
     for (int i = 0; __vfptr[i] != NULL; i++) 
     { 
      if (func == __vfptr[i]) return i; 
     } 
    } 
    CW_FUNC GetFunc(int offset) 
    { 
     return (CW_FUNC)m_old[offset]; 
    } 
}; 

void WINAPI ChangeFunc() 
{ 
    ClassWriter cw; 
    HMODULE hMod = GetModuleHandle("dll_to_change.dll"); 
    IMyInterface *myObj = (IMyInterface*)GetProcAddress(hMod, "GetMyClass")(); 
    cw.SetObj(myObj); 
    int d = cw.GetOffset(myObj->MyFunction); 
    cw.AddOverride(d, OverrideFunction); 
} 
+0

당신이 그 외부 클래스의 소스가없는 대신 실행됩니다 호출? – greatwolf

+0

아니요, 저는 인터페이스와 DLL을 가지고 있습니다 – JINX

+1

함수 검사가 작동해야합니다. 물론, 그것은 사실상 가상 함수라고 가정합니다. 당신이 신경 쓰는 곳은 가상 함수라고하며, 직접적으로는 아닙니다. –

답변

1

: 여기

내 지금까지 코드 내가 올리 디버그 사용하고

,하지만 당신은 할 수 다른 디버거/덤퍼를 사용하십시오.

이렇게하는 가장 좋은 방법은 dll에 코드를 넣는 것입니다. , 다른 컴파일러는 (적어도 나를 위해)를 함수를 실행해야 컴파일되지 않습니다 확인

void OverrideFunction() 
{ 
    HMODULE hMod = GetModuleHandle("mydll.dll"); // If not loaded yet use LoadLibrary() 
    IMyInterface *myObj = (IMyInterface*)GetProcAddress(hMod, "GetMyObject")(); // Get the pointer to your object 
    char buffer[64]; 
    sprintf_s(buffer, "0x%X", OverrideFunction); // Print position of current function into buffer 
    MessageBox(0, buffer, "", 0); 
    myObj->MyFunction(); // Put in your function 
} 

이제 중 메시지 박스 (때까지 코드를 실행) 및 디버거 또는 컴파일러가 만든 경우 그 주소를 엽니 다 그냥 YourDll.OverrideFunction

에 갈 수있는 내보내기 기능, 즉 같은 것을 (컴파일러가 감지되면 이름)

CALL DWORD PTR DS:[<&USER32.MessageBoxA>] 

또는

,369을 아래 라인

봐입니다

CALL DWORD PTR [YourDll._imp__MessageBoxA] 

그 이후 다음 내 경우, 클래스의 기능을해야한다 :

CALL DWORD PTR DS:[EAX+34] 

귀하의 오프셋

는 것 0x34 (52) (육각 숫자를 계산하기 위해 항상 기억). VTable에서 색인을 얻으려면 4 (포인터 크기)로 나누어야하는데, 제 경우에는 13이됩니다.
void __fastcall NewFunc(IMyInterface *myObj, int null, (additional params)) // fastcall stores the first 2 params int ECX and EDX, thiscall stores the this-object in ECX 
{ 
// Your code 
} 

void OverrideFunction() 
{ 
    DWORD dwNull; 
    HMODULE hMod = GetModuleHandle("mydll.dll"); // If not loaded yet use LoadLibrary() 
    IMyInterface *myObj = (IMyInterface*)GetProcAddress(hMod, "GetMyObject")(); // Get the pointer to your object 
    PVOID *vtable = *(PVOID**)myObj; // The first int in your object is a pointer to the vtable 
// OldFunc = vtable[13]; // You might want to call your old function again, so save the pointer 
    VirtualProtect(&vtable[13], 4, PAGE_EXECUTE_READWRITE, &dwNull); // Always unprotect the memory 
    vtable[13] = NewFunc; 
} 

이제 매번 MyObject를가의 MyFunction이 NewFunc이