插件一开始用的资源布局写的,也就是通过R引用,代码如下:
packagecom.netease.ga.plug;importandroid.app.Activity;importandroid.content.Context;importandroid.graphics.Color;importandroid.util.DisplayMetrics;importandroid.view.Gravity;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.EditText;importandroid.widget.FrameLayout;importandroid.widget.LinearLayout;importandroid.widget.PopupWindow;importandroid.widget.RelativeLayout;importandroid.widget.TextView;importandroid.widget.Toast;/*** Created by sing on 2014/12/10. * desc:*/publicclassPlugMain {privatestaticfinalString TAG = "PlugMain";publicstaticString TITLE = "NISHook框架插件(1.0)";publicstaticString mSoPath;privatestaticPlugMain me =null;privateActivity mActivity;privatefloatmDp;privateRelativeLayout.LayoutParams mRlparams;privateViewGroup mRootView;privatePopupWindow popupWindow;staticprivateEditText edt_log;static{ mSoPath=null; }publicPlugMain(Activity paramActivity) {this.mActivity =paramActivity; DisplayMetrics localDisplayMetrics=newDisplayMetrics();this.mActivity.getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics);this.mDp =localDisplayMetrics.density; }publicstaticvoidinit(Activity paramActivity, String paramString) { mSoPath=paramString;if(me ==null) { me=newPlugMain(paramActivity); me.show(); logMsg("init run, target Activity: \n" +paramActivity); logMsg("插件已加载"); Toast.makeText(paramActivity.getApplicationContext(),"插件已加载", Toast.LENGTH_LONG).show(); } }privatevoidshow() {this.mRootView =newRelativeLayout(this.mActivity); FrameLayout.LayoutParams localLayoutParams=newFrameLayout.LayoutParams(-1, -1);this.mActivity.addContentView(this.mRootView, localLayoutParams); initNativeFunC(); initView(); }privatevoidinitNativeFunC() {if(mSoPath !=null) { logMsg("load so: \n" +mSoPath); System.load(mSoPath); }//if (mSoPath != null)//xxUtility.init(this.mActivity, mSoPath);}privatevoidinitView() { Context context= PlugMain.this.mRootView.getContext(); View contentView= View.inflate(context, R.layout.popup_main,null);//getApplicationContext()LinearLayout localLinearLayout=newLinearLayout(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 =newPopupWindow(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(newView.OnClickListener() {publicvoidonClick(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信息 * *@params*/publicstaticvoidlogMsg(String s) {if(edt_log !=null) { String strText=edt_log.getText().toString(); edt_log.setText(strText+ s + "\n"); } }privatevoiddismissPopupWindow() {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"><TextViewandroid:text="NISHook插件"android:textSize="20sp"android:textColor="@android:color/white"android:gravity="center"android:layout_width="match_parent"android:layout_height="wrap_content"/><EditTextandroid: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>
但是感觉蛮复杂的,我们的插件界面又比较简单,所以沿用叉叉助手插件的方式动态创建布局。
写的时候动态创建的控件属性
参考popup_main.xml进行设置。
后来写的时候由于一开始HOOK的是启动类的Activity,这个Activity有时候作为欢迎界面,所以生存周期比较短,当时考虑显示一个桌面悬浮窗口,
于是有了下面的代码:
packagecom.netease.ga.plug;importandroid.app.Activity;importandroid.content.Context;importandroid.graphics.Color;importandroid.graphics.PixelFormat;importandroid.graphics.drawable.GradientDrawable;importandroid.text.InputType;importandroid.text.method.ScrollingMovementMethod;importandroid.util.DisplayMetrics;importandroid.util.Log;importandroid.view.Gravity;importandroid.view.View;importandroid.view.ViewGroup;importandroid.view.WindowManager;importandroid.widget.EditText;importandroid.widget.FrameLayout;importandroid.widget.LinearLayout;importandroid.widget.PopupWindow;importandroid.widget.RelativeLayout;importandroid.widget.TextView;importandroid.widget.Toast;/*** Created by sing on 2014/12/10. * desc:*/publicclassPlugMain {privatestaticfinalString TAG = "PlugMain";publicstaticString TITLE = "NISHook框架插件(1.0)";publicstaticString mSoPath;privatestaticPlugMain me =null;//private Activity mActivity;privateContext mContext;privateWindowManager mWindowManager;privatefloatmDp;privateRelativeLayout.LayoutParams mRlparams;privateViewGroup mRootView;privatePopupWindow popupWindow;staticprivateEditText edt_log;static{ mSoPath=null; }publicPlugMain(Activity paramActivity) { mContext=paramActivity.getApplicationContext(); mWindowManager=(WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics localDisplayMetrics=newDisplayMetrics(); mWindowManager.getDefaultDisplay().getMetrics(localDisplayMetrics);this.mDp =localDisplayMetrics.density; }publicstaticvoidinit(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(); } }privatevoidshow() {this.mRootView =newRelativeLayout(mContext); WindowManager.LayoutParams wmParams=newWindowManager.LayoutParams(); wmParams.type= WindowManager.LayoutParams.TYPE_PHONE;//设置window typewmParams.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(); }privatevoidinitNativeFunC() {if(mSoPath !=null) { logMsg("load so: \n" +mSoPath); System.load(mSoPath); }else{ logMsg("未指定要加载的so文件\n"); }//if (mSoPath != null)//xxUtility.init(this.mActivity, mSoPath);}privatevoidinitView() { Context context= PlugMain.this.mRootView.getContext(); GradientDrawable gradientDrawable; gradientDrawable=newGradientDrawable(); gradientDrawable.setColor(0xff606060); gradientDrawable.setStroke(DensityUtil.dip2px(context,3), 0xffff808); gradientDrawable.setCornerRadius(DensityUtil.dip2px(context,10)); LinearLayout localLinearLayout=newLinearLayout(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=newTextView(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);///创建PopupWindowLinearLayout.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=newTextView(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=newEditText(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(newView.OnClickListener() {publicvoidonClick(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() { @OverridepublicvoidonClick(View view) { dismissPopupWindow(); mWindowManager.removeView(mRootView); } }); }/*** 设置log信息 * *@params*/publicstaticvoidlogMsg(String s) {if(edt_log !=null) { String strText=edt_log.getText().toString(); edt_log.setText(strText+ s + "\n"); } }privatevoiddismissPopupWindow() {if(popupWindow !=null&&popupWindow.isShowing()) { popupWindow.dismiss();//popupWindow = null;} } }
<uses-permissionandroid:name="android.permission.SYSTEM_ALERT_WINDOW"/>
如果目标程序有防二次打包的话,这个方案就不是很好,而且来回操作也挺麻烦,最后无奈只好老老实实按照叉叉助手的插件模式来写,
就是动态创建的方式:
packagecom.netease.ga.plug;importandroid.app.Activity;importandroid.content.Context;importandroid.graphics.Color;importandroid.graphics.drawable.GradientDrawable;importandroid.text.InputType;importandroid.text.method.ScrollingMovementMethod;importandroid.util.DisplayMetrics;importandroid.view.Gravity;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.EditText;importandroid.widget.FrameLayout;importandroid.widget.LinearLayout;importandroid.widget.PopupWindow;importandroid.widget.RelativeLayout;importandroid.widget.TextView;importandroid.widget.Toast;/*** Created by sing on 2014/12/10. * desc:*/publicclassPlugMain {privatestaticfinalString TAG = "PlugMain";publicstaticString TITLE = "NISHook框架插件(1.0)";publicstaticString mSoPath;privatestaticPlugMain me =null;privateActivity mActivity;privatefloatmDp;privateRelativeLayout.LayoutParams mRlparams;privateViewGroup mRootView;privatePopupWindow popupWindow;staticprivateEditText edt_log;static{ mSoPath=null; }publicPlugMain(Activity paramActivity) {this.mActivity =paramActivity; DisplayMetrics localDisplayMetrics=newDisplayMetrics();this.mActivity.getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics);this.mDp =localDisplayMetrics.density; }publicstaticvoidinit(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(); } }privatevoidshow() {this.mRootView =newRelativeLayout(this.mActivity); FrameLayout.LayoutParams localLayoutParams=newFrameLayout.LayoutParams(-1, -1);this.mActivity.addContentView(this.mRootView, localLayoutParams); initView(); }privatevoidinitNativeFunC() {if(mSoPath !=null) { logMsg("load so: \n" +mSoPath); System.load(mSoPath); }else{ logMsg("未指定要加载的so文件\n"); }//if (mSoPath != null)//xxUtility.init(this.mActivity, mSoPath);}privatevoidinitView() { Context context= PlugMain.this.mRootView.getContext(); GradientDrawable gradientDrawable; gradientDrawable=newGradientDrawable(); gradientDrawable.setColor(0xff606060); gradientDrawable.setStroke(DensityUtil.dip2px(context,3), 0xffff808); gradientDrawable.setCornerRadius(DensityUtil.dip2px(context,10)); LinearLayout localLinearLayout=newLinearLayout(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=newTextView(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);///创建PopupWindowLinearLayout.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=newTextView(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=newEditText(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(newView.OnClickListener() {publicvoidonClick(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() { @OverridepublicvoidonClick(View view) { dismissPopupWindow(); mRootView.setVisibility(View.INVISIBLE); } }); }/*** 设置log信息 * *@params*/publicstaticvoidlogMsg(String s) {if(edt_log !=null) { String strText=edt_log.getText().toString(); edt_log.setText(strText+ s + "\n"); } }privatevoiddismissPopupWindow() {if(popupWindow !=null&&popupWindow.isShowing()) { popupWindow.dismiss();//popupWindow = null;} } }
运行预览:
![](https://i-blog.csdnimg.cn/blog_migrate/5176697db46baa35561e0614f8d6a448.png)
HOOK框架界面部分:
packagecom.netease.ga.view;importandroid.app.Activity;importandroid.app.ActivityManager;importandroid.content.ComponentName;importandroid.content.Context;importandroid.content.Intent;importandroid.content.SharedPreferences;importandroid.content.pm.PackageInfo;importandroid.content.pm.PackageManager;importandroid.content.pm.ResolveInfo;importandroid.os.Bundle;importandroid.view.Menu;importandroid.view.MenuItem;importandroid.view.View;importandroid.widget.Button;importandroid.widget.EditText;importandroid.widget.TextView;importcom.netease.ga.Injector;importcom.netease.ga.R;importcom.netease.ga.utils.util;importjava.util.List;publicclassMainActivityextendsActivity {publicstaticfinalString TAG = "MainActivity";privatenativevoidhookApplication(Context context);static{ }privatebooleanbret;privateSharedPreferences sp;privateEditText edt_packageName;privateButton btn_browse;privateTextView tv_activity;privateEditText edt_activity;privateButton btn_startApp;privateButton btn_inject;privatestaticEditText edt_log;privateString strTargetActivity;publicMainActivity() {super(); } @OverrideprotectedvoidonCreate(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() { @OverridepublicvoidonClick(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(newView.OnClickListener() { @OverridepublicvoidonClick(View v) { Intent intent=newIntent(); intent.setClass(MainActivity.this, MyGamesActivity.class); MainActivity.this.startActivityForResult(intent, 0); } });//注入btn_inject.setOnClickListener(newView.OnClickListener() { @OverridepublicvoidonClick(View v) {//把hook的配置信息转换成易读取的文件,逐行写入到:/data/data/com.netease.ga/app_plugin/config.cfg//保证在hook前把最新设置的hook信息配置到文件中去MainActivity.this.setHookConfigFile(); Injector.injectSoToParent(MainActivity.this); } });//运行指定的appbtn_startApp.setOnClickListener(newView.OnClickListener() { @OverridepublicvoidonClick(View view) {//启动的时候先配置好Hook信息MainActivity.this.setHookConfigFile(); util.runApp(MainActivity.this, edt_packageName.getText().toString()); } }); }//把hook的配置信息转换成易读取的文件,逐行写入到:/data/data/com.netease.ga/app_plugin/config.cfgprivatevoidsetHookConfigFile() {//把插件从资源目录下复制到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信息 * *@params*/publicstaticvoidlogMsg(String s) { String strText=edt_log.getText().toString(); edt_log.setText(strText+ s + "\n"); }protectedvoidonActivityResult(intrequestCode,intresultCode, Intent data) {switch(resultCode) {caseRESULT_OK: String packageName= data.getExtras().getString("package"); String mainActivityClassName=null; String topActivityClassName=null; edt_packageName.setText(packageName);//获取包名对应的主activityPackageManager 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; } } @OverridepublicbooleanonCreateOptionsMenu(Menu menu) {//Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);returntrue; } @OverridepublicbooleanonOptionsItemSelected(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.intid =item.getItemId();if(id ==R.id.action_settings) {returntrue; }returnsuper.onOptionsItemSelected(item); } }
![](https://i-blog.csdnimg.cn/blog_migrate/034e024ccf7d21f2120dc95b532065d2.png)
注入后重新运行目标程序,效果:
![](https://i-blog.csdnimg.cn/blog_migrate/93d38ebac8672481bbf9106ead91bcfb.png)
版权声明:本文为博主原创文章,未经博主允许不得转载。