views:

80

answers:

2

Hi ;)

I have succesfully using dyld -macosx- to interpose standard C functions to a third party application, getting important information about the workarounds it does. But what I really need is to replace a certain function of a certain class.

The function I want to override is QString::append(..., ..., ...), so each time a string is appended to another -the whole application uses qstring-, i find out.

Is there a way? Here's the code I already have.

// libinterposers.c
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <dlfcn.h>
#include <stdlib.h>

typedef struct interpose_s {
    void *new_func;
    void *orig_func;
} interpose_t;

int my_open(const char *, int, mode_t);
int my_close(int);
void* my_malloc(size_t);

static const interpose_t interposers[] \
    __attribute__ ((section("__DATA, __interpose"))) = {
        { (void *)my_open,  (void *)open  },
        { (void *)my_close, (void *)close },
        { (void *)my_malloc, (void *)malloc },
    };

int
my_open(const char *path, int flags, mode_t mode)
{
    int ret = open(path, flags, mode);
    printf("--> %d = open(%s, %x, %x)\n", ret, path, flags, mode);
    return ret;
}

int
my_close(int d)
{
    int ret = close(d);
    printf("--> %d = close(%d)\n", ret, d);
    return ret;
}

void*
my_malloc(size_t size)
{
    void *ret = malloc(size);
    //fprintf(stderr, "Reserva de memoria");
    return ret;
}

Thank you very much

+2  A: 

C++ does name mangling. This means member function QString::mid() looks something like __ZNK7QString3midEii to the linker. Run the nm(1) command on the library you are interposing on to see the symbols.

Nikolai N Fetissov
+1 Exactly. Use *nm* to find the correct symbol of the method you want to replace and then create a C function with that exact name on the shared library you are building.
karlphillip
I will as soon as I get home. The function is in a bundle located in the application directory. It's a *.bundle file. If the symbol exists in the .bundle ANd in the main application, what should be done?ç
flaab
Thank you for your answers. Karlphillip: once in know the exact symbol, should I just use the above code to interpose both of them?
flaab
I haven't dug into OSX bundles, so don't know. You can certainly try your approach with mangled symbols. They are just functions to linker, though they are transformed to take `this` as a first argument.
Nikolai N Fetissov
Thank you nikolai: Is it possible to just receive the function call to ___ZNK7QString3midEii(p1,p2,p3,p4), do whatever and then redirect the call to the real function which memory adress i have previously saved without making class posing. Is that it? Thank you :)
flaab
It looks like it should be possible. Don't forget that first implicit pointer argument (forward-declare class types?). I gotta try this, it's fun :)
Nikolai N Fetissov
I will! So if the function is Qstring::func(p1,p2,p3); and the symbol is ___ZNK7QString3midEii, the function I have to declare is my_own____ZNK7QString3midEii(pthis,p1,p2,p3) and forward it to the real function is that it? :D
flaab
You don't have to have such ugly names for your own functions :)
Nikolai N Fetissov
I will try and let you know :-) Thank you. I have a sudden question: what happens it the declaration uses custom datatypes. For instance if the original function declaration is QString::func(CType *p1, CType2 *p2, CType3 *p3), should I include Ctype.h, Ctype2.h and Ctype3.h in my patch when declaring the interposing funtion? :-S And what happens with the first parameter? Shoulw it be QString typed in the declaration? Should all pointers be void? :-P
flaab
That's what I said before - forward declare these types as `struct`'s. I think `void` pointers should work too.
Nikolai N Fetissov
As it turns out, it seems I won't need to interpose any class.
flaab
This is the function I'm interested in replacing: addDealerChatMessage(quint64,quint8,QString,quint8,TPlayerIx,bool). If I can grab the QString in the middle, I'll be the happiest man on earth. I will need to replace it and being able to treat the QString afterwards. I don't have access to TPlayerIx class, maybe a standard pointer will do :P
flaab
But I don't have the header file for that function, and it does not appear as a simbol of the binary. Is there a way to look for it? Maybe at execution time?
flaab
A: 

It is going to be much easier that this. QString uses memcpy to concatenate and work with Strings, and I can easily override memcpy, and apply a regular expression to the result, logging only the strings I want. Piece of cake. No need for magic voodo-hoodo :)

flaab