本帖最后由 咬字分开念 于 2023-9-11 19:53 编辑
吾爱捕鱼达人无限金币抽奖开局VIP6炮台全开cocos2d破解笔记
劇情前戲
支持Android 4.0+
楼主喜欢玩游戏,但是不喜欢被游戏玩.
最近没事就找点单机游戏玩,什么五子棋/打砖块已经打遍电脑无敌手了,下象棋又下不过电脑.所以就看看捕鱼达人吧,好像特效还可以
这个破解只是修改了java层的支付,已经失效了,所以楼主去修改它的游戏so引擎文件,这样才能永久有效.顺便把游戏名称改成了我爱捕鱼
看了大多数捕鱼的破解都是从java层下手,但是其核心代码都在.so文件...所以Java破解支付治标不治本,还是直接干.so比较靠谱
这捕鱼游戏就是牛逼,从代码能看出自带3个AI玩家陪你玩,全程都是单机版,但是各种AI玩家暴击的特效让你以为是网络版,然后疯狂的诱惑你充钱
问题是就算充了1000W个币,火炮的倍数也会被放大到1W倍,就是打一枪1W币没了,按这样的逻辑,多少币都不够打
充多少钱都不够开枪,真是把玩家当作绿油油的韭菜啊.不过也不怪人家,韭菜嘛这家不割总有下一家割...
先放几张爽图自己感受
爽圖展示
抽奖
核弹
千万资产
还嫌不够?再丢几个黄金炸弹,资产10亿
玩法,综上所述,金币再多也没用,分分钟就打完了,如果调成无限金币,游戏就没有意思了.所以:
没钱了怎么办? 去抽奖啊,无限抽奖,抽多几个炸弹去炸鱼就有钱了,有钱了再去抽奖.....
光靠子弹打鱼除非是高手,否则十打久亏,多少币都不够亏.
懂我意思吧!!!
吾爱捕鱼.apk 下载地址,喜欢动手的可以从原帖下载
https://.....
不知道发成品apk会不会违规,不违规的我就在楼下补发,请吾友告知
密码:67b5
https://static.52pojie.cn/static/image/hrline/1.gif
好了 talk is cheep,show me the code
##下载apk 解压
文件在 lib\armeabi-v7a\libecgame.so
用ida x32位版打开,全部默认就行了
如果连ida是啥?的菜菜鸟就直接劝退了,搞ida几乎全部是汇编和16进制,菜菜鸟怕是看不下去
然后依次在左边筛选出图片对应的vip luck Rewardmoney
需要修改的地方都标记出来了
修改的方法是,先找到这个代码关联的汇编代码地址,用右键...这个操作方面可以自己查看搜索引擎,因为可能操作顺序不同会导致看到的结果不同
对于上面这些数字类修改就很简单,在对应地址的16进制里把7改为0或者4改为FF(就是255)
精華部分
比如vip等级这个
关联查代码内存地址方法
稍微复杂的
'int __fastcall Ly_VipLuck::OnBtnVLuck(Ly_VipLuck this, cocos2d::CCObject a2)'
这个方法也是一个非肉眼可见的整数类的条件判断
意思就是不是 if(a>10)这样一样就知道怎么修改的,他是一个内存地址漂移一段距离后的结果和另一个内存地址漂移一段距离的结果做比较,这类判断就不好直接改数字,比如0改为1这样干掉,这种就需要参考下面的方法来处理.逻辑是一样的.图片里也有具体修改的内存位置,可以查看.
至于更复杂的值得一讲的就是下面这个了,因为这个没有明显可见的数字可以修改
[C++] 纯文本查看 复制代码
int __fastcall Ly_VipLuck::SetVLuckRet(Ly_VipLuck *this)
{
Byly_GameData *v2; // r0
Fby_ns::Fby_PlayerControler *v3; // r0
int v4; // r0
Fby_ns::Fby_PlayerControler *v5; // r0
int v6; // r0
int v7; // r1
int v8; // r3
Fby_ns::Fby_PlayerGunInfo *v9; // r0
Fby_ns::Fby_PlayerControler *v10; // r0
int v11; // r0
Fby_ns::Fby_PlayerControler *v12; // r0
int v13; // r0
Fby_ns::Fby_PlayerControler *v14; // r0
int v15; // r0
Byly_GameData *v16; // r0
Byly_GameData *v17; // r0
Byly_GameData *v18; // r0
Byly_GameData *v19; // r0
int v20; // r0
Byly_GameData *v21; // r0
Byly_GameData *v22; // r0
Byly_GameData *v23; // r0
Byly_GameData *v24; // r0
Byly_GameData *v25; // r0
Byly_GameData *v26; // r0
Byly_GameData *v27; // r0
int v28; // r5
Fby_ns::Fby_PlayerControler *v29; // r0
int v30; // r0
Byly_GameData *v31; // r0
int v32; // r0
Byly_GameData *v33; // r8
Byly_GameData *v34; // r0
int v35; // r0
Byly_GameData *v36; // r8
int v37; // r0
Byly_GameData *v38; // r0
Byly_GameData *v39; // r0
Ly_GetReward *v40; // r0
int v41; // r0
Ly_GetReward *v42; // r0
Ly_GetReward *v43; // r0
Ly_GetReward *v44; // r0
_DWORD *v45; // r7
void (__fastcall *v46)(_DWORD *, int, int); // r5
int v47; // r0
int v48; // r7
void (__fastcall *v49)(int, int, int); // r5
int v50; // r1
int v52; // r3
int v53; // r2
int v54; // r3
char s[128]; // [sp+4h] [bp-A4h] BYREF
memset(s, 0, sizeof(s));
strcpy(s, *(const char **)(Byly_Text::g_szGameText + 436));
v2 = (Byly_GameData *)GameSceneBase::m_pGameView;
if ( GameSceneBase::m_pGameView )
{
v2 = (Byly_GameData *)(*(int (__fastcall **)(_DWORD *))(*GameSceneBase::m_pGameView + 316))(GameSceneBase::m_pGameView);
if ( v2 )
{
v54 = *((_DWORD *)this + 152);
v28 = *((_DWORD *)this + v54 + 82);
switch ( v28 )
{
case 1:
v3 = (Fby_ns::Fby_PlayerControler *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 444),
s,
*((_DWORD *)this + v54 + 94));
v4 = Fby_ns::Fby_PlayerControler::sharePlayerControler(v3);
v2 = (Byly_GameData *)Fby_ns::Fby_PlayerGunInfo::ChangePlayerMoney(
*(_DWORD *)(v4 + 8),
*((_DWORD *)this + *((_DWORD *)this + 152) + 94),
1,
0);
goto LABEL_35;
case 2:
v5 = (Fby_ns::Fby_PlayerControler *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 448),
s,
*((_DWORD *)this + v54 + 94));
v6 = Fby_ns::Fby_PlayerControler::sharePlayerControler(v5);
v7 = 1;
v8 = *((_DWORD *)this + 152) + 94;
v9 = *(Fby_ns::Fby_PlayerGunInfo **)(v6 + 8);
break;
case 3:
v10 = (Fby_ns::Fby_PlayerControler *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 452),
s,
*((_DWORD *)this + v54 + 94));
v11 = Fby_ns::Fby_PlayerControler::sharePlayerControler(v10);
v7 = 4;
v8 = *((_DWORD *)this + 152) + 94;
v9 = *(Fby_ns::Fby_PlayerGunInfo **)(v11 + 8);
break;
case 4:
v12 = (Fby_ns::Fby_PlayerControler *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 456),
s,
*((_DWORD *)this + v54 + 94));
v13 = Fby_ns::Fby_PlayerControler::sharePlayerControler(v12);
v7 = 5;
v8 = *((_DWORD *)this + 152) + 94;
v9 = *(Fby_ns::Fby_PlayerGunInfo **)(v13 + 8);
break;
case 5:
v14 = (Fby_ns::Fby_PlayerControler *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 476),
s,
*((_DWORD *)this + v54 + 94));
v15 = Fby_ns::Fby_PlayerControler::sharePlayerControler(v14);
v7 = 7;
v8 = *((_DWORD *)this + 152) + 94;
v9 = *(Fby_ns::Fby_PlayerGunInfo **)(v15 + 8);
break;
default:
switch ( v28 )
{
case 6:
v16 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 488),
s,
*((_DWORD *)this + v54 + 94));
v2 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v16);
*(_DWORD *)(*(_DWORD *)v2 + 172) += *((_DWORD *)this + *((_DWORD *)this + 152) + 94);
break;
case 7:
v17 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 492),
s,
*((_DWORD *)this + v54 + 94));
v2 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v17);
*(_DWORD *)(*(_DWORD *)v2 + 176) += *((_DWORD *)this + *((_DWORD *)this + 152) + 94);
break;
case 8:
v18 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 496),
s,
*((_DWORD *)this + v54 + 94));
v2 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v18);
*(_DWORD *)(*(_DWORD *)v2 + 180) += *((_DWORD *)this + *((_DWORD *)this + 152) + 94);
break;
}
goto LABEL_33;
}
v2 = (Byly_GameData *)Fby_ns::Fby_PlayerGunInfo::AddProp(v9, v7, *((_DWORD *)this + v8), 0);
LABEL_33:
v28 = 1;
goto LABEL_35;
}
}
v52 = *((_DWORD *)this + 152);
v53 = *((_DWORD *)this + v52 + 82);
switch ( v53 )
{
case 1:
v19 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 444),
s,
*((_DWORD *)this + v52 + 94));
v20 = Byly_GameData::shareBylyGameData(v19);
v2 = (Byly_GameData *)Byly_GameData::SetBylyAddPlayerMoney(v20, *((_DWORD *)this + *((_DWORD *)this + 152) + 94));
break;
case 2:
v21 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 448),
s,
*((_DWORD *)this + v52 + 94));
v2 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v21);
*(_DWORD *)(*(_DWORD *)v2 + 36) += *((_DWORD *)this + *((_DWORD *)this + 152) + 94);
break;
case 3:
v22 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 452),
s,
*((_DWORD *)this + v52 + 94));
v2 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v22);
*(_DWORD *)(*(_DWORD *)v2 + 152) += *((_DWORD *)this + *((_DWORD *)this + 152) + 94);
break;
case 4:
v23 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 456),
s,
*((_DWORD *)this + v52 + 94));
v2 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v23);
*(_DWORD *)(*(_DWORD *)v2 + 156) += *((_DWORD *)this + *((_DWORD *)this + 152) + 94);
break;
case 5:
v24 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 476),
s,
*((_DWORD *)this + v52 + 94));
v2 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v24);
*(_DWORD *)(*(_DWORD *)v2 + 160) += *((_DWORD *)this + *((_DWORD *)this + 152) + 94);
break;
case 6:
v25 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 488),
s,
*((_DWORD *)this + v52 + 94));
v2 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v25);
*(_DWORD *)(*(_DWORD *)v2 + 172) += *((_DWORD *)this + *((_DWORD *)this + 152) + 94);
break;
case 7:
v26 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 492),
s,
*((_DWORD *)this + v52 + 94));
v2 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v26);
*(_DWORD *)(*(_DWORD *)v2 + 176) += *((_DWORD *)this + *((_DWORD *)this + 152) + 94);
break;
case 8:
v27 = (Byly_GameData *)sprintf(
s,
*(const char **)(Byly_Text::g_szGameText + 496),
s,
*((_DWORD *)this + v52 + 94));
v2 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v27);
*(_DWORD *)(*(_DWORD *)v2 + 180) += *((_DWORD *)this + *((_DWORD *)this + 152) + 94);
break;
}
v28 = 0;
LABEL_35:
v29 = (Fby_ns::Fby_PlayerControler *)Byly_GameData::shareBylyGameData(v2);
++*(_DWORD *)(*((_DWORD *)v29 + 188) + 24);
if ( v28 == 1 )
{
v30 = Fby_ns::Fby_PlayerControler::sharePlayerControler(v29);
v31 = (Byly_GameData *)Fby_ns::Fby_PlayerGunInfo::ChangePlayerMoney(*(_DWORD *)(v30 + 8), 0, 1, 0);
}
else
{
v32 = Byly_GameData::shareBylyGameData(v29);
v31 = (Byly_GameData *)Byly_GameData::SetBylyAddPlayerMoney(v32, 0);
}
v33 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v31);
v34 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v33);
v35 = Byly_GameData::GetVIP(v34);
v36 = (Byly_GameData *)Byly_GameData::GetVipTurnTimes(v33, v35);
v37 = Byly_GameData::shareBylyGameData(v36);
v38 = (Byly_GameData *)ECAscIILable::setAscIINum(
*((ECAscIILable **)this + 154),
(int)v36 - *(_DWORD *)(*(_DWORD *)(v37 + 752) + 24),
0,
0);
v39 = (Byly_GameData *)Byly_GameData::shareBylyGameData(v38);
v40 = (Ly_GetReward *)Byly_GameData::WriteLyAllData(v39);
v41 = Ly_GetReward::shareLyGetReward(v40);
if ( !(*(int (__fastcall **)(int))(*(_DWORD *)v41 + 316))(v41) )
{
v42 = (Ly_GetReward *)Ly_GetReward::shareLyGetReward(0);
*((_DWORD *)v42 + 87) = 0;
v43 = (Ly_GetReward *)Ly_GetReward::shareLyGetReward(v42);
v44 = (Ly_GetReward *)Ly_GetReward::SetRewardNum(
v43,
*((_DWORD *)this + *((_DWORD *)this + 152) + 82),
*((_DWORD *)this + *((_DWORD *)this + 152) + 94));
if ( v28 == 1 )
{
v30 = Fby_ns::Fby_PlayerControler::sharePlayerControler(v29);
v31 = (Byly_GameData *)Fby_ns::Fby_PlayerGunInfo::ChangePlayerMoney(
*(_DWORD *)(v30 + 8),
-*((_DWORD *)this + 143),
1,
0);//扣钱1
}
else
{
v32 = Byly_GameData::shareBylyGameData(v29);
v31 = (Byly_GameData *)Byly_GameData::SetBylyAddPlayerMoney(v32, -*((_DWORD *)this + 143));//扣钱2
}
}
return ECButton::SetEnabledBtn(*((ECButton **)this + 79), 1);
}
关键代码在这里
[C++] 纯文本查看 复制代码
v31 = (Byly_GameData *)Byly_GameData::SetBylyAddPlayerMoney(v32, -*((_DWORD *)this + 143));//抽奖扣币 关键点
int __fastcall Ly_VipLuck::SetVLuckRet(Ly_VipLuck *this){
...
if ( v28 == 1 )
{
v30 = Fby_ns::Fby_PlayerControler::sharePlayerControler(v29);
v31 = (Byly_GameData *)Fby_ns::Fby_PlayerGunInfo::ChangePlayerMoney(
*(_DWORD *)(v30 + 8),
-*((_DWORD *)this + 143),
1,
0);//扣钱1
}
else
{
v32 = Byly_GameData::shareBylyGameData(v29);
v31 = (Byly_GameData *)Byly_GameData::SetBylyAddPlayerMoney(v32, -*((_DWORD *)this + 143));//扣钱2
}
}
其中
[C++] 纯文本查看 复制代码
-*((_DWORD *)this + 143),
和
[C++] 纯文本查看 复制代码
-*((_DWORD *)this + 143),
2个都是一样的,
出现在不同的地方,意思就是某个内存地址飘移143的长度.具体意思不需要知道,编译器都不一定完全知道,只需要知道结果就行了
2个是扣抽奖10w钱的方法,需要修改为不扣钱,怎么修改呢.(可能有人脑洞大开,想把143改为142或者其他数字...这样内存都不知道会漂移到哪里去了,99%会闪退,1%运气好,内存没漂移飞)找到对应的汇编码是(通过上面的关联查代码内存地址方法)
[Asm] 纯文本查看 复制代码 NEGS R1,R1;INT
对应的16进制是 49 42
我的第一个思路是把-号反过来就行了,
那需要怎么修改这个 49 42呢,因为ida里的汇编码不能直接修改,JEB平台就支持直接汇编.so文件,懒得安装.
于是我就问chatgpt
得到的回答如下
不得不说有了chatgpt,做软件的效率提高了最少20倍
搞定
但是这样改的实际效果不理想,因为每次抽奖余额金额都会爆炸,抽一次就返回无限金币,那多没意思啊.
于是吧,我寻思把它改为一个无意义的数字就行了,这样就不扣钱也不加钱了
具体怎么改呢?2个思路,一个是瞎试 把49 42里的42改为40 或者41 .....
另外一个思路是,在汇编码和16进制里对比开头一样的本函数里存在的对象.比如
[C++] 纯文本查看 复制代码 v52 = *((_DWORD *)this + 152);
(思路补充:为什么要找另外一个函数对象来替换呢,因为本来是要扣10w的,说明这个数字肯定是10W,随便找一个一样类型的对象肯定也是整数啊,再大能有10w大吗,说不定就是几十或者几个,扣几个币无关痛痒)
他们的16进制开头都是D4 F8((通过上面的关联查代码内存地址方法)),只是后面的不同,那就简单了,直接把
[C++] 纯文本查看 复制代码 -*((_DWORD *)this + 143),
D4 F8 后面2位16进制码修改为
[C++] 纯文本查看 复制代码 ((_DWORD *)this + 152);
后面的2位16进制码
为什么要这样改呢,因为如果前面开头的2位16进制码不同,代表不是同一个对象,可能是字符或者其他非int对象,如果前面码不同就会导致报错或者内存泄漏
这是2个思路,个人喜欢用第一个 (正常思路还是推荐用第二个或者按汇编码翻译修改,但是 做软体的人,如果都循规蹈矩那就没办法超越规则了,规则和思路都是用来打破的,不然科技和世界就不会进步了,大家都只能在不知道哪个标准的规矩里原地踏步) ,也就是瞎猜.运气不错,第一次就猜对了,42改40就行了
[C++] 纯文本查看 复制代码 v32 = Byly_GameData::shareBylyGameData(v29);
v31 = (Byly_GameData *)Byly_GameData::SetBylyAddPlayerMoney(v32, -*((_DWORD *)this + 143));//扣钱2
直接就变成了
[C++] 纯文本查看 复制代码 v48 = Byly_GameLobby::m_pBylyGameLobby;
v49 = *(void (__fastcall **)(int, int, int))(*(_DWORD *)Byly_GameLobby::m_pBylyGameLobby + 204);
v50 = Ly_GetReward::shareLyGetReward(v44);
v49(v48, v50, 100);
意思就是从扣钱的逻辑变成了其他无关紧要的逻辑,达到目的就行了,其实很简单的
外传:
这里可以修改大鱼的倍率,是不是看着就超级爽.
这是活力大小的代码,改太猛了会不会没意思 基本上看不到怪了,出来就被秒杀了,金币也分分钟上亿
全部秒杀.对应的半成品.so文件在一楼.
总结
[Asm] 纯文本查看 复制代码
地址1e75fa 原始值04 -> FF #抽奖次数修改
地址1e75b4 原始值00 -> 06 #vip等级修改
地址1dff86 原始值49 42 -> 49 40 #抽奖扣钱10W改为不扣钱 第1处
地址1dff99 原始值49 42 -> 49 40 #抽奖扣钱10W改为不扣钱 第2处
地址1dfb0c 原始值D4 F8 xx x2 -> D4 F8 00 02 #xx x是楼主忘记了,尾号是2一共4个字节.这是判断余额小于10W不能点击抽奖按钮
一共修改5个内存地址实现破解,这答案和过程都快写到大家脸上了,应该能操作了吧最后夫人说:这明明是一个android程序,却给楼主硬生生整成了Windows的感觉,一点android的代码都没有. 确实.不过安卓Java的逆反太多了,.so里的cocos2d在吾爱貌似没有2页搜索结果....
|