A while ago, I just picked up a Google son Nexus 6 from the head office. After Rooting, I used Xposed. I just wanted to be cool, but when one of the apps was opened, it became a virtuous one.
No way, since it won't make me cool, I will do it myself.
Analysis APK
The most basic analysis can use Android Studio, we copy the installation package to the project directory opened by Android Studio, and check it roughly
There is no com.huimai365
package in the dex file , and the so file under the lib accounted for more than 50%. My heart felt cold for a while, I wiped it, it's reinforced!
No, as a first-line programmer, how can you give up lightly!
Shelling
After many thoughts (google), I finally found a fool-style shelling tool dumpDex , which I didn’t expect to be quite easy to use.
After we "clicked unpacking", we /data/data/com.huimai365/dump
found a lot of dex files under the folder, and felt that we were one step closer to success!
The next step is physical work. We pull all dex down, and use the dex2jar tool to convert dex to jar one by one. To this end, I wrote a batch operation script, the "xxx" directory stores all the dex files
dir=../xxx/
for file in $dir/*; do
./d2j-dex2jar.sh $file
done
复制代码
Then use JD-GUI to find the package name we need com.huimai365
. Fortunately, I finally found it. Unfortunately, the code is confusing. You guys can!
Analysis code
Let's first analyze with the toes, this detection Xposed is basically executed in Application
the onCreate
method, and then pop up the window. Okay, then we will look for the Application
classes they implement themselves .
Then analyze onCreate
the method
I found a ar.a();
way, click in and take a look, sure enough! (Here is only part of the code shown) Not only does it detect Xposed, but I also want to turn off Xposed, Woj!
public class ar
{
public static void a()
{
try
{
Field localField = ClassLoader.getSystemClassLoader().loadClass("de.robv.android.xposed.XposedBridge").getDeclaredField("disableHooks");
localField.setAccessible(true);
localField.set(null, Boolean.valueOf(true));
return;
}
catch (Throwable localThrowable) {}
}
public static boolean a(Context paramContext)
{
return (b(paramContext)) || (c(paramContext)) || (b()) || (c());
}
private static boolean b(Context paramContext)
{
paramContext = paramContext.getPackageManager().getInstalledApplications(128);
if (paramContext == null) {
return false;
}
paramContext = paramContext.iterator();
boolean bool = false;
if (paramContext.hasNext())
{
ApplicationInfo localApplicationInfo = (ApplicationInfo)paramContext.next();
if (localApplicationInfo.packageName.equals("de.robv.android.xposed.installer"))
{
ac.d("HookDetection", "Xposed found on the system.");
bool = true;
}
if (!localApplicationInfo.packageName.equals("com.saurik.substrate")) {
break label92;
}
ac.d("HookDetection", "Substrate found on the system.");
bool = true;
}
label92:
for (;;)
{
break;
return bool;
}
}
private static boolean c()
{
try
{
Object localObject = ClassLoader.getSystemClassLoader().loadClass("de.robv.android.xposed.XposedHelpers").newInstance();
if (localObject != null) {
if ((!a(localObject, "fieldCache")) && (!a(localObject, "methodCache")))
{
boolean bool = a(localObject, "constructorCache");
if (!bool) {}
}
else
{
return true;
}
}
}
catch (Throwable localThrowable) {}
return false;
}
}
复制代码
Hook method
From the above analysis, we only need ar
the a()
sum a(Context paramContext)
method in Hook . Then do it!
public class XposedHookInit implements IXposedHookLoadPackage {
private static final String TAG = "XposedHookInit";
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if ("com.huimai365".equals(lpparam.packageName)) {
Log.e(TAG, "Find 优品惠 " + lpparam.packageName);
hookCheckoutXposed(lpparam.classLoader);
}
}
private void hookCheckoutXposed(ClassLoader classLoader) {
XposedHelpers.findAndHookMethod("com.huimai365.util.ar", classLoader, "a", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
Log.e(TAG, "Replace close xposed");
return null;
}
});
XposedHelpers.findAndHookMethod("com.huimai365.util.ar", classLoader, "a", Context.class, new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
Log.e(TAG, "Replace find xposed");
return false;
}
});
}
}
复制代码
But things are not as simple as imagined, an error was reported
2019-01-17 12:46:17.038 5888-5888/? E/Xposed: de.robv.android.xposed.XposedHelpers$ClassNotFoundError: java.lang.ClassNotFoundException: com.huimai365.util.ar
at de.robv.android.xposed.XposedHelpers.findClass(XposedHelpers.java:71)
at de.robv.android.xposed.XposedHelpers.findAndHookMethod(XposedHelpers.java:260)
at com.example.xposeddemo.XposedHookInit.hookCheckoutXposed(XposedHookInit.java:35)
at com.example.xposeddemo.XposedHookInit.handleLoadPackage(XposedHookInit.java:20)
at de.robv.android.xposed.IXposedHookLoadPackage$Wrapper.handleLoadPackage(IXposedHookLoadPackage.java:34)
at de.robv.android.xposed.callbacks.XC_LoadPackage.call(XC_LoadPackage.java:61)
at de.robv.android.xposed.callbacks.XCallback.callAll(XCallback.java:106)
at de.robv.android.xposed.XposedInit$2.beforeHookedMethod(XposedInit.java:134)
at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:340)
at android.app.ActivityThread.handleBindApplication(<Xposed>)
at android.app.ActivityThread.-wrap2(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1546)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6121)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:107)
Caused by: java.lang.ClassNotFoundException: com.huimai365.util.ar
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:400)
at external.org.apache.commons.lang3.ClassUtils.getClass(ClassUtils.java:823)
复制代码
analyse problem
Why is there this class but ClassNotFoundError? To understand the principle of reinforcement, we learned that after the original APP was packed, the classloader was changed. Therefore, when we use the original classloader, an exception that the class cannot be found will be reported. This app uses Tencent’s Legu, and we see that AndroidManifest.xml
the application inside has been replaced withcom.tencent.StubShell.TxAppEntry
Then let's take a look at TxAppEntry
this class, which is in the unpacked classes.dex
file.
protected void attachBaseContext(Context paramContext)
{
super.attachBaseContext(paramContext);
SystemClassLoaderInjector.fixAndroid(paramContext, this);
if (!b(this)) {
return;
}
d(paramContext);
a(this);
}
复制代码
It turns out that the classloader is changed here, so we can get the changed classloader and then hook it? ! OK, OK, OK, let's change the position and do it again
public class XposedHookInit implements IXposedHookLoadPackage {
private static final String TAG = "XposedHookInit";
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if ("com.huimai365".equals(lpparam.packageName)) {
Log.e(TAG, "Find 优品惠 " + lpparam.packageName);
XposedHelpers.findAndHookMethod("com.tencent.StubShell.TxAppEntry", lpparam.classLoader,
"attachBaseContext", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
//获取到Context对象,通过这个对象来获取classloader
Context context = (Context) param.args[0];
//获取classloader,之后hook加固后的就使用这个classloader
ClassLoader realClassLoader = context.getClassLoader();
//下面就是将classloader修改成壳的classloader就可以成功的hook了
hookCheckoutXposed(realClassLoader);
}
});
}
}
private void hookCheckoutXposed(ClassLoader classLoader) {
XposedHelpers.findAndHookMethod("com.huimai365.util.ar", classLoader, "a", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
Log.e(TAG, "Replace close xposed");
return null;
}
});
XposedHelpers.findAndHookMethod("com.huimai365.util.ar", classLoader, "a", Context.class, new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
Log.e(TAG, "Replace find xposed");
return false;
}
});
}
}
复制代码
ending
Ah, the whole world is quiet. As the body shivered, this app became dull...
to sum up
In fact, I am only integrating various tools here, and most of the knowledge is obtained from the Internet. I hope that it will be a good start, so that readers can gain a little bit. Moreover, sincerely admiring these tools-making greats, it seems that I still have a long way to go!
In fact, this is also the first time I write a technical article. I specifically put it on the Nuggets, because this is my favorite domestic platform (no one). I hope that the Nuggets will get better and better. Don't forget the original intention!
Reference
Sorry, Xposed can really do whatever you want-5. Why don't I use Xposed that I brushed myself?