linux qq 崩溃调试分析 QQ调试报告 调试者 I0gan
blog: http://i0gan.cn
github: https://github.com/i0gan
保护 1 2 3 4 5 6 7 8 9 10 ┌[logan☮arch]-(/usr/bin) └> checksec qq [!] Unknown configuration section 'update' [*] '/usr/bin/qq' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled FORTIFY: Enabled
问题 qq在登录之后在拉去消息和好友列表时出现段错误, 在反映比较慢的电脑上出现几率比较小, 在反映过快的电脑中, 每次基本都直接崩溃.
影响版本 2.0.0
原因 多线程条件竞争, 导致对象释放重利用, 然而在调用该函数指针时, 会出现内存地址非法调用
证实: 调试时, 在登录之后, 只运行主线程, 阻断其他线程运行, 能够成功保证登录之后不会崩溃, 只是接受不了消息
其他 由于代码量比较大, 时间性的原因, 只能先暂时提供一下调试信息, 后期会不断更新调试结果, 找出对于的具体漏洞所在
触发段错误漏洞代码块偏移 0xbfdfa0 (vul 1)
0xCCB500 (vul 2)
调试 收到系统信号: sigsegv
线程信息: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 pwndbg> info threads Id Target Id Frame 1 Thread 0x7ffff6964940 (LWP 6251) "qq" 0x00007ffff7ce49e5 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0 2 Thread 0x7ffff6963640 (LWP 6258) "qq" 0x00007ffff7e376a2 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0 3 Thread 0x7ffff6162640 (LWP 6259) "ThreadPoolServi" 0x00007ffff70485de in epoll_wait () from /usr/lib/libc.so.6 5 Thread 0x7ffff5160640 (LWP 6261) "Qnox_LogicThrea" 0x00007ffff70485de in epoll_wait () from /usr/lib/libc.so.6 6 Thread 0x7ffff495f640 (LWP 6262) "Qnox_IOThread" 0x00007ffff70485de in epoll_wait () from /usr/lib/libc.so.6 7 Thread 0x7ffff415e640 (LWP 6263) "ThreadPoolForeg" 0x00007ffff7e379c8 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0 10 Thread 0x7ffff215a640 (LWP 6267) "inotify_reader" 0x00007ffff703fb7b in select () from /usr/lib/libc.so.6 14 Thread 0x7ffff094f640 (LWP 6270) "qq" 0x00007ffff7e376a2 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0 16 Thread 0x7ffff1158640 (LWP 6290) "ThreadPoolForeg" 0x0000555555ff85a0 in ?? () 17 Thread 0x7ffff1959640 (LWP 6291) "ThreadPoolForeg" 0x00007ffff7e379c8 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0 18 Thread 0x7ffff295b640 (LWP 6292) "ThreadPoolForeg" 0x00007ffff7e379c8 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0 19 Thread 0x7ffff315c640 (LWP 6293) "ThreadPoolForeg" 0x0000555556000aa0 in ?? () 20 Thread 0x7ffff395d640 (LWP 6294) "gmain" 0x00007ffff703d46f in poll () from /usr/lib/libc.so.6 21 Thread 0x7fffee64f640 (LWP 6295) "pool-qq" 0x00007ffff7042d5d in syscall () from /usr/lib/libc.so.6 * 22 Thread 0x7fffede4e640 (LWP 6296) "gdbus" 0x00007ffff7ce49e5 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
段错误 主线程段错误信号
1 2 Thread 1 "qq" received signal SIGSEGV, Segmentation fault. 0x00007ffff7ce49e5 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
调试如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────── RAX 0x0 RBX 0x7ffff7000000 (____wcstof128_l_internal+1168) ◂— adc eax, 0x748b0000 RCX 0x7ffff7d42938 ◂— 0x6f5347007065656b /* 'keep' */ RDX 0x7ffff7e450a0 (__pthread_keys) ◂— 0x1 RDI 0x134a77fdde60 ◂— 0xffffecb700000002 RSI 0x7ffff7ce498d (g_main_context_dispatch+493) ◂— mov rdi, qword ptr [rsp + 0x18] R8 0x134a7710b520 ◂— 0x0 R9 0x7fffffffd880 ◂— 0x3000000028 /* '(' */ R10 0x7ffff7fca080 R11 0x286 R12 0x1 R13 0x134a77743890 ◂— 0x0 R14 0x134a77109dc0 ◂— 0x0 R15 0x0 RBP 0x134a774f4bd0 —▸ 0x134a77fdde60 ◂— 0xffffecb700000002 RSP 0x7fffffffd970 —▸ 0x134a77fdde60 ◂— 0xffffecb700000002 RIP 0x7ffff7ce49e5 (g_main_context_dispatch+581) ◂— call qword ptr [rbx + 8] ──────────────────────────────────────────[ DISASM ]────────────────────────────────────────── ► 0x7ffff7ce49e5 <g_main_context_dispatch+581> call qword ptr [rbx + 8] rdi: 0x134a77fdde60 ◂— 0xffffecb700000002 rsi: 0x7ffff7ce498d (g_main_context_dispatch+493) ◂— mov rdi, qword ptr [rsp + 0x18] rdx: 0x7ffff7e450a0 (__pthread_keys) ◂— 0x1 rcx: 0x7ffff7d42938 ◂— 0x6f5347007065656b /* 'keep' */
rbx + 8内存
1 2 3 4 5 6 7 pwndbg> x /40gx $rbx + 8 0x7ffff7000008 <____wcstof128_l_internal+1176>: 0x2444c74820245c89 0x0ff6850000000058 0x7ffff7000018 <____wcstof128_l_internal+1192>: 0xef894c00001c968e 0x448d4c58244c8d48 0x7ffff7000028 <____wcstof128_l_internal+1208>: 0xf90ee8ea89485024 0x8b44ff438d48ffff 0x7ffff7000038 <____wcstof128_l_internal+1224>: 0xdcacbd0f4c20245c 0x2444894800001b58 0x7ffff7000048 <____wcstof128_l_internal+1240>: 0xed85453ff5834918 0x8b48000012c4850f 0x7ffff7000058 <____wcstof128_l_internal+1256>: 0x48240c6348582454 0x01fb834850244c89
然而 call qword ptr [rbx + 8]这条指令就相当于: call 0x2444c74820245c89, 这个地址是非法地址,所以出现段错误
正常情况调试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────── RAX 0x0 RBX 0x7ffff7dc33a0 —▸ 0x7ffff7cdf140 ◂— lock add dword ptr [rdi], 1 RCX 0x7ffff7d42938 ◂— 0x6f5347007065656b /* 'keep' */ RDX 0x7ffff7e450a0 (__pthread_keys) ◂— 0x1 RDI 0x1392c57a14a0 ◂— 0xffffec6f00000002 RSI 0x7ffff7ce498d (g_main_context_dispatch+493) ◂— mov rdi, qword ptr [rsp + 0x18] R8 0x1392c57a1520 ◂— 0x0 R9 0x7fffffffd880 ◂— 0x3000000028 /* '(' */ R10 0x7ffff7fca080 R11 0x286 R12 0x1 R13 0x1392c5ddb900 ◂— 0x0 R14 0x1392c579fdc0 ◂— 0x0 R15 0x0 RBP 0x1392c58e8b60 —▸ 0x1392c57a14a0 ◂— 0xffffec6f00000002 RSP 0x7fffffffd970 —▸ 0x1392c57a14a0 ◂— 0xffffec6f00000002 RIP 0x7ffff7ce49e5 (g_main_context_dispatch+581) ◂— call qword ptr [rbx + 8] ──────────────────────────────────────────[ DISASM ]────────────────────────────────────────── ► 0x7ffff7ce49e5 <g_main_context_dispatch+581> call qword ptr [rbx + 8] 0x7ffff7ce49e8 <g_main_context_dispatch+584> mov rdi, r14 0x7ffff7ce49eb <g_main_context_dispatch+587> call g_mutex_lock <0x7ffff7d32250>
通过以上观察, rbx指向的是0x7ffff7cdf140, 则 rbx + 8内存信息如下
1 2 3 4 pwndbg> x /40gx $rbx + 8 0x7ffff7dc33a8: 0x00007ffff7cdf270 0x00007ffff7cdef50 0x7ffff7dc33b8: 0x0000000000000000 0x00001392c618e070 0x7ffff7dc33c8: 0x00007ffff7ce0650 0x0000000000000000
指向的内存如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 pwndbg> x /40gx 0x00007ffff7cdf270 0x7ffff7cdf270: 0x66c30a74012f83f0 0x0000000000841f0f 0x7ffff7cdf280: 0xfd894818478b4855 0x7f8b480674c08548 0x7ffff7cdf290: 0xe95def8948d0ff10 0x001f0f90ffffffc4 0x7ffff7cdf2a0: 0x2e6690ffffffbbe9 0x0000000000841f0f 0x7ffff7cdf2b0: 0x15fffb8953555441 0x48fb6348000e361c 0x7ffff7cdf2c0: 0x8b44000e485a158d 0x000001b8c5894820 0x7ffff7cdf2d0: 0x0587ba0c87c18900 0x25058b48000e4948 0x7ffff7cdf2e0: 0x0080b88b48000e48 0x4400047fb1e80000 0x7ffff7cdf2f0: 0xc35c415d5b006589 0x0000000000841f0f 0x7ffff7cdf300 <g_clear_handle_id>: 0x1074c08545078b44 0x89440000000007c7 0x7ffff7cdf310 <g_clear_handle_id+16>: 0x0000441f0fe6ffc7 0x00000000801f0fc3 0x7ffff7cdf320 <g_get_real_time>: 0x4864f63128ec8348 0x480000002825048b 0x7ffff7cdf330 <g_get_real_time+16>: 0x8948c03118244489 0x48000e37e115ffe7 0x7ffff7cdf340 <g_get_real_time+32>: 0x48000f4240240469 0x24548b4808244403 0x7ffff7cdf350 <g_get_real_time+48>: 0x002825142b486418 0x28c4834805750000 0x7ffff7cdf360 <g_get_real_time+64>: 0x66000e372915ffc3 0x0000000000841f0f 0x7ffff7cdf370 <g_main_context_query>: 0x495641d789495741 0x41fd89495541ce89 0x7ffff7cdf380 <g_main_context_query+16>: 0xf38953c589445554 0x2ebee86708ec8348 0x7ffff7cdf390 <g_main_context_query+32>: 0x854860458b490005 0x31000000c1840fc0 0x7ffff7cdf3a0 <g_main_context_query+48>: 0x2e6634ebe43145f6 0x0000000000841f0f
单步执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 RAX 0x0 RBX 0x7ffff7dc33a0 —▸ 0x7ffff7cdf140 ◂— lock add dword ptr [rdi], 1 RCX 0x7ffff7d42930 ◂— 0x796f7274736564 /* 'destroy' */ RDX 0x7ffff7e450a0 (__pthread_keys) ◂— 0x1 RDI 0x99bbfa157a0 ◂— 0xfffff66600000002 RSI 0x7ffff7ce498d (g_main_context_dispatch+493) ◂— mov rdi, qword ptr [rsp + 0x18] R8 0x99bbf7f2380 ◂— 0x0 R9 0x7fffede4d9e0 ◂— 0x3000000028 /* '(' */ R10 0x7ffff7fca080 R11 0x286 R12 0x0 R13 0x99bbf9eb250 ◂— 0x0 R14 0x99bbf9f9e70 ◂— 0x0 R15 0x1 RBP 0x99bbf9fc4e0 —▸ 0x99bbfa157a0 ◂— 0xfffff66600000002 RSP 0x7fffede4dac8 —▸ 0x7ffff7ce49e8 (g_main_context_dispatch+584) ◂— mov rdi, r14 RIP 0x7ffff7cdf270 ◂— lock sub dword ptr [rdi], 1 ► 0x7ffff7cdf270 lock sub dword ptr [rdi], 1 ↓ 0x7ffff7cdf276 ret ↓ 0x7ffff7ce49e8 <g_main_context_dispatch+584> mov rdi, r14 0x7ffff7ce49eb <g_main_context_dispatch+587> call g_mutex_lock <0x7ffff7d32250>
可以看到, 原来rbx + 8处的内存储存的是一个该处指令的地址, 这里采用lock sub指令进行对线程使用数 - 1, rdi 指向的是被锁的线程.目前为2
lock前缀指令详解
1 2 3 4 LOCK指令前缀会设置处理器的LOCK#信号(译注:这个信号会使总线锁定,阻止其他处理器接管总线访问内存),直到使用LOCK前缀的指令执行结束,这会使这条指令的执行变为原子操作。在多处理器环境下,设置LOCK#信号能保证某个处理器对共享内存的独占使用。 LOCK指令前缀只能用于以下指令,并且要求指令目的操作数为内存操作数,如果源操作数为内存操作数,就会产生undefined opcode异常:ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B,CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG。LOCK指令前缀用于其他任何指令时,也会产生如果源操作数为内存操作数,就会产生undefined opcode异常。另外,XCHG指令默认会设置LOCK#信号,无论是否使用LOCK指令前缀。 LOCK指令前缀经常用于BTS指令,用来在共享内存进行一次read-modify-write操作。 从P6处理器家族开始,如果使用了LOCK指令前缀的指令要访问的目的地址的内容已经缓存在了cache中,那么LOCK#信号一般就不会被设置,但是当前处理器的cache会被锁定,然后缓存一致性(cache coherency )机制会自动确保操作的原子性。
从g_main_context_dispatch结束的可疑地址1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 ────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────── RAX 0x1 RBX 0x1665cdb9ed01 ◂— 0x0 RCX 0x7fffffffdac0 —▸ 0x1665cdb9edc8 —▸ 0x5555570bdcb0 —▸ 0x55555617bf10 ◂— push rbp RDX 0x7ffff7da0251 ◂— 'non-blocking' RDI 0x1665cda0ddc0 ◂— 0x0 RSI 0x1 R8 0x1665cda0f520 ◂— 0x0 R9 0x7fffffffd920 ◂— 0x3000000028 /* '(' */ R10 0x7ffff7fca080 R11 0x286 R12 0x7fffffffdce8 ◂— '2.0.0-b2' R13 0x7fffffffdc80 —▸ 0x1665cdb9edd0 —▸ 0x5555570bdd00 —▸ 0x55555617bf20 ◂— push rbp R14 0x0 R15 0x1665cdb8d2d0 —▸ 0x5555570bc718 —▸ 0x555556151e10 ◂— push rbp RBP 0x7fffffffdb00 —▸ 0x7fffffffdb30 —▸ 0x7fffffffdbc0 —▸ 0x7fffffffdf10 —▸ 0x55555709abe0 ◂— ... RSP 0x7fffffffdac0 —▸ 0x1665cdb9edc8 —▸ 0x5555570bdcb0 —▸ 0x55555617bf10 ◂— push rbp RIP 0x55555615201a ◂— jne 0x555556152063 ──────────────────────────────────────────[ DISASM ]────────────────────────────────────────── 0x7ffff7ce3144 <g_main_context_iteration+68> pop rbp 0x7ffff7ce3145 <g_main_context_iteration+69> pop r12 0x7ffff7ce3147 <g_main_context_iteration+71> ret ↓ 0x555556152012 mov rcx, qword ptr [r15 + 8] 0x555556152016 cmp byte ptr [rcx + 8], 0 ► 0x55555615201a jne 0x555556152063 ↓ 0x55555615201e setne bl 0x555556152021 mov rdi, qword ptr [rcx] 0x555556152024 mov rax, qword ptr [rdi] 0x555556152027 call qword ptr [rax + 0x20] 0x55555615202a mov rcx, qword ptr [r15 + 8]
程序vmmap
1 2 3 4 5 6 7 0x555555554000 0x555555b69000 r--p 615000 0 /opt/tencent-qq/qq 0x555555b69000 0x5555570a6000 r-xp 153d000 614000 /opt/tencent-qq/qq 0x5555570a6000 0x55555710d000 r--p 67000 1b50000 /opt/tencent-qq/qq 0x55555710d000 0x555557119000 rw-p c000 1bb6000 /opt/tencent-qq/qq 0x555557119000 0x55555717a000 rw-p 61000 0 [heap] ....
程序基址为: 0x555555554000
1 2 pwndbg> p /x 0x555556152012 - 0x555555554000 $4 = 0xbfe012
可疑问题偏移地址:
0xbfe012
找到该调处用汇编代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 0x00bfdfa0 push rbp 0x00bfdfa1 mov rbp, rsp 0x00bfdfa4 push r15 0x00bfdfa6 push r14 0x00bfdfa8 push rbx 0x00bfdfa9 sub rsp, 0x28 0x00bfdfad mov r15, rdi 0x00bfdfb0 movaps xmm0, xmmword [0x00122f40] 0x00bfdfb7 movaps xmmword [rbp - 0x40], xmm0 0x00bfdfbb xorps xmm0, xmm0 0x00bfdfbe movaps xmmword [rbp - 0x30], xmm0 0x00bfdfc2 mov qword [rbp - 0x40], rsi 0x00bfdfc6 mov byte [rbp - 0x38], 0 0x00bfdfca mov r14, qword [rdi + 8] 0x00bfdfce test r14, r14 0x00bfdfd1 je 0xbfdfdc 0x00bfdfd3 mov eax, dword [r14 + 0xc] 0x00bfdfd7 add eax, 1 0x00bfdfda jmp 0xbfdfe1 0x00bfdfdc mov eax, 1 0x00bfdfe1 mov dword [rbp - 0x34], eax 0x00bfdfe4 lea rax, [rbp - 0x40] 0x00bfdfe8 mov qword [r15 + 8], rax 0x00bfdfec mov rdi, qword [r15 + 0x10] 0x00bfdff0 xor esi, esi 0x00bfdff2 jmp 0xbfe00d 0x00bfdff4 nop word cs:[rax + rax] 0x00bfdffe nop 0x00bfe000 test dl, dl 0x00bfe002 jne 0xbfe063 0x00bfe004 xor al, 1 0x00bfe006 mov rdi, qword [r15 + 0x10] 0x00bfe00a movzx esi, al 0x00bfe00d call g_main_context_iteration ; sym.imp.g_main_context_iteration ; 调用 0x00bfe012 mov rcx, qword [r15 + 8] 0x00bfe016 cmp byte [rcx + 8], 0 0x00bfe01a jne 0xbfe063 0x00bfe01c test eax, eax 0x00bfe01e setne bl 0x00bfe021 mov rdi, qword [rcx] 0x00bfe024 mov rax, qword [rdi] 0x00bfe027 call qword [rax + 0x20] 0x00bfe02a mov rcx, qword [r15 + 8] 0x00bfe02e mov qword [rcx + 0x10], rax 0x00bfe032 mov qword [rcx + 0x18], rdx 0x00bfe036 mov rcx, qword [r15 + 8] 0x00bfe03a cmp qword [rcx + 0x10], 0 0x00bfe03f sete al 0x00bfe042 or al, bl 0x00bfe044 movzx edx, byte [rcx + 8] 0x00bfe048 test dl, dl 0x00bfe04a jne 0xbfe000 0x00bfe04c test al, al 0x00bfe04e jne 0xbfe000 0x00bfe050 mov rdi, qword [rcx] 0x00bfe053 mov rax, qword [rdi] 0x00bfe056 call qword [rax + 0x38] 0x00bfe059 mov rcx, qword [r15 + 8] 0x00bfe05d cmp byte [rcx + 8], 0 0x00bfe061 je 0xbfe004 0x00bfe063 mov qword [r15 + 8], r14 0x00bfe067 add rsp, 0x28 0x00bfe06b pop rbx 0x00bfe06c pop r14 0x00bfe06e pop r15 0x00bfe070 pop rbp 0x00bfe071 ret 0x00bfe072 int3 0x00bfe073 int3
IDA伪c代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 char __fastcall sub_BFDFA0 (__int64 a1, __int64 a2) { __int64 v2; __int64 v3; int v4; __int64 v5; __int64 i; __int64 v7; __int64 v8; _BYTE *v9; bool v10; __int64 v11; __int64 v12; _QWORD *v13; __int64 v14; __int128 v16; __int128 v17; v2 = a1; v16 = xmmword_122F40; v17 = 0LL ; *(_QWORD *)&v16 = a2; BYTE8(v16) = 0 ; v3 = *(_QWORD *)(a1 + 8 ); if ( v3 ) v4 = *(_DWORD *)(v3 + 12 ) + 1 ; else v4 = 1 ; HIDWORD(v16) = v4; *(_QWORD *)(a1 + 8 ) = &v16; v5 = *(_QWORD *)(a1 + 16 ); for ( i = 0LL ; ; i = (unsigned __int8)(v7 ^ 1 ) ) { LODWORD(v7) = g_main_context_iteration(v5, i); v9 = *(_BYTE **)(v2 + 8 ); if ( v9[8 ] ) break ; v10 = (_DWORD)v7 != 0 ; v7 = (*(__int64 (__cdecl **)(_QWORD, __int64, __int64, _BYTE *))(**(_QWORD **)v9 + 32LL ))(*(_QWORD *)v9, i, v8, v9); v11 = *(_QWORD *)(v2 + 8 ); *(_QWORD *)(v11 + 16 ) = v7; *(_QWORD *)(v11 + 24 ) = v12; v13 = *(_QWORD **)(v2 + 8 ); LOBYTE(v7) = v10 || v13[2 ] == 0LL ; v14 = *((unsigned __int8 *)v13 + 8 ); if ( (_BYTE)v14 || (_BYTE)v7 ) { if ( (_BYTE)v14 ) break ; } else { LOBYTE(v7) = (*(__int64 (__cdecl **)(_QWORD, __int64, __int64, _QWORD *))(*(_QWORD *)*v13 + 56LL ))( *v13, i, v14, v13); if ( *(_BYTE *)(*(_QWORD *)(v2 + 8 ) + 8LL ) ) break ; } v5 = *(_QWORD *)(v2 + 16 ); } *(_QWORD *)(v2 + 8 ) = v3; return v7; }
发现在该函数中,没有加入线程锁, 多线程时条件竞争时导致出现内存错误.
最初漏洞所在:
在<g_main_context_dispatch+581> call qword ptr [rbx + 8]的地方出现内存错误.
该g_main_context_dispatch函数为g_main_context_iteration所调用
1 2 3 4 5 6 7 8 9 10 11 12 13 │ >0x7ffff7ce49b9 <g_main_context_dispatch+537> lea r8,[rip+0xbb8c5] │ 0x7ffff7ce49c0 <g_main_context_dispatch+544> lea rdx,[rip+0x546aa] │ 0x7ffff7ce49c7 <g_main_context_dispatch+551> call 0x7ffff7d34ad0 │ 0x7ffff7ce49cc <g_main_context_dispatch+556> mov rax,QWORD PTR [rsp+0x18] │ 0x7ffff7ce49d1 <g_main_context_dispatch+561> sub DWORD PTR [r13+0x0],0x1 │ 0x7ffff7ce49d6 <g_main_context_dispatch+566> mov QWORD PTR [r13+0x8],rax │ 0x7ffff7ce49da <g_main_context_dispatch+570> pop rcx │ 0x7ffff7ce49db <g_main_context_dispatch+571> pop rsi │ 0x7ffff7ce49dc <g_main_context_dispatch+572> test rbx,rbx │ 0x7ffff7ce49df <g_main_context_dispatch+575> je 0x7ffff7ce49e8 <g_main_context_dispatch+584> │ 0x7ffff7ce49e1 <g_main_context_dispatch+577> mov rdi,QWORD PTR [rsp] │ 0x7ffff7ce49e5 <g_main_context_dispatch+581> call QWORD PTR [rbx+0x8] //vul │ 0x7ffff7ce49e8 <g_main_context_dispatch+584> mov rdi,r14
1 2 3 4 5 ► 0x55555615200d call g_main_context_iteration@plt <0x5555570a28c0> rdi: 0x3acdd361fdc0 ◂— 0x0 rsi: 0x0 rdx: 0x7fffffffffffffff rcx: 0x5555570bdd00 —▸ 0x55555617bf20 ◂— push rbp
调试漏洞函数最后一次状态 崩溃前
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 RAX 0x0 RBX 0x317f3a79dc01 ◂— 0x0 RCX 0x7fffffffdac0 —▸ 0x317f3a79dc68 —▸ 0x5555570bdcb0 —▸ 0x55555617bf10 ◂— push rbp RDX 0x0 RDI 0x317f3a648dc0 ◂— 0x0 RSI 0x0 R8 0x317f3a5c8003 ◂— 0x0 R9 0x0 R10 0x7ffff7fca080 R11 0x286 R12 0x7fffffffdce8 ◂— '2.0.0-b2' R13 0x7fffffffdc80 —▸ 0x317f3a79dc70 —▸ 0x5555570bdd00 —▸ 0x55555617bf20 ◂— push rbp R14 0x0 R15 0x317f3a7b8090 —▸ 0x5555570bc718 —▸ 0x555556151e10 ◂— push rbp RBP 0x7fffffffdb00 —▸ 0x7fffffffdb30 —▸ 0x7fffffffdbc0 —▸ 0x7fffffffdf10 —▸ 0x55555709abe0 ◂— ... RSP 0x7fffffffdab8 —▸ 0x555556152012 ◂— mov rcx, qword ptr [r15 + 8] RIP 0x7ffff7ce3100 (g_main_context_iteration) ◂— push r12 ─────────────────────────────────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────────────────────────────────── ► 0x7ffff7ce3100 <g_main_context_iteration> push r12
最后一次崩溃g_main_context_iteration的传参
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 RAX 0x0 RBX 0x317f3a79dc01 ◂— 0x0 RCX 0x7fffffffdac0 —▸ 0x317f3a79dc68 —▸ 0x5555570bdcb0 —▸ 0x55555617bf10 ◂— push rbp RDX 0x0 RDI 0x317f3a648dc0 ◂— 0x0 RSI 0x0 R8 0x317f3a5c8003 ◂— 0x0 R9 0x0 ; diff R10 0x17 ; diff R11 0x10 ; diff R12 0x7fffffffdce8 ◂— '2.0.0-b2' R13 0x7fffffffdc80 —▸ 0x317f3a79dc70 —▸ 0x5555570bdd00 —▸ 0x55555617bf20 ◂— push rbp R14 0x0 R15 0x317f3a7b8090 —▸ 0x5555570bc718 —▸ 0x555556151e10 ◂— push rbp RBP 0x7fffffffdb00 —▸ 0x7fffffffdb30 —▸ 0x7fffffffdbc0 —▸ 0x7fffffffdf10 —▸ 0x55555709abe0 ◂— ... RSP 0x7fffffffdab8 —▸ 0x555556152012 ◂— mov rcx, qword ptr [r15 + 8] RIP 0x7ffff7ce3100 (g_main_context_iteration) ◂— push r12 ─────────────────────────────────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────────────────────────────────── ► 0x7ffff7ce3100 <g_main_context_iteration> push r12 ↓ 0x7ffff7ce3105 <g_main_context_iteration+5> push rbp 0x7ffff7ce3106 <g_main_context_iteration+6> mov rbp, rdi 0x7ffff7ce3109 <g_main_context_iteration+9> sub rsp, 8 0x7ffff7ce310d <g_main_context_iteration+13> test rdi, rdi
g_main_context_dispatch函数最后一次崩溃传参
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 Continuing. Thread 1 "qq" hit Breakpoint 2, 0x00007ffff7ce47a0 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0 ERROR: Could not find ELF base! LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ──────────────────────────────────────[ REGISTERS ]────────────────────────────────────── RAX 0x1 RBX 0x1 RCX 0xf0950bcdd20 ◂— 0x0 RDX 0x1 RDI 0xf094fee6dc0 ◂— 0x0 RSI 0x1 R8 0x0 R9 0x7fffffffd840 ◂— 0x3000000028 /* '(' */ R10 0x7ffff7fca080 R11 0x293 R12 0x3 R13 0xf094fee6dc0 ◂— 0x0 R14 0x7fffffffda10 ◂— 0x352 R15 0x2 RBP 0xf095048bf20 ◂— 0x100000021 /* '!' */ RSP 0x7fffffffd9d8 —▸ 0x7ffff7d38621 ◂— jmp 0x7ffff7d384c0 RIP 0x7ffff7ce47a0 (g_main_context_dispatch) ◂— push r15 ───────────────────────────────────────[ DISASM ]──────────────────────────────────────── ► 0x7ffff7ce47a0 <g_main_context_dispatch> push r15 ↓ 0x7ffff7ce47a4 <g_main_context_dispatch+4> mov r14, rdi 0x7ffff7ce47a7 <g_main_context_dispatch+7> push r13 0x7ffff7ce47a9 <g_main_context_dispatch+9> push r12 0x7ffff7ce47ab <g_main_context_dispatch+11> push rbp 0x7ffff7ce47ac <g_main_context_dispatch+12> push rbx 0x7ffff7ce47ad <g_main_context_dispatch+13> sub rsp, 0x68 0x7ffff7ce47b1 <g_main_context_dispatch+17> mov rax, qword ptr fs:[0x28] 0x7ffff7ce47ba <g_main_context_dispatch+26> mov qword ptr [rsp + 0x58], rax 0x7ffff7ce47bf <g_main_context_dispatch+31> xor eax, eax 0x7ffff7ce47c1 <g_main_context_dispatch+33> call g_mutex_lock <0x7ffff7d32250> ────────────────────────────────────────[ STACK ]──────────────────────────────────────── 00:0000│ rsp 0x7fffffffd9d8 —▸ 0x7ffff7d38621 ◂— jmp 0x7ffff7d384c0 01:0008│ 0x7fffffffd9e0 ◂— 0x352 02:0010│ 0x7fffffffd9e8 ◂— 0x249b1fe8 03:0018│ 0x7fffffffd9f0 ◂— 0x100000000 04:0020│ 0x7fffffffd9f8 —▸ 0x7ffff7cead90 (g_poll) ◂— mov esi, esi 05:0028│ 0x7fffffffda00 ◂— 0xaaaaaaaaaaaaaaaa 06:0030│ 0x7fffffffda08 ◂— 0x0 07:0038│ r14 0x7fffffffda10 ◂— 0x352 ──────────────────────────────────────[ BACKTRACE ]────────────────────────────────────── ► f 0 7ffff7ce47a0 g_main_context_dispatch f 1 7ffff7d38621 f 2 7ffff7ce3131 g_main_context_iteration+49 f 3 555556152012 f 4 55555617d0e5 f 5 5555561660ee f 6 555555f0f6f4 f 7 7ffff6f70152 __libc_start_main+242 ───────────────────────────────────────────────────────────────────────────────────────── pwndbg> Continuing. Thread 1 "qq" hit Breakpoint 2, 0x00007ffff7ce47a0 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0 ERROR: Could not find ELF base! LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ──────────────────────────────────────[ REGISTERS ]────────────────────────────────────── RAX 0x1 RBX 0x1 RCX 0x4 ;diff RDX 0x1 RDI 0xf094fee6dc0 ◂— 0x0 RSI 0x1 R8 0x0 R9 0x7fffffffd840 ◂— 0x3000000028 /* '(' */ R10 0x7ffff7fca080 R11 0x293 R12 0x3 R13 0xf094fee6dc0 ◂— 0x0 R14 0x7fffffffda10 ◂— 0x353 ; diff ++ R15 0x2 RBP 0xf095048bf20 ◂— 0x100000021 /* '!' */ RSP 0x7fffffffd9d8 —▸ 0x7ffff7d38621 ◂— jmp 0x7ffff7d384c0 RIP 0x7ffff7ce47a0 (g_main_context_dispatch) ◂— push r15 ───────────────────────────────────────[ DISASM ]──────────────────────────────────────── ► 0x7ffff7ce47a0 <g_main_context_dispatch> push r15 ↓ 0x7ffff7ce47a4 <g_main_context_dispatch+4> mov r14, rdi 0x7ffff7ce47a7 <g_main_context_dispatch+7> push r13 0x7ffff7ce47a9 <g_main_context_dispatch+9> push r12 0x7ffff7ce47ab <g_main_context_dispatch+11> push rbp 0x7ffff7ce47ac <g_main_context_dispatch+12> push rbx 0x7ffff7ce47ad <g_main_context_dispatch+13> sub rsp, 0x68 0x7ffff7ce47b1 <g_main_context_dispatch+17> mov rax, qword ptr fs:[0x28] 0x7ffff7ce47ba <g_main_context_dispatch+26> mov qword ptr [rsp + 0x58], rax 0x7ffff7ce47bf <g_main_context_dispatch+31> xor eax, eax 0x7ffff7ce47c1 <g_main_context_dispatch+33> call g_mutex_lock <0x7ffff7d32250> ────────────────────────────────────────[ STACK ]──────────────────────────────────────── 00:0000│ rsp 0x7fffffffd9d8 —▸ 0x7ffff7d38621 ◂— jmp 0x7ffff7d384c0 01:0008│ 0x7fffffffd9e0 ◂— 0x353 02:0010│ 0x7fffffffd9e8 ◂— 0x15108cf6 03:0018│ 0x7fffffffd9f0 ◂— 0x100000000 04:0020│ 0x7fffffffd9f8 —▸ 0x7ffff7cead90 (g_poll) ◂— mov esi, esi 05:0028│ 0x7fffffffda00 ◂— 0xaaaaaaaaaaaaaaaa 06:0030│ 0x7fffffffda08 ◂— 0x0 07:0038│ r14 0x7fffffffda10 ◂— 0x353 ──────────────────────────────────────[ BACKTRACE ]────────────────────────────────────── ► f 0 7ffff7ce47a0 g_main_context_dispatch f 1 7ffff7d38621 f 2 7ffff7ce3131 g_main_context_iteration+49 f 3 555556152012 f 4 55555617d0e5 f 5 5555561660ee f 6 555555f0f6f4 f 7 7ffff6f70152 __libc_start_main+242 ───────────────────────────────────────────────────────────────────────────────────────── pwndbg> Continuing. Thread 1 "qq" received signal SIGSEGV, Segmentation fault. 0x00007ffff7ce49e5 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0 ERROR: Could not find ELF base! LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ──────────────────────────────────────[ REGISTERS ]────────────────────────────────────── RAX 0x0 RBX 0x7ffff7000000 (____wcstof128_l_internal+1168) ◂— adc eax, 0x748b0000 RCX 0x7ffff7d42938 ◂— 0x6f5347007065656b /* 'keep' */ RDX 0x7ffff7e450a0 (__pthread_keys) ◂— 0x1 RDI 0xf09506b6740 ◂— 0xfffff0f400000002 RSI 0x7ffff7ce498d (g_main_context_dispatch+493) ◂— mov rdi, qword ptr [rsp + 0x18] R8 0xf094fee8520 ◂— 0x0 R9 0x7fffffffd850 ◂— 0x3000000028 /* '(' */ R10 0x7ffff7fca080 R11 0x286 R12 0x1 R13 0xf0950489980 ◂— 0x0 R14 0xf094fee6dc0 ◂— 0x0 R15 0x2 RBP 0xf0950b47d20 —▸ 0xf09506b6740 ◂— 0xfffff0f400000002 RSP 0x7fffffffd940 —▸ 0xf09506b6740 ◂— 0xfffff0f400000002 RIP 0x7ffff7ce49e5 (g_main_context_dispatch+581) ◂— call qword ptr [rbx + 8] ───────────────────────────────────────[ DISASM ]──────────────────────────────────────── ► 0x7ffff7ce49e5 <g_main_context_dispatch+581> call qword ptr [rbx + 8] rdi: 0xf09506b6740 ◂— 0xfffff0f400000002 rsi: 0x7ffff7ce498d (g_main_context_dispatch+493) ◂— mov rdi, qword ptr [rsp + 0x18] rdx: 0x7ffff7e450a0 (__pthread_keys) ◂— 0x1 rcx: 0x7ffff7d42938 ◂— 0x6f5347007065656b /* 'keep' */ 0x7ffff7ce49e8 <g_main_context_dispatch+584> mov rdi, r14 0x7ffff7ce49eb <g_main_context_dispatch+587> call g_mutex_lock <0x7ffff7d32250> 0x7ffff7ce49f1 <g_main_context_dispatch+593> mov edx, dword ptr [rsp + 0x2c] 0x7ffff7ce49f5 <g_main_context_dispatch+597> mov eax, dword ptr [rbp + 0x2c] 0x7ffff7ce49f8 <g_main_context_dispatch+600> test edx, edx 0x7ffff7ce49fa <g_main_context_dispatch+602> jne g_main_context_dispatch+610 <0x7ffff7ce4a02> 0x7ffff7ce49fc <g_main_context_dispatch+604> and eax, 0xfffffffd 0x7ffff7ce49ff <g_main_context_dispatch+607> mov dword ptr [rbp + 0x2c], eax 0x7ffff7ce4a02 <g_main_context_dispatch+610> and eax, 0x41 0x7ffff7ce4a05 <g_main_context_dispatch+613> cmp eax, 0x41 ────────────────────────────────────────[ STACK ]──────────────────────────────────────── 00:0000│ rsp 0x7fffffffd940 —▸ 0xf09506b6740 ◂— 0xfffff0f400000002 01:0008│ 0x7fffffffd948 ◂— 0x0 02:0010│ 0x7fffffffd950 —▸ 0x7ffff7d42938 ◂— 0x6f5347007065656b /* 'keep' */ 03:0018│ 0x7fffffffd958 ◂— 0xc646f4bc63 04:0020│ 0x7fffffffd960 —▸ 0x7ffff7d42760 ◂— '(unnamed)' 05:0028│ 0x7fffffffd968 ◂— 0x1 06:0030│ 0x7fffffffd970 ◂— 0x0 07:0038│ 0x7fffffffd978 —▸ 0x555555c44670 ◂— push rbp ──────────────────────────────────────[ BACKTRACE ]────────────────────────────────────── ► f 0 7ffff7ce49e5 g_main_context_dispatch+581 f 1 7ffff7d38621 f 2 7ffff7ce3131 g_main_context_iteration+49 f 3 555556152012 f 4 55555617d0e5 f 5 5555561660ee f 6 555555f0f6f4 f 7 7ffff6f70152 __libc_start_main+242 ─────────────────────────────────────────────────────────────────────────────────────────
0x527A0 + 581 == x529e5
其他线程漏洞 经过多线程调试, 找到bug2, 发生在Qnox_LogicThrea线程中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 pwndbg> Thread 5 "Qnox_LogicThrea" received signal SIGSEGV, Segmentation fault. 0x000055555621f539 in ?? () LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ───────────────────────────────────────────────[ REGISTERS ]──────────────────────────────────────────────── RAX 0xffffc39f73c44bb8 RBX 0x3c62263bf000 ◂— 0x0 RCX 0x55555621f500 ◂— push rbp RDX 0xf0 RDI 0x7ffff515f830 ◂— 0xaaaaaaaaaaaaaaaa RSI 0x3c622690f240 ◂— 0xffffc39f73c44bb8 R8 0x3c62264ca003 ◂— 0x0 R9 0x1 R10 0x7ffff7fca080 R11 0x286 R12 0x0 R13 0xaaaaaaaaaaaaaaaa R14 0x0 R15 0x3c62267d3000 —▸ 0x5555570c4350 —▸ 0x55555621d7d0 ◂— push rbp RBP 0x7ffff515f870 —▸ 0x7ffff515f930 —▸ 0x7ffff515fa10 —▸ 0x7ffff515fa60 —▸ 0x7ffff515fac0 ◂— ... RSP 0x7ffff515f6e0 ◂— 0x0 RIP 0x55555621f539 ◂— call qword ptr [rax + 0x30] ─────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────── ► 0x55555621f539 call qword ptr [rax + 0x30] 0x55555621f53c mov edi, 2 0x55555621f541 call 0x55555614f1b0 0x55555621f546 test al, al 0x55555621f548 je 0x55555621f5de 0x55555621f54e lea rsi, [rip - 0xb59197] 0x55555621f555 lea rdi, [rbp - 0x178] 0x55555621f55c mov edx, 0x107 0x55555621f561 mov ecx, 2 0x55555621f566 call 0x55555614f2a0 0x55555621f56b lea rdi, [rbp - 0x170]
可以看到, call qword ptr [rax + 0x30]指令中, rax对应的值为: 0xffffc39f73c44bb8
指令: 0x55555 621f539 - 0x55555 5554000 == 0xccb539
vmmap
1 2 3 4 5 6 0x555555554000 0x555555b69000 r--p 615000 0 /opt/tencent-qq/qq 0x555555b69000 0x5555570a6000 r-xp 153d000 614000 /opt/tencent-qq/qq 0x5555570a6000 0x55555710d000 r--p 67000 1b50000 /opt/tencent-qq/qq 0x55555710d000 0x555557119000 rw-p c000 1bb6000 /opt/tencent-qq/qq 0x555557119000 0x55555717a000 rw-p 61000 0 [heap]
在0xccb539处找到call qword ptr [rax+30h]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 0000000CCB500 ; __unwind { .text:0000000000CCB500 push rbp .text:0000000000CCB501 mov rbp, rsp .text:0000000000CCB504 push r15 .text:0000000000CCB506 push r14 .text:0000000000CCB508 push rbx .text:0000000000CCB509 sub rsp, 178h .text:0000000000CCB510 mov r15, rdi .text:0000000000CCB513 mov rax, fs:28h .text:0000000000CCB51C mov [rbp+var_20], rax .text:0000000000CCB520 movaps xmm0, cs:xmmword_122F40 .text:0000000000CCB527 movaps [rbp+var_40], xmm0 .text:0000000000CCB52B mov [rbp+var_30], 0AAAAAAAAh .text:0000000000CCB532 mov rax, [rsi] .text:0000000000CCB535 lea rdi, [rbp+var_40] .text:0000000000CCB539 call qword ptr [rax+30h] // vul .text:0000000000CCB53C mov edi, 2 .text:0000000000CCB541 call sub_BFB1B0 .text:0000000000CCB546 test al, al .text:0000000000CCB548 jz loc_CCB5DE .text:0000000000CCB54E lea rsi, aQnoxMsfMsfping ; "../../qnox/msf/msfping.cc" .text:0000000000CCB555 lea rdi, [rbp+var_178] .text:0000000000CCB55C mov edx, 107h .text:0000000000CCB561 mov ecx, 2 .text:0000000000CCB566 call sub_BFB2A0 .text:0000000000CCB56B lea rdi, [rbp+var_170] .text:0000000000CCB572 lea rsi, unk_19F568 .text:0000000000CCB579 mov edx, 11h .text:0000000000CCB57E call sub_66E360 .text:0000000000CCB583 mov r14, rax .text:0000000000CCB586 lea rbx, [rbp+var_190] .text:0000000000CCB58D lea rsi, [rbp+var_40] .text:0000000000CCB591 mov rdi, rbx .text:0000000000CCB594 call sub_1706710 .text:0000000000CCB599 movzx edx, [rbp+var_179] .text:0000000000CCB5A0 test dl, dl .text:0000000000CCB5A2 jns short loc_CCB5B2 .text:0000000000CCB5A4 mov rbx, [rbp+var_190] .text:0000000000CCB5AB mov rdx, [rbp+var_188] .text:0000000000CCB5B2 .text:0000000000CCB5B2 loc_CCB5B2: ; CODE XREF: vul2+A2↑j .text:0000000000CCB5B2 mov rdi, r14 .text:0000000000CCB5B5 mov rsi, rbx .text:0000000000CCB5B8 call sub_66E360 .text:0000000000CCB5BD cmp [rbp+var_179], 0 .text:0000000000CCB5C4 jns short loc_CCB5D2 .text:0000000000CCB5C6 mov rdi, [rbp+var_190] .text:0000000000CCB5CD call free .text:0000000000CCB5D2 .text:0000000000CCB5D2 loc_CCB5D2: ; CODE XREF: vul2+C4↑j .text:0000000000CCB5D2 lea rdi, [rbp+var_178] .text:0000000000CCB5D9 call sub_BFBB10 .text:0000000000CCB5DE .text:0000000000CCB5DE loc_CCB5DE: ; CODE XREF: vul2+48↑j .text:0000000000CCB5DE add dword ptr [r15+2Ch], 1 .text:0000000000CCB5E3 mov rdi, r15 .text:0000000000CCB5E6 call sub_CCA290 .text:0000000000CCB5EB lea rdi, [rbp+var_40] .text:0000000000CCB5EF call sub_B636B0 .text:0000000000CCB5F4 mov rax, fs:28h .text:0000000000CCB5FD cmp rax, [rbp+var_20] .text:0000000000CCB601 jnz short loc_CCB611 .text:0000000000CCB603 add rsp, 178h .text:0000000000CCB60A pop rbx .text:0000000000CCB60B pop r14 .text:0000000000CCB60D pop r15 .text:0000000000CCB60F pop rbp .text:0000000000CCB610 retn
漏洞2伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 unsigned __int64 __fastcall vul2 (__int64 a1, __int64 a2) { __int64 v2; __int64 *v3; __int64 v4; __int64 *v6; __int64 v7; unsigned __int8 v8; char v9; char v10; __int128 v11; int v12; unsigned __int64 v13; v13 = __readfsqword(0x28 u); v11 = xmmword_122F40; v12 = -1431655766 ; (*(void (__fastcall **)(__int128 *))(*(_QWORD *)a2 + 48LL ))(&v11); if ( sub_BFB1B0(2 ) ) { sub_BFB2A0((__int64)&v9, (__int64)"../../qnox/msf/msfping.cc" , 0x107 u, 2 ); v2 = sub_66E360(&v10, &unk_19F568, 17LL ); v3 = (__int64 *)&v6; sub_1706710(&v6, &v11); v4 = v8; if ( (v8 & 0x80 u) != 0 ) { v3 = v6; v4 = v7; } sub_66E360(v2, v3, v4); if ( (v8 & 0x80 u) != 0 ) free (v6); sub_BFBB10(&v9); } ++*(_DWORD *)(a1 + 44 ); sub_CCA290(a1); sub_B636B0(&v11); return __readfsqword(0x28 u); }
经过以上调试, 发现目前存在两个段错误漏洞, 应该是多线程处理对象时处理不当造成的, 望腾讯公司进行严格的代码审计与修复
Linux QQ 无用解决闪退的方法 解决方案1 删除掉配置文件即可
https://blog.csdn.net/qq_36462403/article/details/105902227
1 rm -r ~/.config/tencent-qq
经过测试, 无效
解决方案2 https://blog.csdn.net/weixin_33692284/article/details/91508019
经过测试,无效
其他知识补充 gtklib之主事件循环 https://www.cnblogs.com/silvermagic/p/9087881.html
介绍 GLib和GTK+应用的主事件循环管理着所有事件源。这些事件的来源有很多种比如文件描述符(文件、管道或套接字)或超时。新类型的事件源可以通过g_source_attach()函数添加。 为了让多组独立事件源能够在不同的线程中被处理,每个事件源都会关联一个 GMainContext 。一个线程只能运行一个GMainContext ,但是在其他线程中能够对事件源进行添加和删除操作。 每个事件源都被赋予了优先级。默认的优先级是G_PRIORITY_DEFAULT(0)。值越小优先级越高,优先级高的事件源优先处理。 Idle函数在没有更高优先级的事件被处理的时候才会执行。 GMainLoop 数据类型代表了一个主事件循环。通过g_main_loop_new()来创建 GMainLoop 对象。在添加完初始事件源后执行g_main_loop_run(),主循环将持续不断的检查每个事件源产生的新事件,然后分发它们,直到处理来自某个事件源的事件的时候触发了 g_main_loop_quit()调用退出主循环为止。 GMainLoop 实例能够被递归创建。在GTK+应用中经常使用这种方式来显示模态对话框。注意如果一个事件源被添加到一个 GMainContext ,那么它将被所有关联这个GMainContext 的主线程检查和分发。 GTK+对这些函数做了些封装,例如gtk_main、gtk_mian_quit和gtk_events_pending。
自定义事件类型 GMainLoop 一个不常用的特性就是能够创建一个新的事件源类型,然后当做内置事件源的扩展来使用。一个新的事件源类型通常用来处理GDK事件。通过继承GSource 结构来创建一个新的事件源类型。继承产生的新事件源类型表示GSource 结构作为新事件源类型的第一个元素然后其他元素紧跟其后。使用g_source_new 函数来创建新的事件源类型实例,函数的参数就是新的事件源类型大小。GSourceFuncs 决定新的事件源类型的行为。 新的事件源有两种基本方式与GMainContext 交互。它们GSourceFuncs 中的准备函数能够设置睡眠事件,用来决定主循环下次检测它们的时间。此外事件源也可以使用g_source_add_poll()函数添加文件描述符到 GMainContext 进行检测。
自定义主循环迭代 执行g_main_context_iteration()函数可以完成 GMainContext 的单次迭代。在一些情况下,我们可能想获取主循环更多的底层控制细节,我们可以调用**g_main_context_iteration()里的组件函数: g_main_context_prepare()、 g_main_context_prepare ()、 g_main_context_query()、 g_main_context_check()和 g_main_context_dispatch()**。
Main Context状态 在UNIX系统上,GLib的主循环和**fork()**是不兼容的。
事件源内存管理 有两种可选的方式来管理传递给GSource 回调函数用户数据的内存。用户数据就是在调用**g_timeout_add()、 g_timeout_add_full()、 g_idle_add()**传入的参数。这些数据通常被timeout或idle回调函数所拥有,比如一个构件或一个网路协议的实现。有些时候这些回调函数会在数据被销毁的后背调用,因为使用了已经被释放的内存,所以这会导致一个错误。
第一种推荐的方法就是保存g_timeout_add()、 g_source_attach()返回的事件源ID,然后在其维持的用户数据被释放后显示的将其从 GMainContext 移除。这样就能保证调用这些回调函数的时候,这些用户数据依然有效。
第二种就是保存这些回调函数中的用户数据对象的引用,然后在GDestroyNotify 回调函数中释放它。这样就能确保数据对象在事件源最后一次调用然后被释放前一直有效。GDestroyNotify 回调函数是GSource 函数的一个变体的入参,它在事件源被释放时调用。 第二条途径有必要提醒下,如果在事件源还没被调用前主循环就结束的情况下,用户数据对象被维持状态是不确定的。
官方文档 gtk库函数 参考:https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html
g_main_context_dispatch () 1 2 void g_main_context_dispatch (GMainContext *context);
Dispatches all pending sources.
You must have successfully acquired the context with g_main_context_acquire()
before you may call this function.
g_main_context_acquire () 1 2 gboolean g_main_context_acquire (GMainContext *context);
Tries to become the owner of the specified context. If some other thread is the owner of the context, returns FALSE
immediately. Ownership is properly recursive: the owner can require ownership again and will release ownership when g_main_context_release()
is called as many times as g_main_context_acquire()
.
You must be the owner of a context before you can call g_main_context_prepare()
, g_main_context_query()
, g_main_context_check()
, g_main_context_dispatch()
.
g_main_context_iteration () 1 2 3 gboolean g_main_context_iteration (GMainContext *context, gboolean may_block);
Runs a single iteration for the given main loop. This involves checking to see if any event sources are ready to be processed, then if no events sources are ready and may_block
is TRUE
, waiting for a source to become ready, then dispatching the highest priority events sources that are ready. Otherwise, if may_block
is FALSE
sources are not waited to become ready, only those highest priority events sources will be dispatched (if any), that are ready at this given moment without further waiting.
Note that even when may_block
is TRUE
, it is still possible for g_main_context_iteration()
to return FALSE
, since the wait may be interrupted for other reasons than an event source becoming ready.
Parameters
context
a GMainContext (if NULL
, the default context will be used).
[nullable]
may_block
whether the call may block.
Returns TRUE
if events were dispatched.
GMainContext 1 typedef struct _GMainContext GMainContext;
The GMainContext
struct is an opaque data type representing a set of sources to be handled in a main loop.