634 lines
31 KiB
C++
634 lines
31 KiB
C++
/**
|
|
* =============================================================================
|
|
* DynamicHooks
|
|
* Copyright (C) 2015 Robin Gohmert. All rights reserved.
|
|
* =============================================================================
|
|
*
|
|
* This software is provided 'as-is', without any express or implied warranty.
|
|
* In no event will the authors be held liable for any damages arising from
|
|
* the use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software in a
|
|
* product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
*
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
*
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
*
|
|
* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc
|
|
* -fPIC thunks correctly
|
|
*
|
|
* Idea and trampoline code taken from DynDetours (thanks your-name-here).
|
|
*/
|
|
|
|
// ============================================================================
|
|
// >> INCLUDES
|
|
// ============================================================================
|
|
#include "hook.h"
|
|
#include "utilities.h"
|
|
#include "asm.h"
|
|
|
|
|
|
using namespace asmjit;
|
|
using namespace asmjit::x86;
|
|
|
|
// ============================================================================
|
|
// >> DEFINITIONS
|
|
// ============================================================================
|
|
#define JMP_SIZE 6
|
|
|
|
|
|
// ============================================================================
|
|
// >> CHook
|
|
// ============================================================================
|
|
CHook::CHook(void* pFunc, ICallingConvention* pConvention)
|
|
{
|
|
m_pFunc = pFunc;
|
|
m_pRegisters = new CRegisters(pConvention->GetRegisters());
|
|
m_pCallingConvention = pConvention;
|
|
|
|
unsigned char* pTarget = (unsigned char *) pFunc;
|
|
|
|
// Determine the number of bytes we need to copy
|
|
int iBytesToCopy = copy_bytes(pTarget, NULL, JMP_SIZE);
|
|
|
|
// Create an array for the bytes to copy + a jump to the rest of the
|
|
// function.
|
|
unsigned char* pCopiedBytes = new unsigned char[iBytesToCopy + JMP_SIZE];
|
|
|
|
// Fill the array with NOP instructions
|
|
memset(pCopiedBytes, 0x90, iBytesToCopy + JMP_SIZE);
|
|
|
|
// Copy the required bytes to our array
|
|
SetMemPatchable(pCopiedBytes, iBytesToCopy + JMP_SIZE);
|
|
copy_bytes(pTarget, pCopiedBytes, JMP_SIZE);
|
|
|
|
// Write a jump after the copied bytes to the function/bridge + number of bytes to copy
|
|
WriteJMP(pCopiedBytes + iBytesToCopy, pTarget + iBytesToCopy);
|
|
|
|
// Save the trampoline
|
|
m_pTrampoline = (void *) pCopiedBytes;
|
|
|
|
// Create the bridge function
|
|
m_pBridge = CreateBridge();
|
|
|
|
// Write a jump to the bridge
|
|
WriteJMP((unsigned char *) pFunc, m_pBridge);
|
|
}
|
|
|
|
CHook::~CHook()
|
|
{
|
|
// Copy back the previously copied bytes
|
|
copy_bytes((unsigned char *) m_pTrampoline, (unsigned char *) m_pFunc, JMP_SIZE);
|
|
|
|
// Free the trampoline array
|
|
free(m_pTrampoline);
|
|
|
|
// Free the asm bridge and new return address
|
|
m_Runtime.release(m_pBridge);
|
|
m_Runtime.release(m_pNewRetAddr);
|
|
|
|
delete m_pRegisters;
|
|
delete m_pCallingConvention;
|
|
}
|
|
|
|
void CHook::AddCallback(HookType_t eHookType, HookHandlerFn* pCallback)
|
|
{
|
|
if (!pCallback)
|
|
return;
|
|
|
|
if (!IsCallbackRegistered(eHookType, pCallback))
|
|
m_hookHandler[eHookType].push_back(pCallback);
|
|
}
|
|
|
|
void CHook::RemoveCallback(HookType_t eHookType, HookHandlerFn* pCallback)
|
|
{
|
|
if (IsCallbackRegistered(eHookType, pCallback))
|
|
m_hookHandler[eHookType].remove(pCallback);
|
|
}
|
|
|
|
bool CHook::IsCallbackRegistered(HookType_t eHookType, HookHandlerFn* pCallback)
|
|
{
|
|
std::list<HookHandlerFn *> callbacks = m_hookHandler[eHookType];
|
|
for(std::list<HookHandlerFn *>::iterator it=callbacks.begin(); it != callbacks.end(); it++)
|
|
{
|
|
if (*it == pCallback)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CHook::AreCallbacksRegistered()
|
|
{
|
|
return !m_hookHandler[HOOKTYPE_PRE].empty() || !m_hookHandler[HOOKTYPE_POST].empty();
|
|
}
|
|
|
|
bool CHook::HookHandler(HookType_t eHookType)
|
|
{
|
|
bool bOverride = false;
|
|
std::list<HookHandlerFn *> callbacks = this->m_hookHandler[eHookType];
|
|
for(std::list<HookHandlerFn *>::iterator it=callbacks.begin(); it != callbacks.end(); it++)
|
|
{
|
|
bool result = ((HookHandlerFn) *it)(eHookType, this);
|
|
if (result)
|
|
bOverride = true;
|
|
}
|
|
return bOverride;
|
|
}
|
|
|
|
void* __cdecl CHook::GetReturnAddress(void* pESP)
|
|
{
|
|
if (m_RetAddr.count(pESP) == 0)
|
|
puts("ESP not present.");
|
|
|
|
return m_RetAddr[pESP];
|
|
}
|
|
|
|
void __cdecl CHook::SetReturnAddress(void* pRetAddr, void* pESP)
|
|
{
|
|
m_RetAddr[pESP] = pRetAddr;
|
|
}
|
|
|
|
void* CHook::CreateBridge()
|
|
{
|
|
X86Assembler a(&m_Runtime);
|
|
Label label_supercede = a.newLabel();
|
|
|
|
// Write a redirect to the post-hook code
|
|
Write_ModifyReturnAddress(a);
|
|
|
|
// Call the pre-hook handler and jump to label_supercede if true was returned
|
|
Write_CallHandler(a, HOOKTYPE_PRE);
|
|
a.cmp(eax.r8(), true);
|
|
|
|
// Restore the previously saved registers, so any changes will be applied
|
|
Write_RestoreRegisters(a);
|
|
|
|
a.je(label_supercede);
|
|
|
|
// Jump to the trampoline
|
|
a.jmp(Ptr(m_pTrampoline));
|
|
|
|
// This code will be executed if a pre-hook returns true
|
|
a.bind(label_supercede);
|
|
|
|
// Finally, return to the caller
|
|
// This will still call post hooks, but will skip the original function.
|
|
a.ret(imm(m_pCallingConvention->GetPopSize()));
|
|
|
|
return a.make();
|
|
}
|
|
|
|
void CHook::Write_ModifyReturnAddress(X86Assembler& a)
|
|
{
|
|
// Save scratch registers that are used by SetReturnAddress
|
|
static void* pEAX = NULL;
|
|
static void* pECX = NULL;
|
|
static void* pEDX = NULL;
|
|
a.mov(dword_ptr_abs(Ptr(&pEAX)), eax);
|
|
a.mov(dword_ptr_abs(Ptr(&pECX)), ecx);
|
|
a.mov(dword_ptr_abs(Ptr(&pEDX)), edx);
|
|
|
|
// Store the return address in eax
|
|
a.mov(eax, dword_ptr(esp));
|
|
|
|
// Save the original return address by using the current esp as the key.
|
|
// This should be unique until we have returned to the original caller.
|
|
void (__cdecl CHook::*SetReturnAddress)(void*, void*) = &CHook::SetReturnAddress;
|
|
a.push(esp);
|
|
a.push(eax);
|
|
a.push(imm_ptr(this));
|
|
a.call(imm_ptr((void *&)SetReturnAddress));
|
|
a.add(esp, 12);
|
|
|
|
// Restore scratch registers
|
|
a.mov(eax, dword_ptr_abs(Ptr(&pEAX)));
|
|
a.mov(ecx, dword_ptr_abs(Ptr(&pECX)));
|
|
a.mov(edx, dword_ptr_abs(Ptr(&pEDX)));
|
|
|
|
// Override the return address. This is a redirect to our post-hook code
|
|
m_pNewRetAddr = CreatePostCallback();
|
|
a.mov(dword_ptr(esp), imm_ptr(m_pNewRetAddr));
|
|
}
|
|
|
|
void* CHook::CreatePostCallback()
|
|
{
|
|
X86Assembler a(&m_Runtime);
|
|
|
|
int iPopSize = m_pCallingConvention->GetPopSize();
|
|
|
|
// Subtract the previously added bytes (stack size + return address), so
|
|
// that we can access the arguments again
|
|
a.sub(esp, imm(iPopSize+4));
|
|
|
|
// Call the post-hook handler
|
|
Write_CallHandler(a, HOOKTYPE_POST);
|
|
|
|
// Restore the previously saved registers, so any changes will be applied
|
|
Write_RestoreRegisters(a);
|
|
|
|
// Save scratch registers that are used by GetReturnAddress
|
|
static void* pEAX = NULL;
|
|
static void* pECX = NULL;
|
|
static void* pEDX = NULL;
|
|
a.mov(dword_ptr_abs(Ptr(&pEAX)), eax);
|
|
a.mov(dword_ptr_abs(Ptr(&pECX)), ecx);
|
|
a.mov(dword_ptr_abs(Ptr(&pEDX)), edx);
|
|
|
|
// Get the original return address
|
|
void* (__cdecl CHook::*GetReturnAddress)(void*) = &CHook::GetReturnAddress;
|
|
a.push(esp);
|
|
a.push(imm_ptr(this));
|
|
a.call(imm_ptr((void *&)GetReturnAddress));
|
|
a.add(esp, 8);
|
|
|
|
// Save the original return address
|
|
static void* pRetAddr = NULL;
|
|
a.mov(dword_ptr_abs(Ptr(&pRetAddr)), eax);
|
|
|
|
// Restore scratch registers
|
|
a.mov(eax, dword_ptr_abs(Ptr(&pEAX)));
|
|
a.mov(ecx, dword_ptr_abs(Ptr(&pECX)));
|
|
a.mov(edx, dword_ptr_abs(Ptr(&pEDX)));
|
|
|
|
// Add the bytes again to the stack (stack size + return address), so we
|
|
// don't corrupt the stack.
|
|
a.add(esp, imm(iPopSize+4));
|
|
|
|
// Jump to the original return address
|
|
a.jmp(dword_ptr_abs(Ptr(&pRetAddr)));
|
|
|
|
// Generate the code
|
|
return a.make();
|
|
}
|
|
|
|
void CHook::Write_CallHandler(X86Assembler& a, HookType_t type)
|
|
{
|
|
bool (__cdecl CHook::*HookHandler)(HookType_t) = &CHook::HookHandler;
|
|
|
|
// Save the registers so that we can access them in our handlers
|
|
Write_SaveRegisters(a);
|
|
|
|
// Call the global hook handler
|
|
a.push(type);
|
|
a.push(imm_ptr(this));
|
|
a.call(imm_ptr((void *&)HookHandler));
|
|
a.add(esp, 8);
|
|
}
|
|
|
|
void CHook::Write_SaveRegisters(X86Assembler& a)
|
|
{
|
|
std::list<Register_t> vecRegistersToSave = m_pCallingConvention->GetRegisters();
|
|
for(std::list<Register_t>::iterator it=vecRegistersToSave.begin(); it != vecRegistersToSave.end(); it++)
|
|
{
|
|
switch(*it)
|
|
{
|
|
// ========================================================================
|
|
// >> 8-bit General purpose registers
|
|
// ========================================================================
|
|
case AL: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_al->m_pAddress)), al); break;
|
|
case CL: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_cl->m_pAddress)), cl); break;
|
|
case DL: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_dl->m_pAddress)), dl); break;
|
|
case BL: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_bl->m_pAddress)), bl); break;
|
|
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case SPL: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_spl->m_pAddress)), spl); break;
|
|
case BPL: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_bpl->m_pAddress)), bpl); break;
|
|
case SIL: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_sil->m_pAddress)), sil); break;
|
|
case DIL: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_dil->m_pAddress)), dil); break;
|
|
case R8B: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_r8b->m_pAddress)), r8b); break;
|
|
case R9B: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_r9b->m_pAddress)), r9b); break;
|
|
case R10B: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_r10b->m_pAddress)), r10b); break;
|
|
case R11B: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_r11b->m_pAddress)), r11b); break;
|
|
case R12B: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_r12b->m_pAddress)), r12b); break;
|
|
case R13B: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_r13b->m_pAddress)), r13b); break;
|
|
case R14B: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_r14b->m_pAddress)), r14b); break;
|
|
case R15B: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_r15b->m_pAddress)), r15b); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
case AH: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_ah->m_pAddress)), ah); break;
|
|
case CH: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_ch->m_pAddress)), ch); break;
|
|
case DH: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_dh->m_pAddress)), dh); break;
|
|
case BH: a.mov(byte_ptr_abs(Ptr(m_pRegisters->m_bh->m_pAddress)), bh); break;
|
|
|
|
// ========================================================================
|
|
// >> 16-bit General purpose registers
|
|
// ========================================================================
|
|
case AX: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_ax->m_pAddress)), ax); break;
|
|
case CX: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_cx->m_pAddress)), cx); break;
|
|
case DX: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_dx->m_pAddress)), dx); break;
|
|
case BX: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_bx->m_pAddress)), bx); break;
|
|
case SP: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_sp->m_pAddress)), x86::sp); break;
|
|
case BP: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_bp->m_pAddress)), bp); break;
|
|
case SI: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_si->m_pAddress)), si); break;
|
|
case DI: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_di->m_pAddress)), di); break;
|
|
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case R8W: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_r8w->m_pAddress)), r8w); break;
|
|
case R9W: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_r9w->m_pAddress)), r9w); break;
|
|
case R10W: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_r10w->m_pAddress)), r10w); break;
|
|
case R11W: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_r11w->m_pAddress)), r11w); break;
|
|
case R12W: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_r12w->m_pAddress)), r12w); break;
|
|
case R13W: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_r13w->m_pAddress)), r13w); break;
|
|
case R14W: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_r14w->m_pAddress)), r14w); break;
|
|
case R15W: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_r15w->m_pAddress)), r15w); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
// ========================================================================
|
|
// >> 32-bit General purpose registers
|
|
// ========================================================================
|
|
case EAX: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_eax->m_pAddress)), eax); break;
|
|
case ECX: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_ecx->m_pAddress)), ecx); break;
|
|
case EDX: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_edx->m_pAddress)), edx); break;
|
|
case EBX: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_ebx->m_pAddress)), ebx); break;
|
|
case ESP: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_esp->m_pAddress)), esp); break;
|
|
case EBP: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_ebp->m_pAddress)), ebp); break;
|
|
case ESI: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_esi->m_pAddress)), esi); break;
|
|
case EDI: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_edi->m_pAddress)), edi); break;
|
|
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case R8D: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_r8d->m_pAddress)), r8d); break;
|
|
case R9D: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_r9d->m_pAddress)), r9d); break;
|
|
case R10D: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_r10d->m_pAddress)), r10d); break;
|
|
case R11D: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_r11d->m_pAddress)), r11d); break;
|
|
case R12D: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_r12d->m_pAddress)), r12d); break;
|
|
case R13D: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_r13d->m_pAddress)), r13d); break;
|
|
case R14D: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_r14d->m_pAddress)), r14d); break;
|
|
case R15D: a.mov(dword_ptr_abs(Ptr(m_pRegisters->m_r15d->m_pAddress)), r15d); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
// ========================================================================
|
|
// >> 64-bit General purpose registers
|
|
// ========================================================================
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case RAX: a.mov(qword_ptr_abs((m_pRegisters->m_rax->m_pAddress)), rax); break;
|
|
case RCX: a.mov(qword_ptr_abs((m_pRegisters->m_rcx->m_pAddress)), rcx); break;
|
|
case RDX: a.mov(qword_ptr_abs((m_pRegisters->m_rdx->m_pAddress)), rdx); break;
|
|
case RBX: a.mov(qword_ptr_abs((m_pRegisters->m_rbx->m_pAddress)), rbx); break;
|
|
case RSP: a.mov(qword_ptr_abs((m_pRegisters->m_rsp->m_pAddress)), rsp); break;
|
|
case RBP: a.mov(qword_ptr_abs((m_pRegisters->m_rbp->m_pAddress)), rbp); break;
|
|
case RSI: a.mov(qword_ptr_abs((m_pRegisters->m_rsi->m_pAddress)), rsi); break;
|
|
case RDI: a.mov(qword_ptr_abs((m_pRegisters->m_rdi->m_pAddress)), rdi); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case R8: a.mov(qword_ptr_abs(Ptr(m_pRegisters->m_r8->m_pAddress)), r8); break;
|
|
case R9: a.mov(qword_ptr_abs(Ptr(m_pRegisters->m_r9->m_pAddress)), r9); break;
|
|
case R10: a.mov(qword_ptr_abs(Ptr(m_pRegisters->m_r10->m_pAddress)), r10); break;
|
|
case R11: a.mov(qword_ptr_abs(Ptr(m_pRegisters->m_r11->m_pAddress)), r11); break;
|
|
case R12: a.mov(qword_ptr_abs(Ptr(m_pRegisters->m_r12->m_pAddress)), r12); break;
|
|
case R13: a.mov(qword_ptr_abs(Ptr(m_pRegisters->m_r13->m_pAddress)), r13); break;
|
|
case R14: a.mov(qword_ptr_abs(Ptr(m_pRegisters->m_r14->m_pAddress)), r14); break;
|
|
case R15: a.mov(qword_ptr_abs(Ptr(m_pRegisters->m_r15->m_pAddress)), r15); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
// ========================================================================
|
|
// >> 64-bit MM (MMX) registers
|
|
// ========================================================================
|
|
case MM0: a.movq(qword_ptr_abs(Ptr(m_pRegisters->m_mm0->m_pAddress)), mm0); break;
|
|
case MM1: a.movq(qword_ptr_abs(Ptr(m_pRegisters->m_mm1->m_pAddress)), mm1); break;
|
|
case MM2: a.movq(qword_ptr_abs(Ptr(m_pRegisters->m_mm2->m_pAddress)), mm2); break;
|
|
case MM3: a.movq(qword_ptr_abs(Ptr(m_pRegisters->m_mm3->m_pAddress)), mm3); break;
|
|
case MM4: a.movq(qword_ptr_abs(Ptr(m_pRegisters->m_mm4->m_pAddress)), mm4); break;
|
|
case MM5: a.movq(qword_ptr_abs(Ptr(m_pRegisters->m_mm5->m_pAddress)), mm5); break;
|
|
case MM6: a.movq(qword_ptr_abs(Ptr(m_pRegisters->m_mm6->m_pAddress)), mm6); break;
|
|
case MM7: a.movq(qword_ptr_abs(Ptr(m_pRegisters->m_mm7->m_pAddress)), mm7); break;
|
|
|
|
// ========================================================================
|
|
// >> 128-bit XMM registers
|
|
// ========================================================================
|
|
// TODO: Also provide movups?
|
|
case XMM0: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm0->m_pAddress)), xmm0); break;
|
|
case XMM1: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm1->m_pAddress)), xmm1); break;
|
|
case XMM2: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm2->m_pAddress)), xmm2); break;
|
|
case XMM3: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm3->m_pAddress)), xmm3); break;
|
|
case XMM4: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm4->m_pAddress)), xmm4); break;
|
|
case XMM5: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm5->m_pAddress)), xmm5); break;
|
|
case XMM6: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm6->m_pAddress)), xmm6); break;
|
|
case XMM7: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm7->m_pAddress)), xmm7); break;
|
|
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case XMM8: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm8->m_pAddress)), xmm8); break;
|
|
case XMM9: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm9->m_pAddress)), xmm9); break;
|
|
case XMM10: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm10->m_pAddress)), xmm10); break;
|
|
case XMM11: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm11->m_pAddress)), xmm11); break;
|
|
case XMM12: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm12->m_pAddress)), xmm12); break;
|
|
case XMM13: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm13->m_pAddress)), xmm13); break;
|
|
case XMM14: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm14->m_pAddress)), xmm14); break;
|
|
case XMM15: a.movaps(qword_ptr_abs(Ptr(m_pRegisters->m_xmm15->m_pAddress)), xmm15); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
// ========================================================================
|
|
// >> 16-bit Segment registers
|
|
// ========================================================================
|
|
case CS: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_cs->m_pAddress)), cs); break;
|
|
case SS: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_ss->m_pAddress)), ss); break;
|
|
case DS: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_ds->m_pAddress)), ds); break;
|
|
case ES: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_es->m_pAddress)), es); break;
|
|
case FS: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_fs->m_pAddress)), fs); break;
|
|
case GS: a.mov(word_ptr_abs(Ptr(m_pRegisters->m_gs->m_pAddress)), gs); break;
|
|
|
|
// ========================================================================
|
|
// >> 80-bit FPU registers
|
|
// ========================================================================
|
|
case ST0: a.fst(dword_ptr_abs(Ptr(m_pRegisters->m_st0->m_pAddress))); break;
|
|
//case ST1: a.mov(tword_ptr_abs(Ptr(m_pRegisters->m_st1->m_pAddress)), st1); break;
|
|
//case ST2: a.mov(tword_ptr_abs(Ptr(m_pRegisters->m_st2->m_pAddress)), st2); break;
|
|
//case ST3: a.mov(tword_ptr_abs(Ptr(m_pRegisters->m_st3->m_pAddress)), st3); break;
|
|
//case ST4: a.mov(tword_ptr_abs(Ptr(m_pRegisters->m_st4->m_pAddress)), st4); break;
|
|
//case ST5: a.mov(tword_ptr_abs(Ptr(m_pRegisters->m_st5->m_pAddress)), st5); break;
|
|
//case ST6: a.mov(tword_ptr_abs(Ptr(m_pRegisters->m_st6->m_pAddress)), st6); break;
|
|
//case ST7: a.mov(tword_ptr_abs(Ptr(m_pRegisters->m_st7->m_pAddress)), st7); break;
|
|
|
|
default: puts("Unsupported register.");
|
|
}
|
|
}
|
|
}
|
|
|
|
void CHook::Write_RestoreRegisters(X86Assembler& a)
|
|
{
|
|
std::list<Register_t> vecRegistersToSave = m_pCallingConvention->GetRegisters();
|
|
for(std::list<Register_t>::iterator it=vecRegistersToSave.begin(); it != vecRegistersToSave.end(); it++)
|
|
{
|
|
switch(*it)
|
|
{
|
|
// ========================================================================
|
|
// >> 8-bit General purpose registers
|
|
// ========================================================================
|
|
case AL: a.mov(al, byte_ptr_abs(Ptr(m_pRegisters->m_al->m_pAddress))); break;
|
|
case CL: a.mov(cl, byte_ptr_abs(Ptr(m_pRegisters->m_cl->m_pAddress))); break;
|
|
case DL: a.mov(dl, byte_ptr_abs(Ptr(m_pRegisters->m_dl->m_pAddress))); break;
|
|
case BL: a.mov(bl, byte_ptr_abs(Ptr(m_pRegisters->m_bl->m_pAddress))); break;
|
|
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case SPL: a.mov(spl, byte_ptr_abs(Ptr(m_pRegisters->m_spl->m_pAddress))); break;
|
|
case BPL: a.mov(bpl, byte_ptr_abs(Ptr(m_pRegisters->m_bpl->m_pAddress))); break;
|
|
case SIL: a.mov(sil, byte_ptr_abs(Ptr(m_pRegisters->m_sil->m_pAddress))); break;
|
|
case DIL: a.mov(dil, byte_ptr_abs(Ptr(m_pRegisters->m_dil->m_pAddress))); break;
|
|
case R8B: a.mov(r8b, byte_ptr_abs(Ptr(m_pRegisters->m_r8b->m_pAddress))); break;
|
|
case R9B: a.mov(r9b, byte_ptr_abs(Ptr(m_pRegisters->m_r9b->m_pAddress))); break;
|
|
case R10B: a.mov(r10b, byte_ptr_abs(Ptr(m_pRegisters->m_r10b->m_pAddress))); break;
|
|
case R11B: a.mov(r11b, byte_ptr_abs(Ptr(m_pRegisters->m_r11b->m_pAddress))); break;
|
|
case R12B: a.mov(r12b, byte_ptr_abs(Ptr(m_pRegisters->m_r12b->m_pAddress))); break;
|
|
case R13B: a.mov(r13b, byte_ptr_abs(Ptr(m_pRegisters->m_r13b->m_pAddress))); break;
|
|
case R14B: a.mov(r14b, byte_ptr_abs(Ptr(m_pRegisters->m_r14b->m_pAddress))); break;
|
|
case R15B: a.mov(r15b, byte_ptr_abs(Ptr(m_pRegisters->m_r15b->m_pAddress))); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
case AH: a.mov(ah, byte_ptr_abs(Ptr(m_pRegisters->m_ah->m_pAddress))); break;
|
|
case CH: a.mov(ch, byte_ptr_abs(Ptr(m_pRegisters->m_ch->m_pAddress))); break;
|
|
case DH: a.mov(dh, byte_ptr_abs(Ptr(m_pRegisters->m_dh->m_pAddress))); break;
|
|
case BH: a.mov(bh, byte_ptr_abs(Ptr(m_pRegisters->m_bh->m_pAddress))); break;
|
|
|
|
// ========================================================================
|
|
// >> 16-bit General purpose registers
|
|
// ========================================================================
|
|
case AX: a.mov(ax, word_ptr_abs(Ptr(m_pRegisters->m_ax->m_pAddress))); break;
|
|
case CX: a.mov(cx, word_ptr_abs(Ptr(m_pRegisters->m_cx->m_pAddress))); break;
|
|
case DX: a.mov(dx, word_ptr_abs(Ptr(m_pRegisters->m_dx->m_pAddress))); break;
|
|
case BX: a.mov(bx, word_ptr_abs(Ptr(m_pRegisters->m_bx->m_pAddress))); break;
|
|
case SP: a.mov(x86::sp, word_ptr_abs(Ptr(m_pRegisters->m_sp->m_pAddress))); break;
|
|
case BP: a.mov(bp, word_ptr_abs(Ptr(m_pRegisters->m_bp->m_pAddress))); break;
|
|
case SI: a.mov(si, word_ptr_abs(Ptr(m_pRegisters->m_si->m_pAddress))); break;
|
|
case DI: a.mov(di, word_ptr_abs(Ptr(m_pRegisters->m_di->m_pAddress))); break;
|
|
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case R8W: a.mov(r8w, word_ptr_abs(Ptr(m_pRegisters->m_r8w->m_pAddress))); break;
|
|
case R9W: a.mov(r9w, word_ptr_abs(Ptr(m_pRegisters->m_r9w->m_pAddress))); break;
|
|
case R10W: a.mov(r10w, word_ptr_abs(Ptr(m_pRegisters->m_r10w->m_pAddress))); break;
|
|
case R11W: a.mov(r11w, word_ptr_abs(Ptr(m_pRegisters->m_r11w->m_pAddress))); break;
|
|
case R12W: a.mov(r12w, word_ptr_abs(Ptr(m_pRegisters->m_r12w->m_pAddress))); break;
|
|
case R13W: a.mov(r13w, word_ptr_abs(Ptr(m_pRegisters->m_r13w->m_pAddress))); break;
|
|
case R14W: a.mov(r14w, word_ptr_abs(Ptr(m_pRegisters->m_r14w->m_pAddress))); break;
|
|
case R15W: a.mov(r15w, word_ptr_abs(Ptr(m_pRegisters->m_r15w->m_pAddress))); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
// ========================================================================
|
|
// >> 32-bit General purpose registers
|
|
// ========================================================================
|
|
case EAX: a.mov(eax, dword_ptr_abs(Ptr(m_pRegisters->m_eax->m_pAddress))); break;
|
|
case ECX: a.mov(ecx, dword_ptr_abs(Ptr(m_pRegisters->m_ecx->m_pAddress))); break;
|
|
case EDX: a.mov(edx, dword_ptr_abs(Ptr(m_pRegisters->m_edx->m_pAddress))); break;
|
|
case EBX: a.mov(ebx, dword_ptr_abs(Ptr(m_pRegisters->m_ebx->m_pAddress))); break;
|
|
case ESP: a.mov(esp, dword_ptr_abs(Ptr(m_pRegisters->m_esp->m_pAddress))); break;
|
|
case EBP: a.mov(ebp, dword_ptr_abs(Ptr(m_pRegisters->m_ebp->m_pAddress))); break;
|
|
case ESI: a.mov(esi, dword_ptr_abs(Ptr(m_pRegisters->m_esi->m_pAddress))); break;
|
|
case EDI: a.mov(edi, dword_ptr_abs(Ptr(m_pRegisters->m_edi->m_pAddress))); break;
|
|
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case R8D: a.mov(r8d, qword_ptr_abs(Ptr(m_pRegisters->m_r8d->m_pAddress))); break;
|
|
case R9D: a.mov(r9d, qword_ptr_abs(Ptr(m_pRegisters->m_r9d->m_pAddress))); break;
|
|
case R10D: a.mov(r10d, qword_ptr_abs(Ptr(m_pRegisters->m_r10d->m_pAddress))); break;
|
|
case R11D: a.mov(r11d, qword_ptr_abs(Ptr(m_pRegisters->m_r11d->m_pAddress))); break;
|
|
case R12D: a.mov(r12d, qword_ptr_abs(Ptr(m_pRegisters->m_r12d->m_pAddress))); break;
|
|
case R13D: a.mov(r13d, qword_ptr_abs(Ptr(m_pRegisters->m_r13d->m_pAddress))); break;
|
|
case R14D: a.mov(r14d, qword_ptr_abs(Ptr(m_pRegisters->m_r14d->m_pAddress))); break;
|
|
case R15D: a.mov(r15d, qword_ptr_abs(Ptr(m_pRegisters->m_r15d->m_pAddress))); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
// ========================================================================
|
|
// >> 64-bit General purpose registers
|
|
// ========================================================================
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case RAX: a.mov(rax, qword_ptr_abs(Ptr(m_pRegisters->m_rax->m_pAddress))); break;
|
|
case RCX: a.mov(rcx, qword_ptr_abs(Ptr(m_pRegisters->m_rcx->m_pAddress))); break;
|
|
case RDX: a.mov(rdx, qword_ptr_abs(Ptr(m_pRegisters->m_rdx->m_pAddress))); break;
|
|
case RBX: a.mov(rbx, qword_ptr_abs(Ptr(m_pRegisters->m_rbx->m_pAddress))); break;
|
|
case RSP: a.mov(rsp, qword_ptr_abs(Ptr(m_pRegisters->m_rsp->m_pAddress))); break;
|
|
case RBP: a.mov(rbp, qword_ptr_abs(Ptr(m_pRegisters->m_rbp->m_pAddress))); break;
|
|
case RSI: a.mov(rsi, qword_ptr_abs(Ptr(m_pRegisters->m_rsi->m_pAddress))); break;
|
|
case RDI: a.mov(rdi, qword_ptr_abs(Ptr(m_pRegisters->m_rdi->m_pAddress))); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case R8: a.mov(r8, qword_ptr_abs(Ptr(m_pRegisters->m_r8->m_pAddress))); break;
|
|
case R9: a.mov(r9, qword_ptr_abs(Ptr(m_pRegisters->m_r9->m_pAddress))); break;
|
|
case R10: a.mov(r10, qword_ptr_abs(Ptr(m_pRegisters->m_r10->m_pAddress))); break;
|
|
case R11: a.mov(r11, qword_ptr_abs(Ptr(m_pRegisters->m_r11->m_pAddress))); break;
|
|
case R12: a.mov(r12, qword_ptr_abs(Ptr(m_pRegisters->m_r12->m_pAddress))); break;
|
|
case R13: a.mov(r13, qword_ptr_abs(Ptr(m_pRegisters->m_r13->m_pAddress))); break;
|
|
case R14: a.mov(r14, qword_ptr_abs(Ptr(m_pRegisters->m_r14->m_pAddress))); break;
|
|
case R15: a.mov(r15, qword_ptr_abs(Ptr(m_pRegisters->m_r15->m_pAddress))); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
// ========================================================================
|
|
// >> 64-bit MM (MMX) registers
|
|
// ========================================================================
|
|
case MM0: a.movq(mm0, qword_ptr_abs(Ptr(m_pRegisters->m_mm0->m_pAddress))); break;
|
|
case MM1: a.movq(mm1, qword_ptr_abs(Ptr(m_pRegisters->m_mm1->m_pAddress))); break;
|
|
case MM2: a.movq(mm2, qword_ptr_abs(Ptr(m_pRegisters->m_mm2->m_pAddress))); break;
|
|
case MM3: a.movq(mm3, qword_ptr_abs(Ptr(m_pRegisters->m_mm3->m_pAddress))); break;
|
|
case MM4: a.movq(mm4, qword_ptr_abs(Ptr(m_pRegisters->m_mm4->m_pAddress))); break;
|
|
case MM5: a.movq(mm5, qword_ptr_abs(Ptr(m_pRegisters->m_mm5->m_pAddress))); break;
|
|
case MM6: a.movq(mm6, qword_ptr_abs(Ptr(m_pRegisters->m_mm6->m_pAddress))); break;
|
|
case MM7: a.movq(mm7, qword_ptr_abs(Ptr(m_pRegisters->m_mm7->m_pAddress))); break;
|
|
|
|
// ========================================================================
|
|
// >> 128-bit XMM registers
|
|
// ========================================================================
|
|
// TODO: Also provide movups?
|
|
case XMM0: a.movaps(xmm0, oword_ptr_abs(Ptr(m_pRegisters->m_xmm0->m_pAddress))); break;
|
|
case XMM1: a.movaps(xmm1, oword_ptr_abs(Ptr(m_pRegisters->m_xmm1->m_pAddress))); break;
|
|
case XMM2: a.movaps(xmm2, oword_ptr_abs(Ptr(m_pRegisters->m_xmm2->m_pAddress))); break;
|
|
case XMM3: a.movaps(xmm3, oword_ptr_abs(Ptr(m_pRegisters->m_xmm3->m_pAddress))); break;
|
|
case XMM4: a.movaps(xmm4, oword_ptr_abs(Ptr(m_pRegisters->m_xmm4->m_pAddress))); break;
|
|
case XMM5: a.movaps(xmm5, oword_ptr_abs(Ptr(m_pRegisters->m_xmm5->m_pAddress))); break;
|
|
case XMM6: a.movaps(xmm6, oword_ptr_abs(Ptr(m_pRegisters->m_xmm6->m_pAddress))); break;
|
|
case XMM7: a.movaps(xmm7, oword_ptr_abs(Ptr(m_pRegisters->m_xmm7->m_pAddress))); break;
|
|
|
|
#if defined(ASMJIT_X64)
|
|
// 64-bit mode only
|
|
case XMM8: a.movaps(xmm8, qword_ptr_abs(Ptr(m_pRegisters->m_xmm8->m_pAddress))); break;
|
|
case XMM9: a.movaps(xmm9, qword_ptr_abs(Ptr(m_pRegisters->m_xmm9->m_pAddress))); break;
|
|
case XMM10: a.movaps(xmm10, qword_ptr_abs(Ptr(m_pRegisters->m_xmm10->m_pAddress))); break;
|
|
case XMM11: a.movaps(xmm11, qword_ptr_abs(Ptr(m_pRegisters->m_xmm11->m_pAddress))); break;
|
|
case XMM12: a.movaps(xmm12, qword_ptr_abs(Ptr(m_pRegisters->m_xmm12->m_pAddress))); break;
|
|
case XMM13: a.movaps(xmm13, qword_ptr_abs(Ptr(m_pRegisters->m_xmm13->m_pAddress))); break;
|
|
case XMM14: a.movaps(xmm14, qword_ptr_abs(Ptr(m_pRegisters->m_xmm14->m_pAddress))); break;
|
|
case XMM15: a.movaps(xmm15, qword_ptr_abs(Ptr(m_pRegisters->m_xmm15->m_pAddress))); break;
|
|
#endif // ASMJIT_X64
|
|
|
|
// ========================================================================
|
|
// >> 16-bit Segment registers
|
|
// ========================================================================
|
|
case CS: a.mov(cs, word_ptr_abs(Ptr(m_pRegisters->m_cs->m_pAddress))); break;
|
|
case SS: a.mov(ss, word_ptr_abs(Ptr(m_pRegisters->m_ss->m_pAddress))); break;
|
|
case DS: a.mov(ds, word_ptr_abs(Ptr(m_pRegisters->m_ds->m_pAddress))); break;
|
|
case ES: a.mov(es, word_ptr_abs(Ptr(m_pRegisters->m_es->m_pAddress))); break;
|
|
case FS: a.mov(fs, word_ptr_abs(Ptr(m_pRegisters->m_fs->m_pAddress))); break;
|
|
case GS: a.mov(gs, word_ptr_abs(Ptr(m_pRegisters->m_gs->m_pAddress))); break;
|
|
|
|
// ========================================================================
|
|
// >> 80-bit FPU registers
|
|
// ========================================================================
|
|
case ST0: a.fld(dword_ptr_abs(Ptr(m_pRegisters->m_st0->m_pAddress))); break;
|
|
//case ST1: a.mov(st1, tword_ptr_abs(Ptr(m_pRegisters->m_st1->m_pAddress))); break;
|
|
//case ST2: a.mov(st2, tword_ptr_abs(Ptr(m_pRegisters->m_st2->m_pAddress))); break;
|
|
//case ST3: a.mov(st3, tword_ptr_abs(Ptr(m_pRegisters->m_st3->m_pAddress))); break;
|
|
//case ST4: a.mov(st4, tword_ptr_abs(Ptr(m_pRegisters->m_st4->m_pAddress))); break;
|
|
//case ST5: a.mov(st5, tword_ptr_abs(Ptr(m_pRegisters->m_st5->m_pAddress))); break;
|
|
//case ST6: a.mov(st6, tword_ptr_abs(Ptr(m_pRegisters->m_st6->m_pAddress))); break;
|
|
//case ST7: a.mov(st7, tword_ptr_abs(Ptr(m_pRegisters->m_st7->m_pAddress))); break;
|
|
|
|
default: puts("Unsupported register.");
|
|
}
|
|
}
|
|
} |