dlsym how do I pass the implicit "this" pointer in nonstatic member function?

167 Views Asked by At

I want to call a function with dlsym and it is a member function of an object, I have the pointer, but it is not working. The function lives in the main executable, and I am loading it from a shared library. The function is not exported so direct dlsym fails, using gdb break I calculated the offset of this function and other known exported function, so I do dlsym in the exported function and calculate the offset to the other function. I need to call it but I can't pass the args correctly, the first argument should be the "this" implicit pointer since it is a nonstatic member function.

The function definition is this:

_int64 __fastcall gplayer_controller::DebugCommandHandler(gplayer_controller *const this, int cmd_type, const void *buf, size_t size)

my code is this:

/* open the needed object */
  void *handle = dlopen(NULL, RTLD_LOCAL | RTLD_LAZY);
  if(handle == NULL){
    printf("error w/ dlopen\n" );
  }
  

  int (*fptr)(controller *, int, mma *, size_t);
  fptr = (int (*)(controller *, int, mma *, size_t))dlsym(handle, "lua_pushboolean");

  if(fptr == NULL){
    printf("error w/ funcion\n" );

  }
  else{
    printf("found, ptr: %p\n", fptr);
  }

  gobject_imp *pImp = (gobject_imp*)skill->GetPlayer()->GetObject().GetImpl();

  int (*fptr2)(controller *, int, mma *, size_t) = fptr - 5638326;
  printf("ptr calculation...: %p\n", fptr2);

  mma _mma;
  _mma.cmd = 2040;
  _mma.skillid = 15000;
  _mma.level = skill->GetLevel() + 1;

  printf("data controller %p\n",pImp->_commander );

  (*fptr2)(pImp->_commander,2040,&_mma,10);

the first parameter is the "this" pointer, the other 3 are the normal function params

1

There are 1 best solutions below

2
Alvaro Hernandorena On

I finally got it working, now I can call that member function like if it where a normal one.

The problem with my code, was that the pointer I was getting was wrong, with gdb I got another address with command info frame, but in fact that pointer was also wrong, the function was been called but with all params in 0, after checking in IDA pro , the address gdb was giving me was after the function started, right after the function setted input params.

.text:0000000000562847                 mov     rbp, rsp
.text:000000000056284A                 push    r15
.text:000000000056284C                 push    r14
.text:000000000056284E                 push    r13
.text:0000000000562850                 push    r12
.text:0000000000562852                 push    rbx
.text:0000000000562853                 sub     rsp, 2528h
.text:000000000056285A                 mov     [rbp+this], rdi
.text:0000000000562861                 mov     [rbp+cmd_type], esi
.text:0000000000562867                 mov     [rbp+buf], rdx
.text:000000000056286E                 mov     [rbp+size], rcx
.text:0000000000562875                 mov     rax, [rbp+this]
.text:000000000056287C                 movzx   eax, byte ptr [rax+44h]
.text:0000000000562880                 xor     eax, 1
.text:0000000000562883                 test    al, al
.text:0000000000562885                 jz      short loc_562891
.text:0000000000562887                 mov     eax, 0
.text:000000000056288C                 jmp     loc_56D049

GDB was giving me the address 0000000000562875, right after moving registers with params to rbp.

I recalculated my ptr to the first line of the function (562847) in IDA. And it worked!! I can call the function, the first param I sent as the implicit "this" param works like a charm.