Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
rainhon opened this issue Nov 7, 2024 · 9 comments
Open

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

rainhon opened this issue Nov 7, 2024 · 9 comments

Comments

@rainhon
Copy link

rainhon commented Nov 7, 2024

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

@ttttupup
Copy link
Owner

ttttupup commented Nov 8, 2024

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

@rainhon
Copy link
Author

rainhon commented Nov 8, 2024

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

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

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

@rainhon
Copy link
Author

rainhon commented Nov 8, 2024

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

@ttttupup
Copy link
Owner

ttttupup commented Nov 9, 2024

int64_t EnterWeChat();

@rainhon
Copy link
Author

rainhon commented Nov 24, 2024

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

@ttttupup
Copy link
Owner

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

@rainhon
Copy link
Author

rainhon commented Nov 25, 2024

这个回调函数就是登录窗口这个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

@ttttupup
Copy link
Owner

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

@rainhon
Copy link
Author

rainhon commented Nov 26, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants