Closed UlyssesWu closed 8 years ago
辣鸡QQ音乐完全没乱码! 写个检测连续三字节字符数量 奇数的话补个汉字wwwwwwwwww 就补 辣鸡中的一个好了wwwwwwww
TO楼上…… 辣鸡QQ音乐是直接发信息给服务器,让服务器再通知辣鸡QQ改状态的。而且他发的时候都是通过ID表示的(我猜),除了他们辣鸡曲库内的歌之外显示不了别的,QZone也是同理(我再猜)
一个不通用的解决方案:
修改PutRSInfo函数(需要用到一些Patch手段),把原来针对GBK字符串的CTXStringA构造函数换成针对UTF8的,经过测试确实解决了问题。但是像这样Patch文件,一更新又没用了。
问题就出在我们传入的BSTR,被当做ANSI编码的字符串处理了。我一个渣渣,不懂C艹,也不太了解BSTR这种东西,但是我听说BSTR都是Unicode编码的。不知道是我太蠢,还是这COM库自己确实有问题。
先写到这,问题还是要继续关注的。先升级win10去了……
每个字我都认识 组合在一起就不认识了orz 每次更新都打个补丁好了! win10大法好!
@UlyssesWu IAT Hook :D
@JixunMoe 确实有在考虑,但是具体要怎么搞仍然一头雾水——说白了就是:我~不~会~啊~巨~巨~Q~A~Q~ (:зゝ∠)
這個是 Inline Hook, 但是應該也夠用了 :D
可以往狀態信息添加一些識別內容,避免正常功能被過濾;也可以需要的時候 Hook 其他時候還原 :D
// HotPatch.cpp
#include "HotPatch.h"
#include "PatchUtil.h"
namespace Jixun {
HotPatch::HotPatch(HMODULE hModule, LPCSTR lpProc, HookFunc myProc)
{
if (!hModule) return ;
uAddr addr = this->fProc = uAddr(GetProcAddress(hModule, lpProc));
if (!addr) return ;
addr -= 5;
// 005049E2 - E9 910CE411 jmp 12345678
// 005049E7 > ^ EB F9 jmp short e.005049E2
DWORD oldProtect;
VirtualProtect(LPVOID(addr), 7, PAGE_EXECUTE_READWRITE, &oldProtect);
WriteUByteRaw(addr, 0xE9);
WriteRelativeAddress(addr + 1, uAddr(myProc));
WriteUShortRaw(addr + 5, 0xF9EB);
VirtualProtect(LPVOID(addr), 7, oldProtect, &oldProtect);
}
bool HotPatch::isHooked()
{
return this->fProc != NULL;
}
void HotPatch::Pause()
{
WriteUShort(this->fProc, 0xFF8B);
}
void HotPatch::Resume()
{
WriteUShort(this->fProc, 0xF9EB);
}
uAddr HotPatch::GetAddress()
{
return this->fProc + 2;
}
}
// HotPatch.h
#pragma once
#include "Common.h"
typedef void* HookFunc;
namespace Jixun {
class HotPatch;
class HotPatch
{
private:
uAddr fProc;
public:
HotPatch(HMODULE hModule, LPCSTR lpProc, HookFunc myProc);
bool isHooked();
void Pause();
void Resume();
uAddr GetAddress();
};
}
其它引入的文件可以在這裏找到:JixunMoe/dll-hijack
@JixunMoe 作为一个渣渣,我连应该hook哪里也不懂……CTXStringA的构造函数?还是PutRSInfo?然而PutRSInfo其实是一个内部函数,并没有导出,图里名字是我自己标注的。如果hook构造函数,怎么判断调用者?另外为了让PutRSInfo能调用另一个CTXStringA的构造函数,其实还需要把那个构造函数添加到导入表,因为原本它是不导入UTF8版函数的,只导入GBK版。 不过我已搞了另一种方案:在上述Patch的基础上,修改导出表,强行导出PutRSInfo函数,然后从我们的程序中调用。经测试似乎也可以用。这样不用考虑每次更新后Patch文件,而是一直调用已经Patch过的DLL就好。
@UlyssesWu 這個思路也是可以噠 :D
我的想法是勾上轉碼函數.. 但是既然你能用別的方法搞定也行啦 :D
以前PutRSInfo是可以接Unicode字符串的,然而在最新版的QQ(7.6 15742)中,它的行为方式变了,他会把输入的字符串都看做ANSI,然后转一个UTF8。结果自然是中文全部乱码,惨不忍睹。英文不受影响。
为了绕过这个问题,我尝试使用这种方式:
结果自然是,前两个字正常显示成功,第三个字由于GB2312的汉字是2个字节,UTF8的汉字是三个字节,因此第9个字节被吃了,并且补了问号。看来是行不通的(虽说偶数个汉字是可以正常显示)。
不知道QQ这是故意为之,还是哪里出BUG。不知这个问题有没有解?