wxhelper icon indicating copy to clipboard operation
wxhelper copied to clipboard

3.9.2.26版本 请求api 检查登录状态 崩溃

Open rainhon opened this issue 1 year ago • 9 comments

Describe the bug 3.9.2.26-v9版本 请求api 检查登录状态 崩溃

image 这个界面的时候调用会崩溃,点击切换就能正常请求了

有没有什么方法跳过这个界面?

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接口请求是正常的

rainhon avatar Nov 07 '24 12:11 rainhon

后面版本增加的有进入微信接口就是直接进入,这个版本应该没有

ttttupup avatar Nov 08 '24 00:11 ttttupup

后面版本增加的有进入微信接口就是直接进入,这个版本应该没有

感谢回复,主要看中这个版本可以搜索好友添加,如果要添加直接进入的接口大概要怎么找到call,我自己试试能不能修改

另外再问下这个提示版本太旧的问题有什么自动化的解决方案吗

rainhon avatar Nov 08 '24 02:11 rainhon

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也都是这个方法,并没有调整啊,还是另外的哪个接口?

rainhon avatar Nov 08 '24 13:11 rainhon

int64_t EnterWeChat();

ttttupup avatar Nov 09 '24 00:11 ttttupup

@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();
}

rainhon avatar Nov 24 '24 16:11 rainhon

这个回调函数就是登录窗口这个ui对象里的一个回调函数,因为调试时发现只会出现一个,所以就用这种简单粗暴的方式直接扫描内存来获取定位。你可以通过spy等其他方式定位。不崩溃的前提是 0x2a66b08这个偏移是正确的。就是那个窗口类的一个回调方法。第二个就是调用这个方法是正确的,可以直接在这个方法断点,看正常操作是传的是什么。wnd->enter_wechat(); 伪码应该就是这种形式,ecx需要传wnd的指针。 定位的位置如果是指针就用mov,是实际内存位置就用lea pushad lea ecx, wnd ; call cb
popad

ttttupup avatar Nov 25 '24 06:11 ttttupup

这个回调函数就是登录窗口这个ui对象里的一个回调函数,因为调试时发现只会出现一个,所以就用这种简单粗暴的方式直接扫描内存来获取定位。你可以通过spy等其他方式定位。不崩溃的前提是 0x2a66b08这个偏移是正确的。就是那个窗口类的一个回调方法。第二个就是调用这个方法是正确的,可以直接在这个方法断点,看正常操作是传的是什么。wnd->enter_wechat(); 伪码应该就是这种形式,ecx需要传wnd的指针。 定位的位置如果是指针就用mov,是实际内存位置就用lea pushad lea ecx, wnd ; call cb popad

我通过修改mov成lea已经不会崩溃了,不过没有进入的效果,我寻找callback和win指针的方式是 1、使用ghidra, 查找字符串login,刚好找到日志记录 image 判断这个就是点击登录按钮的回调 根据函数代码,入参应该是窗口的this指针 2、然后查找这个函数的引用 image 根据引用代码使用xdbg打断点 image 找到ecx当时的值和对应内存内的值 image 将这个内存内的值转换成文件偏移地址可以看到ghidra内对应的是LoginWnd的vftable(是不是就是this指针?) image 今天重新跑,发现这个地址的RVA变成了2A66A18,昨天找到的RVA是2a66b08

大佬帮忙看看这个流程有啥问题没? 这个callback的参数有啥其他方式获取? 现在这样跑下来代码不会崩溃,不过调用后没有任何效果

窗口的话我找到窗口类应该是WeChatLoginWndForPC,但是不知道怎么根据类名获取指针,找来找去只能找到获取句柄的api

rainhon avatar Nov 25 '24 15:11 rainhon

找到LoginWnd的vftable就可以定位了,就2点,先检查callback 函数是否正确,再检查exc是否是loginWnd,就行了。检查ecx中的值的第一个值是不是等于这个vftable就能确定是不是正确的。

ttttupup avatar Nov 26 '24 05:11 ttttupup

终于成功了,还是那个ECX传参应该是用MOV,不能用LEA,感谢大佬指导

rainhon avatar Nov 26 '24 13:11 rainhon