예제 #1
0
    public void addClassTreeHook(HookClass origin, HookClass to) {
      addSuperclassHook(origin, to);

      Set<HookClass> superclassHookSet = new HashSet<HookClass>();
      superclassHookSet.add(origin);

      for (ClassDefItem classDef : mDexFile.ClassDefsSection.getItems()) {
        HookClass superclass = new HookClass(classDef.getSuperclass());

        if (superclassHookSet.contains(superclass)) {
          TypeIdItem classType = classDef.getClassType();
          HookClass newHook = new HookClass(classType);
          superclassHookSet.add(newHook);
          mHooks.put(newHook, classType);
        }
      }

      HookClass[] superclassHooks = superclassHookSet.toArray(new HookClass[0]);

      HashSet<EncodedMethod> newClassMethods = getClassMethodsMap().get(to);

      if (newClassMethods != null) {
        for (EncodedMethod newVirtual : newClassMethods) {
          if (newVirtual.isDirect()) {
            continue;
          }

          for (HookClass superclass : superclassHooks) {
            HookMethod deadMethod = new HookMethod(newVirtual.method);
            deadMethod.mClasspath = superclass.mClasspath;
            mDead.add(deadMethod);
          }
        }
      }
    }
예제 #2
0
    /**
     * Hooks the specified method and all call-through methods
     *
     * @param from
     * @param to
     */
    public void addMethodHook(HookMethod from, MethodIdItem to) {
      mMethodHooksExist = true;

      Queue<HookMethod> affectedMethods = new LinkedList<HookMethod>();
      affectedMethods.add(from);

      do {
        HookMethod affected = affectedMethods.remove();
        mHooks.put(affected, to);

        Set<String> allSubclasses = getSubclassMap().get(affected.mClasspath);
        if (allSubclasses == null) {
          continue;
        }

        for (String subclass : allSubclasses) {
          HookMethod possible = affected.clone();
          possible.mClasspath = subclass;

          MethodIdItem possibleMethodInfo = getMethodMap().get(possible);
          if (possibleMethodInfo == null || possibleMethodInfo.isFallthrough()) {
            affectedMethods.add(possible);
          }
        }

      } while (!affectedMethods.isEmpty());
    }
예제 #3
0
  public void hookSuperclass(HookMap hooks, ClassDefItem classDef) {
    HookItem oldTarget = HookItem.getInstance(classDef.getSuperclass());

    if (oldTarget == null) {
      return;
    }

    if (!hooks.containsKey(oldTarget)) {
      return;
    }

    TypeIdItem newTarget = (TypeIdItem) hooks.get(oldTarget);

    assert (newTarget != null);

    if (newTarget == classDef.getClassType()) {
      return;
    }

    classDef.setSuperclass(newTarget);

    HookClass classType = new HookClass(classDef.getClassType());

    if (hooks.mIgnoreMethods.contains(classType)) {
      return;
    }

    if (hooks.mDead.isEmpty()) {
      return;
    }

    // get rid of virtual methods so the hooked class method is called instead

    String className = newTarget.getTypeDescriptor();

    List<EncodedMethod> newDirects = new LinkedList<EncodedMethod>();
    List<EncodedMethod> newVirtuals = new LinkedList<EncodedMethod>();

    ClassDataItem classData = classDef.getClassData();

    for (EncodedMethod encodedMethod : classData.getDirectMethods()) {
      newDirects.add(encodedMethod);
    }

    for (EncodedMethod encodedMethod : classData.getVirtualMethods()) {
      HookMethod method = new HookMethod(encodedMethod.method);
      method.mClasspath = className;

      if (!hooks.mDead.contains(method)) {
        newVirtuals.add(encodedMethod);
      }
    }

    classData.update(newDirects, newVirtuals);
  }
예제 #4
0
 public HookMethod clone() {
   HookMethod result = new HookMethod(mClasspath, mName, null, mReturn);
   result.mArgs = mArgs;
   return result;
 }