Skip to content

Commit

Permalink
参考了Inspeckage的实现,但是做得比它更优雅。
Browse files Browse the repository at this point in the history
小米Max,Android 7测试成功。
  • Loading branch information
Monkeylord committed Mar 29, 2019
1 parent 40cd02a commit 4a9cc7e
Show file tree
Hide file tree
Showing 10 changed files with 35 additions and 179 deletions.
8 changes: 6 additions & 2 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ android {
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "0.4.7"
versionName "0.5.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
Expand Down
5 changes: 0 additions & 5 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@
android:name="xposeddescription"
android:value="Dynamic trace/invoke via http-server" />

<service
android:name=".utils.TargetService"
android:enabled="true"
android:exported="true"
android:persistent="true"></service>
</application>

</manifest>
2 changes: 1 addition & 1 deletion app/src/main/assets/pages/methodview.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ <h1>Monitor</h1>
var messages="";
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket(document.origin.replace("http","ws")+"/methodview?class=${class}&method=${method}&javaname=${javaName}");
websocket = new WebSocket(document.location.origin.replace("http","ws")+"/methodview?class=${class}&method=${method}&javaname=${javaName}");
}
else {
alert('当前浏览器 Not support websocket')
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/assets/pages/tracer.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
var messages="";
var timer;
if ('WebSocket' in window) {
websocket = new WebSocket(document.origin.replace("http","ws"));
websocket = new WebSocket(document.location.origin.replace("http","ws"));
}
else {
alert('Current Browser Not support websocket')
Expand Down
48 changes: 7 additions & 41 deletions app/src/main/java/monkeylord/XServer/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.os.MemoryFile;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
Expand All @@ -19,31 +16,25 @@
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.List;

import monkeylord.XServer.utils.TargetService;
import monkeylord.XServer.utils.netUtil;

public class MainActivity extends Activity {
SharedPreferences sp;
String hookee;
boolean isReg;
TextView info;
EditText appname;
File sharedFile=null;
MemoryFile memFile=null;
//CheckBox regEx;

private static boolean isModuleActive() {
return false;
}
private File getFile(){ return null; }

public void makeWorldReadable(){
new File("/data/data/" + XServer.class.getPackage().getName().toLowerCase()).setExecutable(true, false);
new File("/data/data/" + XServer.class.getPackage().getName().toLowerCase() + "/shared_prefs/XServer.xml").setReadable(true, false);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand All @@ -54,18 +45,9 @@ protected void onCreate(Bundle savedInstanceState) {
ViewGroup.LayoutParams.WRAP_CONTENT);
layout.setOrientation(LinearLayout.VERTICAL);
super.setContentView(layout, param);
sp = getSharedPreferences("XServer", MODE_PRIVATE);
sharedFile=getFile();
sp = getSharedPreferences("XServer", isModuleActive()?MODE_WORLD_READABLE:MODE_PRIVATE);
makeWorldReadable();
hookee = sp.getString("targetApp", "com.");
/*
try {
if(memFile!=null)hookee = new BufferedReader(new InputStreamReader(memFile.getInputStream())).readLine();
else if(sharedFile!=null)hookee = new BufferedReader(new FileReader(sharedFile)).readLine();
else hookee = sp.getString("targetApp", "com.");
} catch (Exception e) {
hookee = sp.getString("targetApp", "com.");
}
*/
//isReg = sp.getBoolean("isReg", false);
final AppAdapter appAdapter = new AppAdapter(this);
final AlertDialog selector = new AlertDialog.Builder(this)
Expand Down Expand Up @@ -129,29 +111,13 @@ public void onClick(View view) {
layout.addView(selectApp);
layout.addView(tips);
update();
//启动目标指示服务
startService(new Intent(this,TargetService.class));
}

public void update() {
SharedPreferences.Editor editor = sp.edit();
editor.putString("targetApp", hookee);
//editor.putBoolean("isReg", isReg);
editor.commit();
if(memFile!=null)try{
BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(memFile.getOutputStream()));
writer.write(hookee.trim());
writer.newLine();
writer.flush();
}catch (IOException e){
e.printStackTrace();
}else if(sharedFile!=null) try {
BufferedWriter writer=new BufferedWriter(new FileWriter(sharedFile));
writer.write(hookee);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
info.setText("Target App:\r\n" + hookee);
appname.setText(hookee);
//regEx.setChecked(isReg);
Expand Down
105 changes: 17 additions & 88 deletions app/src/main/java/monkeylord/XServer/XposedEntry.java
Original file line number Diff line number Diff line change
@@ -1,39 +1,16 @@
package monkeylord.XServer;

import android.content.BroadcastReceiver;
import android.app.AndroidAppHelper;
import android.content.pm.ApplicationInfo;
import android.content.res.XModuleResources;
import android.os.MemoryFile;
import android.os.Process;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.IXposedHookZygoteInit;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XSharedPreferences;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import monkeylord.XServer.utils.NanoHTTPD;
import monkeylord.XServer.utils.netUtil;


/*
某些Android 4版本,需要修改依赖库的配置才能兼容,否则会报pre-verifed错误。
Expand All @@ -47,49 +24,37 @@ public class XposedEntry implements IXposedHookLoadPackage, IXposedHookZygoteIni
public static boolean debug=true;
public static ClassLoader classLoader;
public static XModuleResources res;
static File sharedFile;
static MemoryFile memFile;
String targetApp = new XSharedPreferences(this.getClass().getPackage().getName().toLowerCase(), "XServer").getString("targetApp", "MadMode");
public static XSharedPreferences sPrefs;
String packageName;
Boolean isFirstApplication;
String processName;
ApplicationInfo appInfo;

@Override
public void initZygote(StartupParam startupParam) throws Throwable {
res = XModuleResources.createInstance(startupParam.modulePath, null);
sPrefs = new XSharedPreferences(this.getClass().getPackage().getName().toLowerCase(), "XServer");
sPrefs.makeWorldReadable();
}

@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {

//告知界面模块已启动
//告知界面模块已启动,同时解除Android N以上对MODE_WORLD_READABLE的限制
if (loadPackageParam.packageName.equals("monkeylord.xserver")) {
XposedHelpers.findAndHookMethod("monkeylord.XServer.MainActivity", loadPackageParam.classLoader, "isModuleActive", XC_MethodReplacement.returnConstant(true));
XposedHelpers.findAndHookMethod("monkeylord.XServer.MainActivity", loadPackageParam.classLoader, "getFile", XC_MethodReplacement.returnConstant(sharedFile));
}
//System Server方法(这次应该兼容MIUI了)
if(loadPackageParam.packageName.equals("android")){
//systemServer();
return;
}else {
String App=new netUtil("http://127.0.0.1:7999/","",null).getRet();
if(App.length()>0)targetApp=App;
XposedHelpers.findAndHookMethod("android.app.ContextImpl", loadPackageParam.classLoader, "checkMode",int.class, XC_MethodReplacement.returnConstant(null));
}
XposedBridge.log("[XServer Debug]:ThisApp->"+loadPackageParam.packageName);
XposedBridge.log("[XServer Debug]:TargetApp->"+targetApp);
//刷新目标APP名称
//从共享文件中刷新目标APP名称(For Android 7.0, MIUI not compatible, sad...)
/*
String memApp=new BufferedReader(new InputStreamReader(memFile.getInputStream())).readLine().trim();
if(memApp.length()!=0)targetApp=memApp;
else memFile.writeBytes(targetApp.getBytes(),0,0,targetApp.length());
*/
//从共享文件中刷新目标APP名称(For Android 7.0)
//targetApp=new BufferedReader(new FileReader(sharedFile)).readLine();
//从XPreferences中刷新目标APP名称(Unavailable in Android 7.0)
//targetApp = new XSharedPreferences(this.getClass().getPackage().getName().toLowerCase(), "XServer").getString("targetApp", "monkeylord.demoapp");
//获取目标包名
sPrefs.reload();
String targetApp = sPrefs.getString("targetApp", "MadMode");
//if(targetApp.equals("MadMode"))XposedBridge.log("XServer Cannot Figure Out TargetApp...Hooking Everyone Now!!");
if (!targetApp.equals("MadMode")&&!loadPackageParam.packageName.equals(targetApp)) return;
gatherInfo(loadPackageParam);
//启动XServer
new XServer(8000);
if(!targetApp.equals("MadMode"))new XServer(8000);
new XServer(Process.myPid());
XposedBridge.log("XServer Listening...");
XposedBridge.log("XServer Listening... @"+loadPackageParam.packageName);
}

private void gatherInfo(XC_LoadPackage.LoadPackageParam loadPackageParam) {
Expand All @@ -99,40 +64,4 @@ private void gatherInfo(XC_LoadPackage.LoadPackageParam loadPackageParam) {
processName = loadPackageParam.processName;
appInfo = loadPackageParam.appInfo;
}

@Override
public void initZygote(StartupParam startupParam) throws Throwable {
res = XModuleResources.createInstance(startupParam.modulePath, null);
//内存文件
/*
try {
memFile=new MemoryFile("xserver",512);
memFile.allowPurging(false);
targetApp=targetApp+"\r\n";
memFile.writeBytes(targetApp.getBytes(), 0, 0, targetApp.length());
}catch (IOException e){
XposedBridge.log("MemoryFile 写入异常");
}
*/
//临时文件
/*
BufferedWriter writer;
String filePath="/data/data/"+this.getClass().getPackage().getName().toLowerCase()+"/XServer.conf";
XposedBridge.log(filePath);
sharedFile=new File(filePath);
if (!sharedFile.exists()){
sharedFile.createNewFile();
Runtime.getRuntime().exec("chmod 777 "+filePath);
}
//targetApp=new BufferedReader(new FileReader(sharedFile)).readLine();
//if(targetApp==null)targetApp="com.example";
//sharedFile.setReadable(true);
//sharedFile.setWritable(true);
//sharedfd=new FileInputStream(sharedFile).getFD();
writer=new BufferedWriter(new FileWriter(sharedFile));
writer.write(targetApp);
writer.flush();
*/
}
}
38 changes: 0 additions & 38 deletions app/src/main/java/monkeylord/XServer/utils/TargetService.java

This file was deleted.

2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip

0 comments on commit 4a9cc7e

Please sign in to comment.