Esempio n. 1
0
static void de_robv_android_xposed_XposedBridge_hookMethodNative(JNIEnv* env, jclass clazz, jobject declaredClassIndirect, jint slot) {
    // Usage errors?
    if (declaredClassIndirect == NULL) {
        dvmThrowIllegalArgumentException("declaredClass must not be null");
        return;
    }
    
    // Find the internal representation of the method
    ClassObject* declaredClass = (ClassObject*) dvmDecodeIndirectRef(dvmThreadSelf(), declaredClassIndirect);
    Method* method = dvmSlotToMethod(declaredClass, slot);
    if (method == NULL) {
        dvmThrowNoSuchMethodError("could not get internal representation for method");
        return;
    }
    
    if (findXposedOriginalMethod(method) != xposedOriginalMethods.end()) {
        // already hooked
        return;
    }
    
    // Save a copy of the original method
    xposedOriginalMethods.push_front(*((MethodXposedExt*)method));

    // Replace method with our own code
    SET_METHOD_FLAG(method, ACC_NATIVE);
    method->nativeFunc = &xposedCallHandler;
    method->registersSize = method->insSize;
    method->outsSize = 0;

    if (PTR_gDvmJit != NULL) {
        // reset JIT cache
        MEMBER_VAL(PTR_gDvmJit, DvmJitGlobals, codeCacheFull) = true;
    }
}
Esempio n. 2
0
static void de_robv_android_xposed_XposedBridge_hookMethodNative(JNIEnv* env,
		jclass clazz, jobject reflectedMethodIndirect,
		jobject declaredClassIndirect, jint slot,
		jobject additionalInfoIndirect) {
	// Usage errors?
	if (declaredClassIndirect == NULL || reflectedMethodIndirect == NULL) {
		dvmThrowIllegalArgumentException(
				"method and declaredClass must not be null");
		return;
	}

	// Find the internal representation of the method
	ClassObject* declaredClass = (ClassObject*) dvmDecodeIndirectRef(
			dvmThreadSelf(), declaredClassIndirect);
	Method* method = dvmSlotToMethod(declaredClass, slot);
	if (method == NULL) {
		dvmThrowNoSuchMethodError(
				"could not get internal representation for method");
		return;
	}


	if (xposedIsHooked(method)) {
		ALOGD("Hook: Ignored! [%s] [%s]\n", declaredClass->descriptor, method->name);
		// already hooked
		return;
	}
	else {
		ALOGD("Hook: [%s] [%s]\n", declaredClass->descriptor, method->name);
	}

	// Save a copy of the original method and other hook info
	XposedHookInfo* hookInfo = (XposedHookInfo*) calloc(1,
			sizeof(XposedHookInfo));
	memcpy(hookInfo, method, sizeof(hookInfo->originalMethodStruct));
	hookInfo->reflectedMethod = dvmDecodeIndirectRef(dvmThreadSelf(),
			env->NewGlobalRef(reflectedMethodIndirect));
	hookInfo->additionalInfo = dvmDecodeIndirectRef(dvmThreadSelf(),
			env->NewGlobalRef(additionalInfoIndirect));

	// Replace method with our own code
	SET_METHOD_FLAG(method, ACC_NATIVE);
	method->nativeFunc = &xposedCallHandler;
	method->insns = (const u2*) hookInfo;
	method->registersSize = method->insSize;
	method->outsSize = 0;

	if (PTR_gDvmJit != NULL) {
		// reset JIT cache
		MEMBER_VAL(PTR_gDvmJit, DvmJitGlobals, codeCacheFull) = true;
	}
}
Esempio n. 3
0
static void xposedCallHandler(const u4* args, JValue* pResult, const Method* method, ::Thread* self) {
    XposedOriginalMethodsIt original = findXposedOriginalMethod(method);
    if (original == xposedOriginalMethods.end()) {
        dvmThrowNoSuchMethodError("could not find Xposed original method - how did you even get here?");
        return;
    }
    
    ThreadStatus oldThreadStatus = MEMBER_VAL(self, Thread, status);
    JNIEnv* env = MEMBER_VAL(self, Thread, jniEnv);
    
    // get java.lang.reflect.Method object for original method
    jobject originalReflected = env->ToReflectedMethod(
        (jclass)xposedAddLocalReference(self, original->clazz),
        (jmethodID)method,
        true);
  
    // convert/box arguments
    const char* desc = &method->shorty[1]; // [0] is the return type.
    Object* thisObject = NULL;
    size_t srcIndex = 0;
    size_t dstIndex = 0;
    
    // for non-static methods determine the "this" pointer
    if (!dvmIsStaticMethod(&(*original))) {
        thisObject = (Object*) xposedAddLocalReference(self, (Object*)args[0]);
        srcIndex++;
    }
    
    jclass objectClass = env->FindClass("java/lang/Object");
    jobjectArray argsArray = env->NewObjectArray(strlen(method->shorty) - 1, objectClass, NULL);
    
    while (*desc != '\0') {
        char descChar = *(desc++);
        JValue value;
        Object* obj;

        switch (descChar) {
        case 'Z':
        case 'C':
        case 'F':
        case 'B':
        case 'S':
        case 'I':
            value.i = args[srcIndex++];
            obj = (Object*) dvmBoxPrimitive(value, dvmFindPrimitiveClass(descChar));
            dvmReleaseTrackedAlloc(obj, NULL);
            break;
        case 'D':
        case 'J':
            value.j = dvmGetArgLong(args, srcIndex);
            srcIndex += 2;
            obj = (Object*) dvmBoxPrimitive(value, dvmFindPrimitiveClass(descChar));
            dvmReleaseTrackedAlloc(obj, NULL);
            break;
        case '[':
        case 'L':
            obj  = (Object*) args[srcIndex++];
            break;
        default:
            ALOGE("Unknown method signature description character: %c\n", descChar);
            obj = NULL;
            srcIndex++;
        }
        env->SetObjectArrayElement(argsArray, dstIndex++, xposedAddLocalReference(self, obj));
    }
    
    // call the Java handler function
    jobject resultRef = env->CallStaticObjectMethod(
        xposedClass, xposedHandleHookedMethod, originalReflected, thisObject, argsArray);
        
    // exceptions are thrown to the caller
    if (env->ExceptionCheck()) {
        dvmChangeStatus(self, oldThreadStatus);
        return;
    }
    
    // return result with proper type
    Object* result = dvmDecodeIndirectRef(self, resultRef);
    ClassObject* returnType = dvmGetBoxedReturnType(method);
    if (returnType->primitiveType == PRIM_VOID) {
        // ignored
    } else if (result == NULL) {
        if (dvmIsPrimitiveClass(returnType)) {
            dvmThrowNullPointerException("null result when primitive expected");
        }
        pResult->l = NULL;
    } else {
        if (!dvmUnboxPrimitive(result, returnType, pResult)) {
            dvmThrowClassCastException(result->clazz, returnType);
        }
    }
    
    // set the thread status back to running. must be done after the last env->...()
    dvmChangeStatus(self, oldThreadStatus);
}