4

This is a terrible idea, but i'm seeing if it's even feasible before I walk down this road.

I have to write a Win32 C++ program that can dynamically load a library based on a file that has serialized information on what dll, function, signature, and arguements to use. Loading the library is trivial (LoadLibraryEx works fine). Then getting the function pointer is easy (not a big deal, the GetProcAdderss takes care of this). However the rest is tricky.

Here's my plan of attack, feel free to let me know if this isn't the best approach:

  1. Open the serialized information from a file on what DLL to load, and what function to execute.
  2. LoadLibraryEx to bring in the DLL
  3. GetProcAddress to get the function pointer (after casting the byte array to a string)
  4. Write the arguments (which are read in as a byte array) to memory in bytes.
  5. Get the address to the beginning of each argument (i'll know from serialization what the size of each argument is).
  6. Using assembly jump to the beginning of the function pointer, push the addresses on the heap to the arguments in the stack (in reverse order).
  7. Execute and get back the return value address (as a void * ?)
  8. Use the memory address of the return value (that I got from assembly) and the size (which I got from the serialization) of the return type value and write the raw bytes back to a file.

Keep in mind my limitations:

  1. I will never know except for run-time what the signature, dll, function name is.
  2. It is always read in from a file.

Is there a better approach, will this approach even work?

Update

For anyone who comes poking in this thread to learn more, I found a solution. In C you can dynamically load a library using dlopen (there's a winlib of this for ease of use). Once loaded you can dynamically execute functions using libffi (supports mac/ios/win 64 and 32bit). This only gets you to C functions and primitive types (pointer,uint,int,double,float) and thats about it. However using macosx objective-c bridge you can access objective-c by loading libobjc (osx's native obj-c to c "toll free" bridge). Then through that dynamically create obj-c and c++ classes. A similar technique can be done on windows using C# and its marshaling capabilities.

This ends up with HIGH overhead, and you must be VERY careful about your memory, in addition don't mix pointers from C/C#/C++. Finally, whatever you do, at runtime. BE ABSOLUTELY SURE YOU KNOW YOUR TYPES.... seriously. BTW, libffi/cinvoke, amazing libraries.

11
  • Hardcore, dude. I agree -- this is a terrible idea. Are you sure there's not a better way to do this? If the set of DLLs you have to load is small, can you just maintain a set of possible functions to call for each one or something? I don't really understand the problem background, so it's hard to come up with any suggestions. Commented Jun 11, 2013 at 18:22
  • @aardvarkk I completely agree, I wish there was a simpler way. Effectively a remote application will be telling this application what to do. Dynamically... The application has to be completely dumb to the requests. Unfortunately I cannot use RPC or any other remote function calls... :/ Commented Jun 11, 2013 at 18:28
  • by sending it dlls with metadata about signatures? Maybe you need embedded scripting? Commented Jun 11, 2013 at 18:30
  • @yurikilochek I do have the serialized signature (e.g., metadata). The signature always holds the size of the arguments and return type size. So I can hopefully be dumb to what i'm executing and (maybe?) just treat everything as raw bytes instead of trying to cast/implement anything. Commented Jun 11, 2013 at 18:43
  • 1
    @zindorsky has it right. Also, the calling convention can change the way parameters are passed. __fastcall, __cdecl, and __stdcall all pass parameters differently. And things change more if the return value is a large structure. Basically, somebody needs to know how to call the function. If you don't know, then you have to make your caller tell you. Commented Jun 12, 2013 at 1:02

2 Answers 2

3

There are existing libraries that can do what you describe, such as C/Invoke:

http://www.nongnu.org/cinvoke/

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I ended up settling with libffi, with A LOT of careful learning about memory allocation and management on both 64/32 bit environments in addition to differences in calling mechanisms by compiler, os and bit environments I was able to get it working, pretty fluidly too with not too bad of overhead.
2

General rule, that if you have a terrible idea, drop it and find a good one.

If the signature is not known at all, what you describe will fall on face. Suppose your call works for my function as it is. I change the function from __stdcall to __cdecl or back, and you will crash.

Also you don't handle the return.

If you relax the "unknown" to allow some limitations, like fixing a return type and calling convention, you are somewhat ahead -- then really you can emulate the call but what is it good for? This whole thing sounds like a self-service hack-me engine.

The normal way is to publish some fixed interface (using function signatures), and make the DLL support it. Or arrange some uniform data transfer mechanism.

I'd suggest you to describe what you're after really and post ask that, maybe on Programmers SE.

5 Comments

I agree, i'm searching for a better way but I'm not the architect of this software, nor do I agree with the approach they insist is possible. Effectively its implementing a client-server type approach to remotely executing any dll call. To be a bit clearer, I do have the signature type as a serialized string. So I know the size of each argument along with its value, and the return type size. I don't need to know anything about whats running. I can uniformly treat everything as pointers and big buckets of raw bytes. I just need to write the return value back to the file in bytes.
If someone insists on anything against your best judgement, make him do it. All the way, dealing with all the consequences. Those bullies get all their strength only from those to bend. -- for the technical part you must consult the ABI documentation on how function params are passed and especially returned.
Her, not him. I agree it'll be convoluted and i'd love to tell her to do it herself. But I also value my job :). Best thing I can do at this point is some CYA and jump head first in to assembly...
These are the very situations when CYA is to refuse eating the shit sandwich. Tomorrow you will be blamed for any problem from this implementation and no one will remember that you did it on a supposed order. If someone manipulates the data and hacks the system you might even end up in jail. But it's your decision to make. (While she does a great CYA job using you as shield.)
This is what variants and the like are for. Look into COM and how it handles (the very restricted subset of) these things. Typically, you're required to pass a struct of a constant/known size which both contains a values and declares (in a pre-known list) the type of the value. You then use the arity of the function to build a very small set of prototypes (say 1-5 args), differing only on stack size expectations, and the DLL can advertise that it contains 4 functions, function 1 has arity 1, that means Variant f(Variant), and so on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.