Page 1 of 1
c++ bespoke virtual table lookup, call functions. How?
Posted: Tue Jun 30, 2015 4:27 am
by tsdnz
Hi, I am about to add custom gcc compiled code into my OS.
This code is compiled without any knowledge of the OS, except for the lookup table pointer at 0x7100
Virtual table of functions start at 0x7100
When the OS is ready it will set these addresses up and call the newly compiled code.
eg. 0x7100 points to Return44, a static function with no parameters and returns a QWORD
Here is the SystemFunction class, this resides with in the OS
Code: Select all
class tSystemFunction
{
public:
FIL void Init();
static QWORD Return44() { return 0x1234567890ABCDEF; }
};
This code resides in the user space code.
Code: Select all
namespace SystemFunction
{
FIL QWORD __ptr(DWORD Index) { return (QWORD)(0x7100 + (Index * sizeof(void*))); }
FIL QWORD Return44()
{
typedef QWORD(Kernel::tSystemFunction::*tReturn44)();
tReturn44 vReturn44;
*(QWORD*)&vReturn44 = __ptr(0);
return vReturn44();
}
};
I am unsure how to get the above code to work correctly, some guidance would be appreciated.
Thanks, Alistair
Re: c++ bespoke virtual table lookup, call functions. How?
Posted: Tue Jun 30, 2015 5:03 am
by tsdnz
Solved.
Server code
Code: Select all
class tSystemFunction
{
public:
static FIL void Init();
static QWORD Return44() { return 0x1234567890ABCDEF; }
};
FIL void tSystemFunction::Init()
{
*(QWORD*)0x7100 = reinterpret_cast<QWORD>(Return44);
}
User Code
Code: Select all
namespace SystemFunction
{
FIL QWORD __ptr__(DWORD Index) { return *(QWORD*)(0x7100 + (Index * sizeof(void*))); }
FIL QWORD Return44()
{
typedef QWORD(*tReturn44)();
return reinterpret_cast<tReturn44>(__ptr__(0))();
}
};
Re: c++ bespoke virtual table lookup, call functions. How?
Posted: Tue Jun 30, 2015 12:50 pm
by Candy
You could just make actual vtables and let the C++ runtime figure it out? It's a documented and mostly portable ABI.
Code: Select all
#include <stdlib.h>
struct C {
virtual int x() = 0;
};
int func(void*) {
return 42;
}
struct X {
int (**funcs)(void*);
};
int main() {
X* x = (X*)malloc(sizeof(X));
x->funcs = (int(**)(void*))malloc(sizeof(int(*)(void*)));
x->funcs[0] = &func;
C* c = reinterpret_cast<C*>(x);
return c->x();
}
Re: c++ bespoke virtual table lookup, call functions. How?
Posted: Tue Jun 30, 2015 1:32 pm
by tsdnz
Thanks, not sure your example will work for me.
The functions have different parameters.
The functions must reside at a known address so the User Code when run knows where to find the function.
Here is the finished example, just has one function for now.
OS Code:Code: Select all
class tSystemFunction
{
private:
static FIL QWORD* SetAt(DWORD Index) { return (QWORD*)(0x7100 + (Index * sizeof(void*))); }
public:
static FIL void Init();
static QWORD SystemFunctionSanityCheck(QWORD XOR) { return ((QWORD)0xFEDCBA0987654321) ^ XOR; }
};
FIL void tSystemFunction::Init()
{
*SetAt(0) = reinterpret_cast<QWORD>(SystemFunctionSanityCheck);
}
Client Code:Code: Select all
namespace SystemFunction
{
FIL QWORD __ptr__(DWORD Index) { return *(QWORD*)(0x7100 + (Index * sizeof(void*))); }
FIL QWORD SystemFunctionSanityCheck(QWORD XOR) { return reinterpret_cast<QWORD(*)(QWORD XOR)>(__ptr__(0))(XOR); }
};
Candy wrote:You could just make actual vtables and let the C++ runtime figure it out? It's a documented and mostly portable ABI.
Code: Select all
#include <stdlib.h>
struct C {
virtual int x() = 0;
};
int func(void*) {
return 42;
}
struct X {
int (**funcs)(void*);
};
int main() {
X* x = (X*)malloc(sizeof(X));
x->funcs = (int(**)(void*))malloc(sizeof(int(*)(void*)));
x->funcs[0] = &func;
C* c = reinterpret_cast<C*>(x);
return c->x();
}
Re: c++ bespoke virtual table lookup, call functions. How?
Posted: Wed Jul 01, 2015 4:00 am
by Icee
Why all the unnecessary explicit address calculations?
Code: Select all
struct call_table {
void (*my_first_function)(int);
int (*my_other_function)(int, const void *, size_t);
// etc.
};
const struct call_table *call_table = (const struct call_table *) (const void *) (uintptr_t) 0x7100;
Re: c++ bespoke virtual table lookup, call functions. How?
Posted: Wed Jul 01, 2015 2:58 pm
by tsdnz
Very nice, I like it, cheers.
Icee wrote:Why all the unnecessary explicit address calculations?
Code: Select all
struct call_table {
void (*my_first_function)(int);
int (*my_other_function)(int, const void *, size_t);
// etc.
};
const struct call_table *call_table = (const struct call_table *) (const void *) (uintptr_t) 0x7100;
Re: c++ bespoke virtual table lookup, call functions. How?
Posted: Wed Jul 01, 2015 7:30 pm
by tsdnz
I had to add a section to get it working, but much cleaner your way.
Code: Select all
SECTIONS
{
.SystemFunctions 0x7100 :
{
*(.SystemFunctions)
}
}
Code: Select all
struct tSystemFunction
{
void (*DoSomething)(QWORD);
QWORD (*SystemFunctionSanityCheck)(QWORD);
};
const __attribute__((section(".SystemFunctions"))) struct tSystemFunction* SystemFunction = null;
tsdnz wrote:Very nice, I like it, cheers.
Icee wrote:Why all the unnecessary explicit address calculations?
Code: Select all
struct call_table {
void (*my_first_function)(int);
int (*my_other_function)(int, const void *, size_t);
// etc.
};
const struct call_table *call_table = (const struct call_table *) (const void *) (uintptr_t) 0x7100;
Re: c++ bespoke virtual table lookup, call functions. How?
Posted: Wed Jul 01, 2015 8:12 pm
by tsdnz
Forgot to add (NOLOAD) to sections.
Code: Select all
SECTIONS
{
.SystemFunctions 0x7100 (NOLOAD) :
{
*(.SystemFunctions)
}
........