某科某御 某吃鸡游戏 辅助的一次简单分析

查看 71|回复 11
作者:ganyilu   
由于太过简单,就特别简短,可能略过一些不关键的,将就着看。


bf64a321-0f61-4c17-85e2-58e1eaf9d947.png (103.95 KB, 下载次数: 2)
下载附件
2025-10-11 02:21 上传

其实我不想查壳的,还是查一下吧,一般都有壳,其实有没有也无所谓了。反正要破,有壳就不破了吗,有壳就一定要脱吗。(其实是我不会)
有效信息  32位,VC6,得得得,易语言没跑了。
先抓包,查IP。是什么御的。对接的,通常来说就简单多了,因为有源码模块参考。自写的会稍微费工夫去分析。
破解省时三大步,参数,特征码,API。
按顺序来,先搜索文本吧。如果文本没需要的信息,那就特征码,API。有信息,只能说省一点点时间而已。强度上没区别,真正的强度不是只在这加密。


9ea9c6d3-b18a-448e-8445-9c157fd7a6ef.png (218.16 KB, 下载次数: 2)
下载附件
2025-10-11 02:22 上传

密钥什么的都没加密。虽然代码VM加了一大堆。这种就是反面教材。大家不要学。
第一个短的,是公钥。第二个长的,是私钥。这是RSA加密。最关键的东西已经拿到了。
进入科什么御后台,发现,除了RSA密钥外,还需要版本和项目ID,版本还好解决,找不到就强行测试几次,也能试出来,或者拿旧版打开,自动弹出最新版的版本。


126de753-5fe9-43c2-9538-e2a689d3e799.png (2.12 KB, 下载次数: 1)
下载附件
2025-10-11 03:51 上传

现在就剩下一个项目ID了。既然RSA参数没加密,项目ID更加不可能加密,但是OD又没扫出来,应该是没用局部变量申明,直接填写的参数。
所以,项目ID一定是明文存在。而且不是基址方式。而是动态地址。
易语言有个BUG,如果是局部变量直接申明某些参数,会以基址方式存在。常量也是一样的。所以RSA密钥都是绿色基址。
现在有几个办法找到项目ID,第一种,虽然很傻但很有效,直接遍历所有 长度为8位的 字符串。
第二种,抓包看看,是不是明文方式,还真是。POST http://api.XXXXXXX.xyz/v3/Project/appInfo/67d7b473 HTTP/1.1
第三种,通过对接源码,秒了他。“Project/appInfo/”  后面拼接项目ID
找到 Project/appInfo/ 下个访问断点,即可。后面会接上项目ID的。
三种方式都能轻而易举拿到项目ID。
RSA公钥私钥,最关键的已经拿到。项目ID已经拿到 67d7b473 。版本1.87  也已经拿到。版本无需替换,只需要在后台填写即可。换了也可以,直接通杀,不需要后台改
现在要做的,是怎么替换我们的RSA密钥。其实RSA密钥,很好替换的。甚至直接修改文件就行了。加没加壳都没关系。可惜了项目ID不能这样处理,因为不是基址的。
现在为了一个项目ID,浪费时间。
第一种替换方法,HOOK 发包 API,这个我们就不说了。简单粗暴。也没有检测。会API HOOK很容易实现。
第二种替换方法,HOOK EXE模块。发现有VMP内存保护,在OD里面调试环境,没触发,没想到正常使用时,会出现保护,报错退出。
那就干掉VMP的保护,再进行HOOK吧。既然都这么麻烦了,就顺便处理RSA密钥吧,不修改文件了。
因为启动的时候,会初始化,使用项目ID和RSA密钥。所以,必须要快。远程和注入劫持其实都可以。
直接写个全版本通杀的劫持DLL吧。
啥都有了,其实本地山寨也可以。这是服务器山寨的,可以少写很多东西,省事。
.版本 2
.子程序 HOOK内容
.局部变量 局模块句柄, 整数型
.局部变量 局地址, 整数型
.局部变量 临时数组, 整数型, , "0"
.局部变量 临时结果, 整数型
.局部变量 公钥地址, 整数型
.局部变量 私钥地址, 整数型
.局部变量 文本地址, 整数型
.局部变量 HOOK地址, 整数型
.局部变量 跳转文本, 文本型
.局部变量 HOOK文本, 文本型
.局部变量 临时文本, 文本型
.判断循环首 (判断执行 = 真)
    局模块句柄 = 进程_取模块句柄 (动态解密 ({ 138, 144, 128, 136, 136, 28 }))
    .如果真 (局模块句柄 > 1)
        内存进程_打开句柄 (PID)
        进程句柄 = 内存进程_取句柄 ()
        .判断循环首 (取进程模块函数地址 (进程句柄, 局模块句柄, “ZwProtectVirtualMemory”) ≤ 0)
            处理事件 ()
        .判断循环尾 ()
        局地址 = 取进程模块函数地址 (进程句柄, 局模块句柄, “ZwProtectVirtualMemory”)
        .判断循环首 (内存读_字节数组 (局地址, 1) ≠ 动态解密 ({ 0, 244, 187 }))
            处理事件 ()
        .判断循环尾 ()
        内存写_字节集 (局地址, 字节集_十六进制到字节集 (删全部空 (“B8 50 00 00 00”)))  ' 解除HOOK
        ' 前面不用看了。
        ' 内存写_字节集 (模块句柄 + 十六到十 (“137E22”), 到字节集 (#公钥短))  ' 公钥短
        ' 内存写_字节集 (模块句柄 + 十六到十 (“137FED”), 到字节集 (#私钥长))  ' 私钥长
        模块句柄 = 进程_取模块句柄 (进程名)  ' 模块地址+1C46000
        .判断循环首 (内存读_字节数组 (模块句柄, 1) ≠ “4D”)
            处理事件 ()
        .判断循环尾 ()
        超级延时 (10, )
        清除数组 (临时数组)
        临时结果 = 内存搜_首次 (“-----BEGIN PUBLIC KEY-----”, 0, 临时数组, 模块句柄, 模块句柄 + 29646848, 假, 3)  ' 公钥短
        .如果真 (临时结果 > 0)
            公钥地址 = 临时数组 [1]
        .如果真结束
        ' 信息框 (“公钥地址” + 到文本 (临时结果), 0, , )
        清除数组 (临时数组)
        临时结果 = 内存搜_首次 (“-----BEGIN PRIVATE KEY-----”, 0, 临时数组, 模块句柄, 模块句柄 + 29646848, 假, 3)  ' 私钥长
        .如果真 (临时结果 > 0)
            私钥地址 = 临时数组 [1]
        .如果真结束
        ' 信息框 (“私钥地址” + 到文本 (临时结果), 0, , )
        清除数组 (临时数组)
        临时结果 = 内存搜_首次 (“83 C4 04 58 89 45 F4 FF 75 FC FF 75 F8 FF 75 F4 B9 03 00 00 00”, 6, 临时数组, 模块句柄, 模块句柄 + 29646848, 假, 3)
        .如果真 (临时结果 > 0)
            HOOK地址 = 临时数组 [1] - 38
        .如果真结束
        ' 信息框 (“HOOK地址” + 到文本 (临时结果), 0, , )
        清除数组 (临时数组)
        临时结果 = 内存搜_首次 (“Project/appInfo/”, 0, 临时数组, 模块句柄, 模块句柄 + 29646848, 假, 3)
        .如果真 (临时结果 > 0)
            文本地址 = 临时数组 [1]
        .如果真结束
        ' 信息框 (“文本地址” + 到文本 (临时结果), 0, , )
        临时文本 = 十到十六 (HOOK地址 + 5 - 模块句柄 - 十六到十 (“2BB”) - 5, 真)
        .如果真 (取文本长度 (临时文本) = 16)
            临时文本 = 取文本右边 (临时文本, 8)
        .如果真结束
        临时文本 = 取基址倒转 (临时文本)
        HOOK文本 = “508B4424048D388D35C5024000B908000000F3A45868” + 取基址倒转 (十到十六 (文本地址, 真)) + “E9” + 临时文本 + “90”
        跳转文本 = 十到十六 (模块句柄 + 十六到十 (动态解密 ({ 160, 175, 159, 110 })) - HOOK地址 - 5, 真)
        .如果真 (取文本长度 (跳转文本) = 16)
            跳转文本 = 取文本右边 (跳转文本, 8)
        .如果真结束
        跳转文本 = 取基址倒转 (跳转文本)
        内存写_字节集 (公钥地址, 到字节集 (#公钥短))  ' 公钥短
        内存写_字节集 (私钥地址, 到字节集 (#私钥长))  ' 私钥长
        内存写_字节集 (模块句柄 + 十六到十 (“2C5”), 到字节集 (#新项目ID))  ' 2C5  项目写进去
        内存写_字节集 (模块句柄 + 十六到十 (“2A1”), 字节集_十六进制到字节集 (HOOK文本))  ' 空白地址
        内存写_字节集 (HOOK地址, 字节集_十六进制到字节集 (删全部空 (“E9” + 跳转文本)))  ' 跳转到写好的地方
        跳出循环 ()
    .如果真结束
    处理事件 ()
.判断循环尾 ()


1730586e-f100-44c4-a0b0-4f7a5fde61e8.png (407.87 KB, 下载次数: 2)
下载附件
2025-10-11 03:51 上传

没有正版卡,没用变量就有功能了,说明作者水平不行。防破解不行,那么防封更加不行。
结果是显而易见,可预测的。一把封了。秒拉闸的货,费那劲更新干啥。还一直更新。好意思吗。我都不好意思了。


e3fc353e-977e-478e-b3a1-cd3f85401aff.png (138.86 KB, 下载次数: 2)
下载附件
2025-10-11 04:18 上传

反面教材,此处仅供参考和反思,请勿学习。绿色游戏,公平竞技。

句柄, 文本

ganyilu
OP
  


smallmouse228 发表于 2025-10-11 08:25
破是破了,问题是管理员权限在人家手里,想封你没商量

不会。你都替换了,相当于是你的软件。除非原作者看到了,带着破解版去找验证管理告状。否则你这个就是你自己的软件,后台是不知道的。还有,RSA密钥都替换了,其实已经可以自己本地山寨,完全脱离原有的验证。如果基址还是这种明文方式存在,甚至可以自己替换基址,更新基址。你想的那些东西,不存在的。
ganyilu
OP
  


scncrenyong 发表于 2025-10-11 13:12
有没有一种可能,因为你是破解,缺少变量数据,所以封号,正版的不封。

不知道,我也没正版卡。不过这样搞其实意义不大,买张正版卡抓包就能解决的事情,单单变量,正版卡下,几乎没有防破效果,随便抓包替换。应该也没这个可能,因为能玩一把,下一把一开,号就没了。要是有检测,通过变量获取数据处理,没处理,估计也没机会打完一把。综合鉴定,这种就是圈钱的。
alongzhenggang   

这种就是竭泽而渔杀鸡取卵,玩过一次就不好玩了
Gijia   

大佬精彩的过程 学习了
hxd97244   

没防封也敢发布,也是醉了
骑狗的猴子   

这破的也太快了 都是经验的积累呀。优雅
1027102633   

这哪是辅助,分明就是给人戒网瘾的
nitian0963   

没防封也敢发布,也是醉了
smallmouse228   

破是破了,问题是管理员权限在人家手里,想封你没商量
您需要登录后才可以回帖 登录 | 立即注册

返回顶部