Skip to content

Add default convention to CallingConvention. #344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3d0d875
Added default convention to ICallingConvention.
CookStar Aug 5, 2020
fb87d77
Changed constructor to create the default convention from MakeDynamic…
CookStar Aug 14, 2020
f2c403c
Removed "ICallingConventionWrapper *" from the held type.
CookStar Aug 15, 2020
025a421
Fixed removal of setting null.
CookStar Aug 15, 2020
dd295d3
Changed m_pCallingConvention to m_pDefaultCallingConvention.
CookStar Aug 15, 2020
f39a6c4
Simplified CFunction destructor.
CookStar Aug 16, 2020
adbc65a
Fixed a crash introduced by removing "ICallingConventionWrapper *".
CookStar Aug 16, 2020
f3aa765
Removed the convention headers.
CookStar Aug 17, 2020
854d96f
Fixed a crash on unloading Source.Python.
CookStar Aug 24, 2020
f275acc
Fix for VC++ 2010.
CookStar Aug 25, 2020
c47ca12
Fix2 for VC++ 2010.
CookStar Aug 25, 2020
1ae3f1d
Merge branch 'master' into add_default_callingconvention
CookStar Aug 29, 2020
0062175
Added an overload for C-type functions to CFunction::AddHook.
CookStar Sep 1, 2020
3c4935b
Resolved conflicts.
CookStar Sep 29, 2020
8aab63b
Fixed CallingConvention's leaks/issues.
jordanbriere Oct 2, 2020
6b68369
Minor fixes.
jordanbriere Oct 2, 2020
118070b
Merge pull request #2 from jordanbriere/add_default_callingconvention
CookStar Oct 3, 2020
b4cb2c0
Modified CFunction to initialize CallingConvention with default_conve…
CookStar Oct 5, 2020
121a496
Added custom_convention(m_oCallingConvention) attribute to Function.
CookStar Oct 5, 2020
282bf03
Added post-construction initialization support.
jordanbriere Oct 5, 2020
6d26bca
Fixed built-in conventions leaking when they are being unhooked while…
jordanbriere Oct 5, 2020
98d9853
Replaced the post-construction wrapper with stackable policies.
jordanbriere Oct 6, 2020
958cb03
Merge pull request #3 from jordanbriere/add_default_callingconvention
CookStar Oct 6, 2020
f651f57
Fixed namespace issue.
CookStar Oct 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions src/core/modules/memory/memory_function.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "memory_function.h"
#include "memory_utilities.h"
#include "memory_hooks.h"
#include "memory_wrap.h"

// DynamicHooks
#include "conventions/x86MsCdecl.h"
Expand Down Expand Up @@ -87,7 +88,7 @@ int GetDynCallConvention(Convention_t eConv)
// ============================================================================
// >> MakeDynamicHooksConvention
// ============================================================================
ICallingConvention* MakeDynamicHooksConvention(Convention_t eConv, std::vector<DataType_t> vecArgTypes, DataType_t returnType, int iAlignment=4)
ICallingConvention* MakeDynamicHooksConvention(Convention_t eConv, std::vector<DataType_t> vecArgTypes, DataType_t returnType, int iAlignment)
{
#ifdef _WIN32
switch (eConv)
Expand Down Expand Up @@ -149,17 +150,17 @@ CFunction::CFunction(unsigned long ulAddr, object oCallingConvention, object oAr
catch( ... )
{
PyErr_Clear();

// A custom calling convention will be used...
m_eCallingConvention = CONV_CUSTOM;
object _oCallingConvention = oCallingConvention(m_tArgs, m_eReturnType);
m_oCallingConvention = oCallingConvention(m_tArgs, m_eReturnType);

// FIXME:
// This is required to fix a crash, but it will also cause a memory leak,
// because no calling convention object that is created via this method will ever be deleted.
// TODO: Pretty sure this was required due to the missing held type definition. It was added, but wasn't tested yet.
Py_INCREF(_oCallingConvention.ptr());
m_pCallingConvention = extract<ICallingConvention*>(_oCallingConvention);
Py_INCREF(m_oCallingConvention.ptr());
m_pCallingConvention = extract<ICallingConvention*>(m_oCallingConvention);

// We didn't allocate the calling convention, someone else is responsible for it.
m_bAllocatedCallingConvention = false;
Expand Down Expand Up @@ -188,6 +189,20 @@ CFunction::CFunction(unsigned long ulAddr, Convention_t eCallingConvention,

CFunction::~CFunction()
{
// If we created custom calling convention, clean it up.
// This does not apply to hooked calling convention.
if (!m_oCallingConvention.is_none())
{
CHook* pHook = GetHookManager()->FindHook((void *) m_ulAddr);
if (!pHook || pHook->m_pCallingConvention != m_pCallingConvention)
{
Py_DECREF(m_oCallingConvention.ptr());
m_pCallingConvention = NULL;
}

return;
}

// If we didn't allocate the calling convention, then it is not our responsibility.
if (!m_bAllocatedCallingConvention)
return;
Expand Down
8 changes: 8 additions & 0 deletions src/core/modules/memory/memory_function.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,15 @@ class CFunction: public CPointer, private boost::noncopyable
// DynamicHooks calling convention (built-in and custom)
ICallingConvention* m_pCallingConvention;
bool m_bAllocatedCallingConvention;

// Custom calling convention
object m_oCallingConvention = object();
};


//---------------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------------
ICallingConvention* MakeDynamicHooksConvention(Convention_t eConv, std::vector<DataType_t> vecArgTypes, DataType_t returnType, int iAlignment=4);

#endif // _MEMORY_FUNCTION_H
21 changes: 12 additions & 9 deletions src/core/modules/memory/memory_wrap.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -820,18 +820,19 @@ void export_registers(scope _memory)
// ============================================================================
void export_calling_convention(scope _memory)
{
class_<ICallingConventionWrapper, ICallingConventionWrapper *, boost::noncopyable>(
class_<ICallingConventionWrapper, boost::noncopyable>(
"CallingConvention",
"An an abstract class that is used to create custom calling "
"conventions (only available for hooking function and not for"
" calling functions).\n",
init< object, DataType_t, optional<int> >(
(arg("arg_types"), arg("return_type"), arg("alignment")),
init< object, DataType_t, optional<int, Convention_t> >(
(arg("arg_types"), arg("return_type"), arg("alignment")=4, arg("default_convention")=CONV_CUSTOM),
"Initialize the calling convention.\n"
"\n"
":param iterable arg_types: A list of :class:`DataType` values that define the argument types of a function.\n"
":param DataType return_type: The return type of a function.\n"
":param int alignment: The stack alignment."
":param int alignment: The stack alignment.\n"
":param Convention_t default_convention: The default convention for un override function."
)
)

Expand All @@ -844,14 +845,15 @@ void export_calling_convention(scope _memory)
&ICallingConventionWrapper::GetPopSize,
"Return the number of bytes that should be added to the stack to clean up."
)

.def("get_argument_ptr",
&ICallingConventionWrapper::GetArgumentPtrWrapper,
&ICallingConventionWrapper::GetArgumentPtr,
(arg("index"), arg("registers")),
"Return a pointer to the argument at the given index.\n"
"\n"
":param int index: The index of the argument.\n"
":param Registers registers: A snapshot of all saved registers."
":param Registers registers: A snapshot of all saved registers.",
return_by_value_policy()
)

.def("argument_ptr_changed",
Expand All @@ -865,11 +867,12 @@ void export_calling_convention(scope _memory)
)

.def("get_return_ptr",
&ICallingConventionWrapper::GetReturnPtrWrapper,
&ICallingConventionWrapper::GetReturnPtr,
(arg("registers")),
"Return a pointer to the return value.\n"
"\n"
":param Registers registers: A snapshot of all saved registers."
":param Registers registers: A snapshot of all saved registers.",
return_by_value_policy()
)

.def("return_ptr_changed",
Expand Down
70 changes: 53 additions & 17 deletions src/core/modules/memory/memory_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@
// ============================================================================
// DynamicHooks
#include "convention.h"
#include "conventions/x86MsCdecl.h"
#include "conventions/x86MsThiscall.h"
#include "conventions/x86MsStdcall.h"
#include "conventions/x86GccCdecl.h"
#include "conventions/x86GccThiscall.h"

// Memory
#include "memory_function.h"

// Utilities
#include "memory_utilities.h"
Expand All @@ -48,14 +56,26 @@ using namespace boost::python;
class ICallingConventionWrapper: public ICallingConvention, public wrapper<ICallingConvention>
{
public:
ICallingConventionWrapper(object oArgTypes, DataType_t returnType, int iAlignment=4)
ICallingConventionWrapper(object oArgTypes, DataType_t returnType, int iAlignment=4, Convention_t eDefaultConv=CONV_CUSTOM)
:ICallingConvention(ObjectToDataTypeVector(oArgTypes), returnType, iAlignment)
{
if (eDefaultConv != CONV_CUSTOM) {
m_pDefaultCallingConvention = MakeDynamicHooksConvention(eDefaultConv, m_vecArgTypes, m_returnType, m_iAlignment);
}
}

~ICallingConventionWrapper()
{
delete m_pDefaultCallingConvention;
m_pDefaultCallingConvention = nullptr;
}

virtual std::list<Register_t> GetRegisters()
{
override get_registers = get_override("get_registers");
if (!get_registers && m_pDefaultCallingConvention) {
return m_pDefaultCallingConvention->GetRegisters();
}
CHECK_OVERRIDE(get_registers);

object registers = get_registers();
Expand All @@ -71,47 +91,60 @@ class ICallingConventionWrapper: public ICallingConvention, public wrapper<ICall
virtual int GetPopSize()
{
override get_pop_size = get_override("get_pop_size");
if (!get_pop_size && m_pDefaultCallingConvention) {
return m_pDefaultCallingConvention->GetPopSize();
}
CHECK_OVERRIDE(get_pop_size);

return get_pop_size();
}

virtual void* GetArgumentPtr(int iIndex, CRegisters* pRegisters)
{
CPointer* ptr = extract<CPointer*>(GetArgumentPtrWrapper(iIndex, pRegisters));
return (void *) ptr->m_ulAddr;
}

object GetArgumentPtrWrapper(int iIndex, CRegisters* pRegisters)
virtual void* GetArgumentPtr(int iIndex, CRegisters* pRegisters)
{
override get_argument_ptr = get_override("get_argument_ptr");
if (!get_argument_ptr && m_pDefaultCallingConvention) {
return m_pDefaultCallingConvention->GetArgumentPtr(iIndex, pRegisters);
}
CHECK_OVERRIDE(get_argument_ptr);
return get_argument_ptr(iIndex, ptr(pRegisters));

object argument_ptr = get_argument_ptr(iIndex, ptr(pRegisters));
CPointer* _ptr = extract<CPointer*>(argument_ptr);
return (void *) _ptr->m_ulAddr;
}

virtual void ArgumentPtrChanged(int iIndex, CRegisters* pRegisters, void* pArgumentPtr)
{
override argument_ptr_changed = get_override("argument_ptr_changed");
if (!argument_ptr_changed && m_pDefaultCallingConvention) {
m_pDefaultCallingConvention->ArgumentPtrChanged(iIndex, pRegisters, pArgumentPtr);
return;
}
CHECK_OVERRIDE(argument_ptr_changed);
argument_ptr_changed(iIndex, ptr(pRegisters), CPointer((unsigned long) pArgumentPtr));
}

virtual void* GetReturnPtr(CRegisters* pRegisters)
{
CPointer* ptr = extract<CPointer*>(GetReturnPtrWrapper(pRegisters));
return (void *) ptr->m_ulAddr;
}

object GetReturnPtrWrapper(CRegisters* pRegisters)
{
override get_return_ptr = get_override("get_return_ptr");
CHECK_OVERRIDE(get_return_ptr);
return get_return_ptr(ptr(pRegisters));
if (!get_return_ptr && m_pDefaultCallingConvention) {
return m_pDefaultCallingConvention->GetReturnPtr(pRegisters);
}
CHECK_OVERRIDE(get_return_ptr)

object return_ptr = get_return_ptr(ptr(pRegisters));
CPointer* _ptr = extract<CPointer*>(return_ptr);
return (void *) _ptr->m_ulAddr;
}

virtual void ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr)
{
override return_ptr_changed = get_override("return_ptr_changed");
if (!return_ptr_changed && m_pDefaultCallingConvention) {
m_pDefaultCallingConvention->ReturnPtrChanged(pRegisters, pReturnPtr);
return;
}
CHECK_OVERRIDE(return_ptr_changed);

return_ptr_changed(ptr(pRegisters), CPointer((unsigned long) pReturnPtr));
}

Expand All @@ -125,6 +158,9 @@ class ICallingConventionWrapper: public ICallingConvention, public wrapper<ICall

return tuple(argumentTypes);
}

public:
ICallingConvention* m_pDefaultCallingConvention = nullptr;
};


Expand Down