台服dnf吧 关注:116,412贴子:1,826,401

脑洞X亢龙有悔——外置插件科技革命(致敬神牛、Sid)

只看楼主收藏回复

1. 前言
感谢Sid大佬,前段时间贴吧的私聊,帮助我理清思路。
感谢神牛大佬的演示作品提供的思路。
致敬前辈们。
首先来说一下,我为什么一直在强调外置插件,在程序设计上,过多的入侵式设计会带来各种各样的问题,在做插件的这段时间里,总有人会提到插件冲突的问题,就是如此。目前Frida和Dp已经普及,但是对于小白来说,合并DP和Frida功能,会造成更大的困扰。以及入侵式设计的合规问题有待考量。所以从6月中旬开始,便开始对外置插件进行研究,这里不再赘述整体的功能。而是一直依赖,服务端通信给客户端内容的屏障很难打破,即如何用外置插件实现服务端通知客户端,让客户端自由进行一些列操作。
以下会以外置装备为例(实现基础属性增加(力量),实现额外属性增加(属强),实现nut里的ap),说一下我是如何做的。
2. 架构图

3. Frida内存操作方案3.1. Frida注入
神牛大佬提到,将dll挂载到exe的方案,但是目前大多数登录器还是没有自由挂载dll权限的,所以应该有一个方案,进行dll挂载,这里选择劫持d3d9.dll。
c++代码如下:
BOOL __stdcall DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
HINSTANCE hDllInst = LoadLibrary("ranmu.dll");
if (dwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hModule);
return Load();
}
else if (dwReason == DLL_PROCESS_DETACH)
{
Free();
}
return TRUE;
}
客户端,放至相关的js就可以了。
3.2. 数据交互
玩家操作客户端插件,选择一件装备进行装备,该装备的属性为+100力量+100光强,释放十字斩时释放大闪光。此装备属性落在数据库表中。(无视内容,只是举例)

使用frida的socket模块,从插件服务端获取正在穿装备的属性。(frida的socket使用方法看官网就好了)
3.3. Frida改内存方案
Socket获取到数据后,改内存就可以,其实就是“辅助”的工作原理。伪代码如下:
function httpSend(){
var rwjz = 0X1AB7CDC;
var rwzz = ptr(rwjz).readPointer();
var wqzz = rwzz.add(0X3038).readPointer();
var ll = wqzz.add(0x4E0);
var zl = wqzz.add(0X4F8);
var tl = wqzz.add(0X4EC);
writeEncode(eval(ll.toString()),1000);
writeEncode(eval(zl.toString()),1000);
writeEncode(eval(tl.toString()),1000);
}
3.4. Frida写nut方案
在3.3中,其实暴露了很多的风险,玩家可以随意改造firda.js的中内容,比如获取的力量为100,可以硬编码成10000,这里也没有很好的方案能解决。看到了神牛大佬的方案,决定使用nut解决该问题。
神牛大佬通过dll注入,写入了nut方法,可以对内存进行读写,当然也可以直接调用socket进行服务端插件调用。但是本质还是要写外置插件,修改注入nut方法,仍然不算是外置,从而影响了exe本身。(有的人会说frida注入dll也算注入啊,先别急,最终的方案是支持脱frida的,只是现在示例中用了frida做介质)。
神牛大佬的nut热调试,大家应该都听说过了。我们借助这个方案继续进行。
Frida将读到的服务端额外装备数据写到nut文件中。
Frida写文件代码(这是写日志的,写nut文件同理):
function log(msg)
{
var f_log = new File('fr.log', 'a+');
f_log.write(msg + '\n');
f_log.flush();
}
写完的nut文件示例(+50力量,3攻速,加残影):
function ranmutest(obj){
sq_SendCreatePassiveObjectPacket(obj,8362,0,0,0,0,obj.getDirection());
local appendage = CNSquirrelAppendage.sq_AppendAppendage(obj, obj, -1, false, "character/atfighter/fireworks/ap_fireworks.nut", true);
local spectrumAppendage = appendage.sq_GetOcularSpectrum("ocularSpectrum");
if(!spectrumAppendage)
{
spectrumAppendage = appendage.sq_AddOcularSpectrum("ocularSpectrum", obj, obj, 100);
}
sq_SetParameterOcularSpectrum(spectrumAppendage, 300, 100, true, sq_RGBA(192, 192, 192, 155), sq_RGBA(192, 192, 192, 0), 2, 2, 2);
sq_SetParameterOcularSpectrum(spectrumAppendage, 300, 100, true, sq_RGBA(192, 192, 192, 155), sq_RGBA(192, 192, 192, 0), 2, 0, 1);
local change_appendage = appendage.sq_getChangeStatus("400360007");
local physicalAttack = 50;
local attackSpeed = 30;
if (!change_appendage)
{
change_appendage = appendage.sq_AddChangeStatus("400360007", obj, obj, 0,CHANGE_STATUS_TYPE_ATTACK_SPEED, false, attackSpeed);
}
if (change_appendage)
{
change_appendage.clearParameter();
change_appendage.addParameter(CHANGE_STATUS_TYPE_PHYSICAL_ATTACK, false, physicalAttack.tofloat());
}
}
3.5. 安全性与脱离frida
在3.4的描述中,nut仍然是明文的,玩家可以任意修改客户端目录下的nut。并且刚才说了要脱离frida的注入。方案修改如下:
客户端插件读取数据库,并写nut文件,该nut文件仅返回一个全局加密变量,代表增长的相关属性。例如服务端插件返回报文为physicalAttck50,magicalAtcck60,通过ASE(自己写加密算法)进行加密。生产的nut文件内容为;
local ranmu_attr = “加密字符串”;
在pvf中,dofile该nut即可读到全局变量ranmu_attr。用对应的方法解密得到真实返回报文。再解析出报文,执行相关nut即可。
4. 建议
不介意内置的,可以考虑直接用frida方案,或者神牛大佬的注册nut函数方案。
和我一样有强迫症的,以及考虑到一些网络安全风险的,可以自己写插件端。具体插件端的形式,也从最早的网页,现在升级到了electron的桌面应用,如果有更好的建议和想法,欢迎与我交流。


IP属地:天津1楼2023-07-10 15:00回复


    IP属地:天津来自Android客户端2楼2023-07-10 15:01
    回复


      IP属地:天津来自Android客户端3楼2023-07-10 15:37
      回复
        内容太复杂,以至于我无法发表言论


        IP属地:河北来自Android客户端4楼2023-07-10 16:20
        回复
          来了来了


          IP属地:安徽来自iPhone客户端6楼2023-07-10 16:23
          回复


            IP属地:广东通过百度相册上传7楼2023-07-10 16:43
            回复
              太牛逼了,反正我是一点也看不明白,只能说大佬牛逼。


              IP属地:四川来自Android客户端8楼2023-07-10 17:13
              回复
                https://gitee.com/sunstar59/nut-function-extension


                IP属地:吉林来自Android客户端9楼2023-07-12 11:50
                收起回复
                  看不懂的 就是牛大佬


                  IP属地:山西来自Android客户端10楼2023-07-12 12:38
                  回复
                    牛逼 借楼有偿找个能把城镇人物放大的老哥 私信我


                    IP属地:山东来自iPhone客户端11楼2023-07-12 13:05
                    回复
                      牛逼牛逼牛逼


                      IP属地:湖南来自iPhone客户端12楼2023-07-12 15:33
                      回复
                        123


                        IP属地:甘肃来自Android客户端13楼2023-07-12 16:25
                        回复
                          看不懂的 就是牛大佬


                          IP属地:辽宁来自Android客户端14楼2023-07-12 17:48
                          回复
                            🐮


                            IP属地:海南来自iPhone客户端15楼2023-07-12 18:29
                            回复
                              ???问号脸


                              IP属地:黑龙江来自Android客户端16楼2023-07-12 19:35
                              回复