查看原文
其他

Android破解实战:游戏蜂窝3.19版本破解记录

猪会被杀掉 看雪学院 2019-05-26

下载ApkTool

ApkTool下载地址:

https://ibotpeaches.github.io/Apktool/

ApkTool安装说明:

https://ibotpeaches.github.io/Apktool/install/

  • 运行apktool d target.apk反编译资源

  • 运行apktool byouxifengwo -o ReYXFW.apk 重打包APK

  • uiautomatorviewer在sdk的tool目录下


生成签名密钥

唤出CMD:开始—运行—输入CMD后,点确定或按ENTER回车键。

唤出CMD后输入下面命令后按回车键:

cd /d C:\Program Files\Java\jdk1.7.0\bin

输入后按回车再输入下面命令后按回车

keytool -genkey -alias abc.keystore-keyalg RSA -validity 20000 -keystore abc.keystore

abc可改为其他名称,命令区分大小写。

执行命令后会出现下面步骤:

  • 输入keystore密码:[密码不显示,输入密码按回车即可开

  • 再次输入新密码:[密码不显示,输入密码按回车即可开

  • 您的名字与姓氏是什么?

  • [Unknown]:  tttabc

  • 您的组织单位名称是什么?

  • [Unknown]:  www.tttabc.com

  • 您的组织名称是什么?

  • [Unknown]:  www.tttabc.com

  • 您的组织名称是什么?

  • [Unknown]:  www.tttabc.com

  • 您所在的城市或区域名称是什么?

  • [Unknown]:  NewYork

  • 您所在的州或省份名称是什么?

  • [Unknown]:  NewYork

  • 该单位的两字母国家代码是什么

  • [Unknown]:  CN

  • CN=abc,OU=www.tttabc.com,O=www.tttabc.com,L=New York,ST

    =New York, C=CN 正确吗?

  • [否]:  Y

  • 输入<abc.keystore>的主密码

  • (如果和 keystore 密码相同,按回车):

成功后将会在C:\Program Files\Java\jdk1.7.0\bin 下产生一个名为abc.keystore的文件。

其中参数-validity为证书有效天数,这里我们写的大些——20000天。在输入密码时没有回显,只管输入就可以了,一般位数建议使用20位,需要记下来后面还要用。

接下来我们开始为apk文件签名了。


签名apk文件

将要签名的APK放到C:\Program Files\Java\jdk1.7.0\bin 下,apk最好命名为简单的名字,如123.apk。

唤出CMD: 开始—运行—输入CMD后,点确定或按ENTER回车键。

唤出CMD后输入下面命令后按回车键:

cd C:\Program Files\Java\jdk1.7.0\bin

输入后,按回车;

再输入下面命令后,按回车:

jarsigner-verbose -keystore abc.keystore -signedjar 123x.apk new_target.apk abc.keystore

接着,输入密码按回车。

这样,就可以生成签名的apk文件了。这里输入文件abc.apk,最终生成123x.apk,为android签名后的APK执行文件。下面提示输入的密码和keytool输入的一样就行了 。

如果是修改APK或ZIP格式刷机ROM,需要签名,推荐用auto-sign签名,简单方便:

  • 下载 auto-sign.zip ;

  • 运行需安装JAVA jdk;

  • auto-sign解压到如E盘下;

  • 将需要签名的APK或ZIP放到 auto-sign签名工具同目录下;

  • 运行auto-sign签名批处理工具即可自动签名。


安装APK测试

  • Adb install 123x.apk

安卓设备上运行重打包过的apk正常登录,提示签名错误,说明APK文件有检查apk的签名,第一步绕过重打包签名验证。


开始逆向和反编译破解加密解密的数据

抓取登录数据包:

  • 下载数据包抓取工具charles,工具的使用请自行搜索;

  • 通过数据包,发现登录请求的数据回答是显示签名错误。

  • 开始对比正常的数据包—— 一个正常登录的数据包,里面的数据是被加密过的;

  • 开始尝试解密数据包,先反编译APK。如果没被加密,反编译的方法请自行搜索;

  • 开始寻找APK里面的登录验证解密函数。


调试和反编译APK查看加密解密函数

先上传IDAPRO的调试支持,使用SU权限运行。

adbpush android_server /data/local/tmp/

adbshell chmod 777 /data/local/tmp/android_server

su /data/local/tmp/android_server

adb forward tcp:23946 tcp:23946

运行adb logcat ActivityManager:I *:s查看Android应用包/Activity。

再运行命令,等待IDAPRO附加调试:

adb shell am start-D -n com.cyjh.gundam/.fengwo.ui.activity.WelcomeActivity

IDAPRO附加进程命令:

Debugger - > Attach -> RemoteArmLinux/Android debugger

 这种方法尝试之后好像不能调试到Dalvik虚拟机。

现在开始dex文件的反编译-dex2jar和jd-gui:

  • d2j-dex2jar.bat classes2.dex生成classes2-dex2jar.jar

  • 下载jd-gui打开classes2-dex2jar.jar


写个SOHOOK掉解密函数

下载

xposed(http://repo.xposed.info/module/de.robv.android.xposed.installer) 

编译一个Hook插件拦截解密函数,分析整理解密函数与原始数据包并对应到URL

(范例https://github.com/jackuhan/LoginHook)


去掉APK自校验重新打包(lib/xxx/libcjencrypt.so)


.text:F3E69478decrypt; DATA XREF: .data:F3E7D030↓o
.text:F3E69478;__unwind {
.text:F3E69478PUSH           {R4-R7,LR}
.text:F3E6947AADD            R7, SP, #0xC
.text:F3E6947CPUSH.W         {R8,R9,R11}
.text:F3E69480MOV            R9, R1
.text:F3E69482MOV            R1, R3
.text:F3E69484MOV            R8, R2
.text:F3E69486MOV            R6, R0
.text:F3E69488BL             sub_F3E694C4
.text:F3E6948CMOV            R4, R0
.text:F3E6948ELDR            R0, =(off_F3E7D004 - 0xF3E69494)
.text:F3E69490ADD            R0, PC;off_F3E7D004
.text:F3E69492LDR            R1, [R0]; "8CF8BD517174351E61BBCF776B3B83376195D65"
.text:F3E69494MOV            R0, R4; s1
.text:F3E69496BLX            strcmp; apk checksum
.text:F3E6949AMOV            R5, R0
.text:F3E6949CMOV            R0, R4; ptr
.text:F3E6949EBLX            free
.text:F3E694A2CBZ            R5, loc_F3E694AC
.text:F3E694A4MOVS           R0, #0
.text:F3E694A6POP.W          {R8,R9,R11}
.text:F3E694AAPOP            {R4-R7,PC}
.text:F3E694AC;---------------------------------------------------------------------------
.text:F3E694AC
.text:F3E694ACloc_F3E694AC; CODE XREF:decrypt+2A↑j
.text:F3E694ACMOV            R0, R6
.text:F3E694AEMOV            R1, R9
.text:F3E694B0MOV            R2, R8
.text:F3E694B2POP.W          {R8,R9,R11}
.text:F3E694B6POP.W          {R4-R7,LR}
.text:F3E694BAB.W            sub_F3E68C88
.text:F3E694BA; Endof function decrypt


VIP权限


.methodpublic setIsVip(I)V
  .locals 4
  .param p1, "isVip"    # I
  .prologue
  .line 274    
  iput p1, p0, Lcom/cyjh/gundam/model/UserInfo;->IsVip:I
      constv0, 0x1
      iputv0, p0, Lcom/cyjh/gundam/model/UserInfo;->IsVip:I   
  .line 275
  return-void
.end method
CODE:00704F1C# Source file: UserInfo.java
CODE:00704F1Cpublic int com.cyjh.gundam.model.UserInfo.getIsVip()
CODE:00704F1Cthis =v1                              # CODE XREF: VipPresenter_setUserInfo@VL+A↑p
CODE:00704F1C                                        # LeftMenuFragment_setInfo@VL:loc_6BE372↑p ...
CODE:00704F1C                .prologue_end
CODE:00704F1C                .line 270
CODE:00704F1C                iget                           v0, this, stru_B09E4
CODE:00704F20                const/4                        v0, 1
CODE:00704F22
CODE:00704F22locret:
CODE:00704F22                return                         v0
CODE:00705046Method End


VIP过期时间


.methodpublic setVIPExpireTime(Ljava/lang/String;)V
  .locals 4
  .param p1, "VIPExpireTime"    # Ljava/lang/String
;
  .prologue
  .line 282  
  iput-object p1, p0,Lcom/cyjh/gundam/model/UserInfo;->VIPExpireTime:Ljava/lang/String;
      const-string/jumbov0, "2022-12-31"
      iputv0, p0, Lcom/cyjh/gundam/model/UserInfo;->VIPExpireTime:Ljava/lang/String;
  .line 283
  return-void
.endmethod
CODE:0070503C# Source file: UserInfo.java
CODE:0070503Cpublic java.lang.String com.cyjh.gundam.model.UserInfo.getVIPExpireTime()
CODE:0070503Cthis =v1                              # CODE XREF: LeftMenuFragment_setInfo@VL+DE↑p
CODE:0070503C                                        # LeftMenuFragment_setInfo@VL+F2↑p ...
CODE:0070503C                .prologue_end
CODE:0070503C                .line 278
CODE:0070503C                iget-object                    v0, this, stru_B0A4C
CODE:00705040                const-string/jumbo             v0, a20221231 # "2022-12-31"
CODE:00705046
CODE:00705046locret:
CODE:00705046                return-object                  v0
CODE:00705046Method End


VIP类型


.methodpublic setVIPType(I)V
  .locals 4
  .param p1, "VIPType"    # I
  .prologue
  .line 110
  iput p1, p0, Lcom/cyjh/gundam/model/UserInfo
;->VIPType:I     
      constv0, 0x2
      iputv0, p0, Lcom/cyjh/gundam/model/UserInfo;->VIPType:I     
  .line 111
  return-void
.endmethod
CODE:00705058# Source file: UserInfo.java
CODE:00705058public int com.cyjh.gundam.model.UserInfo.getVIPType()
CODE:00705058this =v1                              # CODE XREF: LeftMenuFragment_setInfo@VL+162↑p
CODE:00705058                                        # LoginManager_updateUserInfo@VLL+3C↑p
CODE:00705058                .prologue_end
CODE:00705058                .line 106
CODE:00705058                iget                           v0, this, stru_B0A54
CODE:0070505C                const/4                        v0, 2
CODE:0070505E
CODE:0070505Elocret:
CODE:0070505E                return                         v0
CODE:0070505EMethod End


去除时间限制


com.cyjh.gundam.manager.LoginManager.java
.methodpublic getDisCountSecond()J
  .locals 2
  .prologue
  .line 965
  invoke-virtual {p0}, Lcom/cyjh/gundam/manager/LoginManager;->isLoginV70()Z
  move-result v0
  if-eqz v0, :cond_0
  .line 966
  iget-object v0, p0,Lcom/cyjh/gundam/manager/LoginManager;->mInfo:Lcom/cyjh/gundam/model/LoginResultInfo;
  iget-wide v0, v0, Lcom/cyjh/gundam/model/LoginResultInfo;->DisCountSecond:J
  .line 968
  :goto_0
      const-wide/32v0, 0x10000
  return-wide v0
  :cond_0
  const-wide/16 v0, 0x0
      const-wide/32v0, 0x10000
  goto :goto_0
.endmethod
.methodpublic getFreeSecond()J
  .locals 2
  .prologue
  .line 975
  invoke-virtual {p0}, Lcom/cyjh/gundam/manager/LoginManager;->isLoginV70()Z
  move-result v0
  if-eqz v0, :cond_0
  .line 976
  iget-object v0, p0,Lcom/cyjh/gundam/manager/LoginManager;->mInfo:Lcom/cyjh/gundam/model/LoginResultInfo;
  iget-wide v0, v0, Lcom/cyjh/gundam/model/LoginResultInfo;->FreeSecond:J
  .line 978
  :goto_0
      const-wide/32v0, 0x10000
  return-wide v0
  :cond_0
  const-wide/16 v0, 0x0
      const-wide/32v0, 0x10000
  goto :goto_0
.endmethod


免登录打开脚本支持的游戏

a)  源码文件夹

com.cyjh.gundam.fengwo,“com\cyjh\gundam\fengwo”

b)  搜索isLoginV70函数调用,smali里面修改返回值免登录。


"我的脚本" 免登录

a)  源码

com.cyjh.gundam.utils.IntentUtil.java

b)  定位函数toMyScriptActivity里面的isLoginV70,修改返回值


强制免费使用脚本

a)  源码文件夹

com\cyjh\gundam\fengwoscript\

b)  搜索isLogin函数调用, 修改返回值。

c)  源码文件夹

(com.cyjh.gundam.fengwoscript.model.manager.HeartAndPermManager.java)

d)  搜索函数checkRunPerm,修改里面的判断语句

  • viprunperminfo.KickedOut

  • viprunperminfo.BanRun

  • viprunperminfo.TryExpired

实现强制选择目标脚本,进入“本地挂机”按钮界面,按钮默认状态被禁止。

e)  源码文件夹

com.cyjh.gundam.fengwoscript.ui.help.SzScriptInfoSetHelp.java

f)  搜索函数setInfo,修改vipadresultinfo.RunPerm.Run和vipadresultinfo.RunPerm.Try实现恢复“本地挂机”按钮,但是无法弹出外挂对话框。

g)  源码文件夹

com.cyjh.gundam.fengwoscript.model.manager.HeartAndPermManager.java

h)  找到函数isRun,修改viprunperminfo.KickedOut、viprunperminfo.BanRun、viprunperminfo.TryExpired,实现弹出外挂设置对话框。

i)  源码文件夹

(com.cyjh.gundam.fengwo.pxkj.script.ui.presenter.ScriptRunPresenter.java)

j)  搜索vipadresultinfo.RunPerm.KickedOut,修改掉判断语句。

k)  源码文件夹

(com.cyjh.gundam.fengwoscript.presenter.ScriptInfoPresenter.java)

l)  找到函数startScriptOnClick,修改vipadresultinfo.RunPerm.Run和vipadresultinfo.RunPerm.Try

触发“本地挂机”按钮事件强制运行脚本,脚本运行后马上停止。

m)  源码文件夹

(com.cyjh.gundam.fengwoscript.model.manager.HeartAndPermManager.java)

n)  搜索onEventMainThread检测线程函数,修改vipscriptheartinfo.Status状态值为3,即可实现强制使用脚本.

o)  找到源码文件夹

(com.cyjh.gundam.activity.GunDamMainActivity.java)

p)  定位到函数setBottomDataByPreData,(首页、"TargetType": 6),(云手机、TargetType": 8),(我的、"TargetType":7,),(免Root脚本、"TargetType":11),(变态游戏、  "TargetType":9),分别对应到APK的底下菜单栏处理。

q)  找到源码文件夹

(com.cyjh.gundam.fengwoscript.ui.help.SzScriptInfoSetHelp.java)

r)  找到函数setInfo,修改vipadresultinfo.EachTryTime语句关闭剩余试用的提示。

s)  找到源码文件夹

(com.cyjh.gundam.fengwoscript.ui.help.ScriptTopRaqViewHelp.java)

t)  找到函数setData,改为mFaqTv.setVisibility(0)关闭脚本使用常见问题.

u)  找到源码文件夹

(com.cyjh.gundam.fengwoscript.presenter.ScriptInfoPresenter.java)

v)  找到函数isShowAd,改为返回false关闭非会员运行脚本展示广告。

 

心跳包线程

com.cyjh.gundam.fengwoscript.presenter.ScriptInfoPresenter.java

{
     booleanflag = true;
     Strings = com/cyjh/gundam/fengwoscript/presenter/ScriptInfoPresenter.getSimpleName();
     StringBuilderstringbuilder = (new StringBuilder()).append("PermStatueEvent --\u5FC3\u8DF3\u662F\u5426\u8C03\u7528\uFF1A");
     if(permstatueevent.resultInfo!= null)
           flag= false;
     CLog.i(s,stringbuilder.append(flag).toString());
     try
     {
           SZScriptInfoszscriptinfo = permstatueevent.resultInfo.ScriptInfo;
           if(szscriptinfo!= null)
           {
                 mInfo.EncryptKey= szscriptinfo.EncryptKey;
                 mInfo.IsEncrypt= szscriptinfo.IsEncrypt;
                 mInfo.NewEncryptKey= szscriptinfo.NewEncryptKey;
                 mInfo.ScriptPath= szscriptinfo.ScriptPath;
                 loadScript(true);
           }else
           {
                 loadScript(false);
           }
     }
     catch(Exceptionexception) { }
}


心跳包检测跳过

com.cyjh.gundam.fengwoscript.model.ScriptHeartModel.java

以下4个函数直接返回:

.methodprivate load()V
  .locals 1
  .prologue
  .line 137
      return-void    
  iget-object v0, p0,Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->mListener:Lcom/kaopu/core/basecontent/http/inf/IUIDataListener;
  invoke-virtual {p0, v0},Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->loadData(Lcom/kaopu/core/basecontent/http/inf/IUIDataListener;)V
  .line 138
  return-void
.endmethod
.methodprivate pauseHear()V
  .locals 0
  .prologue
  .line 116    
      return-void     
  invoke-direct {p0},Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->removeHeart()V
  .line 117
  return-void
.endmethod
.methodprivate resumeHear()V
  .locals 2
  .prologue
  .line 122   
      return-void   
  const/4 v0, 0x2
  iput v0, p0,Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->mStartOrStop:I
  .line 123
  iget-object v0, p0,Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->mPathModel:Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartPathModel;
  const/4 v1, 0x0
  invoke-virtual {v0, v1},Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartPathModel;->setCount(I)V
  .line 128
  iget v0, p0,Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->mHeartbeatInterval:I
  if-gtz v0, :cond_0
  .line 129
  const/16 v0, 0x12c
  iput v0, p0,Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->mHeartbeatInterval:I
  .line 131
  :cond_0
  iget v0, p0,Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->mHeartbeatInterval:I
  mul-int/lit16 v0, v0, 0x3e8
  invoke-direct {p0, v0},Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->sendHeartHandler(I)V
  .line 132
  return-void
.endmethod
.methodpublic startHear(I)V
  .locals 3
  .param p1, "time"    # I
  .prologue   
      return-void  
  const/4 v2, 0x1
  .line 108
  iput p1, p0,Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->mHeartbeatInterval:I
  .line 109
  iput v2, p0,Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->mStartOrStop:I
  .line 110
  iget-object v0, p0,Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->mPathModel:Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartPathModel;
  const/4 v1, 0x0
  invoke-virtual {v0, v1},Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartPathModel;->setCount(I)V
  .line 111
  invoke-direct {p0, v2},Lcom/cyjh/gundam/fengwoscript/model/ScriptHeartModel;->sendHeartHandler(I)V
  .line 112
  return-void
.endmethod


免登录运行脚本分析

PXJY脚本心跳请求:

目录:

com.cyjh.gundam.fengwo.pxkj.script.ui.presenter

源码:

  • ScriptInfoViewPresenter.java ScriptHeartAndPermManager.java

  • ScriptManager.java

  • ScriptRunPermModel.java

  • ScriptInfoViewPresenter.java


加载脚本心跳请求函数:

public void load()
{
 iView.showLoading();
ScriptHeartAndPermManager.getInstance().loadScriptPerm();
}


开始函数

public void start()
{
Log.i(com/cyjh/gundam/fengwo/pxkj/script/ui/presenter/ScriptInfoViewPresenter.getSimpleName(),"start()");
 mInfo =CurrOpenAppManager.getInstance().getScriptInfo();
mScriptFileCompleteReceiver.registerReceiver(BaseApplication.getInstance(), newIntentFilter("pxkj_action_script_file_complete"));
 IntentFilterintentfilter = new IntentFilter();
intentfilter.addAction("0x1_scriptinfo");
 LocalBroadcastManager.getInstance(iView.getCurrentContext()).registerReceiver(mScriptInfoReceiver,intentfilter);
 load();
}

ScriptHeartAndPermManager.java

发送GetRunPerm心跳请求

public void loadScriptPerm()
{
 mRunPermModel = newScriptRunPermModel(CurrOpenAppManager.getInstance().getScriptInfo());
 mRunPermModel.load();
}


收到心跳回答包,并且发送toLocalBradcastForScriptInfo通知脚本信息:

public voiduiDataSuccess(Object obj)
{
 isRunPermLoading =false;
 BaseResultWrapperbaseresultwrapper = (BaseResultWrapper)obj;
 if(baseresultwrapper!= null && baseresultwrapper.code.intValue() == 1)
 {
     VipAdResultInfovipadresultinfo = (VipAdResultInfo)baseresultwrapper.data;
     if(vipadresultinfo!= null && vipadresultinfo.ScriptInfo != null)
      IntentUtil.toLocalBradcastForScriptInfo(1, vipadresultinfo.ScriptInfo);
     else
      IntentUtil.toLocalBroadcastForScriptperm(vipadresultinfo);
 }
}


ScriptInfoViewPresenter.java

接受toLocalBradcastForScriptInfo通知信息,并下载脚本。

public voidonReceive(Context context, Intent intent)
{
Log.i(com/cyjh/gundam/fengwo/pxkj/script/ui/presenter/ScriptInfoViewPresenter.getSimpleName(),"onrecive:");
 SZScriptInfoszscriptinfo =(SZScriptInfo)intent.getParcelableExtra("0x1_key_scriptinfo_bundle");
 if(szscriptinfo !=null)
 {
     mInfo.EncryptKey= szscriptinfo.EncryptKey;
     mInfo.EncryptKey= szscriptinfo.NewEncryptKey;
     mInfo.ScriptPath= szscriptinfo.ScriptPath;
     mInfo.IsEncrypt= szscriptinfo.IsEncrypt;
     loadScript();
 }
}


FengWoScript心跳检查:

com.cyjh.gundam.fengwoscript.presenter.ScriptInfoPresenter.java

public voidonEventMainThread(com.cyjh.gundam.fengwoscript.event.Event.PermStatueEventpermstatueevent)
{
 booleanflag = true;
 String s= com/cyjh/gundam/fengwoscript/presenter/ScriptInfoPresenter.getSimpleName();
StringBuilder stringbuilder = (newStringBuilder()).append("PermStatueEvent --\u5FC3\u8DF3\u662F\u5426\u8C03\u7528\uFF1A");
if(permstatueevent.resultInfo != null)
 flag =false;
CLog.i(s, stringbuilder.append(flag).toString());
 try
 {
       SZScriptInfoszscriptinfo = permstatueevent.resultInfo.ScriptInfo;
       if(szscriptinfo!= null)
       {
        mInfo.EncryptKey = szscriptinfo.EncryptKey;
        mInfo.IsEncrypt = szscriptinfo.IsEncrypt;
        mInfo.NewEncryptKey = szscriptinfo.NewEncryptKey;
        mInfo.ScriptPath = szscriptinfo.ScriptPath;
        loadScript(true);
       }else
       {
        loadScript(false);
       }
 }
catch(Exception exception) { }
}


协议回答的UUID检查绕过

  •  源码文件夹:

    com.cyjh.gundam.utils.UUIDManager.java

  •  修改UUIDManager.getInstance().isExist的返回值为true

  •  修改UUIDManager.getInstance().generateUUID生成一个固定UUID

  • “1c59f8d2-a569-4968-ba4c-89488b3f1f34”


跳过对GetRunPerm协议的处理

源码文件夹:

com/cyjh/gundam/utils/DesUtils.java

找到解密函数decode_new,修改其让其跳过对GetRunPerm协议的回答进行解密,我们的服务器返回明文字符串,让其正常解析。下面是添加后的代码:

.methodpublicdecode_new2(Ljava/lang/String;Landroid/content/Context;)Ljava/lang/String;
  .locals 4
  .param p1, "paramString"    # Ljava/lang/String;
  .param p2, "paramContext"    #Landroid/content/Context;
  .prologue
  .line 41
  const-string/jumbo v2, "myhook"
  const-string/jumbo v3, "decode_new"
  invoke-static {v2, v3},Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I
  .line 42
  const-string/jumbo v0, "1c59f8d2-a569-4968-ba4c-89488b3f1f34"
  .line 43
  .local v0, "code":Ljava/lang/String;
  const/4 v2, 0x0
  const/16 v3, 0x24
  invoke-virtual {p1, v2, v3},Ljava/lang/String;->substring(II)Ljava/lang/String;
  move-result-object v1
  .line 45
  .local v1, "str2":Ljava/lang/String;
  invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
  move-result v2
  if-eqz v2, :cond_0
  .line 49
  .end local p1    # "paramString":Ljava/lang/String;
  :goto_0
  return-object p1
  .restart local p1    # "paramString":Ljava/lang/String;
  :cond_0
  const-string/jumbo p1, ""
  goto :goto_0
.end method
.methodpublic decode_new(Ljava/lang/String;Landroid/content/Context;)Ljava/lang/String;
  .locals 4
  .param p1, "data"    # Ljava/lang/String;
  .param p2, "context"    # Landroid/content/Context;
  .annotation system Ldalvik/annotation/Throws;
      value = {
          Ljava/lang/Exception;
      }
  .end annotation
  .prologue
  .line 130
  invoke-static {p1},Landroid/text/TextUtils;->isEmpty(Ljava/lang/CharSequence;)Z
  move-result v2
  if-eqz v2, :cond_0
  .line 131
  const-string/jumbo v2, ""
  .line 152
  :goto_0
  return-object v2
:cond_0
  invoke-virtual {p0, p1, p2},Lcom/mfwfz/game/utils/DesUtils;->decode_new2(Ljava/lang/String;Landroid/content/Context;)Ljava/lang/String;
  move-result-object v0
  .local v0, "str":Ljava/lang/String;
  if-eqz v0, :cond_3
  .line 58
  .end local v0    # "str":Ljava/lang/String;
  return-object v0
  .restart local v0    # "str":Ljava/lang/String;
  .line 134
:cond_3
  if-nez p2, :cond_2
  .line 135
  invoke-static {},Lcom/mfwfz/game/application/BaseApplication;->getInstance()Lcom/mfwfz/game/application/BaseApplication;
  move-result-object v2
  if-nez v2, :cond_1
  .line 136
  const-string/jumbo v2, "decode"
  const-string/jumbo v3, "\u62a5\u9519decode: context=null"
  invoke-static {v2, v3},Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
  .line 137
  const-string/jumbo v2, ""
  goto :goto_0
  .line 139
  :cond_1
  invoke-static {},Lcom/mfwfz/game/application/BaseApplication;->getInstance()Lcom/mfwfz/game/application/BaseApplication;
  move-result-object p2
  .line 143
  :cond_2
  :try_start_0
  new-instance v0, Lcom/cyjh/cjencrypt/CJEncrypt;
  invoke-direct {v0}, Lcom/cyjh/cjencrypt/CJEncrypt;-><init>()V
  .line 144
  .local v0, "cjEncrypt":Lcom/cyjh/cjencrypt/CJEncrypt;
  invoke-virtual {v0, p1},Lcom/cyjh/cjencrypt/CJEncrypt;->setSource(Ljava/lang/String;)V
  .line 145
  const/4 v2, 0x2
  invoke-virtual {v0, v2}, Lcom/cyjh/cjencrypt/CJEncrypt;->setCryptType(I)V
  .line 146
  const/4 v2, 0x0
  invoke-virtual {v0, v2}, Lcom/cyjh/cjencrypt/CJEncrypt;->setPurpose(I)V
  .line 147
  const/4 v2, 0x0
  invoke-virtual {v0, v2}, Lcom/cyjh/cjencrypt/CJEncrypt;->setIndex(I)V
  .line 148
  new-instance v2, Lcom/cyjh/cjencrypt/EncryptJni;
  invoke-direct {v2}, Lcom/cyjh/cjencrypt/EncryptJni;-><init>()V
  invoke-virtual {v2, v0, p2},Lcom/cyjh/cjencrypt/EncryptJni;->Encrypt(Lcom/cyjh/cjencrypt/CJEncrypt;Landroid/content/Context;)Ljava/lang/String;
  :try_end_0
  .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
  move-result-object v2
  goto :goto_0
  .line 149
  .end local v0    #"cjEncrypt":Lcom/cyjh/cjencrypt/CJEncrypt;
  :catch_0
  move-exception v1
  .line 150
  .local v1, "e":Ljava/lang/Exception;
  invoke-virtual {v1}, Ljava/lang/Exception;->printStackTrace()V
  .line 152
  const-string/jumbo v2, ""
  goto :goto_0
.end method

 

反编译修改包名

  • 利用apktool拆包

  • 首先更改AndroidManifest.xml里面的包名

  • 全局更改com.xxx.xxxx类似的包名

  • 全局更改smali类型代码的包名字符串Lcom/xxx/xxxx

  • 全局更改所有com/xxx/xxxx文件夹的名称,因为java文件里面要求包名和文件夹路径要对应

  • apktoolb打包apk

  • jarsigner 签名 ,安装apk

 

KILL掉统计信息

  • 替换程序中的url

  • url被加密则让其url加载错误


屏蔽掉开启外挂后回到游戏蜂窝

源码文件夹:

Lcom/mfwfz/game/fengwoscript/ui/help/ScriptTopViewHelp

找到两个函数setData,找到内部调用,改为红色字体的值:


去广告的另一种方式

修改android窗口布局的xml文件,本例去掉云挂机的广告(cloud_hook_entry_view.xml)(见下面的红色字体部分):


 

关闭打开APP时弹出的“游戏蜂窝”加密广播

源码文件夹:

com/mfwfz/game/manager/alarmtask/AlarmTaskManager.java

找到函数showTaskNotification直接返回。

 

找按钮事件的另一种方式

先找到按钮所在窗口的xml布局文件(一般res目录下),然后人工分析窗口的xml布局找到按钮的ID,再通过ID找到按钮的十六进制值,本例用“楚留香”挂机示范。


如果不能直接找到“云挂机”的按钮ID值和ID名称,先找左边的“本地挂机”ID名称“go_run_script_ly”,然后res目录搜索“go_run_script_ly”就能找到“云挂机”的ID名称“go_run_ygj_btn”,再然后搜索ID值就能找到相应的按钮事件。

 

更改AndroidManifest.xml的版本号

先使用AXMLPrinter2.jar,还原二进制的AndroidManifest.xml,到字符串的AndroidManifest.xml.java -jar AXMLPrinter2.jar  AndroidManifest.xml >newxml.xml

然后打开WinHex搜索版本字符串,本例修改了两处“3.1.9升级为3.2.0”,如下图:

第一处:


第二处:



云手机试用时间限制

com\cyjh\gundam\fengwo\presenter\cloud\CloudHookHomePagePresenter.javaorderInfo.TryMinute

 

游戏蜂窝的技术优势

  • 所有信息均从web服务器取到本地,也就是Google和Apple推荐的这种信息安全存取方式。

  • 一个帐号登录之后没有退出按钮,从根本上杜绝了垃圾帐号或者一台设备登录多个帐号的可能性;设备每次登录服务端都会判断设备是否在线,然后踢下在线的设备,保持一个帐号只能同时登录一个设备。

  • 每条发送到服务端的协议均有签名,签名不对的时候服务器拒绝回答。这里有个BUG,它是判断APK的自签名是不是与特定值有效,无效就拒绝计算协议的签名,其实应该把计算出来APK包的签名值也带入协议中,放在服务器做判断APK包是否被修改过。

  • 判断自校验的代码没有做自校验,导致可以被随便修改。

  • 协议防重放攻击。


游戏蜂窝的技术劣势

  • 不会善用APK加固程序,就算免费的也能做到很好的对抗APK包修改者,可能兼容性有一定的下降。





看雪ID:猪会被杀掉     

https://bbs.pediy.com/user-687175.htm




本文由看雪论坛 猪会被杀掉 原创

转载请注明来自看雪社区






热门技术文章推荐:





戳原文,看看大家都是怎么说的?

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存