9、substrate和xposed两个HOOK框架综合-同时支持的插件框架

插件一开始用的资源布局写的,也就是通过R引用,代码如下:
package com.netease.ga.plug; import android.app.Activity; importandroid.content.Context; import android.graphics.Color; importandroid.util.DisplayMetrics; import android.view.Gravity; import android.view.View;import android.view.ViewGroup; import android.widget.EditText; importandroid.widget.FrameLayout; import android.widget.LinearLayout; importandroid.widget.PopupWindow; import android.widget.RelativeLayout; importandroid.widget.TextView; import android.widget.Toast; /** * Created by sing on 2014/12/10. * desc: */ public class PlugMain { private static final String TAG = "PlugMain"public static String TITLE = "NISHook框架插件(1.0)"public static String mSoPath; private static PlugMain me = nullprivate Activity mActivity; private floatmDp; private RelativeLayout.LayoutParams mRlparams; private ViewGroup mRootView;private PopupWindow popupWindow; static private EditText edt_log; static { mSoPath =null; } public PlugMain(Activity paramActivity) { this.mActivity = paramActivity; DisplayMetrics localDisplayMetrics new DisplayMetrics();this.mActivity.getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics); this.mDp = localDisplayMetrics.density; } public static void init(Activity paramActivity, String paramString) { mSoPath = paramString; if (me == null) { me =new PlugMain(paramActivity); me.show(); logMsg("init run, target Activity: \n" +paramActivity); logMsg("插件已加载"); Toast.makeText(paramActivity.getApplicationContext(), "插件已加载", Toast.LENGTH_LONG).show(); } } private void show() { this.mRootView = newRelativeLayout(this.mActivity); FrameLayout.LayoutParams localLayoutParams newFrameLayout.LayoutParams(-1, -1); this.mActivity.addContentView(this.mRootView, localLayoutParams); initNativeFunC(); initView(); } private void initNativeFunC() {if (mSoPath != null) { logMsg("load so: \n" + mSoPath); System.load(mSoPath); } // if (mSoPath != null) // xxUtility.init(this.mActivity, mSoPath); private voidinitView() { Context context = PlugMain.this.mRootView.getContext(); View contentView= View.inflate(context, R.layout.popup_main, null);//getApplicationContext()LinearLayout localLinearLayout new LinearLayout(this.mActivity); localLinearLayout.setOrientation(LinearLayout.VERTICAL); localLinearLayout.setBackgroundResource(R.drawable.rounded_corners_view); localLinearLayout.setPadding((int) (4.0F * this.mDp), (int) (4.0F * this.mDp), (int) (4.0F * this.mDp), (int) (4.0F * this.mDp)); RelativeLayout.LayoutParams localLayoutParams newRelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); localLayoutParams.addRule(11); localLayoutParams.addRule(15); LinearLayout.LayoutParams localLayoutParams1 newLinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); TextView localTextView1 newTextView(this.mActivity); localTextView1.setText("查看"); localTextView1.setTextSize(26.0F); localTextView1.setTextColor(Color.WHITE); localLinearLayout.addView(localTextView1, localLayoutParams1);this.mRootView.addView(localLinearLayout, localLayoutParams); this.mRlparams = newRelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); this.mRlparams.addRule(11);this.mRlparams.addRule(15);//创建PopupWindow //将布局文件转成view,该view用于显示PopupWindow中的内容contentView.setBackgroundResource(R.drawable.rounded_corners_view); edt_log =(EditText) contentView.findViewById(R.id.edt_log); //创建PopupWindow窗体时必须要指定窗体的大小,否则不会显示在界面上。参数一:窗体中用于显示内容的viewContent,参数二、三:表示PopupWindow窗体的宽和高 popupWindow = new PopupWindow(contentView, DensityUtil.dip2px(context, 300), ViewGroup.LayoutParams.WRAP_CONTENT, true); // 注意:一定要给popwindow设置背景图片或背景资源,如果不设置背景资源 , 动画、 焦点的处理 都会产生问题。popupWindow.setBackgroundDrawable(PlugMain.this.mActivity.getResources().getDrawable(R.drawable.rounded_corners_pop));/localTextView1.setOnClickListener(new View.OnClickListener() { public voidonClick(View paramView) { dismissPopupWindow(); //参数一:PopupWindow挂载在那个View上,参数二:设置PopupWindow显示的重心位置 //参数三:PopupWindow在View上X轴的偏移量,参数四:PopupWindow在View上Y轴的偏移量。X、Y轴的偏移量是相对于当前Activity所在的窗体,参照点为(0,0)popupWindow.showAtLocation(mRootView, Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0); } }); } /** * 设置log信息 * * @param s */ publicstatic void logMsg(String s) { if (edt_log != null) { String strText =edt_log.getText().toString(); edt_log.setText(strText + s + "\n"); } } private voiddismissPopupWindow() { if (popupWindow != null && popupWindow.isShowing()) { popupWindow.dismiss(); //popupWindow = null; } } }

资源布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/ll_popup_container" android:background="@android:color/darker_gray"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"> <TextView android:text="NISHook插件"android:textSize="20sp" android:textColor="@android:color/white"android:gravity="center" android:layout_width="match_parent"android:layout_height="wrap_content" /> <EditText android:id="@+id/edt_log"android:textColor="@android:color/black" android:background="@android:color/white"android:layout_margin="2dp" android:editable="false"android:layout_width="match_parent" android:layout_height="match_parent"android:hint="信息输出栏..." android:inputType="textMultiLine"android:gravity="left|top" android:minLines="10" android:scrollbars="vertical"android:layout_alignParentBottom="true"/> </LinearLayout>
由于插件被加载后R实际上是找不到的,完美的解决方案可以参考:

但是感觉蛮复杂的,我们的插件界面又比较简单,所以沿用叉叉助手插件的方式动态创建布局。
写的时候动态创建的控件属性 参考popup_main.xml进行设置。
后来写的时候由于一开始HOOK的是启动类的Activity,这个Activity有时候作为欢迎界面,所以生存周期比较短,当时考虑显示一个桌面悬浮窗口,
于是有了下面的代码:
package com.netease.ga.plug; import android.app.Activity; importandroid.content.Context; import android.graphics.Color; importandroid.graphics.PixelFormat; import android.graphics.drawable.GradientDrawable;import android.text.InputType; import android.text.method.ScrollingMovementMethod;import android.util.DisplayMetrics; import android.util.Log; importandroid.view.Gravity; import android.view.View; import android.view.ViewGroup; importandroid.view.WindowManager; import android.widget.EditText; importandroid.widget.FrameLayout; import android.widget.LinearLayout; importandroid.widget.PopupWindow; import android.widget.RelativeLayout; importandroid.widget.TextView; import android.widget.Toast; /** * Created by sing on 2014/12/10. * desc: */ public class PlugMain { private static final String TAG = "PlugMain"public static String TITLE = "NISHook框架插件(1.0)"public static String mSoPath; private static PlugMain me = null//private Activity mActivity; privateContext mContext; private WindowManager mWindowManager; private float mDp; privateRelativeLayout.LayoutParams mRlparams; private ViewGroup mRootView; privatePopupWindow popupWindow; static private EditText edt_log; static { mSoPath null; }public PlugMain(Activity paramActivity) { mContext =paramActivity.getApplicationContext(); mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics localDisplayMetricsnew DisplayMetrics(); mWindowManager.getDefaultDisplay().getMetrics(localDisplayMetrics); this.mDp =localDisplayMetrics.density; } public static void init(Activity paramActivity, String strSoPath) { mSoPath = strSoPath; if (me == null) { me new PlugMain(paramActivity); me.show(); logMsg("init run, target Activity: \n" + paramActivity); me.initNativeFunC(); logMsg("插件已加载"); Toast.makeText(paramActivity.getApplicationContext(), "插件已加载", Toast.LENGTH_LONG).show(); } } private void show() { this.mRootView = newRelativeLayout(mContext); WindowManager.LayoutParams wmParams newWindowManager.LayoutParams(); wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;// 设置window type wmParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明 wmParams.gravity = Gravity.CENTER; // 以屏幕左上角为原点,设置x、y初始值 wmParams.x = 0; wmParams.y = 0// 设置悬浮窗口长宽数据 wmParams.width =WindowManager.LayoutParams.WRAP_CONTENT;; wmParams.height=WindowManager.LayoutParams.WRAP_CONTENT;; mWindowManager.addView(this.mRootView, wmParams); initView(); } private void initNativeFunC() { if (mSoPath != null) { logMsg("load so: \n" + mSoPath); System.load(mSoPath); }else{ logMsg("未指定要加载的so文件\n"); } // if (mSoPath != null) // xxUtility.init(this.mActivity, mSoPath); }private void initView() { Context context = PlugMain.this.mRootView.getContext(); GradientDrawable gradientDrawable; gradientDrawable new GradientDrawable(); gradientDrawable.setColor(0xff606060); gradientDrawable.setStroke(DensityUtil.dip2px(context, 3), 0xffff808); gradientDrawable.setCornerRadius(DensityUtil.dip2px(context, 10)); LinearLayout localLinearLayout new LinearLayout(mContext); localLinearLayout.setOrientation(LinearLayout.VERTICAL); localLinearLayout.setBackgroundDrawable(gradientDrawable); localLinearLayout.setPadding((int) (4.0F * this.mDp), (int) (4.0F * this.mDp), (int) (4.0F * this.mDp), (int) (4.0F * this.mDp)); RelativeLayout.LayoutParams localLayoutParams newRelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); localLayoutParams.addRule(11); localLayoutParams.addRule(15); LinearLayout.LayoutParams localLayoutParams1 newLinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); TextView localTextView1 newTextView(mContext); localTextView1.setText("查看"); localTextView1.setTextSize(26.0F); localTextView1.setTextColor(Color.WHITE); localLinearLayout.addView(localTextView1, localLayoutParams1); TextView localTextView2 new TextView(mContext); localTextView2.setText("退出"); localTextView2.setTextSize(26.0F); localTextView2.setTextColor(Color.RED); localLinearLayout.addView(localTextView2, localLayoutParams1); this.mRootView.addView(localLinearLayout, localLayoutParams);this.mRlparams = newRelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); this.mRlparams.addRule(11);this.mRlparams.addRule(15);//创建PopupWindow LinearLayout.LayoutParams layoutParamsPopView = newLinearLayout.LayoutParams(DensityUtil.dip2px(context, 300), DensityUtil.dip2px(context, 250)); LinearLayout contentView newLinearLayout(mContext); contentView.setOrientation(LinearLayout.VERTICAL); contentView.setLayoutParams(layoutParamsPopView); gradientDrawable newGradientDrawable(); gradientDrawable.setColor(0xff606060); gradientDrawable.setStroke(DensityUtil.dip2px(context, 3), 0xffff808); gradientDrawable.setCornerRadius(DensityUtil.dip2px(context, 6)); contentView.setBackgroundDrawable(gradientDrawable); contentView.setPadding(DensityUtil.dip2px(context, 4), DensityUtil.dip2px(context, 4), DensityUtil.dip2px(context, 4), DensityUtil.dip2px(context, 4)); //创建一个标题LinearLayout.LayoutParams layoutParamsTitle = newLinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); layoutParamsTitle.gravity = Gravity.CENTER; TextView tv_Title new TextView(mContext); tv_Title.setText("NISHook插件"); tv_Title.setTextSize(22.0f); tv_Title.setTextColor(Color.WHITE); tv_Title.setPadding(1, 1, 1, 1); contentView.addView(tv_Title, layoutParamsTitle); //创建一个信息输出栏 LinearLayout.LayoutParams layoutParamsLog = newLinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); edt_log new EditText(mContext); edt_log.setHint("信息输出栏..."); edt_log.setTextColor(Color.BLACK); edt_log.setBackgroundColor(Color.WHITE); edt_log.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE); edt_log.setSingleLine(false); //改变默认的单行模式 edt_log.setMinLines(10); edt_log.setMaxLines(15); edt_log.setVerticalScrollBarEnabled(true); edt_log.setMovementMethod(ScrollingMovementMethod.getInstance()); edt_log.setGravity(Gravity.LEFT | Gravity.TOP); contentView.addView(edt_log, layoutParamsLog); //创建PopupWindow窗体时必须要指定窗体的大小,否则不会显示在界面上。参数一:窗体中用于显示内容的viewContent,参数二、三:表示PopupWindow窗体的宽和高 popupWindow = newPopupWindow(contentView, DensityUtil.dip2px(context, 300), ViewGroup.LayoutParams.WRAP_CONTENT, true); // 注意:一定要给popwindow设置背景图片或背景资源,如果不设置背景资源 , 动画、 焦点的处理 都会产生问题。 gradientDrawable newGradientDrawable(); gradientDrawable.setColor(0xffffffff); gradientDrawable.setStroke(DensityUtil.dip2px(context, 3), 0xffff808); gradientDrawable.setCornerRadius(DensityUtil.dip2px(context, 6)); popupWindow.setBackgroundDrawable(gradientDrawable); popupWindow.getBackground().setAlpha(153);/localTextView1.setOnClickListener(new View.OnClickListener() { public voidonClick(View paramView) { dismissPopupWindow(); //参数一:PopupWindow挂载在那个View上,参数二:设置PopupWindow显示的重心位置 //参数三:PopupWindow在View上X轴的偏移量,参数四:PopupWindow在View上Y轴的偏移量。X、Y轴的偏移量是相对于当前Activity所在的窗体,参照点为(0,0)popupWindow.showAtLocation(mRootView, Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0); } }); localTextView2.setOnClickListener(newView.OnClickListener() { @Override public void onClick(View view) { dismissPopupWindow(); mWindowManager.removeView(mRootView); } }); } /** * 设置log信息 * * @param s */ public static void logMsg(String s) { if (edt_log != null) { String strText = edt_log.getText().toString(); edt_log.setText(strText + s + "\n"); } }private void dismissPopupWindow() { if (popupWindow != null &&popupWindow.isShowing()) { popupWindow.dismiss(); //popupWindow = null; } } }
但是显示悬浮窗口需要一个权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
当插件被加载到目标进程中时,是需要宿主拥有这个权限才行,只能通过先静态修改目标APK包添加上这个权限,然后安装重复以上步骤。
如果目标程序有防二次打包的话,这个方案就不是很好,而且来回操作也挺麻烦,最后无奈只好老老实实按照叉叉助手的插件模式来写,
就是动态创建的方式:
package com.netease.ga.plug; import android.app.Activity; importandroid.content.Context; import android.graphics.Color; importandroid.graphics.drawable.GradientDrawable; import android.text.InputType; importandroid.text.method.ScrollingMovementMethod; import android.util.DisplayMetrics;import android.view.Gravity; import android.view.View; import android.view.ViewGroup;import android.widget.EditText; import android.widget.FrameLayout; importandroid.widget.LinearLayout; import android.widget.PopupWindow; importandroid.widget.RelativeLayout; import android.widget.TextView; importandroid.widget.Toast; /** * Created by sing on 2014/12/10. * desc: */ public classPlugMain { private static final String TAG = "PlugMain"public static String TITLE = "NISHook框架插件(1.0)"public static String mSoPath; private static PlugMain me =nullprivate Activity mActivity; private float mDp; privateRelativeLayout.LayoutParams mRlparams; private ViewGroup mRootView; privatePopupWindow popupWindow; static private EditText edt_log; static { mSoPath null; }public PlugMain(Activity paramActivity) { this.mActivity = paramActivity; DisplayMetrics localDisplayMetrics new DisplayMetrics();this.mActivity.getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics); this.mDp = localDisplayMetrics.density; } public static void init(Activity paramActivity, String strSoPath) { mSoPath = strSoPath; if (me == null) { me newPlugMain(paramActivity); me.show(); logMsg("init run, target Activity: \n" +paramActivity); me.initNativeFunC(); logMsg("插件已加载"); Toast.makeText(paramActivity.getApplicationContext(), "插件已加载", Toast.LENGTH_LONG).show(); } } private void show() { this.mRootView = newRelativeLayout(this.mActivity); FrameLayout.LayoutParams localLayoutParams newFrameLayout.LayoutParams(-1, -1); this.mActivity.addContentView(this.mRootView, localLayoutParams); initView(); } private void initNativeFunC() { if (mSoPath !=null) { logMsg("load so: \n" + mSoPath); System.load(mSoPath); } else { logMsg("未指定要加载的so文件\n"); } // if (mSoPath != null) // xxUtility.init(this.mActivity, mSoPath); private void initView() { Context context = PlugMain.this.mRootView.getContext(); GradientDrawable gradientDrawable; gradientDrawable new GradientDrawable(); gradientDrawable.setColor(0xff606060); gradientDrawable.setStroke(DensityUtil.dip2px(context, 3), 0xffff808); gradientDrawable.setCornerRadius(DensityUtil.dip2px(context, 10)); LinearLayout localLinearLayout new LinearLayout(mActivity); localLinearLayout.setOrientation(LinearLayout.VERTICAL); localLinearLayout.setBackgroundDrawable(gradientDrawable); localLinearLayout.setPadding((int) (4.0F * this.mDp), (int) (4.0F * this.mDp), (int) (4.0F * this.mDp), (int) (4.0F * this.mDp)); RelativeLayout.LayoutParams localLayoutParams newRelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); localLayoutParams.addRule(11); localLayoutParams.addRule(15); LinearLayout.LayoutParams localLayoutParams1 newLinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); TextView localTextView1 newTextView(mActivity); localTextView1.setText("查看"); localTextView1.setTextSize(26.0F); localTextView1.setTextColor(Color.WHITE); localLinearLayout.addView(localTextView1, localLayoutParams1); TextView localTextView2 new TextView(mActivity); localTextView2.setText("退出"); localTextView2.setTextSize(26.0F); localTextView2.setTextColor(Color.RED); localLinearLayout.addView(localTextView2, localLayoutParams1);this.mRootView.addView(localLinearLayout, localLayoutParams); this.mRlparams = newRelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); this.mRlparams.addRule(11);this.mRlparams.addRule(15);//创建PopupWindow LinearLayout.LayoutParams layoutParamsPopView = newLinearLayout.LayoutParams(DensityUtil.dip2px(context, 300), DensityUtil.dip2px(context, 250)); LinearLayout contentView newLinearLayout(mActivity); contentView.setOrientation(LinearLayout.VERTICAL); contentView.setLayoutParams(layoutParamsPopView); gradientDrawable newGradientDrawable(); gradientDrawable.setColor(0xff606060); gradientDrawable.setStroke(DensityUtil.dip2px(context, 3), 0xffff808); gradientDrawable.setCornerRadius(DensityUtil.dip2px(context, 6)); contentView.setBackgroundDrawable(gradientDrawable); contentView.setPadding(DensityUtil.dip2px(context, 4), DensityUtil.dip2px(context, 4), DensityUtil.dip2px(context, 4), DensityUtil.dip2px(context, 4)); //创建一个标题LinearLayout.LayoutParams layoutParamsTitle = newLinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); layoutParamsTitle.gravity = Gravity.CENTER; TextView tv_Title new TextView(mActivity); tv_Title.setText("NISHook插件"); tv_Title.setTextSize(22.0f); tv_Title.setTextColor(Color.WHITE); tv_Title.setPadding(1, 1, 1, 1); contentView.addView(tv_Title, layoutParamsTitle); //创建一个信息输出栏 LinearLayout.LayoutParams layoutParamsLog = newLinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); edt_log new EditText(mActivity); edt_log.setHint("信息输出栏..."); edt_log.setTextColor(Color.BLACK); edt_log.setBackgroundColor(Color.WHITE); edt_log.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE); edt_log.setSingleLine(false); //改变默认的单行模式 edt_log.setMinLines(10); edt_log.setMaxLines(15); edt_log.setVerticalScrollBarEnabled(true); edt_log.setMovementMethod(ScrollingMovementMethod.getInstance()); edt_log.setGravity(Gravity.LEFT | Gravity.TOP); contentView.addView(edt_log, layoutParamsLog); //创建PopupWindow窗体时必须要指定窗体的大小,否则不会显示在界面上。参数一:窗体中用于显示内容的viewContent,参数二、三:表示PopupWindow窗体的宽和高 popupWindow = newPopupWindow(contentView, DensityUtil.dip2px(context, 300), ViewGroup.LayoutParams.WRAP_CONTENT, true); // 注意:一定要给popwindow设置背景图片或背景资源,如果不设置背景资源 , 动画、 焦点的处理 都会产生问题。 gradientDrawable newGradientDrawable(); gradientDrawable.setColor(0xffffffff); gradientDrawable.setStroke(DensityUtil.dip2px(context, 3), 0xffff808); gradientDrawable.setCornerRadius(DensityUtil.dip2px(context, 6)); popupWindow.setBackgroundDrawable(gradientDrawable); popupWindow.getBackground().setAlpha(153);/localTextView1.setOnClickListener(new View.OnClickListener() { public voidonClick(View paramView) { dismissPopupWindow(); //参数一:PopupWindow挂载在那个View上,参数二:设置PopupWindow显示的重心位置 //参数三:PopupWindow在View上X轴的偏移量,参数四:PopupWindow在View上Y轴的偏移量。X、Y轴的偏移量是相对于当前Activity所在的窗体,参照点为(0,0)popupWindow.showAtLocation(mRootView, Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0); } }); localTextView2.setOnClickListener(newView.OnClickListener() { @Override public void onClick(View view) { dismissPopupWindow(); mRootView.setVisibility(View.INVISIBLE); } }); } /** * 设置log信息 * * @param s */ public static void logMsg(String s) { if (edt_log != null) { String strText = edt_log.getText().toString(); edt_log.setText(strText + s + "\n"); } } private void dismissPopupWindow() { if (popupWindow != null &&popupWindow.isShowing()) { popupWindow.dismiss(); //popupWindow = null; } } }
运行预览:

HOOK框架界面部分:
package com.netease.ga.view; import android.app.Activity; importandroid.app.ActivityManager; import android.content.ComponentName; importandroid.content.Context; import android.content.Intent; importandroid.content.SharedPreferences; import android.content.pm.PackageInfo; importandroid.content.pm.PackageManager; import android.content.pm.ResolveInfo; importandroid.os.Bundle; import android.view.Menu; import android.view.MenuItem; importandroid.view.View; import android.widget.Button; import android.widget.EditText;import android.widget.TextView; import com.netease.ga.Injector; importcom.netease.ga.R; import com.netease.ga.utils.util; import java.util.List; publicclass MainActivity extends Activity { public static final String TAG = "MainActivity"private native void hookApplication(Context context); static { }private boolean bret; private SharedPreferences sp; private EditText edt_packageName;private Button btn_browse; private TextView tv_activity; private EditText edt_activity; private Button btn_startApp; private Button btn_inject; private staticEditText edt_log; private String strTargetActivity; public MainActivity() { super(); } @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); edt_packageName = (EditText) findViewById(R.id.edt_package); btn_browse = (Button) findViewById(R.id.btn_browse); tv_activity = (TextView) findViewById(R.id.tv_activity); edt_activity = (EditText) findViewById(R.id.edt_activity); btn_startApp = (Button) findViewById(R.id.btn_startApp); btn_inject = (Button) findViewById(R.id.btn_inject); edt_log = (EditText) findViewById(R.id.edt_log); edt_log.setFocusableInTouchMode(false); sp = getSharedPreferences("config", Context.MODE_PRIVATE); //SharedPreferences.Editor editor = sp.edit(); String packageName = sp.getString("hookpackage", "com.netease.anep"); strTargetActivity = sp.getString("launcherActivity", ""); edt_packageName.setText(packageName); edt_activity.setText(strTargetActivity); tv_activity.setOnClickListener(newView.OnClickListener() { @Override public void onClick(View view) { String topActivityClassName null; ActivityManager am = (ActivityManager) MainActivity.this.getSystemService(Activity.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> mRunningTasks = am.getRunningTasks(10); for(ActivityManager.RunningTaskInfo runningTaskInfo : mRunningTasks) { ComponentName cn= runningTaskInfo.topActivity; String activityName = cn.getClassName(); if(activityName.indexOf("com.netease.ga.view") == -1 && activityName.indexOf("com.android.") == -1) { activityName = activityName.replace('.', '/'); topActivityClassName = activityName; } } if(topActivityClassName != null) { strTargetActivity = topActivityClassName; logMsg("launcher:" + strTargetActivity); edt_activity.setText(strTargetActivity); SharedPreferences.Editor editor = sp.edit(); editor.putString("launcherActivity", strTargetActivity); editor.commit(); } } }); //显示到信息框中 logMsg("HOOK目标信息:"); logMsg("package: " + packageName); logMsg("launcher: " + strTargetActivity + "\n");if (strTargetActivity.isEmpty()) { logMsg("[×]尚未选择目标,请先选择目标!"); } //浏览app列表 btn_browse.setOnClickListener(new View.OnClickListener() { @Override public voidonClick(View v) { Intent intent new Intent(); intent.setClass(MainActivity.this, MyGamesActivity.class); MainActivity.this.startActivityForResult(intent, 0); } }); //注入 btn_inject.setOnClickListener(new View.OnClickListener() { @Override public voidonClick(View v) { //把hook的配置信息转换成易读取的文件,逐行写入到:/data/data/com.netease.ga/app_plugin/config.cfg //保证在hook前把最新设置的hook信息配置到文件中去 MainActivity.this.setHookConfigFile(); Injector.injectSoToParent(MainActivity.this); } }); //运行指定的appbtn_startApp.setOnClickListener(new View.OnClickListener() { @Override public voidonClick(View view) { //启动的时候先配置好Hook信息 MainActivity.this.setHookConfigFile(); util.runApp(MainActivity.this, edt_packageName.getText().toString()); } }); } //把hook的配置信息转换成易读取的文件,逐行写入到:/data/data/com.netease.ga/app_plugin/config.cfg private void setHookConfigFile() {//把插件从资源目录下复制到app_plugin目录下 String plugPath = Injector.getPluginPath(edt_packageName.getText().toString(), this); bret = Injector.copyAssetsFileToDir("plug.apk", plugPath, this); bret = bret && Injector.setFileAttr755(plugPath + "/plug.apk"); logMsg(bret ? "[√]插件APK部署成功" : "[×]插件APK部署失败"); bret = Injector.copyAssetsFileToDir("libplug.so", plugPath,this); bret = bret && Injector.setFileAttr755(plugPath + "/libplug.so"); logMsg(bret? "[√]部署插件SO成功" : "[×]部署插件SO失败"); //plugPath = "/data/data/com.netease.anep/app_plugin"; bret = Injector.setHookConfigFile(this, edt_packageName.getText().toString(), strTargetActivity,"com.netease.ga.plug.PlugMain", plugPath + "/plug.apk", plugPath + "/libplug.so"); bret = bret && Injector.setFileAttr755(plugPath + "/config.cfg"); logMsg(bret ? "[√]HOOK配置文件部署成功" : "[×]HOOK配置文件部署失败"); logMsg(""); } /** * 设置log信息 * *@param s */ public static void logMsg(String s) { String strText =edt_log.getText().toString(); edt_log.setText(strText + s + "\n"); } protected voidonActivityResult(int requestCode, int resultCode, Intent data) { switch (resultCode) { case RESULT_OK: String packageName = data.getExtras().getString("package"); String mainActivityClassName null; String topActivityClassName null; edt_packageName.setText(packageName); //获取包名对应的主activity PackageManager localPackageManager = this.getPackageManager(); try { PackageInfo localPackageInfo = localPackageManager.getPackageInfo(packageName, 0); Intent localIntent1 newIntent("android.intent.action.MAIN", null); localIntent1.addCategory("android.intent.category.LAUNCHER"); localIntent1.setPackage(localPackageInfo.packageName); List localList = localPackageManager.queryIntentActivities(localIntent1, 0); if(localList.iterator().hasNext()) { ResolveInfo localResolveInfo = (ResolveInfo) localList.iterator().next(); mainActivityClassName =localResolveInfo.activityInfo.name; mainActivityClassName = mainActivityClassName.replace('.', '/'); //完美点可以动态检查一下该类是否有onCreate方法实现,此处默认它是有的 //... } } catch (PackageManager.NameNotFoundException localNameNotFoundException) { localNameNotFoundException.printStackTrace(); } ActivityManager am = (ActivityManager) MainActivity.this.getSystemService(Activity.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> mRunningTasks = am.getRunningTasks(10); for(ActivityManager.RunningTaskInfo runningTaskInfo : mRunningTasks) { ComponentName cn= runningTaskInfo.topActivity; String activityName = cn.getClassName(); if(activityName.indexOf(packageName) != -1) { activityName = activityName.replace('.', '/'); topActivityClassName = activityName; } } if (topActivityClassName == null) { //说明目标程序当前没有运行,则默认使用启动类 strTargetActivity = mainActivityClassName; logMsg("[乄]所选择的目标程序当前没有运行,默认使用LAUNCHER属性的Activity作为HOOK目标! 如果该Activity的生存周期很短,意味着插件也会很快消失。"); logMsg("靠谱的做法是先启动一次目标程序,进入到生存周期较长的页面,然后再点击“浏览”按钮,本程序会自动识别有效的Activity。"); } else { //说明是从正在运行的程序列表中找到的目标类,最有效! strTargetActivity = topActivityClassName; logMsg("[√]目标程序已经运行,将自动识别HOOK目标的Activity! 识别成功后请杀死目标进程,然后点击“启动”按钮。"); } logMsg("launcher:" + strTargetActivity); edt_activity.setText(strTargetActivity); SharedPreferences.Editor editor = sp.edit(); editor.putString("hookpackage", packageName); editor.putString("launcherActivity", strTargetActivity); editor.commit(); break; } } @Override public booleanonCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id =item.getItemId(); if (id == R.id.action_settings) { return true; } returnsuper.onOptionsItemSelected(item); } }
运行预览:

注入后重新运行目标程序,效果:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

asmcvc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值