Save this pointer on windows after calling original function

ecx might get cleared before the original function returns leading to garbage in the post handler.
This commit is contained in:
Peace-Maker 2016-12-13 17:47:59 -07:00
parent b18e3284e1
commit 8221a6522b
4 changed files with 23 additions and 0 deletions

View File

@ -225,6 +225,9 @@ public:
ReturnPtrChanged(pRegisters, m_pSavedReturnBuffer); ReturnPtrChanged(pRegisters, m_pSavedReturnBuffer);
} }
virtual void SavePostCallRegisters(CRegisters* pRegisters) {}
virtual void RestorePostCallRegisters(CRegisters* pRegisters) {}
public: public:
ke::Vector<DataTypeSized_t> m_vecArgTypes; ke::Vector<DataTypeSized_t> m_vecArgTypes;
DataTypeSized_t m_returnType; DataTypeSized_t m_returnType;

View File

@ -49,6 +49,7 @@ x86MsThiscall::x86MsThiscall(ke::Vector<DataTypeSized_t> &vecArgTypes, DataTypeS
{ {
m_pReturnBuffer = NULL; m_pReturnBuffer = NULL;
} }
m_pSavedThisPointer = malloc(sizeof(size_t));
} }
x86MsThiscall::~x86MsThiscall() x86MsThiscall::~x86MsThiscall()
@ -57,6 +58,7 @@ x86MsThiscall::~x86MsThiscall()
{ {
free(m_pReturnBuffer); free(m_pReturnBuffer);
} }
free(m_pSavedThisPointer);
} }
ke::Vector<Register_t> x86MsThiscall::GetRegisters() ke::Vector<Register_t> x86MsThiscall::GetRegisters()
@ -159,3 +161,13 @@ void x86MsThiscall::ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr)
memcpy(pRegisters->m_edx, (void *) ((unsigned long) m_pReturnBuffer + 4), 4); memcpy(pRegisters->m_edx, (void *) ((unsigned long) m_pReturnBuffer + 4), 4);
} }
} }
void x86MsThiscall::SavePostCallRegisters(CRegisters* pRegisters)
{
memcpy(m_pSavedThisPointer, GetArgumentPtr(0, pRegisters), sizeof(size_t));
}
void x86MsThiscall::RestorePostCallRegisters(CRegisters* pRegisters)
{
memcpy(GetArgumentPtr(0, pRegisters), m_pSavedThisPointer, sizeof(size_t));
}

View File

@ -78,8 +78,12 @@ public:
virtual void* GetReturnPtr(CRegisters* pRegisters); virtual void* GetReturnPtr(CRegisters* pRegisters);
virtual void ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr); virtual void ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr);
virtual void SavePostCallRegisters(CRegisters* pRegisters);
virtual void RestorePostCallRegisters(CRegisters* pRegisters);
private: private:
void* m_pReturnBuffer; void* m_pReturnBuffer;
void* m_pSavedThisPointer;
}; };
#endif // _X86_MS_THISCALL_H #endif // _X86_MS_THISCALL_H

View File

@ -157,6 +157,8 @@ ReturnAction_t CHook::HookHandler(HookType_t eHookType)
{ {
if (m_LastPreReturnAction == ReturnAction_Override) if (m_LastPreReturnAction == ReturnAction_Override)
m_pCallingConvention->RestoreReturnValue(m_pRegisters); m_pCallingConvention->RestoreReturnValue(m_pRegisters);
if (m_LastPreReturnAction < ReturnAction_Supercede)
m_pCallingConvention->RestorePostCallRegisters(m_pRegisters);
} }
ReturnAction_t returnAction = ReturnAction_Ignored; ReturnAction_t returnAction = ReturnAction_Ignored;
@ -177,6 +179,8 @@ ReturnAction_t CHook::HookHandler(HookType_t eHookType)
m_LastPreReturnAction = returnAction; m_LastPreReturnAction = returnAction;
if (returnAction == ReturnAction_Override) if (returnAction == ReturnAction_Override)
m_pCallingConvention->SaveReturnValue(m_pRegisters); m_pCallingConvention->SaveReturnValue(m_pRegisters);
if (returnAction < ReturnAction_Supercede)
m_pCallingConvention->SavePostCallRegisters(m_pRegisters);
} }
return returnAction; return returnAction;