【FF14】我帮拂晓修BUG之提高登录器自动更新速度

Posted by on February 28, 2023 · 1 min read

其实这个问题我很早就研究过了,只是近期都比较忙一直没时间写,原来博客的内容也一直没时间迁移过来。。。

这个问题是我在B站刷到过一个视频,受这个启发才去研究的,这里主要讲讲视频中没讲到的东西以及如果直接用视频中方法可能会遇到的问题。

首先为啥自动更新那么慢?

更新的逻辑在sqexPatch.dll中 这边逻辑比较简单,我也就没标变量名结构体啥的,dwContext的244和248偏移位置应该分别指向接收buffer的头和尾,相减得到buffer长度给v6,比较v6和传入的length参数,取较小值,然后就调WinHttpReadData往里面读这么长的数据。WinHttpReadData的定义如下:

WINHTTPAPI BOOL WinHttpReadData(
  [in]  HINTERNET hRequest,
  [out] LPVOID    lpBuffer,
  [in]  DWORD     dwNumberOfBytesToRead,
  [out] LPDWORD   lpdwNumberOfBytesRead
);

这边get_http_data的length实际传入的值为8KB,也就是每次只会读8KB大小的数据,而这个函数是通过winHttpSetStatusCallback注册的回调函数,如下图所示,在连接完成,读写完成等事件发生时调用该回调函数: 如果缓冲区太小就会导致需要调用的次数非常多效率变得很低,视频中选择了直接hook这个函数,将这个参数直接改大的操作,但这么做很容易导致溢出,崩溃事小,万一哪天DNS被劫持了或者拂晓想搞点事情,那可就直接送了个堆溢出。。。。

实际上这个缓冲区大小还挺大的,从调试器里看是在堆上的0x100000字节(1MB)的一块buffer,所以最大一次能读1MB的数据,这个缓冲区就比8KB大得多了,再大就得去看分配的逻辑让他分配多一点了,不过也没必要。

Patch

Patch很简单,下图中0x10035180处的jb,就是比较如果buffer长度小于length,就跳过伪代码中的v5=&v6那行,也就是用buffer长度作为读取的字节数,否则就使用传入的length作为读取的字节数,那么patch就只要把这行jb改为nop,让他永远执行v5=&v6就可以了(改两个字节就可以了,比另外写个程序去hook应该要方便得多)。 patch后:

实测改完之后速度大概在2MB/s,虽然跑不满,但更新不大的话也够用了


更新:目前拂晓似乎已经修复了这个问题,登陆器自动更新变快了