Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Header files
- #include <udis86.h>
- #include <sys/mman.h>
- #include <unistd.h>
- #include <string.h>
- // Class header
- #include "detour.h"
- // Page execution constants (way more good-looking in the code)
- const int PageExecuteReadWrite = (PROT_READ | PROT_WRITE | PROT_EXEC);
- const int PageExecuteRead = (PROT_READ | PROT_EXEC);
- // Static member variables
- byte Detour::m_jmpOperator[] = "\xFF\x25\xEF\xBE\xAD\xDE";
- size_t Detour::m_jmpSize = sizeof(m_jmpOperator) - 1;
- uint Detour::m_jmpOffset = 2;
- Detour::Detour(void * targetFunc, void * detourFunc)
- {
- // Reset/update all members
- m_targetFunc = (byte*) targetFunc;
- m_detourFunc = (byte*) detourFunc;
- m_trampoline = null;
- // Calculate required target size
- m_preludeSize = SizeRequired();
- }
- Detour::~Detour(void)
- {
- // We only need to unpatch
- Unpatch();
- }
- bool Detour::Unpatch(void)
- {
- // Check memory (both protection and if it's allocated)
- if(m_trampoline == null || !SetAddressProtection(m_targetFunc, PageExecuteReadWrite))
- return false;
- // Copy the old patch back again
- memcpy(m_targetFunc, m_trampoline, m_preludeSize);
- // Reset address protection (we don't care if it succeeds or not)
- SetAddressProtection(m_targetFunc, PageExecuteRead);
- // Free memory
- delete [] m_trampoline;
- m_trampoline = null;
- // Return success
- return true;
- }
- bool Detour::Patch(void)
- {
- // Our buffer to use
- byte * buffer = null;
- // Calculate the buffers required size
- size_t bufferSize = m_preludeSize + m_jmpSize + 2 * sizeof(size_t);
- // Setup our trampolines buffer
- m_trampoline = buffer = new byte[bufferSize];
- // Setup our pointers for the addresses
- size_t * targetPtr = (size_t*)(buffer + m_preludeSize + m_jmpSize);
- size_t * detourPtr = (size_t*)(buffer + m_preludeSize + m_jmpSize + sizeof(size_t));
- *targetPtr = (size_t) m_targetFunc + m_preludeSize;
- *detourPtr = (size_t) m_detourFunc;
- // Copy the target prelude to our trampoline
- memcpy(m_trampoline, m_targetFunc, m_preludeSize);
- // Write the jump operator to the trampoline & change address
- memcpy(buffer + m_preludeSize, m_jmpOperator, m_jmpSize);
- memcpy(buffer + m_preludeSize + m_jmpOffset, &targetPtr, sizeof(size_t));
- // Create a buffer for overwriting the target prelude, this will allow us to copy
- // instructions in one pass to limit the time the function is effectively broken
- byte jmpBuffer[m_jmpSize];
- buffer = jmpBuffer;
- memcpy(buffer, m_jmpOperator, m_jmpSize);
- memcpy(buffer + m_jmpOffset, &detourPtr, sizeof(size_t));
- // Set execute rights to the page that contains our trampoline
- if(SetAddressProtection(m_trampoline, PageExecuteReadWrite))
- {
- // And update address protection at the target function address
- if(SetAddressProtection(m_targetFunc, PageExecuteReadWrite))
- {
- // Write 'jmp' to the target function
- memcpy(m_targetFunc, buffer, m_jmpSize);
- // Update address protection (we don't care about the result)
- SetAddressProtection(m_targetFunc, PageExecuteRead);
- // Return success
- return true;
- }
- }
- // Free the allocated memory
- delete [] m_trampoline;
- m_trampoline = null;
- // Return failure
- return false;
- }
- size_t Detour::SizeRequired(void)
- {
- // Temporary variable
- size_t required = 0;
- ud_t disas;
- ud_init(&disas);
- // Setup the disassembly buffer
- ud_set_input_buffer(&disas, m_targetFunc, 20);
- ud_set_mode(&disas, 32);
- // Loop until there is enough memory for a jump
- while((required += ud_disassemble(&disas)) < m_jmpSize);
- // Return the amount
- return required;
- }
- int Detour::SetAddressProtection(void * addr, int protection)
- {
- // Constant holding the page size value
- const size_t pageSize = sysconf(_SC_PAGE_SIZE);
- // Calculate relative page offset
- size_t temp = (size_t) addr;
- temp -= temp % pageSize;
- // Update address
- addr = (void*) temp;
- // Update memory area protection
- return !mprotect(addr, pageSize, protection);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement