首先上游戏安卓包:
链接:https://pan.baidu.com/s/1fNe29ZwOhOvywcvjzVrcug
提取码:a21f
附上xposed的github地址:https://github.com/rovo89
环境:Android4.0、夜神Android5.0版(这个必须是5.0,7.0亲测安装Xposed会导致开不了机)、Jeb2.2.7
-
打开AS在项目app目录下添加读写库
compileOnly ‘de.robv.android.xposed:api:53’
compileOnly ‘de.robv.android.xposed:api:53:sources’ //源码解读库(自行需要导入) -
打开项目分支src/main目录下的AndroidManifest.xml 在application标签里面添加内容
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="Hello Xposed" /> //自定义模块的名字
<meta-data
android:name="xposedminversion"
android:value="53" /> 刚才导入库的版本要对应
- 新建Hook入口类HookMain实现xposed的接口IXposedHookLoadPackage并重写方法handleLoadPackage 这个写法格式是固定的。具体用法代码后都有具体的注释
import android.content.Context;
import android.util.Log;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import static androidx.constraintlayout.widget.Constraints.TAG;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
public class HookMain implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
//固定格式
findAndHookMethod(
"android.telephony.TelephonyManager", //要hook的包名+类名
lpparam.classLoader, //classLoader固定
"getDeviceId", //要hook的方法名
//方法参数 没有就不填
new XC_MethodHook() {
@Override
//方法执行前执行
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
}
//方法执行后执行,改方法的返回值一定要在方法执行完毕后更改
protected void afterHookedMethod(MethodHookParam param)
throws Throwable {
param.setResult("355888888888888");
XposedBridge.log("劫持后的返回值"+param.getResult());
}
}
);}
- 编写框架所需模块 Hook系统的imei检测hook环境是否配置成功MainActivity.class
我这里直接使用了android高版本所以要先申请手机操作所对应的权限
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (PackageManager.PERMISSION_DENIED != ActivityCompat.checkSelfPermission(this,Manifest.permission.READ_PHONE_STATE))
Log.i("手机的imei是",getIMEI(this)+"。");
else
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_PHONE_STATE},10);
}
public static final String getIMEI(Context context) {
try {
//实例化TelephonyManager对象
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
//获取IMEI号
String imei = telephonyManager.getDeviceId();
//在次做个验证,也不是什么时候都能获取到的啊
if (imei == null) {
imei = "";
}
return imei;
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
Log.i("手机的imei是",getIMEI(this)+"。");
}
}
}
- AndroidMainfest.xml对应的声明权限
这里我将一些常用的权限都写了
大家自行添加
<!-- 网络访问权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 接收广播的权限 -->
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- 读取手机状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 内置sd卡写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 内置sd卡读权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 电源管理权限 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--应用内intent安装apk,需要该权限否则android 7.0以上系统无法安装应用.-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
- 在src/main/assets下新建文件xposed_init并将HookMain类并将hook的主入口类以包名+类名的格式写进去。
com.example.xposed_test.HookMain
7.这里运行后发现打印的信息如下:发现并不是我们修改后的355888888888888,当时能打印出来证明已经成功配置了Hook的环境了,那么可以对夜神模拟器操作了
8. 将xposedInstaller框架安装到手机
链接:https://pan.baidu.com/s/1qsXPhLmuNSLdvi1XgL4Oqg
提取码:a21d
进入xposedInstaller框架后点击下载Xposed,给root权限(这也是博主用模拟器的原因真机root真费时间),安装完后会提示重启,!!!如果大家发现重启直接卡死,那么请新建一个夜神android5.0因为7.0就是这样,博主就是在这里卡了好几个小时最后自己给摸索出来了,这东西还百度不到!!!
-
打开框架模块给我们当时新建的模块后面勾上会提示重启,重启之后打开程序发现 运行成功了 打印也为:355888888888888,那么恭喜你第一个hook程序已经完成了
-
我们这里讲破解游戏,进入我们的主题,我们通过Jeb打开游戏的apk文件发现代码有混淆,通过游戏界面我慢慢总结出流程了从mainfest文件发现程序入口为:
-
我们进入这个Acitivity从主界面看出有两个按钮(美女找茬、美女视频)从源码中看到果断进入
-
这里我们来到了游戏的第二个界面
然后发现有四个选项按钮(开始、设置、帮助、关于)
果然想的没错在MainActivity里面发现监听
-
进入SelectActivity也就是我们游戏的选择关卡页面从代码得知游戏界面是PlayActivity(寻找技巧是看按钮监听)
14. 进入到游戏界面后发现游戏金币在求助按钮弹出的页面,通过代码于是推断出在SOSActivity
15. 进入SOSActivity页面后发现这里显示着游戏金币,通过代码找到一个关键方法getMoney()推断一波就是给游戏金币设置数据的TextView控件这里我们就只要在Hook层通过改变Util.getMoney()方法的返回值就达到99999金币的目的了
来到代码层HookMain.java添加抓取代码监听
//找茬
if (!lpparam.packageName.equals("com.jimmy.beauty.pick")){ //过滤进程
return;
}
Log.i(TAG, "Hook开始工作");
findAndHookMethod(
"com.jimmy.beauty.pick.Util", //要hook的包名+类名
lpparam.classLoader, //classLoader固定
"getMoney", //要hook的方法名
Context.class,
//方法参数 没有就不填
new XC_MethodHook() {
@Override
//方法执行前执行
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
}
//方法执行后执行,改方法的返回值一定要在方法执行完毕后更改
protected void afterHookedMethod(MethodHookParam param)
throws Throwable {
XposedBridge.log("劫持前的返回值"+param.getResult());
XposedBridge.log("参数一"+param.args[0].toString());
param.setResult(999999);
XposedBridge.log("劫持后的返回值"+param.getResult());
}
}
);
- 运行apk重启模拟器然后发现我们的猜想果然没错
- 当前还有一个解法就是在我们点击“使用”按钮是不是也对金币余额进行修改了
- 我们把要操作的方法名修改为setMoney,因为setMoney有两个参数所以我们添加一个int.class并在hook前修改方法参数
//找茬
if (!lpparam.packageName.equals("com.jimmy.beauty.pick")){ //过滤进程
return;
}
Log.i(TAG, "Hook开始工作");
findAndHookMethod(
"com.jimmy.beauty.pick.Util", //要hook的包名+类名
lpparam.classLoader, //classLoader固定
"setMoney", //要hook的方法名
Context.class,
int.class,
//方法参数 没有就不填
new XC_MethodHook() {
@Override
//方法执行前执行
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
param.args[1] = 999;
Log.i("Tiger_test","成功充值999金币");
}
//方法执行后执行,改方法的返回值一定要在方法执行完毕后更改
protected void afterHookedMethod(MethodHookParam param)
throws Throwable {
XposedBridge.log("劫持前的返回值"+param.getResult());
XposedBridge.log("参数一"+param.args[0].toString());
// param.setResult(999999);
XposedBridge.log("劫持后的返回值"+param.getResult());
}
}
);
好了。游戏至此破解完成
这里给大家推荐一个学习逆向的网站:吾爱破解
本人写这篇的博客也是受吾爱里面的博主影响给逆向行业做微微贡献,因为博主在学习逆向的路程中经常遇到一些问题,遇到了基本上一天或者几天都在解决问题,度娘那里因为逆向资料大都比较老,所以博主踩得坑想帮助到大家快速解决没有必要花费的时间,也算是有感而发吧!(虽然博主现在还不是吾爱会员不过我相信迟早有那么一天,加油!)