3.9.2.26版本 请求api 检查登录状态 崩溃
Describe the bug 3.9.2.26-v9版本 请求api 检查登录状态 崩溃
这个界面的时候调用会崩溃,点击切换就能正常请求了
有没有什么方法跳过这个界面?
To Reproduce Steps to reproduce the behavior: 注入3.9.2.26版本微信, 请求/api/?type=0 微信崩溃
Desktop (please complete the following information):
- OS: win11
Additional context 其他api接口请求是正常的
后面版本增加的有进入微信接口就是直接进入,这个版本应该没有
后面版本增加的有进入微信接口就是直接进入,这个版本应该没有
感谢回复,主要看中这个版本可以搜索好友添加,如果要添加直接进入的接口大概要怎么找到call,我自己试试能不能修改
另外再问下这个提示版本太旧的问题有什么自动化的解决方案吗
INT64 Manager::CheckLogin() {
INT64 success = -1;
UINT64 accout_service_addr = base_addr_ + offset::kGetAccountServiceMgr;
func::__GetAccountService GetSevice = (func::__GetAccountService)accout_service_addr;
// UINT64 service_addr = _GetAccountService(accout_service_addr);
UINT64 service_addr = GetSevice();
if (service_addr) {
success = *(UINT64 *)(service_addr + 0x7F8);
}
return success;
}
大佬,我看后面版本的checkLogin也都是这个方法,并没有调整啊,还是另外的哪个接口?
int64_t EnterWeChat();
@ttttupup 大佬求助,根据3.9.8.25版本的进入微信的思路,我这边找到了3.9.2.23版本相关的入口和参数,但是一执行就崩溃了,能不能帮忙看看是什么原因?相关代码如下
int AccountMgr::EnterWeChat() {
int success = -1;
DWORD enter_wechat_callback_addr = base_addr_ + WX_ENTER_WECHAT_CALLBACK_OFFSET; //#define WX_ENTER_WECHAT_CALLBACK_OFFSET 0xaf5050
std::vector<DWORD> vec;
bool found = Utils::ScanAndMatchValue(base_addr_ + 0x2a66b08, vec);
if (found) {
HANDLE handle = GetCurrentProcess();
for (int i = 0; i < vec.size(); i++) {
DWORD ptr = vec.at(i);
SPDLOG_ERROR("enter wechat search ptr: {:X}", ptr);
DWORD value;
if (ReadProcessMemory(handle, (LPVOID)ptr, &value, sizeof(value), NULL)) {
if (value == base_addr_ + 0x2a66b08) {
DWORD login_wnd = ptr;
__asm {
PUSHAD
// MOV ECX, login_wnd
LEA ECX, login_wnd //修改为LEA后不崩溃了,但是在头像登录那个界面没有任何效果
CALL enter_wechat_callback_addr
POPAD
}
break;
}
}
}
}
return success;
}
bool Utils::ScanAndMatchValue(DWORD value, std::vector<DWORD>& result) {
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
LPVOID current_addr = sys_info.lpMinimumApplicationAddress;
DWORD pageSize = sys_info.dwPageSize;
MEMORY_BASIC_INFORMATION mem_info = {};
HANDLE handle = GetCurrentProcess();
while (current_addr < sys_info.lpMaximumApplicationAddress) {
if (VirtualQueryEx(handle, current_addr, &mem_info, sizeof(MEMORY_BASIC_INFORMATION))) {
if (mem_info.State == MEM_COMMIT && (mem_info.Protect & (PAGE_READONLY | PAGE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE))) {
// 读取内存并搜索值
LPVOID pBuffer = new BYTE[mem_info.RegionSize];
if (ReadProcessMemory(handle, mem_info.BaseAddress, pBuffer, mem_info.RegionSize, NULL)) {
for (DWORD i = 0; i < mem_info.RegionSize; i += sizeof(DWORD)) {
if (*(PDWORD)((LPBYTE)pBuffer + i) == value) {
result.push_back((DWORD)mem_info.BaseAddress + i);
}
}
}
delete[] pBuffer;
}
current_addr = (LPBYTE)mem_info.BaseAddress + mem_info.RegionSize;
}
else {
current_addr = (LPBYTE)current_addr + pageSize;
}
};
return !result.empty();
}
这个回调函数就是登录窗口这个ui对象里的一个回调函数,因为调试时发现只会出现一个,所以就用这种简单粗暴的方式直接扫描内存来获取定位。你可以通过spy等其他方式定位。不崩溃的前提是 0x2a66b08这个偏移是正确的。就是那个窗口类的一个回调方法。第二个就是调用这个方法是正确的,可以直接在这个方法断点,看正常操作是传的是什么。wnd->enter_wechat(); 伪码应该就是这种形式,ecx需要传wnd的指针。 定位的位置如果是指针就用mov,是实际内存位置就用lea
pushad
lea ecx, wnd ;
call cb
popad
这个回调函数就是登录窗口这个ui对象里的一个回调函数,因为调试时发现只会出现一个,所以就用这种简单粗暴的方式直接扫描内存来获取定位。你可以通过spy等其他方式定位。不崩溃的前提是 0x2a66b08这个偏移是正确的。就是那个窗口类的一个回调方法。第二个就是调用这个方法是正确的,可以直接在这个方法断点,看正常操作是传的是什么。wnd->enter_wechat(); 伪码应该就是这种形式,ecx需要传wnd的指针。 定位的位置如果是指针就用mov,是实际内存位置就用lea pushad lea ecx, wnd ; call cb popad
我通过修改mov成lea已经不会崩溃了,不过没有进入的效果,我寻找callback和win指针的方式是
1、使用ghidra, 查找字符串login,刚好找到日志记录
判断这个就是点击登录按钮的回调
根据函数代码,入参应该是窗口的this指针
2、然后查找这个函数的引用
根据引用代码使用xdbg打断点
找到ecx当时的值和对应内存内的值
将这个内存内的值转换成文件偏移地址可以看到ghidra内对应的是LoginWnd的vftable(是不是就是this指针?)
今天重新跑,发现这个地址的RVA变成了2A66A18,昨天找到的RVA是2a66b08
大佬帮忙看看这个流程有啥问题没? 这个callback的参数有啥其他方式获取? 现在这样跑下来代码不会崩溃,不过调用后没有任何效果
窗口的话我找到窗口类应该是WeChatLoginWndForPC,但是不知道怎么根据类名获取指针,找来找去只能找到获取句柄的api
找到LoginWnd的vftable就可以定位了,就2点,先检查callback 函数是否正确,再检查exc是否是loginWnd,就行了。检查ecx中的值的第一个值是不是等于这个vftable就能确定是不是正确的。
终于成功了,还是那个ECX传参应该是用MOV,不能用LEA,感谢大佬指导