Permalink
Browse files

switched from substrate to xposed

  • Loading branch information...
UweM committed May 31, 2015
1 parent 1eeed27 commit aeb3fc65545b59cc9f0a27982cc1f4e280177cb5
View
@@ -7,10 +7,10 @@ NFCGate is an Android application meant to relay communication between an NFC re
This application was developed for security research purposes by students of the [TU Darmstadt](https://www.tu-darmstadt.de/), [Secure Mobile Networking Lab](https://www.seemoo.tu-darmstadt.de/). Please do not use this application for malicious purposes.
## Requirements
- Two android phones with NFC Chips, running Android 4.4+ (API-Level 19+). Android 5 is not compatible with Substrate and will not work (see [#57](https://github.com/malexmave/nfcgate/issues/57) for the current state of our efforts to change that).
- Two android phones with NFC Chips, running Android 4.4+ (API-Level 19+).
- At least one of these devices needs to support HCE (Host Card Emulation). Most NFC-Enabled phones of the last few years should support that.
- The HCE phone needs to use `libnfc-nci` (compatible phones include the Nexus 4 and 5, more on that below).
- The HCE phone needs to be rooted and have [Cydia Substrate](http://www.cydiasubstrate.com/) installed and enabled (see [here](https://github.com/malexmave/nfcgate/wiki/Cydia-Substrate) for help on how to get that done)
- The HCE phone needs to be rooted and have [Xposed](http://repo.xposed.info/) installed and enabled
- One server to proxy communication between the two phones (see [nfcgate-misc](https://github.com/malexmave/nfcgate-misc) repository for server code)
## Requirements for compilation
@@ -20,7 +20,7 @@ This application was developed for security research purposes by students of the
## Usage
The usage of this application is a bit fiddly right now, so follow these instructions exactly in order to make sure everything works.
After having installed and activated Cydia Substrate on at least one of the devices, install the application. Cydia Substrate will prompt you to reboot your phone, which you should do. Only the HCE device requires Cydia Substrate, the other one can work without it.
After having installed and activated Xposed on at least one of the devices, install the application. Xposed will prompt you to reboot your phone, which you should do. Only the HCE device requires Xposed, the other one can work without it.
Afterwards, launch the app on both phones. Enter the IP and Port of the Server (default Port is 5566, feel free to set default values in the settings to avoid having to type them in each time) and hit "Create session" on one of the devices. The device will connect and display a session token with 6 digits. Hit "Join session" on the other device and enter that code. You should now be connected.
@@ -38,7 +38,7 @@ There are some caveats, so read this section carefully before using the applicat
### Native code patch compatibility
Our patch to the android NFC Daemon only works with devices using `libnfc-nci` (not `libnfc-nxp`). If you are unsure what libnfc your device is using, a good rule of thumb is: If it supports HCE, it uses `libnfc-nci`. Our code has been successfully tested on the Nexus 4 and 5, and may or may not work on other devices using the same libnfc (for example, we are currently experiencing some problems with the OnePlus One). On incompatible devices, the application may still start, but it will be unable to proxy commands from the NFC reader. This is due to limitations in the Android API.
The patch is also only compatible with devices that can run Cydia Substrate (e.g. not running Android 5, and not blocking Substrate from working through other methods like SELinux).
The patch is also only compatible with devices that can run Xposed.
### DESFire workaround
The Android NFC Libraries contain a bug which makes it impossible to use our application with MiFare DESFire cards (a common NFC card for payment systems). We are using a workaround to enable us to still read these cards, but that workaround has some side effects. When you start the application, you will get a warning. Please read the information carefully.
@@ -57,6 +57,6 @@ Right now, all data is sent unencrypted over the network. We may or may not get
## Used Libraries
This application uses the following external libraries:
- [Cydia Substrate](http://www.cydiasubstrate.com/) (Unknown license)
- [Xposed](http://repo.xposed.info/) (Licensed under the [Apache License v2.0](http://opensource.org/licenses/Apache-2.0))
- [LibNFC](https://android.googlesource.com/platform/external/libnfc-nci/) (Licensed under the [Apache License v2.0](http://opensource.org/licenses/Apache-2.0))
- [Protobuf](https://code.google.com/p/protobuf/) (Licensed under the [BSD 3-Clause license](http://opensource.org/licenses/BSD-3-Clause))
View
@@ -11,7 +11,7 @@ android {
versionCode 2
versionName "1.1"
ndk {
moduleName "nfcipc"
moduleName "nfcgate-ipc"
cFlags "-std=c++11 -fexceptions"
ldLibs "log"
abiFilters "armeabi"
@@ -26,8 +26,9 @@ android {
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile fileTree(include: ['*.jar'], dir: 'libs')
compile project(':nfcd')
compile files('libs/protobuf-java-2.6.1.jar')
compile 'com.android.support:support-v4:22.0.0'
compile files('libs/XposedBridgeApi-20150213.jar')
}
View
Binary file not shown.
@@ -2,9 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="tud.seemuh.nfcgate" >
<uses-permission android:name="android.permission.NFC" />
<!-- < Wifi Direct > -->
<uses-permission
android:name="android.permission.NFC"
android:required="true" />
<uses-permission
android:name="android.permission.ACCESS_WIFI_STATE"
android:required="true" />
@@ -18,12 +18,23 @@
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:required="true" />
<!-- < / Wifi Direct > -->
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="Modules for NFCGate code hooks" />
<meta-data
android:name="xposedminversion"
android:value="58" />
<activity
android:name=".gui.MainActivity"
android:label="@string/app_name"
@@ -0,0 +1 @@
tud.seemuh.nfcgate.xposed.Hooks
@@ -6,7 +6,7 @@
*/
public class DaemonConfiguration {
static {
System.loadLibrary("nfcipc");
System.loadLibrary("nfcgate-ipc");
mInstance = new DaemonConfiguration();
}
static DaemonConfiguration mInstance;
@@ -0,0 +1,60 @@
package tud.seemuh.nfcgate.xposed;
import android.provider.MediaStore;
import android.util.Log;
import java.io.File;
import static de.robv.android.xposed.XposedHelpers.findAndHookConstructor;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.IXposedHookZygoteInit;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
public class Hooks implements IXposedHookLoadPackage, IXposedHookZygoteInit {
private final String IPC_SOCK_DIR = "/data/data/tud.seemuh.nfcgate/ipc";
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if(!"com.android.nfc".equals(lpparam.packageName))
return;
Log.i("NATIVENFC", "load...");
//System.loadLibrary("nfcgate-native");
System.load("/data/data/tud.seemuh.nfcgate/lib/libnfcgate-native.so");
Log.i("NATIVENFC", "loaded...");
findAndHookMethod("com.android.nfc.cardemulation.HostEmulationManager", lpparam.classLoader, "findSelectAid", byte[].class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.i("HOOKNFC", "beforeHookedMethod");
if (isPatchEnabled()) {
Log.i("HOOKNFC", "enabled");
// setting a result will prevent the original method to run.
// F0010203040506 is a aid registered by the nfcgate hce service
param.setResult("F0010203040506");
}
}
});
}
@Override
public void initZygote(StartupParam startupParam) throws Throwable {
try {
File f = new File(IPC_SOCK_DIR);
if (!f.exists()) {
f.mkdir();
f.setExecutable(true, false);
f.setReadable(true, false);
f.setWritable(true, false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public native boolean isPatchEnabled();
}
@@ -97,6 +97,7 @@ JNIEXPORT void JNICALL Java_tud_seemuh_nfcgate_nfc_hce_DaemonConfiguration_uploa
* connect to the nfc daemon
*/
void connect() {
LOGI("connect");
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
LOGE("E socket: %s", strerror(errno));
@@ -12,7 +12,7 @@
<string name="state_loading">Loading...</string>
<string name="aboutpage">DISCLAIMER \n \n \nThis application was built solely for research purposes. Do NOT misuse this application for malicious activities. \n \nThis application is licensed under the TBD license.\nIt uses the following libraries:\n - Cydia Substrate (Licensed under the LGPLv3)\n - LibNFC (Licensed under the Apache License, v2.0)\n - Protobuf (Licensed under the BSD 3-Clause license) \n \nWe take no responsibility for, and will not be liable for, the application behaving silly due to technical issues beyond our control. \n \n \n \n NFCgate v1.0 </string>
<string name="aboutpage">DISCLAIMER \n \n \nThis application was built solely for research purposes. Do NOT misuse this application for malicious activities. \n \nThis application is licensed under the TBD license.\nIt uses the following libraries:\n - Xposed (Licensed under the Apache License, v2.0)\n - LibNFC (Licensed under the Apache License, v2.0)\n - Protobuf (Licensed under the BSD 3-Clause license) \n \nWe take no responsibility for, and will not be liable for, the application behaving silly due to technical issues beyond our control. \n \n \n \n NFCgate v1.0 </string>
<string name="Yes">Yes</string>
<string name="No">No</string>
View
0 gradlew 100755 → 100644
No changes.
View
@@ -10,9 +10,9 @@ android {
versionCode 1
versionName "1.0"
ndk {
moduleName "nfc.cy"
moduleName "nfcgate-native"
cFlags "-std=c++11 -fexceptions"
ldLibs "log", "substrate-dvm", "substrate -L${project.buildDir}/../src/main/libs/armeabi"
ldLibs "log"
abiFilters "armeabi"
}
}
@@ -2,6 +2,4 @@
package="tud.seemuh.nfcgate.nfcd">
<uses-permission android:name="cydia.permission.SUBSTRATE"/>
</manifest>
@@ -1,6 +1,7 @@
#include "nfcd.h"
#include <cstring>
/**
* Commands of the broadcom configuration interface
*/
View

This file was deleted.

Oops, something went wrong.
View
@@ -1,68 +1,57 @@
#include "nfcd.h"
#include "vendor/hook.h"
#include <dlfcn.h>
#include <unistd.h>
#include <stdio.h>
bool patchEnabled = false;
static void onHostEmulationLoad(JNIEnv *jni, jclass _class, void *data);
static void hookNative();
const char *hooklibfile = "/system/lib/libnfc-nci.so";
/**
* configure substrate to hook into the app_process process (zygote)
*/
MSConfig(MSFilterExecutable, "/system/bin/app_process")
/**
* intialize call of substrate
*/
MSInitialize {
// when in zygote, register for a callback when the HostEmulationManager gets loaded.
// this is our signal that we reached the nfc daemon process
const char *classname = "com/android/nfc/cardemulation/HostEmulationManager";
MSJavaHookClassLoad(NULL, classname, &onHostEmulationLoad);
ipc_prepare();
}
static void onModuleLoad() __attribute__((constructor));
/**
* callback when HostEmulationManager gets loaded.
* => we are now in the nfc daemon process
*/
static void onHostEmulationLoad(JNIEnv *jni, jclass _class, void *data) {
LOGI("onHostEmulationLoad, loading hooks");
// hooking into the java and native part of the nfcd
hookJava(jni, _class);
void onModuleLoad() {
LOGI("onModuleLoad::begin");
hookNative();
ipc_init();
LOGI("onModuleLoad::end");
}
JNIEXPORT jboolean JNICALL Java_tud_seemuh_nfcgate_xposed_Hooks_isPatchEnabled(JNIEnv* env, jobject javaThis) {
return patchEnabled;
}
/**
* find a native symbol and hook it
*/
static void findAndHook(void *handle, const char *symbol, void* hook, void **original) {
void *fptr = dlsym(handle, symbol);
if(fptr) {
MSHookFunction(fptr, hook, original);
LOGI("hooked: %s", symbol);
} else {
LOGE("could NOT hook: %s", symbol);
}
static void findAndHook(void* handle, const char *symbol, void* hook, void **original) {
*original = dlsym(handle, symbol);
do_hook(hooklibfile, (uint32_t)hook, symbol);
LOGI("hooked: %s", symbol);
}
/**
* hook into native functions of the libnfc-nci broadcom nfc driver
*/
static void hookNative() {
const char *libfile = "/system/lib/libnfc-nci.so";
if(access(libfile, F_OK) == -1) {
LOGE("could not access %s to load symbols", libfile);
if(access(hooklibfile, F_OK) == -1) {
LOGE("could not access %s to load symbols", hooklibfile);
return;
}
void *handle = dlopen(hooklibfile, 0);
void *handle = dlopen(libfile, 0);
findAndHook(handle, "NFC_SetStaticRfCback", (void*)&hook_SetRfCback, (void**)&nci_SetRfCback);
//findAndHook(handle, "dummy", (void*)&hook_NfcSetConfig, (void**)&nci_NfcSetConfig);
findAndHook(handle, "NFC_SetConfig", (void*)&hook_NfcSetConfig, (void**)&nci_NfcSetConfig);
findAndHook(handle, "NFC_SetStaticRfCback", (void*)&hook_SetRfCback, (void**)&nci_SetRfCback);
if(nci_NfcSetConfig == hook_NfcSetConfig) LOGI("original missing");
// find pointer to ce_t4t control structure
ce_cb = (tCE_CB*)dlsym(handle, "ce_cb");
View
@@ -1,9 +1,11 @@
#ifndef __ANDROID__
#define __ANDROID__
#endif
#include <android/log.h>
#include <jni.h>
#include "vendor/substrate.h"
#include <stdint.h>
#include "vendor/libnfc.h"
#define LOG_TAG "NATIVENFC"
Oops, something went wrong.

0 comments on commit aeb3fc6

Please sign in to comment.