This week only. Pastebin PRO Accounts Christmas Special! Don't miss out!Want more features on Pastebin? Sign Up, it's FREE!
Guest

Source file

By: a guest on May 3rd, 2012  |  syntax: C++  |  size: 3.91 KB  |  views: 18  |  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. // Header files
  2. #include <udis86.h>
  3. #include <sys/mman.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6.  
  7. // Class header
  8. #include "detour.h"
  9.  
  10. // Page execution constants (way more good-looking in the code)
  11. const int PageExecuteReadWrite = (PROT_READ | PROT_WRITE | PROT_EXEC);
  12. const int PageExecuteRead = (PROT_READ | PROT_EXEC);
  13.  
  14. // Static member variables
  15. byte    Detour::m_jmpOperator[] = "\xFF\x25\xEF\xBE\xAD\xDE";
  16. size_t  Detour::m_jmpSize       = sizeof(m_jmpOperator) - 1;
  17. uint    Detour::m_jmpOffset     = 2;
  18.  
  19. Detour::Detour(void * targetFunc, void * detourFunc)
  20. {
  21.         // Reset/update all members
  22.         m_targetFunc    = (byte*) targetFunc;
  23.         m_detourFunc    = (byte*) detourFunc;
  24.         m_trampoline    = null;
  25.  
  26.         // Calculate required target size
  27.         m_preludeSize = SizeRequired();
  28. }
  29.  
  30. Detour::~Detour(void)
  31. {
  32.         // We only need to unpatch
  33.         Unpatch();
  34. }
  35.  
  36. bool Detour::Unpatch(void)
  37. {
  38.         // Check memory (both protection and if it's allocated)
  39.         if(m_trampoline == null || !SetAddressProtection(m_targetFunc, PageExecuteReadWrite))
  40.                 return false;
  41.  
  42.         // Copy the old patch back again
  43.         memcpy(m_targetFunc, m_trampoline, m_preludeSize);
  44.  
  45.         // Reset address protection (we don't care if it succeeds or not)
  46.         SetAddressProtection(m_targetFunc, PageExecuteRead);
  47.  
  48.         // Free memory
  49.         delete [] m_trampoline;
  50.         m_trampoline = null;
  51.  
  52.         // Return success
  53.         return true;
  54. }
  55.  
  56. bool Detour::Patch(void)
  57. {
  58.         // Our buffer to use
  59.         byte * buffer = null;
  60.  
  61.         // Calculate the buffers required size
  62.         size_t bufferSize = m_preludeSize + m_jmpSize + 2 * sizeof(size_t);
  63.  
  64.         // Setup our trampolines buffer
  65.         m_trampoline = buffer = new byte[bufferSize];
  66.  
  67.         // Setup our pointers for the addresses
  68.         size_t * targetPtr = (size_t*)(buffer + m_preludeSize + m_jmpSize);
  69.         size_t * detourPtr = (size_t*)(buffer + m_preludeSize + m_jmpSize + sizeof(size_t));
  70.  
  71.         *targetPtr = (size_t) m_targetFunc + m_preludeSize;
  72.         *detourPtr = (size_t) m_detourFunc;
  73.  
  74.         // Copy the target prelude to our trampoline
  75.         memcpy(m_trampoline, m_targetFunc, m_preludeSize);
  76.  
  77.         // Write the jump operator to the trampoline & change address
  78.         memcpy(buffer + m_preludeSize, m_jmpOperator, m_jmpSize);
  79.         memcpy(buffer + m_preludeSize + m_jmpOffset, &targetPtr, sizeof(size_t));
  80.  
  81.         // Create a buffer for overwriting the target prelude, this will allow us to copy
  82.         // instructions in one pass to limit the time the function is effectively broken
  83.         byte jmpBuffer[m_jmpSize];
  84.         buffer = jmpBuffer;
  85.  
  86.         memcpy(buffer, m_jmpOperator, m_jmpSize);
  87.         memcpy(buffer + m_jmpOffset, &detourPtr, sizeof(size_t));
  88.  
  89.         // Set execute rights to the page that contains our trampoline
  90.         if(SetAddressProtection(m_trampoline, PageExecuteReadWrite))
  91.         {
  92.                 // And update address protection at the target function address
  93.                 if(SetAddressProtection(m_targetFunc, PageExecuteReadWrite))
  94.                 {
  95.                         // Write 'jmp' to the target function
  96.                         memcpy(m_targetFunc, buffer, m_jmpSize);
  97.  
  98.                         // Update address protection (we don't care about the result)
  99.                         SetAddressProtection(m_targetFunc, PageExecuteRead);
  100.  
  101.                         // Return success
  102.                         return true;
  103.                 }
  104.         }
  105.  
  106.         // Free the allocated memory
  107.         delete [] m_trampoline;
  108.         m_trampoline = null;
  109.  
  110.         // Return failure
  111.         return false;
  112. }
  113.  
  114. size_t Detour::SizeRequired(void)
  115. {
  116.         // Temporary variable
  117.         size_t required = 0;
  118.  
  119.         ud_t disas;
  120.         ud_init(&disas);
  121.  
  122.         // Setup the disassembly buffer
  123.         ud_set_input_buffer(&disas, m_targetFunc, 20);
  124.         ud_set_mode(&disas, 32);
  125.  
  126.         // Loop until there is enough memory for a jump
  127.         while((required += ud_disassemble(&disas)) < m_jmpSize);
  128.  
  129.         // Return the amount
  130.         return required;
  131. }
  132.  
  133. int Detour::SetAddressProtection(void * addr, int protection)
  134. {
  135.         // Constant holding the page size value
  136.         const size_t pageSize = sysconf(_SC_PAGE_SIZE);
  137.  
  138.         // Calculate relative page offset
  139.         size_t temp = (size_t) addr;
  140.         temp -= temp % pageSize;
  141.  
  142.         // Update address
  143.         addr = (void*) temp;
  144.  
  145.         // Update memory area protection
  146.         return !mprotect(addr, pageSize, protection);
  147. }
clone this paste RAW Paste Data