C++ jump to other method execution

浪尽此生 提交于 2019-12-04 01:35:25

Arguments are passed manually in assembly using a set calling convention. In this case, the arguments are passed in registers beginning with %rcx. Any modification to the registers used as calling conventions will change the arguments perceived by any proceeding jmp.

Calling printf before your jmp changes the value of %rcx from *env to a pointer to constant "hello". After you change the value of %rcx you need to restore it to the value it was previously. The following code should work:

void* interceptor(JNIEnv *env, jclass clazz, ...){

//just an example
int x=8;

printf("hey");

// restoring stack pointers
asm (
    "movl %ebp, %esp;"
    "mov %rbp, %rsp"
);

// restore %rcx to equal *env
asm volatile("mov %rcx, 0x10(%rbp)");

// add 4 to the function address to skip "push ebp / mov ebp esp"
asm volatile("jmp *%0;"::"r" (originalfunc+4));

// will not get here anyway
return NULL;

}

What architecture is this? From the register names, it appears to be x64.

You say the parameters are wrong. I agree. You jump from there to believing the stack is wrong. Probably not. x64 passes some parameters in registers, but not varargs. So the function signature for your forwarder is simply incompatible with the function you are trying to call.

Post the assembly for a direct call to Java_main_Main_theOriginalFunction and then for a call to your forwarder using the exact same parameters; you'll see a terrible difference in how the arguments are passed.

Most likely any function you call before your forwarding destroys the structure that is needed to handle the variable argument list (in your assembly there is still the mingw_printf call of which you didn't show the disassembly).

To understand better what's going on you might want to have a look at this question.

To solve your problem you could consider to add another indirection, I think that the following might work (but I haven't tested it).

void *forward_interceptor(env, clazz, ... ) {
    // add 4 to the function address to skip "push ebp / mov ebp esp"
    asm volatile("jmp *%0;"::"r" (originalfunc+4));
    // will not get here anyway
    return NULL;
}

void* interceptor(JNIEnv *env, jclass clazz, ...){
    //do your preparations 
    ...

    va_list args;
    va_start(args, clazz);
    forward_interceptor(env, clazz, args);
    va_end(args);
}

IMHO the important thing is that you need the va_list/va_start/va_end setup to make sure that the parameters are properly passed on to the next function.

However, since you seem to know the signature of the function you are forwarding to and it doesn't seem to accept a variable number of arguments, why not extract the arguments, and call the function properly like:

void* interceptor(JNIEnv *env, jclass clazz, ...){
    //do your preparations 
    ...

    va_list args;
    va_start(args, clazz);

    jboolean p1 = va_arg(args, jboolean); 
    jbyte p2 =  va_arg(args, jbyte); 
    jshort p3 = va_arg(args, jshort); 
    ...
    Java_main_Main_theOriginalFunction(env, clazz, p1, p2, ...
    va_end(args);

    return NULL; 
}

Note, however, that va_arg can not check whether the parameter is of the correct type or available at all.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!