Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call C address as function without prototype

Tags:

c

assembly

64-bit

I need to call a function in C by just knowing it address, and no information on it prototype (I can't cast it to a C function pointer).

The information I have on this function is it address.

I also know the parameters I want to pass to it (Thanks to a void pointer) and the size of the arguments array (accessed trough the void pointer).

I also want to respect the C calling convention. For x86 version, I pretty much know how to do it (allocate the space on the stack, copy the parameters to that space and finally call the function).

The problem is with x64 convention (Linux one for now) where parameters are passed through registers. I have no idea of the size of each parameter to fill appropriately registers, I only know the size of the parameter array.

Also, I don't want to depend on gcc so I can't use __builtin_apply that seems to be not standard and also be pretty dark.

I want to write my own piece of code to support multi compiler and also to learn interesting stuff.

So basically, the function I want to write as the same prototype as __builtin_apply which is:

void *call_ptr(void (*fun)(), void *params, size_t size);

I want also the code to write it in C (thanks to asm inline) or pure x64 asm.

So is there a way to do this properly and with respect of the calling convention ? Or is this impossible with the x64 convention without knowing exactly the prototype of the function called ?

like image 418
Zerkan Avatar asked Nov 02 '22 16:11

Zerkan


1 Answers

Especially for x64 calling convention on Linux this will not work at all.

The reason is the very complicated calling convention.

Some examples:

void funcA(float64 x);
void funcB(int64 x);

In these two cases the value "x" is passed to the functions differently because floating point and integer are passed to the functions in different registers.

void funcC(float64 x,int64 y);
void funcD(int64 y,float64 x);

In these two cases the arguments "x" and "y" are in different order. However they are passed to the function in the same way (both functions use the same register for "x" and the same register for "y").

Conclusion: To create a function that does what you want you'd have to pass a string containing the argument types of each argument to the assembler function. The number/size of arguments is definitely not enough. However it would definitely be possible - as long as it must work only on Linux.

like image 138
Martin Rosenau Avatar answered Nov 09 '22 06:11

Martin Rosenau