Advertisement
Guest User

Source file

a guest
May 3rd, 2012
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.91 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement