bool HookDalvikMethod(jmethodID jmethod){ Method *method = (Method*)jmethod; //关键!!将目标方法修改为native方法 SET_METHOD_FLAG(method, ACC_NATIVE); int argsSize = dvmComputeMethodArgsSize(method); if (!dvmIsStaticMethod(method)) argsSize++; method->registersSize = method->insSize = argsSize; if (dvmIsNativeMethod(method)) { method->nativeFunc = dvmResolveNativeMethod; method->jniArgInfo = computeJniArgInfo(&method->prototype); } }
extern "C" int hook_dvm(JNIEnv *env, struct hook_java_args *args) { jclass clz, tmp; jmethodID jm; bool isStatic = false; struct hook_java_args *ha = NULL; Method *method; int argsSize; if (loadDVM()) { LOGE("hook_dvm: loadDVM() failed"); return -1; } if ((args->prev || args->post) && args->func) { LOGE("hook_dvm: invalid argument"); return -1; } tmp = hsdk_find_clz(env, args->clz); if (tmp == NULL) { LOGE("hook_dvm: class `%s\' not found", args->clz); return -1; } // XXX: find_clz3w // saying given clz is invalid //W/dalvikvm( 8493): Invalid indirect reference 0x41cd9338 in decodeIndirectRef //E/dalvikvm( 8493): VM aborting clz = (jclass) env->NewGlobalRef(tmp); env->DeleteLocalRef(tmp); if (clz == NULL) { LOGE("hook_dvm: unable to ref clz"); return -1; } jm = env->GetMethodID(clz, args->mtd, args->sig); if (jm == NULL) { if (env->ExceptionOccurred()) env->ExceptionClear(); jm = env->GetStaticMethodID(clz, args->mtd, args->sig); if (env->ExceptionOccurred()) env->ExceptionClear(); if (jm == NULL) { LOGE("hook_dvm: method `%s\' with sig `%s\' not found", args->mtd, args->sig); env->DeleteGlobalRef(clz); return -1; } isStatic = true; } // XXX: leak the global ref so GC won't recycle the class then Member will be always valid? env->DeleteGlobalRef(clz); method = (Method *) jm; if ((method->nativeFunc == hsdk_bridge_func) || (method->nativeFunc == dvmCallJNIMethod && method->insns == args->func)) { LOGD("hook_dvm: already hooked"); return 0; } // hook args->old = calloc(1, sizeof(*method)); if (args->old) memcpy(args->old, jm, sizeof(*method)); if (!args->func) { ha = (struct hook_java_args *) calloc(1, sizeof(*ha)); if (!ha) { LOGE("hook_dvm: calloc failed"); if (args->old) { free(args->old); args->old = 0; } return -1; } ha->clz = strdup(args->clz); ha->mtd = strdup(args->mtd); ha->sig = strdup(args->sig); ha->prev = args->prev; ha->post = args->post; } argsSize = dexProtoComputeArgsSize(&method->prototype); if (!isStatic) argsSize += 1; method->registersSize = argsSize; method->insSize = argsSize; method->outsSize = 0; method->insns = NULL; method->jniArgInfo = computeJniArgInfo(&method->prototype); if (!args->func) { method->insns = (const u2*) ha; method->nativeFunc = hsdk_bridge_func; } else { dvmUseJNIBridge(method, args->func); } SET_METHOD_FLAG(method, ACC_NATIVE); if (args->func) { LOGD("hook_dvm: %sL%s;%s->%s => %p", isStatic ? "static " : "", args->clz, args->mtd, args->sig, args->func); } return 0; }