alibaba / dexposed

dexposed enable 'god' mode for single android application.
4.51k stars 1.07k forks source link

ART系统类方法Hook支持 #59

Closed mimers closed 7 years ago

mimers commented 8 years ago

1.对ART的支持现在是否还有人在继续开发?

2.手淘是否使用了其他的方案来代替dexposed?

3.我测试了ART下自定义函数的可以hook,但是对于View的方法比如performClick不可以hook, dexposed/dexposed_so/dexposed_art/dexposed.cpp里的EnableXposedHook

static void EnableXposedHook(JNIEnv* env, ArtMethod* art_method, jobject additional_info)
      // Create a backup of the ArtMethod object
      ArtMethod* backup_method = down_cast<ArtMethod*>(art_method->Clone(soa.Self()));
      // Set private flag to avoid virtual table lookups during invocation
      backup_method->SetAccessFlags(backup_method->GetAccessFlags() /*| kAccXposedOriginalMethod*/);
      // Create a Method/Constructor object for the backup ArtMethod object
      jobject reflect_method;
      if (art_method->IsConstructor()) {
        reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Constructor);
      } else {
        reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Method);
      }
      env->SetObjectField(reflect_method, WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod,
          env->NewGlobalRef(soa.AddLocalReference<jobject>(backup_method)));
      // Save extra information in a separate structure, stored instead of the native method
      DexposedHookInfo* hookInfo = reinterpret_cast<DexposedHookInfo*>(calloc(1, sizeof(DexposedHookInfo)));
      hookInfo->reflectedMethod = env->NewGlobalRef(reflect_method);
      hookInfo->additionalInfo = env->NewGlobalRef(additional_info);
      hookInfo->originalMethod = backup_method;

      jstring shorty = (jstring)env->GetObjectField(additional_info,additionalhookinfo_shorty_field);
      hookInfo->shorty = env->GetStringUTFChars(shorty, 0);
      LOG(INFO) << "dexposed: >>> EnableXposedHook shorty:" << hookInfo->shorty;

    #if PLATFORM_SDK_VERSION < 22
        art_method->SetNativeMethod(reinterpret_cast<uint8_t *>(hookInfo));
    #else
        art_method->SetEntryPointFromJni(reinterpret_cast<void *>(hookInfo));
    #endif

      art_method->SetEntryPointFromQuickCompiledCode(GetQuickDexposedInvokeHandler());
      //art_method->SetEntryPointFromInterpreter(art::artInterpreterToCompiledCodeBridge);
      // Adjust access flags
      art_method->SetAccessFlags((art_method->GetAccessFlags() & ~kAccNative) /*| kAccXposedHookedMethod*/);

是什么原因导致的这个问题呢? 另外xposed也支持了6.0的hook,在android_art/runtime/art_method.cc里的

void ArtMethod::EnableXposedHook(ScopedObjectAccess& soa, jobject additional_info) {

  // Create a backup of the ArtMethod object
  auto* cl = Runtime::Current()->GetClassLinker();
  ArtMethod* backup_method = cl->AllocArtMethodArray(soa.Self(), 1);
  backup_method->CopyFrom(this, cl->GetImagePointerSize());
  backup_method->SetAccessFlags(backup_method->GetAccessFlags() | kAccXposedOriginalMethod);

  // Create a Method/Constructor object for the backup ArtMethod object
  mirror::AbstractMethod* reflect_method;
  if (IsConstructor()) {
    reflect_method = mirror::Constructor::CreateFromArtMethod(soa.Self(), backup_method);
  } else {
    reflect_method = mirror::Method::CreateFromArtMethod(soa.Self(), backup_method);
  }
  reflect_method->SetAccessible<false>(true);

  // Save extra information in a separate structure, stored instead of the native method
  XposedHookInfo* hookInfo = reinterpret_cast<XposedHookInfo*>(calloc(1, sizeof(XposedHookInfo)));
  hookInfo->reflectedMethod = soa.Vm()->AddGlobalRef(soa.Self(), reflect_method);
  hookInfo->additionalInfo = soa.Env()->NewGlobalRef(additional_info);
  hookInfo->originalMethod = backup_method;
  SetEntryPointFromJni(reinterpret_cast<uint8_t*>(hookInfo));

  ThreadList* tl = Runtime::Current()->GetThreadList();
  soa.Self()->TransitionFromRunnableToSuspended(kSuspended);
  tl->SuspendAll("Hooking method");
  {
    MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
    tl->ForEach(StackReplaceMethod, this);
  }
  tl->ResumeAll();
  soa.Self()->TransitionFromSuspendedToRunnable();

  SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler());
  SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);

  // Adjust access flags
  SetAccessFlags((GetAccessFlags() & ~kAccNative & ~kAccSynchronized) | kAccXposedHookedMethod);

是否可以借鉴一下?

hwjump commented 8 years ago

xposed close some Art compile optimization when dex2oat. that was why xposed can hook View.performClick(), which use EntryPointFromQuickCompiledCode bridge when the method was called. But dexposed can't close compile optimization, so current now it only can hook the method which called using EntryPointFromQuickCompiledCode bridge.
About Android M, it also can take a reference from xposed. thank you for your information.

randomeval commented 8 years ago

Is there a way to find out which method in framework can hook, and which can not?

hwjump commented 7 years ago

Now You can refer the "dev_art" branch. I rewriter the hook core for art. thanks.