c++ bespoke virtual table lookup, call functions. How?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

c++ bespoke virtual table lookup, call functions. How?

Post 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
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: c++ bespoke virtual table lookup, call functions. How?

Post 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))();
	}
};
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re: c++ bespoke virtual table lookup, call functions. How?

Post 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();
}
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: c++ bespoke virtual table lookup, call functions. How?

Post 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();
}
Icee
Member
Member
Posts: 100
Joined: Wed Jan 08, 2014 8:41 am
Location: Moscow, Russia

Re: c++ bespoke virtual table lookup, call functions. How?

Post 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;
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: c++ bespoke virtual table lookup, call functions. How?

Post 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;
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: c++ bespoke virtual table lookup, call functions. How?

Post 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;
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: c++ bespoke virtual table lookup, call functions. How?

Post by tsdnz »

Forgot to add (NOLOAD) to sections.

Code: Select all

SECTIONS
{
	.SystemFunctions 0x7100 (NOLOAD) :
	{
		*(.SystemFunctions)
	}

........
Post Reply