Skip to content

Commit

Permalink
Initial version (1.0)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tungstwenty committed Jul 31, 2014
1 parent a9ad1da commit e910c46
Show file tree
Hide file tree
Showing 17 changed files with 646 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="lib" path="lib/XposedBridgeApi-52.jar"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin
/gen
33 changes: 33 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>FakeIDFix</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
291 changes: 291 additions & 0 deletions .settings/org.eclipse.jdt.core.prefs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions .settings/org.eclipse.jdt.ui.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
eclipse.preferences.version=1
formatter_profile=_Tungstwenty
formatter_settings_version=12
31 changes: 31 additions & 0 deletions AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="tungstwenty.xposed.fakeidfix"
android:versionCode="1"
android:versionName="1.0" xmlns:tools="http://schemas.android.com/tools">

<uses-sdk android:minSdkVersion="15" tools:ignore="UsesMinSdkAttributes"/>

<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" android:allowBackup="false">
<activity
android:name="tungstwenty.xposed.fakeidfix.XposedModActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="de.robv.android.xposed.category.MODULE_SETTINGS" />
</intent-filter>
</activity>
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="@string/app_mod_summary" />
<meta-data
android:name="xposedminversion"
android:value="52+" />
</application>

</manifest>
1 change: 1 addition & 0 deletions assets/xposed_init
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tungstwenty.xposed.fakeidfix.XposedMod
Binary file added lib/XposedBridgeApi-52.jar
Binary file not shown.
11 changes: 11 additions & 0 deletions project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.

# Project target.
target=android-15
Binary file added res/drawable-hdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-ldpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-mdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-xhdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions res/layout/main.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/about_title"
android:textAppearance="@android:style/TextAppearance.Medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/about_author" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/about_description" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/about_noconfigs" />
<TextView
android:id="@+id/tvActive"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/about_active"
android:textColor="@android:color/holo_green_dark" />
<TextView
android:id="@+id/tvNotActive"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/about_notactive"
android:textColor="@android:color/holo_red_dark" />
</LinearLayout>
</ScrollView>
22 changes: 22 additions & 0 deletions res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Fake ID fix</string>
<string name="app_mod_summary">Patch the system against the Fake ID vulnerability (bug 13678484)</string>

<string name="about_title">Android vulnerability fix</string>
<string name="about_author">By <a href="mailto:Tungstwenty@gmail.com">Tungstwenty</a> @ <a href="http://forum.xda-developers.com/member.php?u=4322181">XDA Developers</a></string>
<string name="about_description">This patch fixes the Fake ID vulnerability (bug 13678484).\n\nThe bug allows malicious apps to pretend to be signed by trusted providers and be loaded as extensions
in several contexts, such as NFC access, browser plugins and others, depending on the device and which extension
mechanisms the manufacturer chose to include.
\n
\nA great explanation of the implications and why the problem occurs can be found on <a href="http://bluebox.com/technical/android-fake-id-vulnerability/">this article</a> by
Jeff Forristal from Bluebox.
\n\nFor any questions, please visit <a href="http://forum.xda-developers.com/xposed/modules/mod-fakeid-vulnerability-fix-t2833854">this thread</a>.</string>
<string name="about_noconfigs">This appliction does not have any configurations.
It is an Xposed mod that should be enabled on its framework manager to produce effects!</string>
<string name="about_active">The patch is active. You should be protected from
this vulnerability.</string>
<string name="about_notactive"><b>Note</b>: The patch is not active! Verify that the
<a href="http://forum.xda-developers.com/xposed/xposed-installer-versions-changelog-t2714053">Xposed framework</a> is running properly
and that this module is enabled. If so, check the Xposed logs for any errors.</string>
</resources>
Expand Down
161 changes: 161 additions & 0 deletions src/tungstwenty/xposed/fakeidfix/XposedMod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package tungstwenty.xposed.fakeidfix;

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

import java.lang.reflect.Method;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.LinkedList;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.IXposedHookZygoteInit;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;

public class XposedMod implements IXposedHookZygoteInit, IXposedHookLoadPackage {

private static final String THIS_PACKAGE = XposedMod.class.getPackage().getName();
private static final String BLUEBOX_PACKAGE = "com.bluebox.labs.onerootscanner";

private static boolean hookSuccessful = false;

private static final ThreadLocal<Object> insideCollectCertificates = new ThreadLocal<Object>();

@Override
public void initZygote(StartupParam startupParam) throws Throwable {

boolean romAlreadyFixed;
try {
XposedHelpers.findMethodExact("org.apache.harmony.security.utils.JarUtils", null, "createChain",
X509Certificate.class, X509Certificate[].class, boolean.class);
romAlreadyFixed = true;
} catch (Throwable t) {
romAlreadyFixed = false;
}

if (romAlreadyFixed) {
hookSuccessful = true;
return;
}

findAndHookMethod("org.apache.harmony.security.utils.JarUtils", null, "createChain", X509Certificate.class,
X509Certificate[].class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
if (insideCollectCertificates.get() == null) {
// Not in a relevant place, default to previous behavior
return;
}

try {
X509Certificate signer = (X509Certificate) param.args[0];
X509Certificate[] candidates = (X509Certificate[]) param.args[1];
param.setResult(createChain_fix(signer, candidates));
} catch (Throwable t) {
// If any exception occurs, send it to the caller as the invocation result
// instead of having Xposed fallback to the original (unpatched) method
param.setThrowable(t);
}
}
});

findAndHookMethod("android.content.pm.PackageParser", null, "collectCertificates",
"android.content.pm.PackageParser$Package", int.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
insideCollectCertificates.set("dummy");
}

@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
insideCollectCertificates.set(null);
}
});

// All hooks installed successfully
hookSuccessful = true;
}

@SuppressWarnings({ "rawtypes", "unchecked" })
private static X509Certificate[] createChain_fix(X509Certificate signer, X509Certificate[] candidates) {
LinkedList chain = new LinkedList();
chain.add(0, signer);
// Signer is self-signed
if (signer.getSubjectDN().equals(signer.getIssuerDN())) {
return (X509Certificate[]) chain.toArray(new X509Certificate[1]);
}
Principal issuer = signer.getIssuerDN();
X509Certificate issuerCert;
X509Certificate subjectCert = signer;
int count = 1;
while (true) {
issuerCert = findCert_fix(issuer, candidates, subjectCert, true);
if (issuerCert == null) {
break;
}
chain.add(issuerCert);
count++;
if (issuerCert.getSubjectDN().equals(issuerCert.getIssuerDN())) {
break;
}
issuer = issuerCert.getIssuerDN();
subjectCert = issuerCert;
}
return (X509Certificate[]) chain.toArray(new X509Certificate[count]);
}

private static X509Certificate findCert_fix(Principal issuer, X509Certificate[] candidates,
X509Certificate subjectCert, boolean chainCheck) {
for (int i = 0; i < candidates.length; i++) {
if (issuer.equals(candidates[i].getSubjectDN())) {
if (chainCheck) {
try {
subjectCert.verify(candidates[i].getPublicKey());
} catch (Exception e) {
continue;
}
}
return candidates[i];
}
}
return null;
}

@Override
public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
if (!hookSuccessful) {
// Hooks not installed, don't report success to the activity nor the Bluebox scanner
return;
}

if (THIS_PACKAGE.equals(lpparam.packageName)) {
findAndHookMethod(XposedModActivity.class.getName(), lpparam.classLoader, "isActive",
XC_MethodReplacement.returnConstant(true));
}

if (BLUEBOX_PACKAGE.equals(lpparam.packageName)) {
// Change the reported "createChain" method signature to Bluebox Security Scanner so it marks the bug as
// fixed
findAndHookMethod(Method.class, "getParameterTypes", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Method m = (Method) param.thisObject;
if ("createChain".equals(m.getName())
&& "org.apache.harmony.security.utils.JarUtils".equals(m.getDeclaringClass().getName())) {
Class<?>[] result = (Class<?>[]) param.getResult();
if (result.length == 2) {
// Simulate that the method receives a 3rd parameter, boolean
Class<?>[] newResult = new Class<?>[3];
System.arraycopy(result, 0, newResult, 0, 2);
newResult[2] = boolean.class;
param.setResult(newResult);
}
}
}
});
}
}

}
38 changes: 38 additions & 0 deletions src/tungstwenty/xposed/fakeidfix/XposedModActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package tungstwenty.xposed.fakeidfix;

import android.app.Activity;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class XposedModActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

ViewGroup vg = (ViewGroup) getLayoutInflater().inflate(R.layout.main, null);
makeTextViewsClickable(vg);
setContentView(vg);

boolean isActive = isActive();
((TextView) findViewById(R.id.tvActive)).setVisibility(isActive ? View.VISIBLE : View.GONE);
((TextView) findViewById(R.id.tvNotActive)).setVisibility(isActive ? View.GONE : View.VISIBLE);
}

private static void makeTextViewsClickable(ViewGroup vg) {
for (int i = vg.getChildCount() - 1; i >= 0; i--) {
View v = vg.getChildAt(i);
if (v instanceof TextView)
((TextView) v).setMovementMethod(LinkMovementMethod.getInstance());
else if (v instanceof ViewGroup)
makeTextViewsClickable((ViewGroup) v);
}
}

public static boolean isActive() {
return false;
}
}

0 comments on commit e910c46

Please sign in to comment.