3、叉叉助手逆向分析(下)

plugin/117/xxFknsg.apk --ui-name:com/xxAssistant/FknsgUI/xxMain --activity-name:com/babeltimes/main/MainActivity --so-path:/data/data/com.xxAssistant/app_plugin/117/libxxfknsg.so
我们将手机里的apk提取出来:com.babeltime.fknsango_360-1.apk,分析xml:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="3" android:versionName="1.1.8"android:installLocation="0" package="com.babeltime.fknsango_360" > <supports-screens android:anyDensity="true" android:smallScreens="true" android:normalScreens="true"android:largeScreens="true" android:resizeable="true" > </supports-screens> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" > </uses-sdk> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" > </uses-permission>
……
<uses-permission android:name="android.permission.VIBRATE" > </uses-permission> <application android:theme="@7F060001" android:label="@7F050000" android:icon="@7F020000"android:allowBackup="true" > <activity android:theme="@android:01030007" android:label="@7F050000" android:name="com.babeltimes.main.MainActivity"android:screenOrientation="1" android:configChanges="0x00000080" > <intent-filter > <action android:name="android.intent.action.MAIN" > </action> <categoryandroid:name="android.intent.category.LAUNCHER" > </category> </intent-filter> </activity> <activity android:theme="@android:01030007" android:label="@7F050000"android:name="com.babeltimes.main.CrashHandler" android:screenOrientation="1" android:configChanges="0x00000080" > <intent-filter > <categoryandroid:name="android.intent.category.LAUNCHER" > </category> </intent-filter> </activity> <activity android:theme="@android:01030010"android:name="com.qihoopay.insdk.activity.ContainerActivity" android:configChanges="0x400006E4" > </activity> <activity android:theme="@android:01030010"android:name="com.qihoopp.qcoinpay.QcoinActivity" android:configChanges="0x400006E4" android:windowSoftInputMode="0x00000013" > </activity> <meta-dataandroid:name="QHOPENSDK_APPID" android:value="200983446" > </meta-data> …… <meta-data android:name="QHOPENSDK_CHANNEL" android:value="default" > </meta-data> <activityandroid:theme="@7F060015" android:name="cn.paypalm.pppayment.InitialAct" android:screenOrientation="3" android:configChanges="0x000004A0"android:windowSoftInputMode="0x00000003" > </activity> …… <activity android:theme="@7F060015" android:name="cn.paypalm.pppayment.BankcardAgreement"android:screenOrientation="3" android:configChanges="0x000004A0" android:windowSoftInputMode="0x00000003" > </activity> </application></manifest>
可以看出:
game-name为游戏包名,
apk-path为插件全路径
ui-name为插件界面
activity-name为游戏启动activity
so-path为插件so库全路径

再分析插件xxFknsg.apk:
<?xml version="1.0" encoding="utf-8"?><manifest android:versionCode="1" android:versionName="1.0" package="com.xxAssistant.FknsgUI"xmlns:android="http://schemas.android.com/apk/res/android"> <application android:theme="@style/AppTheme" android:label="@string/app_name"android:icon="@drawable/ic_launcher" android:debuggable="true" android:allowBackup="true"> <activity android:label="@string/app_name"android:name="com.xxAssistant.FknsgUI.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <categoryandroid:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
Application是没有name标签的,activity:com.xxAssistant.FknsgUI.MainActivity:
package com.xxAssistant.FknsgUI; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuInflater; public classMainActivity extends Activity { protected void onCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentView(2130903040); xxMain.init(thisnull); } publicboolean onCreateOptionsMenu(Menu paramMenu) { getMenuInflater().inflate(2131165184, paramMenu); return true; } }
插件的MainActivity只是调用了一个xxMain.init,查看xxMain.class:
package com.xxAssistant.FknsgUI; import android.app.Activity; import android.graphics.drawable.Drawable; import android.util.DisplayMetrics; import android.view.Display; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout.LayoutParams; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.RelativeLayout; import android.widget.RelativeLayout.LayoutParams; import android.widget.TextView; import com.xxAssistant.FknsgUI.bg.ShapeBg;public class xxMain { public static String TITLE = "叉叉放开那三国助手 1.0.0"public static String mSoPath = nullprivate static xxMain me = nullprivate xxAbout mAboutView; private Activity mActivity; private float mDp; private RelativeLayout.LayoutParams mRlparams; private ViewGroup mRootView; private xxSettingView mSettingView; public xxMain(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); for (xxMain localxxMain = new xxMain(paramActivity); ; localxxMain = me) { me = localxxMain; me.show(); return; } } private void initNativeFunC() { if (mSoPath != null) xxUtility.init(this.mActivity, mSoPath); }private void initView() { this.mSettingView = new xxSettingView(this.mActivity, this.mRootView); this.mAboutView = new xxAbout(this.mActivity, this.mRootView);this.mAboutView.setXXVersionString(TITLE); LinearLayout localLinearLayout = new LinearLayout(this.mActivity); localLinearLayout.setOrientation(1); ShapeBg localShapeBg = new ShapeBg(this.mActivity); localShapeBg.setColor(-16777216); localShapeBg.setCornerRadii(new float[] { 4.0F0.0F0.0F4.0F }); localLinearLayout.setBackgroundDrawable(localShapeBg); localLinearLayout.getBackground().setAlpha(153); 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 = new RelativeLayout.LayoutParams(-2, -2); localLayoutParams.addRule(11); localLayoutParams.addRule(15); LinearLayout.LayoutParams localLayoutParams1 = new LinearLayout.LayoutParams(-2, -2); TextView localTextView1 = new TextView(this.mActivity); localTextView1.setText("设置"); localTextView1.setTextSize(16.0F); localTextView1.setTextColor(-1); LinearLayout.LayoutParams localLayoutParams2 = new LinearLayout.LayoutParams(-2, -2); TextView localTextView2 = new TextView(this.mActivity); localTextView2.setText("叉叉"); localTextView2.setTextSize(16.0F); localTextView2.setTextColor(-16711936); localLayoutParams2.topMargin = ((int)(5.0F *this.mDp)); localLinearLayout.addView(localTextView1, localLayoutParams1); localLinearLayout.addView(localTextView2, localLayoutParams2);this.mRootView.addView(localLinearLayout, localLayoutParams); this.mRlparams = new RelativeLayout.LayoutParams(-1, -1); this.mRlparams.addRule(11);this.mRlparams.addRule(15); localTextView1.setOnClickListener(new View.OnClickListener() { public void onClick(View paramAnonymousView) { xxMain.this.mRootView.removeView(xxMain.this.mAboutView); xxMain.this.mRootView.removeView(xxMain.this.mSettingView); xxMain.this.mRootView.addView(xxMain.this.mSettingView, xxMain.this.mRlparams); } }); localTextView2.setOnClickListener(new View.OnClickListener() { public voidonClick(View paramAnonymousView) { xxMain.this.mRootView.removeView(xxMain.this.mAboutView); xxMain.this.mRootView.removeView(xxMain.this.mSettingView); xxMain.this.mRootView.addView(xxMain.this.mAboutView, xxMain.this.mRlparams); } }); } private void show() { this.mRootView = new RelativeLayout(this.mActivity); FrameLayout.LayoutParams localLayoutParams = new FrameLayout.LayoutParams(-1, -1); this.mActivity.addContentView(this.mRootView, localLayoutParams); initNativeFunC(); initView(); } }


package
 com.xxAssistant.FknsgUI; import android.app.Activity; import android.graphics.drawable.Drawable; import android.util.DisplayMetrics; importandroid.view.Display; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup; importandroid.view.WindowManager; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.RelativeLayout; importandroid.widget.RelativeLayout.LayoutParams; import android.widget.ScrollView; import android.widget.SeekBar; importandroid.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; import com.xxAssistant.FknsgUI.bg.ShapeBg; public class xxSettingView extendsRelativeLayout { private static int MAX; private static int mSpeed = 0; private Activity mActivity; private float mDp; private ViewGroup mParent; privateLinearLayout mRealSettingView; private RelativeLayout mSettingView; static { MAX = 100; } public xxSettingView(Activity paramActivity, ViewGroup paramViewGroup) { super(paramActivity); this.mActivity = paramActivity; this.mParent = paramViewGroup; this.mSettingView = this; DisplayMetrics localDisplayMetrics = new DisplayMetrics(); this.mActivity.getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics); this.mDp = localDisplayMetrics.density; initView(); } private void initView() { this.mSettingView.setGravity(17); this.mSettingView.setBackgroundColor(-16777216);this.mSettingView.getBackground().setAlpha(80); this.mRealSettingView = new LinearLayout(this.mActivity); this.mRealSettingView.setOrientation(1);this.mRealSettingView.setGravity(1); int i = (int)(16.0F * this.mDp); this.mRealSettingView.setPadding(i, i, i, i); ShapeBg localShapeBg1 = newShapeBg(this.mActivity); localShapeBg1.setCornerRadius(8.0F); localShapeBg1.setColor(-16777216); localShapeBg1.setStroke(1, -1);this.mRealSettingView.setBackgroundDrawable(localShapeBg1); this.mRealSettingView.getBackground().setAlpha(153); RelativeLayout.LayoutParams localLayoutParams = new RelativeLayout.LayoutParams((int)(300.0F * this.mDp), -2); this.mSettingView.addView(this.mRealSettingView, localLayoutParams); TextView localTextView1 =new TextView(this.mActivity); localTextView1.setText("设置"); localTextView1.setTextSize(22.0F); localTextView1.setTextColor(-1); localTextView1.setGravity(1);this.mRealSettingView.addView(localTextView1); ScrollView localScrollView = new ScrollView(this.mActivity); localScrollView.setScrollBarStyle(0); LinearLayout localLinearLayout1 = new LinearLayout(this.mActivity); localLinearLayout1.setOrientation(1); LinearLayout localLinearLayout2 = newLinearLayout(this.mActivity); LinearLayout localLinearLayout3 = new LinearLayout(this.mActivity); ShapeBg localShapeBg2 = new ShapeBg(this.mActivity); localShapeBg2.setCornerRadius(10.0F); localShapeBg2.setColor(-1); localLinearLayout2.setBackgroundDrawable(localShapeBg2); localLinearLayout3.setBackgroundDrawable(localShapeBg2); (int)(6.0F * this.mDp); LinearLayout.LayoutParams localLayoutParams1 = newLinearLayout.LayoutParams(-1, -2); localLayoutParams1.topMargin = (int)(8.0F * this.mDp); this.mRealSettingView.addView(localScrollView, localLayoutParams1); localScrollView.addView(localLinearLayout1); TextView localTextView2 = new TextView(this.mActivity); localTextView2.setText("游戏加速:0 倍"); localTextView2.setTextColor(-1); localTextView2.setTextSize(17.0F); localTextView2.setGravity(14); SeekBar localSeekBar = new SeekBar(this.mActivity); localSeekBar.setMinimumHeight(2 * (int)this.mDp); localLinearLayout1.addView(localTextView2, localLayoutParams1); localLinearLayout1.addView(localSeekBar, localLayoutParams1); localSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(localTextView2) { public void onProgressChanged(SeekBar paramSeekBar, int paramInt, boolean paramBoolean) { xxSettingView.mSpeed = paramInt * (xxSettingView.MAX / 100); this.val$tittle.setText("游戏加速:" + xxSettingView.mSpeed + " 倍"); if (xxSettingView.mSpeed == 0); for (int i = 1000; ; i = 1000 * xxSettingView.mSpeed) { xxUtility.setTimeScale(i); return; } } public void onStartTrackingTouch(SeekBar paramSeekBar) { } public void onStopTrackingTouch(SeekBar paramSeekBar) { } });this.mSettingView.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View paramView, MotionEvent paramMotionEvent) { float f1 = paramMotionEvent.getX(); float f2 = paramMotionEvent.getY(); float f3 = xxSettingView.this.mRealSettingView.getLeft(); float f4 = xxSettingView.this.mRealSettingView.getTop(); float f5 = xxSettingView.this.mRealSettingView.getBottom(); float f6 = xxSettingView.this.mRealSettingView.getRight(); switch (paramMotionEvent.getAction()) { defaultreturn falsecase 0: } if ((f1 < f3) || (f1 > f6)); while(true) { xxSettingView.this.mParent.removeView(xxSettingView.this.mSettingView); return falseif (f2 < f4) continueif (f2 <= f5) break; } } }); } }


package
 com.xxAssistant.FknsgUI; import android.app.Activity; import android.app.AlertDialog.Builder; import android.content.DialogInterface; importandroid.content.DialogInterface.OnClickListener; import android.graphics.drawable.Drawable; import android.util.DisplayMetrics; import android.view.Display; importandroid.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup;import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.RelativeLayout; importandroid.widget.RelativeLayout.LayoutParams; import android.widget.TextView; import com.xxAssistant.FknsgUI.bg.ShapeBg; public class xxAbout extends RelativeLayout {private RelativeLayout mAbout; private Activity mActivity; private float mDp; private ViewGroup mParent; private LinearLayout mRealAbout; private TextView mTvContent;private TextView mTvTitle; public xxAbout(Activity paramActivity, ViewGroup paramViewGroup) { super(paramActivity); this.mActivity = paramActivity; this.mParent = paramViewGroup; this.mAbout = this; DisplayMetrics localDisplayMetrics = new DisplayMetrics();this.mActivity.getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics); this.mDp = localDisplayMetrics.density; initView(); } private void initView() {this.mAbout.setGravity(17); this.mAbout.setBackgroundColor(-16777216); this.mAbout.getBackground().setAlpha(0); this.mRealAbout = new LinearLayout(this.mActivity);this.mRealAbout.setOrientation(1); this.mRealAbout.setGravity(1); ShapeBg localShapeBg1 = new ShapeBg(this.mActivity); localShapeBg1.setCornerRadius(8.0F); localShapeBg1.setColor(-16777216); localShapeBg1.setStroke(1, -1); this.mRealAbout.setBackgroundDrawable(localShapeBg1); this.mRealAbout.getBackground().setAlpha(153); inti = (int)(16.0F * this.mDp); this.mRealAbout.setPadding(i, i, i, i); RelativeLayout.LayoutParams localLayoutParams = new RelativeLayout.LayoutParams((int)(300.0F *this.mDp), (int)(150.0F * this.mDp)); this.mAbout.addView(this.mRealAbout, localLayoutParams); this.mTvTitle = new TextView(this.mActivity);this.mTvTitle.setTextSize(22.0F); this.mTvTitle.setText("关于"); this.mTvTitle.setTextColor(-1); this.mTvTitle.setGravity(17); this.mRealAbout.addView(this.mTvTitle);this.mTvContent = new TextView(this.mActivity); ShapeBg localShapeBg2 = new ShapeBg(this.mActivity); localShapeBg2.setCornerRadius(6.0F); localShapeBg2.setColor(-1);this.mTvContent.setBackgroundDrawable(localShapeBg2); this.mTvContent.setTextColor(-16777216); this.mTvContent.setTextSize(18.0F); int j = (int)(4.0F * this.mDp);this.mTvContent.setPadding(j, j, j, j); this.mTvContent.setGravity(3); LinearLayout.LayoutParams localLayoutParams1 = new LinearLayout.LayoutParams(-1, -2); localLayoutParams1.topMargin = (int)(20.0F * this.mDp); this.mRealAbout.addView(this.mTvContent, localLayoutParams1); TextView localTextView = newTextView(this.mActivity); localTextView.setText("隐藏界面"); localTextView.setTextColor(-16711936); LinearLayout.LayoutParams localLayoutParams2 = newLinearLayout.LayoutParams(-2, -2); localLayoutParams2.topMargin = (int)(20.0F * this.mDp); localLayoutParams2.gravity = 5; this.mRealAbout.addView(localTextView, localLayoutParams2); localTextView.setOnClickListener(new View.OnClickListener() { public void onClick(View paramView) { AlertDialog.Builder localBuilder = newAlertDialog.Builder(xxAbout.this.mActivity); localBuilder.setMessage("警告:界面隐藏后,只能在下次游戏启动时再次出现,请确认是否执行该操作。"); localBuilder.setPositiveButton("确定",new DialogInterface.OnClickListener() { public void onClick(DialogInterface paramDialogInterface, int paramInt) { xxAbout.this.mParent.removeAllViews(); } }); localBuilder.setNegativeButton("取消", null); localBuilder.show(); } }); this.mAbout.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View paramView, MotionEvent paramMotionEvent) { float f1 = paramMotionEvent.getX(); float f2 = paramMotionEvent.getY(); float f3 = xxAbout.this.mRealAbout.getLeft(); float f4 = xxAbout.this.mRealAbout.getTop(); float f5 = xxAbout.this.mRealAbout.getBottom(); float f6 = xxAbout.this.mRealAbout.getRight(); switch (paramMotionEvent.getAction()) {defaultreturn falsecase 0: } if ((f1 < f3) || (f1 > f6)); while (true) { xxAbout.this.mParent.removeView(xxAbout.this.mAbout); return falseif (f2 < f4) continueif(f2 <= f5) break; } } }); } public void setXXVersionString(String paramString) { this.mTvContent.setText(paramString); } }


其中 xxUtility.setTimeScale在xxUtility中:
package com.xxAssistant.FknsgUI; import android.app.Activity; public class xxUtility { public static Activity mActivity; private static boolean mIsInitOk = false;private static native void doSetTimeScale(int paramInt); public static void init(Activity paramActivity, String paramString) { mActivity = paramActivity; if (paramString != null) { System.load(paramString); mIsInitOk = xxdohook(); } } public static void setTimeScale(int paramInt) { if(mIsInitOk) doSetTimeScale(paramInt); } private static native boolean xxdohook(); }
加载对应的插件目录下的libxxfknsg.so:
对gettimeofday和clock_gettime做一些hook,然后通过xxUtility::setTimeScale加速设置加速倍数。



再分析“天天星连萌”的插件:
package com.xxAssistant.UI; import android.app.Activity; import android.content.Context; import android.util.Log; import android.widget.RelativeLayout; importandroid.widget.Toast; public class UniversalUI extends RelativeLayout { private static String mSoPath; private static UniversalUI me = nullprivate Activity mActivity; private Context mContext; private boolean mShow; private UniversalUI(Activity paramActivity) { super(paramActivity); this.mContext = paramActivity;this.mActivity = paramActivity; this.mShow = false; } public static void init(Activity paramActivity, String paramString) { if (me == null); for(UniversalUI localUniversalUI = new UniversalUI(paramActivity); ; localUniversalUI = me) { me = localUniversalUI; mSoPath = paramString; me.show(); return; } } private void show() { if (!this.mShow) { this.mShow = true; Log.d("native", "叉叉辅助已成功装载"); Toast.makeText(this.mContext.getApplicationContext(), "叉叉辅助已成功装载1111111111111111111111111111111111", 1).show(); System.load(mSoPath); xxdohook(); } } private native void xxdohook(); }
可以看出都有一个静态的init函数,插桩修改打印参数:
.class public Lcom/xxAssistant/UI/UniversalUI; .super Landroid/widget/RelativeLayout; .source "UniversalUI.java" # static fields .field private staticmSoPath:Ljava/lang/String; .field private static me:Lcom/xxAssistant/UI/UniversalUI; # instance fields .field private mActivity:Landroid/app/Activity; .fieldprivate mContext:Landroid/content/Context; .field private mShow:Z # direct methods .method static constructor <clinit>()V .locals 1 .prologue .line 12 const/4 v0, 0x0 sput-object v0, Lcom/xxAssistant/UI/UniversalUI;->me:Lcom/xxAssistant/UI/UniversalUI; .line 17 return-void .end method .method private constructor <init>(Landroid/app/Activity;)V .locals 1 .parameter "activity" .prologue .line 20 invoke-direct {p0, p1}, Landroid/widget/RelativeLayout;-><init>(Landroid/content/Context;)V .line 22 iput-object p1, p0, Lcom/xxAssistant/UI/UniversalUI;->mContext:Landroid/content/Context; .line 23 iput-object p1, p0, Lcom/xxAssistant/UI/UniversalUI;->mActivity:Landroid/app/Activity; .line 24 const/4 v0, 0x0 iput-boolean v0, p0, Lcom/xxAssistant/UI/UniversalUI;->mShow:Z#debug by sing const-string v0, "MODBYSING" invoke-virtual {p1}, Ljava/lang/Object;->toString()Ljava/lang/String; move-result-object v1 invoke-static {v0, v1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I #debug by sing .line 25 return-void.end method .method public static init(Landroid/app/Activity;Ljava/lang/String;)V .locals 1 .parameter "activity" .parameter "soPath" .prologue .line 29 sget-object v0, Lcom/xxAssistant/UI/UniversalUI;->me:Lcom/xxAssistant/UI/UniversalUI; if-nez v0, :cond_0 new-instance v0, Lcom/xxAssistant/UI/UniversalUI; invoke-direct {v0, p0}, Lcom/xxAssistant/UI/UniversalUI;-><init>(Landroid/app/Activity;)V :goto_0 sput-object v0, Lcom/xxAssistant/UI/UniversalUI;->me:Lcom/xxAssistant/UI/UniversalUI; .line 30 sput-object p1, Lcom/xxAssistant/UI/UniversalUI;->mSoPath:Ljava/lang/String; .line 31 sget-object v0, Lcom/xxAssistant/UI/UniversalUI;->me:Lcom/xxAssistant/UI/UniversalUI; invoke-direct {v0}, Lcom/xxAssistant/UI/UniversalUI;->show()V .line 32 return-void .line 29 :cond_0 sget-object v0, Lcom/xxAssistant/UI/UniversalUI;->me:Lcom/xxAssistant/UI/UniversalUI; goto :goto_0 .end method .method private show()V .locals 3 .prologue const/4 v2, 0x1 .line 35 iget-boolean v0, p0, Lcom/xxAssistant/UI/UniversalUI;->mShow:Z if-nez v0, :cond_0 .line 36 iput-boolean v2, p0, Lcom/xxAssistant/UI/UniversalUI;->mShow:Z .line 38 const-string v0, "native" const-string v1, "\u53c9\u53c9\u8f85\u52a9\u5df2\u6210\u529f\u88c5\u8f7d" invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 39 iget-object v0, p0, Lcom/xxAssistant/UI/UniversalUI;->mContext:Landroid/content/Context; invoke-virtual {v0}, Landroid/content/Context;->getApplicationContext()Landroid/content/Context; move-result-object v0const-string v1, "\u53c9\u53c9\u8f85\u52a9\u5df2\u6210\u529f\u88c5\u8f7d1111111111111111MODBYSING" invoke-static {v0, v1, v2}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; move-result-object v0 invoke-virtual {v0}, Landroid/widget/Toast;->show()V .line 40 sget-object v0, Lcom/xxAssistant/UI/UniversalUI;->mSoPath:Ljava/lang/String; #debug by sing const-string v1, "MODBYSING" invoke-static{v1,v0} ,Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I #debug by sing invoke-static {v0}, Ljava/lang/System;->load(Ljava/lang/String;)V .line 41 invoke-direct {p0}, Lcom/xxAssistant/UI/UniversalUI;->xxdohook()V .line 43 :cond_0 return-void .end method .method privatenative xxdohook()V .end method



此插件实现的效果是任意消除,捕获的log信息:
04-09 15:46:23.770: V/MODBYSING(13478): com.tencent.lian.MiniGame@41c711a8 04-09 15:46:23.800: V/MODBYSING(13478): /data/data/com.xxAssistant/app_plugin/105/libxxlianmeng_mm.so
实际运行中MainActivity::onCreate并没有执行(单独直接运行APK会执行,仅仅方便开发使用,具体启动游戏时插件的运行逻辑中不会执行到MainActivity::onCreate),证实Activity确实是游戏的主Activity。

再看插件so文件导出的xxdohook函数,Java_com_xxAssistant_UI_UniversalUI_xxdohook:
函数内部调用了do_hook:
调用了MSHookFunction(libSubstrate.so提供的函数)来hook原游戏libGameApp.so中的函数。


下面把插件APK直接安装运行,这个是滑雪大冒险的插件运行效果图:
可以看出和启动游戏后的插件显示效果类似,只不过单独运行时只是一个hello world的界面。

综合以上分析猜测:
所有插件按照一定格式编写,需要有一个.xxplist配置文件,一个可以安装运行的APK(可以直接安装运行是为了方便插件的开发),如果有做底层hook操作的还会有一个so文件。
.xxplist配置文件的内容格式如下:
game-name为游戏包名,
apk-path为插件全路径
ui-name为插件界面
activity-name为游戏启动activity
so-path为插件so库全路径
叉叉助手游戏列表中保存有插件id,点击“启动游戏”时按照item对应的插件id加载创建目录对应的插件apk,启动规则是按照插件目录下的.xxplist配置文件来的。
叉叉助手在运行时会做一次注入操作,在叉叉助手里启动游戏时,将相应的插件配置文件重定向到一个plist.xx的公共配置文件,由于做了注入,处于底层的监控层监控到游戏启动时判断当前的activity的包名是否和配置文件中的包名吻合,如果吻合说明当前游戏和当前插件匹配,则通过配置文件读取插件apk并动态加载,并调用一个静态的init函数,传递参数为:参数1是游戏的activity启动实例,参数2为配置文件中的插件so库文件路径。init函数完成插件的界面配置,显示为游戏界面上的悬浮窗口,加载so库并调用so的导出函数进行hook操作。

待研究内容
1、libsubstrate的hook框架。
2、验证:注入后如何监控游戏的启动并加载插件。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

asmcvc

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

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

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

打赏作者

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

抵扣说明:

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

余额充值