Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

tricky C++ question

Options
  • 02-06-2004 1:45pm
    #1
    Registered Users Posts: 1,372 ✭✭✭


    does anyone know:
    Using Windows, how can you call a constructor using a function pointer (i.e. the return from ::GetProcAddress ) ?

    I am trying to reverse-engineer a dll for which I don't have the .lib file (or the source, obviously)
    However I know the .dll exports the following functions I want to call

    InitialisationClass::InitialisationClass()
    static SomeClass::DoSomeStuff()
    InitialisationClass::~InitialisationClass()

    I can use LoadLibrary and GetProcAddress to get function pointers, but how can I call them?

    Could I somehow manufacture a .lib file and let the compiler look after it?


Comments

  • Closed Accounts Posts: 9,314 ✭✭✭Talliesin


    A couple of different problems here.

    GetProcAddress returns a void* (well a FARPROC, which is normally defined, give or take, as a void* or as something that can be cast to a function pointer anyway).

    With normal function pointers this is a simple cast, a reinterpret_cast, though the old C-style casts will also work.

    static member functions are just the same as global or namespace scoped functions, except that they are in the class's namespace, so you can cast the result of GetProcAddress to the correct type and call through it.

    With member function pointers such a cast is not allowed however, one can only cast between that type and the type of a similar member function on a derived class.

    At a lower level though, it's all just a 32-bit number (64-bit if you're playing with that new-fangled 64-bit Windows). So we can create a non-portable kludge that just forces the bits into the correct variable:
    template<typename To, typename From> inline To union_cast(From fr) throw(){
        union{
            From f;
            To t;
        } uc;
        uc.f = fr;
        return uc.t;
    }
    

    The above ugly, bad, non-portable, error-prone code will do the trick. Nasty, but it'll do it.

    We can use this for all non-virtual, non-static functions except for constructors.

    For virtual functions you have to cast the first 4 bytes of a constructed object into a pointer. This points to the vTable for the class. Then you have to cast the result of FARPROC into a size_t. Then some pointer arithmetic will give you the address of the function pointed to (I can't remember the exact details, but that's the gist of it and you should be able to work out the rest through experimentation).

    For constructors we have an syntax problem. Constructors aren't called through function pointers, the closest thing to doing so is the placement version of the new operator. However for the placement version of the new operator to work you need to compile with the layout of the class known, and you don't know it (though your reverse information may enable you to create a dummy header file at some point).

    All is not lost however. Recall that the C++ function
    void X::Y()
    
    is pretty much equivalent to the C function
    void Y(X* this)
    
    . Also while a C++ constructor has no return type, to a C view that essentially means it has a void return type. Therefore we can create a dummy function type void InitInitialisationClass(void* ptr) cast the result of GetProcAddress to that, obtain enough memory to safely contain an InitialisationClass object and then away we go.

    Well, I haven't tested any of the above so I may be a bit rough on some details, but then reverse-engineering is never easy.


  • Registered Users Posts: 1,372 ✭✭✭silverside


    most helpful, thanks - will try later. Although I *may* be getting sent the source, it's still good to know - depending how bored I get in the meantime I may try it anyway :)


  • Registered Users Posts: 1,268 ✭✭✭hostyle


    I always feel I owe Talliesin a pint when he explains stuff like he did there, whether its me who asked the question or not ...


Advertisement