• 某 IM 软件登录代理异常分析


    日志分析

    通过 EXCEPTION_ACCESS_VIOLATION 可以判断异常类型是非法内存访问。

    触发异常的指令地址位于 EIP=A95A3399,指向非法内存区域。

    栈帧底部地址位于 EBP=1127F7C4,可以帮助恢复函数调用栈的结构。

    Type: EXCEPTION_ACCESS_VIOLATION
    Error: Execute address 0xA95A3399
    Address: A95A3399
    
    CallStack:
    0xA95A3399<unknown module>
    msf + D602
    xpng_dll + 3A3B2
    xpng_dll + 3A514
    xpng_dll + 39989
    xpng_dll + 3B161
    xpng_dll + 31374
    ...
    
    Regs:
    EAX=10D6DE00, EBX=10D490E0, ECX=10D521E0, EDX=00000000
    ESI=10D52250, EDI=10A4AA20, EBP=1127F7C4, ESP=1127F760, EIP=A95A3399
    

    堆栈分析

    通过日志记录的调用栈可以恢复函数调用链:

    xpng::PacketStreamSocket::NotifyOnClose()
        msf::TCPChannelConnector::OnChannelClose()
            msf::TCPChannelConnector::HandleConnectFailed()
                delete msf::MSFChannelTCP
            msf::MSFChannelTCP::Close()
    

    流量分析

    使用通过 HTTP 代理的 Happy Eyeballs 连接算法。

    IPv4 连接:

    CONNECT 180.109.156.44:443 HTTP/1.1
    Host: 180.109.156.44:443
    Accept: */*
    Content-Type: text/html
    Proxy-Connection: Keep-Alive
    Content-length: 0
    
    HTTP/1.1 200 Connection established
    Connection: close
    

    IPv6 连接:

    CONNECT msfwifiv6.3g.qq.com:14000 HTTP/1.1
    Host: msfwifiv6.3g.qq.com:14000
    Accept: */*
    Content-Type: text/html
    Proxy-Connection: Keep-Alive
    Content-length: 0
    
    HTTP/1.1 200 Connection established
    Connection: close
    

    代码分析

    当网络连接因为异常原因而中止时,OnChannelClose 函数首先会调用 HandleConnectFailed 函数,其中 HandleConnectFailed 函数会把 MSFChannelTCP 类给释放掉,然后再调用 MSFChannelTCP 类中的 Close 虚函数。

    由于此时 MSFChannelTCP 类已经被释放掉,结构体中第一项的虚表指针被 msvcrt(ucrt) 堆管理机制重新指向了之前被释放的一个 Chunk,所以 Chunk 中的第三项会被当作 Close 虚函数的地址进行调用,导致程序崩溃并抛出 EXCEPTION_ACCESS_VIOLATION 异常。

    上面那个虚表指针指向的 Chunk 实际是由相邻的两个小 Chunk 释放之后被 RtlpHpVsChunkCoalesce 函数合并得到的,其中第三项正好是高地址的小 chunk 中被内核 RtlpHpHeapGlobals 异或保护的 Header,所以只要不重启系统每一次取出的虚函数指针都是相同的,即触发非法执行的 EIP 保持不变。

    调试脚本如下,可以在断点处自动打印调用栈和对象地址:

    from __future__ import print_function
    
    import ida_dbg
    import ida_ida
    import ida_lines
    from idc import *
    
    class MyDbgHook(ida_dbg.DBG_Hooks):
        """ Own debug hook class that implementd the callback functions """
    
        def __init__(self):
            ida_dbg.DBG_Hooks.__init__(self) # important
            self.steps = 0
    
        def dbg_stack_trace(self):
            tmp_ea = get_reg_value('eip')
            print('#### 0x%X %s' % (tmp_ea, get_func_off_str(tmp_ea)))
            ebp = get_reg_value('ebp')
            dep = 1
            while 1:
                tmp_ea = read_dbg_dword(ebp+4)
                if tmp_ea == 0:
                    break
                print('#' * dep + '#### 0x%X %s' % (tmp_ea, get_func_off_str(tmp_ea)))
                ebp = read_dbg_dword(ebp)
                dep += 1
    
        def dbg_bpt(self, tid, ea):
            # Object trace
            print('### 0x%X %s 0x%X' % (ea, get_func_off_str(ea), get_reg_value('ecx')))
            # Stack trace
            self.dbg_stack_trace()
            # ida_dbg.continue_process()
            return 0
    
    
    # Remove an existing debug hook
    try:
        if debughook:
            print("Removing previous hook ...")
            debughook.unhook()
    except:
        pass
    
    # Install the debug hook
    debughook = MyDbgHook()
    debughook.hook()
    

    参考文章

    https://www.blackhat.com/docs/us-16/materials/us-16-Yason-Windows-10-Segment-Heap-Internals-wp.pdf

  • 相关阅读:
    layui镜像站文档
    mysql 查询 包含哪个字符串
    laydate时间点击后马上消失
    timer_dma_enable
    map文件堆栈大小
    回调函数
    复位电路
    stm32 map文件的分析
    如何在VSCode里面写代码进行调试和运行
    DMA为CPU减负
  • 原文地址:https://www.cnblogs.com/algonote/p/15350928.html
Copyright © 2020-2023  润新知