3

编辑:

我进行了更多调查,下面报告的问题似乎仅在我使用 Visual Studio 2017 暂停该过程时才会发生。似乎当 rip 指向一个无效位置时,它总是从正确的指令开始偏移 +1 个字节。

此外,就上下文而言,这是一个包含大量 dll 的大型 C++ 项目,其中一些使用 MSVC 2015 编译,其余使用 icc(英特尔编译器 2017)。这是在使用 boost C++/python 绑定的 python 进程中运行的。

原帖:

我正在随机暂停我的程序,以查看在一些繁重的计算过程中我的线程在做什么。请注意,我不是在调试崩溃,而是恢复程序正常工作。

但是 VS 调试器有时无法反汇编机器代码。例如,在 rip=000007FE8B048EE2 的一个线程上,它显示如下:

000007FE8B048EDE  ?? ?? 
000007FE8B048EDF  ?? ?? 
000007FE8B048EE0  ?? ?? 
000007FE8B048EE1  ?? ?? 
                    }

                    if (params.derandomize) {
000007FE8B048EE2  adc         ebp,eax  
                        GetRNG().Seed(id);
000007FE8B048EE4  pop         rax  
000007FE8B048EE5  wait  
000007FE8B048EE6  adc         byte ptr [rax],al  
000007FE8B048EE8  mov         rcx,rax  

解码后的 x86 指令似乎也错误(adc、pop、wait、adc ??),所以我也尝试附加 WinDBG(非侵入模式):

0:019> u rip
somedll!<lambda239>::operator()+0x132:
000007fe`8b048ee2 13e8            adc     ebp,eax
000007fe`8b048ee4 58              pop     rax
000007fe`8b048ee5 9b              wait
000007fe`8b048ee6 1000            adc     byte ptr [rax],al
000007fe`8b048ee8 4889c1          mov     rcx,rax
000007fe`8b048eeb 8b9570080000    mov     edx,dword ptr [rbp+870h]
000007fe`8b048ef1 e8fa911000      call    somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)
000007fe`8b048ef6 4c8ba5b0080000  mov     r12,qword ptr [rbp+8B0h]

好吧,它是同样的垃圾......但后来我尝试从略高于 rip 的地址进行反汇编:

0:019> u rip-30
somedll!<lambda239>::operator()+0x102:
000007fe`8b048eb2 00488b          add     byte ptr [rax-75h],cl
000007fe`8b048eb5 084863          or      byte ptr [rax+63h],cl
000007fe`8b048eb8 81d003000048    adc     eax,48000003h
000007fe`8b048ebe 83f8ff          cmp     eax,0FFFFFFFFh
000007fe`8b048ec1 740a            je      somedll!<lambda239>::operator()+0x11d (000007fe`8b048ecd)
000007fe`8b048ec3 4889c2          mov     rdx,rax
000007fe`8b048ec6 48899570080000  mov     qword ptr [rbp+870h],rdx
000007fe`8b048ecd 486381e0030000  movsxd  rax,dword ptr [rcx+3E0h]
0:019> u
somedll!<lambda239>::operator()+0x124:
000007fe`8b048ed4 483bd0          cmp     rdx,rax
000007fe`8b048ed7 7501            jne     somedll!<lambda239>::operator()+0x12a (000007fe`8b048eda)
000007fe`8b048ed9 cc              int     3
000007fe`8b048eda 80b96303000000  cmp     byte ptr [rcx+363h],0
000007fe`8b048ee1 7413            je      somedll!<lambda239>::operator()+0x146 (000007fe`8b048ef6)
000007fe`8b048ee3 e8589b1000      call    somedll!bla::bla::blabla::GetRNG (000007fe`8b152a40)
000007fe`8b048ee8 4889c1          mov     rcx,rax
000007fe`8b048eeb 8b9570080000    mov     edx,dword ptr [rbp+870h]
0:019> u
somedll!<lambda239>::operator()+0x141:
000007fe`8b048ef1 e8fa911000      call    somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)
000007fe`8b048ef6 4c8ba5b0080000  mov     r12,qword ptr [rbp+8B0h]
000007fe`8b048efd 488d95f0070000  lea     rdx,[rbp+7F0h]
000007fe`8b048f04 488d8dc0070000  lea     rcx,[rbp+7C0h]
000007fe`8b048f0b 498b0424        mov     rax,qword ptr [r12]
000007fe`8b048f0f 4c8da570080000  lea     r12,[rbp+870h]
000007fe`8b048f16 488942d0        mov     qword ptr [rdx-30h],rax
000007fe`8b048f1a 4c8962d8        mov     qword ptr [rdx-28h],r12

第一条指令在 000007fe`8b048eb2 处“添加字节 ptr”和“或字节 ptr”没有意义,因为 rip-30 可能位于指令中间,但在它似乎重新同步后,因为它对应于源代码:

if (id == params.dbgbreak_id) {
    __debugbreak();
}

if (params.derandomize) {
    GetRNG().Seed(id);
}

000007fe`8b048ecd 486381e0030000  movsxd  rax,dword ptr [rcx+3E0h]
000007fe`8b048ed4 483bd0          cmp     rdx,rax                  // if (id == params.dbgbreak_id) {
000007fe`8b048ed7 7501            jne     somedll!<lambda239>::operator()+0x12a (000007fe`8b048eda)
000007fe`8b048ed9 cc              int     3                        // __debugbreak(); }
000007fe`8b048eda 80b96303000000  cmp     byte ptr [rcx+363h],0    // if (params.derandomize)
000007fe`8b048ee1 7413            je      somedll!<lambda239>::operator()+0x146 (000007fe`8b048ef6)
000007fe`8b048ee3 e8589b1000      call    somedll!bla::bla::blabla::GetRNG (000007fe`8b152a40)
000007fe`8b048ee8 4889c1          mov     rcx,rax
000007fe`8b048eeb 8b9570080000    mov     edx,dword ptr [rbp+870h]
000007fe`8b048ef1 e8fa911000      call    somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)

显然没有从 000007fe8b048ee2 开始的指令!000007fe8b048ee1 有 je,拨打 000007fe8b048ee3

所以......我想,嗯,调试器中有一个错误......让我们检查一下寄存器:

0:019> r
rax=ffffffffffffffff rbx=000000000021d420 rcx=000000000021d5d0
rdx=0000000002696568 rsi=0000000000005d38 rdi=0000000056eefc40
rip=000007fe8b048ee2 rsp=0000000056eef5b0 rbp=0000000056eef5e0
 r8=0000000000000006  r9=000000000021d0b8 r10=0000000006456570
r11=0000000000000006 r12=0000000056eefe50 r13=00000000069a8820
r14=000000000021d1a8 r15=0000000056eefe60
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246

什么??撕裂=000007fe8b048ee2 ?? 这怎么可能?

它解释了为什么调试器显示垃圾:它试图从 rip 开始反汇编,但 rip 指向指令的中间。但是为什么报告的撕裂是错误的?操作系统是罪魁祸首吗?我错过了什么吗?

4

0 回答 0