[Android] Xposed: Как скрыть наличие Xposed/Cydia

[Android] Xposed: Как скрыть наличие Xposed/Cydia

@webware

t.me/webware

Привет,

Данная статья является логическим продолжением "Android/Xposed/Cydia: Ищем root и то, что может скрыть его", где я в прошлый раз рассказал как можно задетектить наличие root прав на девайсе. Сейчас рассмотрим то, как скрывать это для тех, кому это не нужно знать.

Все основные и часто используемые методы сокрытия su давно изучены и описаны, в том числе и кодом (хорошим примером является проект от Matt Joseph (devadvance) именуемый "rootcloak").

Но я хочу отдельно обратить ваше внимание на методе, который я описал в предыдущей статье и назвал "Xposed or Cydia". Его суть -- это поиск подстрок xposed или substrate в стектрейсе.


Первым шагом нам нужно составить список способов, как можно получить Stack Trace.

Да, как оказалось способов больше чем один и мы нашли 4 способа (если кто знает еще, велкам в комментарии)

  1. getStackTrace в java.lang.Thread
  2. getAllStackTraces в java.lang.Thread
  3. getStackTrace в java.lang.Throwable
  4. getStackTraceString android.util.Log

Дальше нужно понять как мы будем хукать методы. На самом деле в инфицированном Zygote это не так то и сложно сделать, а Xposed Framework вообще облегчает эту задачу (огромным плюсом у этого фреймворка явлется понятная и обширная документация, которая укажет нам на findAndHookMethod)

import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;

Остается дело за малым -- написать код, который будет отлавливать все обращения в stack trace и вычищать из него все упоминания о xposed.


Покажу на примере getAllStackTraces в java.lang.Thread

findAndHookMethod("java.lang.Thread", lpparam.classLoader, "getAllStackTraces", new XC_MethodHook() {
    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        Map<Thread, StackTraceElement[]> services = (Map<Thread, StackTraceElement[]>)param.getResult();
        Map<Thread, StackTraceElement[]> newTh = new HashMap<>();
        for (Thread th : services.keySet()) {
            List<StackTraceElement> stackTraceElementsList = new LinkedList<>(Arrays.asList((StackTraceElement[])services.get(th)));

//                    XposedBridge.log("---BEFORE===   " + stackTraceElementsList.toString());

            Iterator<StackTraceElement> iter = stackTraceElementsList.iterator();
            StackTraceElement stackTraceElement;

            while (iter.hasNext()) {
                stackTraceElement = iter.next();
                if (stackTraceElement == null) {
                    continue;
                }
                if (stackTraceElement.getClassName().contains("xposed") ||
                        (stackTraceElement.getFileName() != null &&
                                stackTraceElement.getFileName().toLowerCase().contains("xposed"))) {
                    iter.remove();
                }
            }

//                    XposedBridge.log("===AFTER===   " + stackTraceElementsList.toString());

            newTh.put(th, stackTraceElementsList.toArray(new StackTraceElement[stackTraceElementsList.size()]));
        }
        param.setResult(newTh);
    }
});

Все остальные способы ±похожи, но для того, чтобы понять суть решения этого более, чем достаточно.


Как вы уже поняли, Xposed это очень сильный инструмент, который позволяет сделать очень многое. Если у вас остались вопросы, велкам в комментарии.

Источник codeby.net

Report Page