package com.taobao.dexposed;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import com.taobao.android.dexposed.DexposedBridge;
import com.taobao.android.dexposed.XC_MethodHook;
import com.taobao.patch.PatchMain;
import com.taobao.patch.PatchResult;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
static {
// load xposed lib for hook.
try {
if (android.os.Build.VERSION.SDK_INT == 22) {
System.loadLibrary("dexposed_l51");
} else if (android.os.Build.VERSION.SDK_INT > 19 && android.os.Build.VERSION.SDK_INT <= 21) {
System.loadLibrary("dexposed_l");
} else if (android.os.Build.VERSION.SDK_INT > 14) {
System.loadLibrary("dexposed");
}
} catch (Throwable e) {
e.printStackTrace();
}
}
private boolean isSupport = false;
private boolean isLDevice = false;
private TextView mLogContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLogContent = (TextView) (this.findViewById(R.id.log_content));
// check device if support and auto load libs
isSupport = true;
isLDevice = android.os.Build.VERSION.SDK_INT >= 20;
}
public void hookjava(View view) {
DexposedBridge.findAndHookMethod(System.class, "setProperty", String.class, String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// hook 参数
String tag = (String) param.args[0];
// String msg = (String) param.args[1];
if (tag.startsWith("ijm")) {
param.args[1] = "you have been hooked";
}
Log.i(TAG, "beforeHookedMethod");
}
@Override
protected void afterHookedMethod(MethodHookParam arg0) throws Throwable {
String tag = (String) arg0.args[0];
String msg = (String) arg0.args[1];
mLogContent.setText(tag + "," + msg);
Log.i(TAG, "afterHookedMethod");
}
});
DexposedBridge.findAndHookMethod(TelephonyManager.class, "getDeviceId", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// hook 返回值
Log.i(TAG, "beforeHookedMethod param.args.length=" + param.args.length);
param.setResult("1024_" + (int) (Math.random() * 1000));
}
});
DexposedBridge.findAndHookMethod(TelephonyManager.class, "getNetworkOperatorName", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// hook 返回值
param.setResult("networkOperatorName_hook");
}
});
DexposedBridge.findAndHookMethod(TelephonyManager.class, "getSubscriberId", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// hook 返回值
param.setResult("hook 310260000000000");
}
});
DexposedBridge.findAndHookMethod(SmsManager.class, "sendTextMessage",
String.class, String.class, String.class,
PendingIntent.class, PendingIntent.class,new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.i(TAG, "hook sendTextMessage "+param.args[0].toString());
Log.i(TAG, param.args[1].toString());
Log.i(TAG, param.args[2].toString());
}
});
DexposedBridge.findAndHookMethod(Log.class, "e", String.class,String.class,new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.i("", "beforeHookedMethod loge");
//param.set
//hook住不调用该方法,直接返回了,已经有返回值就就不调用系统的log.e方法了
param.setResult(-1);
//param.setThrowable(new Throwable("hehe"));
//param.setThrowable(new RuntimeException("hehe"));
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//super.afterHookedMethod(param);
Log.i("", "afterHookedMethod loge");
}
});
DexposedBridge.findAndHookMethod(MainActivity.class, "showLog", String.class,String.class,new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.i("", "beforeHookedMethod showLog");
//hook住不调用该方法,直接返回了,已经有返回值就就不调用系统的log.e方法了
//param.setResult(-1);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Log.i("", "afterHookedMethod showLog");
}
});
Log.i(TAG, "hookjava ok");
}
public void testhookjava(View view) {
System.setProperty("ijm_name", "1024_ijm");
Log.i(TAG, System.getProperty("ijm_name"));
System.setProperty("test", "1024_test");
Log.i(TAG, System.getProperty("test"));
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Activity.TELEPHONY_SERVICE);
String deviceId = telephonyManager.getDeviceId();
Log.i(TAG, "deviceId=" + deviceId);
String networkOperatorName = telephonyManager.getNetworkOperatorName();
Log.i(TAG, "networkOperatorName=" + networkOperatorName);
String subscriberId = telephonyManager.getSubscriberId();
Log.i(TAG, "subscriberId=" + subscriberId);
Log.e(TAG, "test log e");
SmsManager smsManager=SmsManager.getDefault();
smsManager.sendTextMessage("110", "120", "test sms", null, null);
showLog(TAG, "showLog");
try {
Field idField = Build.class.getDeclaredField("ID");
idField.setAccessible(true);
Log.i(TAG, "Build.ID old=" + Build.ID);
idField.set(Build.class, "changed");
Log.i(TAG, "Build.ID new=" + Build.ID);
Log.i(TAG, "SDK_INT=" + Build.VERSION.SDK_INT);
Field sdk_int_Field = Build.VERSION.class.getDeclaredField("SDK_INT");
sdk_int_Field.setAccessible(true);
sdk_int_Field.setInt(Build.VERSION.class, 10);
Log.i(TAG, "new SDK_INT=" + Build.VERSION.SDK_INT);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void testhookjava2(View view) {
Log.i(TAG, "Build.ID=" + Build.ID);
}
// Hook system log click
public void hookSystemLog(View view) {
if (isSupport) {
DexposedBridge.findAndHookMethod(isLDevice ? this.getClass() : Log.class, isLDevice ? "showLog" : "d",
String.class, String.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam arg0) throws Throwable {
String tag = (String) arg0.args[0];
String msg = (String) arg0.args[1];
mLogContent.setText(tag + "," + msg);
}
});
if (isLDevice) {
showLog("dexposed", "It doesn't support AOP to system method on ART devices");
} else {
Log.d("dexposed", "Logs are redirected to display here");
}
} else {
mLogContent.setText("This device doesn't support dexposed!");
}
}
private void showLog(String tag, String msg) {
Log.d(tag, msg);
}
// Hook choreographer click
public void hookChoreographer(View view) {
Log.d("dexposed", "hookChoreographer button clicked.");
if (isSupport && !isLDevice) {
ChoreographerHook.instance().start();
} else {
showLog("dexposed", "This device doesn't support this!");
}
}
// Run patch apk
@SuppressLint("NewApi")
public void runPatchApk(View view) {
Log.d("dexposed", "runPatchApk button clicked.");
if (isLDevice) {
showLog("dexposed", "It doesn't support this function on L device.");
return;
}
if (!isSupport) {
Log.d("dexposed", "This device doesn't support dexposed!");
return;
}
File cacheDir = getExternalCacheDir();
if (cacheDir != null) {
String fullpath = cacheDir.getAbsolutePath() + File.separator + "patch.apk";
Log.d("Hotpatch", "fullpath=" + fullpath);
PatchResult result = PatchMain.load(this, fullpath, null);
if (result.isSuccess()) {
Log.e("Hotpatch", "patch success!");
} else {
Log.e("Hotpatch", "patch error is " + result.getErrorInfo());
}
}
showDialog();
}
private void showDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
File cacheDir = getExternalCacheDir();
String fullpath = cacheDir.getAbsolutePath() + File.separator + "patch.apk";
builder.setTitle("Dexposed sample")
.setMessage("Please clone patchsample project to generate apk, and copy it to " + fullpath)
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
}).create().show();
}
}