Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Oct 25th, 2009  |  syntax: C++  |  size: 4.54 KB  |  views: 1,185  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  Test a detour of a member function (member.cpp of member.exe)
  4. //
  5. //  Microsoft Research Detours Package, Version 2.1.
  6. //
  7. //  Copyright (c) Microsoft Corporation.  All rights reserved.
  8. //
  9. //  By default, C++ member functions use the __thiscall calling convention.
  10. //  In order to Detour a member function, both the trampoline and the detour
  11. //  must have exactly the same calling convention as the target function.
  12. //  Unfortunately, the VC compiler does not support a __thiscall, so the only
  13. //  way to create legal detour and trampoline functions is by making them
  14. //  class members of a "detour" class.
  15. //
  16. //  In addition, C++ does not support converting a pointer to a member
  17. //  function to an arbitrary pointer.  To get a raw pointer, the address of
  18. //  the member function must be moved into a temporrary member-function
  19. //  pointer, then passed by taking it's address, then de-referencing it.
  20. //  Fortunately, the compiler will optimize the code to remove the extra
  21. //  pointer operations.
  22. //
  23. //  If X::Target is a virtual function, the following code will *NOT* work
  24. //  because &X::Target is the address of a thunk that does a virtual call,
  25. //  not the real address of the X::Target.  You can get the real address
  26. //  of X::Target by looking directly in the VTBL for class X, but there
  27. //  is no legal way to 1) get the address of X's VTBL or 2) get the offset
  28. //  of ::Target within that VTBL.  You can of course, figure these out for
  29. //  a particular class and function, but there is no general way to do so.
  30. //
  31. #include <stdio.h>
  32.  
  33. #include <windows.h>
  34. #include <detours.h>
  35.  
  36. #include "..\slept\verify.cpp"
  37.  
  38. //////////////////////////////////////////////////////////////// Target Class.
  39. //
  40. class CMember
  41. {
  42.   public:
  43.     void Target(void);
  44. };
  45.  
  46. void CMember::Target(void)
  47. {
  48.     printf("  CMember::Target!   (this:%p)\n", this);
  49. }
  50.  
  51. //////////////////////////////////////////////////////////////// Detour Class.
  52. //
  53. class CDetour /* add ": public CMember" to enable access to member variables... */
  54. {
  55.   public:
  56.     void Mine_Target(void);
  57.     static void (CDetour::* Real_Target)(void);
  58.  
  59.     // Class shouldn't have any member variables or virtual functions.
  60. };
  61.  
  62. void CDetour::Mine_Target(void)
  63. {
  64.     printf("  CDetour::Mine_Target! (this:%p)\n", this);
  65.     (this->*Real_Target)();
  66. }
  67.  
  68. void (CDetour::* CDetour::Real_Target)(void) = (void (CDetour::*)(void))&CMember::Target;
  69.  
  70. //////////////////////////////////////////////////////////////////////////////
  71. //
  72. int main(int argc, char **argv)
  73. {
  74.     (void)argc;
  75.     (void)argv;
  76.  
  77.     //////////////////////////////////////////////////////////////////////////
  78.     //
  79.  
  80. #if (_MSC_VER < 1310)
  81.     void (CMember::* pfTarget)(void) = CMember::Target;
  82.     void (CDetour::* pfMine)(void) = CDetour::Mine_Target;
  83.  
  84.     Verify("CMember::Target", *(PBYTE*)&pfTarget);
  85.     Verify("*CDetour::Real_Target", *(PBYTE*)&CDetour::Real_Target);
  86.     Verify("CDetour::Mine_Target", *(PBYTE*)&pfMine);
  87. #else
  88.     Verify("CMember::Target", (PBYTE)(&(PBYTE&)CMember::Target));
  89.     Verify("*CDetour::Real_Target", *(&(PBYTE&)CDetour::Real_Target));
  90.     Verify("CDetour::Mine_Target", (PBYTE)(&(PBYTE&)CDetour::Mine_Target));
  91. #endif
  92.  
  93.     printf("\n");
  94.  
  95.     DetourTransactionBegin();
  96.     DetourUpdateThread(GetCurrentThread());
  97.  
  98. #if (_MSC_VER < 1310)
  99.     pfMine = CDetour::Mine_Target;
  100.  
  101.     DetourAttach(&(PVOID&)CDetour::Real_Target,
  102.                  *(PBYTE*)&pfMine);
  103. #else
  104.     DetourAttach(&(PVOID&)CDetour::Real_Target,
  105.                  (PVOID)(&(PVOID&)CDetour::Mine_Target));
  106. #endif
  107.  
  108.     LONG l = DetourTransactionCommit();
  109.     printf("DetourTransactionCommit = %d\n", l);
  110.     printf("\n");
  111.  
  112. #if (_MSC_VER < 1310)
  113.     pfTarget = CMember::Target;
  114.     pfMine = CDetour::Mine_Target;
  115.  
  116.     Verify("CMember::Target", *(PBYTE*)&pfTarget);
  117.     Verify("*CDetour::Real_Target", *(&(PBYTE&)CDetour::Real_Target));
  118.     Verify("CDetour::Mine_Target", *(PBYTE*)&pfMine);
  119. #else
  120.     Verify("CMember::Target", (PBYTE)(&(PBYTE&)CMember::Target));
  121.     Verify("*CDetour::Real_Target", *(&(PBYTE&)CDetour::Real_Target));
  122.     Verify("CDetour::Mine_Target", (PBYTE)(&(PBYTE&)CDetour::Mine_Target));
  123. #endif
  124.     printf("\n");
  125.  
  126.     //////////////////////////////////////////////////////////////////////////
  127.     //
  128.     CMember target;
  129.  
  130.     printf("Calling CMember (w/o Detour):\n");
  131.     (((CDetour*)&target)->*CDetour::Real_Target)();
  132.  
  133.     printf("Calling CMember (will be detoured):\n");
  134.     target.Target();
  135.  
  136.     return 0;
  137. }