{"id":110490,"date":"2024-11-08T07:00:00","date_gmt":"2024-11-08T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=110490"},"modified":"2025-03-02T20:23:21","modified_gmt":"2025-03-03T04:23:21","slug":"20241108-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20241108-00\/?p=110490","title":{"rendered":"The case of a program that crashed on its first instruction"},"content":{"rendered":"<p>A customer was baffled by crash reports that indicated that their program was failing on its very first instruction.<\/p>\n<p>I opened one of the crash dumps, and it was so weird, the debugger couldn&#8217;t even say what went wrong.<\/p>\n<pre>ERROR: Unable to find system thread FFFFFFFF\r\nERROR: The thread being debugged has either exited or cannot be accessed\r\nERROR: Many commands will not work properly\r\nThis dump file has an exception of interest stored in it.\r\nThe stored exception information can be accessed via .ecxr.\r\nERROR: Exception C0000005 occurred on unknown thread FFFFFFFF\r\n(61c.ffffffff): Access violation - code c0000005 (first\/second chance not available)\r\n0:???&gt; r\r\nWARNING: The debugger does not have a current process or thread\r\nWARNING: Many commands will not work\r\n       ^ Illegal thread error in 'r'\r\n0:???&gt; .ecxr\r\nWARNING: The debugger does not have a current process or thread\r\nWARNING: Many commands will not work\r\n0:???&gt;\r\n<\/pre>\n<p>Let&#8217;s see what threads we have.<\/p>\n<pre>0:???&gt; ~\r\nWARNING: The debugger does not have a current process or thread\r\nWARNING: Many commands will not work\r\n   0  Id: 61c.12b4 Suspend: 1 Teb: 000000c7`9604d000 Unfrozen\r\n   1  Id: 61c.22d4 Suspend: 1 Teb: 000000c7`9604f000 Unfrozen\r\n   2  Id: 61c.1ab0 Suspend: 1 Teb: 000000c7`96051000 Unfrozen\r\n   3  Id: 61c.3308 Suspend: 1 Teb: 000000c7`96053000 Unfrozen\r\n   4  Id: 61c.2af0 Suspend: 1 Teb: 000000c7`96055000 Unfrozen\r\n   5  Id: 61c.2054 Suspend: 1 Teb: 000000c7`96059000 Unfrozen\r\n0:???&gt;\r\n<\/pre>\n<p>I wonder what those threads are doing.<\/p>\n<p>We&#8217;ll switch to each thread just to see what instruction they are at<\/p>\n<pre>0:???&gt; ~0s\r\nWARNING: The debugger does not have a current process or thread\r\nWARNING: Many commands will not work\r\nntdll!RtlUserThreadStart:\r\n00007ffa`bb16df50 4883ec78        sub     rsp,78h\r\n0:000&gt; ~*s\r\n         ^ Illegal thread error in '~*s'\r\n0:000&gt; ~1s\r\n00000293`42074058 66894340        mov     word ptr [rbx+40h],ax ds:00007ff6`e4600040=1f0e\r\n0:001&gt; ~2s\r\nntdll!ZwWaitForWorkViaWorkerFactory+0x14:\r\n00007ffa`bb1b29c4 c3              ret\r\n0:002&gt; ~3s\r\nntdll!ZwWaitForWorkViaWorkerFactory+0x14:\r\n00007ffa`bb1b29c4 c3              ret\r\n0:003&gt; ~4s\r\nntdll!ZwWaitForWorkViaWorkerFactory+0x14:\r\n00007ffa`bb1b29c4 c3              ret\r\n0:004&gt; ~5s\r\nntdll!ZwDelayExecution+0x14:\r\n00007ffa`bb1af3f4 c3              ret\r\n<\/pre>\n<p>The ostensible reason for the crash was an invalid write instruction, and only thread\u00a01 is doing a write. Let&#8217;s take a closer look at what it&#8217;s trying to write to.<\/p>\n<pre>0:001&gt; !address @rbx\r\n\r\nUsage:                  Image\r\nBase Address:           00007ff6`e4600000\r\nEnd Address:            00007ff6`e4601000\r\nRegion Size:            00000000`00001000 (   4.000 kB)\r\nState:                  00001000          MEM_COMMIT\r\nProtect:                00000002          PAGE_READONLY\r\nType:                   01000000          MEM_IMAGE\r\nAllocation Base:        00007ff6`e4600000\r\nAllocation Protect:     00000080          PAGE_EXECUTE_WRITECOPY\r\nImage Path:             C:\\Program Files\\Contoso\\ContosoDeluxe.exe\r\nModule Name:            ContosoDeluxe\r\nLoaded Image Name:      ContosoDeluxe.exe\r\nMapped Image Name:      C:\\Program Files\\Contoso\\ContosoDeluxe.exe\r\nMore info:              lmv m ContosoDeluxe\r\nMore info:              !lmi ContosoDeluxe\r\nMore info:              ln 0x7ff6e4600000\r\nMore info:              !dh 0x7ff6e4600000\r\n\r\nContent source: 2 (mapped), length: 400\r\n0:001&gt; ln @rbx\r\n(00000000`00000000)   ContosoDeluxe!__ImageBase\r\n<\/pre>\n<p>Okay, so we are writing to the mapped image header for ContosoDeluxe itself. This is a read-only page (<code>PAGE_<wbr \/>READ\u00adONLY<\/code>), which is why we take a write access violation.<\/p>\n<p>In fact, we&#8217;re writing into the image header, which is not something anybody normally does. This looks quite suspicious.<\/p>\n<p>If we ask for stacks, we get this:<\/p>\n<pre>0:001&gt; ~*k\r\n\r\n   0  Id: 61c.12b4 Suspend: 1 Teb: 000000c7`9604d000 Unfrozen\r\nChild-SP          RetAddr               Call Site\r\n000000c7`962ffd48 00000000`00000000     ntdll!RtlUserThreadStart\r\n\r\n   1  Id: 61c.22d4 Suspend: 1 Teb: 000000c7`9604f000 Unfrozen\r\nChild-SP          RetAddr               Call Site\r\n000000c7`963ff900 00007ff6`e4600000     0x00000293`42074058\r\n\r\n   2  Id: 61c.1ab0 Suspend: 1 Teb: 000000c7`96051000 Unfrozen\r\nChild-SP          RetAddr               Call Site\r\n000000c7`964ff718 00007ffa`bb145a0e     ntdll!ZwWaitForWorkViaWorkerFactory+0x14\r\n000000c7`964ff720 00007ffa`ba25244d     ntdll!TppWorkerThread+0x2ee\r\n000000c7`964ffa00 00007ffa`bb16df78     kernel32!BaseThreadInitThunk+0x1d\r\n000000c7`964ffa30 00000000`00000000     ntdll!RtlUserThreadStart+0x28\r\n\r\n   3  Id: 61c.3308 Suspend: 1 Teb: 000000c7`96053000 Unfrozen\r\nChild-SP          RetAddr               Call Site\r\n000000c7`965ff6a8 00007ffa`bb145a0e     ntdll!ZwWaitForWorkViaWorkerFactory+0x14\r\n000000c7`965ff6b0 00007ffa`ba25244d     ntdll!TppWorkerThread+0x2ee\r\n000000c7`965ff990 00007ffa`bb16df78     kernel32!BaseThreadInitThunk+0x1d\r\n000000c7`965ff9c0 00000000`00000000     ntdll!RtlUserThreadStart+0x28\r\n\r\n   4  Id: 61c.2af0 Suspend: 1 Teb: 000000c7`96055000 Unfrozen\r\nChild-SP          RetAddr               Call Site\r\n000000c7`966ffad8 00007ffa`bb145a0e     ntdll!ZwWaitForWorkViaWorkerFactory+0x14\r\n000000c7`966ffae0 00007ffa`ba25244d     ntdll!TppWorkerThread+0x2ee\r\n000000c7`966ffdc0 00007ffa`bb16df78     kernel32!BaseThreadInitThunk+0x1d\r\n000000c7`966ffdf0 00000000`00000000     ntdll!RtlUserThreadStart+0x28\r\n\r\n   5  Id: 61c.2054 Suspend: 1 Teb: 000000c7`96059000 Unfrozen\r\nChild-SP          RetAddr               Call Site\r\n000000c7`968ffcb8 00007ffa`bb165833     ntdll!ZwDelayExecution+0x14\r\n000000c7`968ffcc0 00007ffa`b88f9fcd     ntdll!RtlDelayExecution+0x43\r\n000000c7`968ffcf0 00000293`420a1efd     KERNELBASE!SleepEx+0x7d\r\n000000c7`968ffd70 00000000`00000000     0x00000293`420a1efd\r\n<\/pre>\n<p>Thread\u00a01 is the suspicious thread that committed the access violation.<\/p>\n<p>There&#8217;s another suspicious thread, thread\u00a05, which is in a <code>SleepEx<\/code> call called from the same suspicious source <code>0x00000293`420xxxxx<\/code>. This other thread is probably waiting for something to happen, so let&#8217;s take a look at it.<\/p>\n<p>First, let&#8217;s see what kind of memory we are executing from.<\/p>\n<pre>0:001&gt; !address 00000293`420a1ee0\r\n\r\nUsage:                  &lt;unknown&gt;\r\nBase Address:           00000293`420a0000\r\nEnd Address:            00000293`420ca000\r\nRegion Size:            00000000`0002a000 ( 168.000 kB)\r\nState:                  00001000          MEM_COMMIT\r\nProtect:                00000040          PAGE_EXECUTE_READWRITE\r\nType:                   00020000          MEM_PRIVATE\r\nAllocation Base:        00000293`420a0000\r\nAllocation Protect:     00000040          PAGE_EXECUTE_READWRITE\r\n<\/pre>\n<p>Yikes, <code>PAGE_<wbr \/>EXECUTE_<wbr \/>READ\u00adWRITE<\/code>. That&#8217;s not a good sign. That smells like malicious code injection, because it is highly unusual for normal code to be read-write. But let&#8217;s hold out hope that maybe there&#8217;s a legitimate explanation for all of this, and it&#8217;s just a matter of finding it.<\/p>\n<p>Let&#8217;s see what code we are executing.<\/p>\n<pre>00000293`420a1ed9 add     rsp,30h\r\n00000293`420a1edd pop     rdi\r\n00000293`420a1ede ret\r\n00000293`420a1edf int     3\r\n00000293`420a1ee0 push    rbx\r\n00000293`420a1ee2 sub     rsp,20h\r\n00000293`420a1ee6 call    00000293`420a13e0\r\n00000293`420a1eeb mov     qword ptr [00000293`420c0c78],rax\r\n00000293`420a1ef2 mov     ecx,3E8h\r\n00000293`420a1ef7 call    qword ptr [00000293`420b4028]\r\n                  ^^^^^^^^ YOU ARE HERE\r\n00000293`420a1efd call    00000293`420a13e0 \/\/ do it again\r\n00000293`420a1f02 mov     rdx,rax\r\n00000293`420a1f05 mov     rbx,rax\r\n00000293`420a1f08 call    00000293`420a19d0\r\n00000293`420a1f0d test    eax,eax\r\n00000293`420a1f0f jne     00000293`420a1f22\r\n00000293`420a1f11 mov     rax,qword ptr [00000293`420c0c78]\r\n00000293`420a1f18 mov     qword ptr [00000293`420c0c78],rbx\r\n00000293`420a1f1f mov     rbx,rax\r\n00000293`420a1f22 mov     rcx,rbx\r\n00000293`420a1f25 call    00000293`420a17f0\r\n00000293`420a1f2a jmp     00000293`420a1ef2\r\n<\/pre>\n<p>The first few instructions, up to the <code>int 3<\/code> appear to be the end of the previous function, so we can start our analysis at the <code>push rbx<\/code>.<\/p>\n<pre>    push rbx                        ; preserve register\r\n    sub rsp, 20h                    ; stack frame\r\n    call 00000293`420a13e0          ; mystery function 1\r\n    mov  [00000293`420c0c78],rax    ; save answer in global\r\n\r\n00000293`420a1ef2:\r\n    mov  ecx, 3E8h                  ; decimal 1000\r\n    call [00000293`420b4028]        ; mystery function 2\r\n    ^^^^^^^^ YOU ARE HERE\r\n\r\n    call 00000293`420a13e0          ; mystery function 1\r\n    mov  rdx, rax                   ; return value becomes param1\r\n    mov  rbx, rax                   ; save return value in rbx\r\n    call 00000293`420a19d0          ; mystery function 3\r\n    test eax,eax                    ; Q: did it succeed?\r\n    jne  00000293`420a1f22          ; N: Skip\r\n    mov  rax, [00000293`420c0c78]   ; get previous value\r\n    mov  [00000293`420c0c78], rbx   ; replace with new value\r\n    mov  rbx, rax                   ; save previous value in rbx\r\n\r\n00000293`420a1f22:\r\n    mov   rcx, rbx                  ; rcx = updated value in rbx\r\n    call    00000293`420a17f0       ; mystery function 3\r\n    jmp     00000293`420a1ef2       ; loop back forever\r\n<\/pre>\n<p>One thing that&#8217;s apparent here is that this thread never exits. It&#8217;s an infinite loop.<\/p>\n<p>First, let&#8217;s see if we can identify the mystery functions.<\/p>\n<p>The easiest is probably mystery function\u00a02, since it looks like a call to an imported function.<\/p>\n<pre>0:001&gt; dps 00000293`420b4028 L1\r\n00000293`420b4028  00007ffa`ba258370 kernel32!SleepStub\r\n<\/pre>\n<p>Aha, mystery function\u00a02 is <code>Sleep<\/code>, and the call is a <code>Sleep(1000)<\/code>. Which we sort of knew from the stack trace but it&#8217;s nice to see confirmation.<\/p>\n<p>But let&#8217;s look around near that address, since that may be <a title=\"Any sufficiently advanced uninstaller is indistinguishable from malware\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230911-00\/?p=108749\"> part of a larger table of function pointers<\/a>.<\/p>\n<pre>00000293`420b4000  00007ffa`baa59810 advapi32!RegCloseKeyStub\r\n00000293`420b4008  00007ffa`baa596e0 advapi32!RegQueryInfoKeyWStub\r\n00000293`420b4010  00007ffa`baa595a0 advapi32!RegOpenKeyExWStub \r\n00000293`420b4018  00007ffa`baa5ab30 advapi32!RegEnumValueWStub\r\n00000293`420b4020  00000000`00000000\r\n00000293`420b4028  00007ffa`ba258370 kernel32!SleepStub\r\n00000293`420b4030  00007ffa`ba250cc0 kernel32!GetLastErrorStub\r\n00000293`420b4038  00007ffa`ba266b60 kernel32!lstrcatW\r\n00000293`420b4040  00007ffa`ba25ff00 kernel32!CloseHandle\r\n00000293`420b4048  00007ffa`ba254380 kernel32!CreateThreadStub\r\n<\/pre>\n<p>Bingo, this appears to be a table of imported function pointers.<\/p>\n<p>Mystery function 1 seems to be called to start things off, and then again in a loop, so it seems kind of important. Let&#8217;s see what it is.<\/p>\n<pre>00000293`420a13e0 mov     qword ptr [rsp+8],rbx\r\n00000293`420a13e5 mov     qword ptr [rsp+10h],rsi\r\n00000293`420a13ea mov     qword ptr [rsp+18h],rdi\r\n00000293`420a13ef push    rbp\r\n00000293`420a13f0 mov     rbp,rsp\r\n00000293`420a13f3 sub     rsp,80h\r\n00000293`420a13fa mov     rax,qword ptr [00000293`420bf010]\r\n00000293`420a1401 xor     rax,rsp\r\n00000293`420a1404 mov     qword ptr [rbp-8],rax\r\n00000293`420a1408 mov     ecx,40h\r\n00000293`420a140d call    00000293`420a8478 \/\/ mystery function 3\r\n<\/pre>\n<p>This looks like a typical C function, not hand-coded assembly. After saving non-volatile registers, it builds a stack frame, and the <code>mov rax, [global]<\/code> followed by a <code>xor rax, rsp<\/code> looks a lot like a <tt>\/GS<\/tt> stack canary.<\/p>\n<p>So at least it&#8217;s nice that this rogue code was compiled with stack buffer overflow protection. Can&#8217;t be too careful.<\/p>\n<p>Let&#8217;s look at mystery function\u00a03.<\/p>\n<pre>00000293`420a8478\r\n    push rbx\r\n    sub  rsp, 20h\r\n    mov  rbx, rcx\r\n    jmp  00000293`420a8492\r\n\r\n00000293`420a8483\r\n    mov  rcx, rbx\r\n    call 00000293`420aad50\r\n    test eax, eax\r\n    je   00000293`420a84a2\r\n    mov  rcx, rbx\r\n\r\n00000293`420a8492\r\n    call 00000293`420aadb4\r\n    test rax, rax\r\n    je   00000293`420a8483\r\n    add  rsp, 20h\r\n    pop  rbx\r\n    ret\r\n\r\n00000293`420a84a2\r\n    cmp  rbx, 0FFFFFFFFFFFFFFFFh\r\n    je   00000293`420a84ae\r\n\r\n    call 00000293`420a8c80\r\n    int  3\r\n\r\n00000293`420a84ae\r\n    call 00000293`420a8ca0\r\n    int  3\r\n\r\n00000293`420a84b4\r\n    jmp  00000293`420a8478\r\n<\/pre>\n<p>This reverse-compiles to<\/p>\n<pre>uint64_t something(uint64_t value)\r\n{\r\n    uint64_t p;\r\n    while ((p = func00000293420aadb4(value)) == 0) {\r\n        if (!func00000293420aad50(value)) {\r\n            if (value == ~0ULL) {\r\n                func00000293420a8ca0();\r\n            } else {\r\n                func00000293420a8c80();\r\n            }\r\n            \/\/ NOTREACHED\r\n        }\r\n    }\r\n    return p;\r\n}\r\n<\/pre>\n<p>This seems to call a function at <code>func00000293420aadb4<\/code> repeatedly.<\/p>\n<pre>00000293`420aadb4 jmp     00000293`420acf8c\r\n<\/pre>\n<p>This appears to be an incremental linking thunk. So whatever this is, it looks like it was compiled in debug mode.<\/p>\n<pre>00000293`420acf8c\r\n    push rbx\r\n    sub  rsp, 20h\r\n    mov  rbx,rcx\r\n    cmp  rcx, 0FFFFFFFFFFFFFFE0h\r\n    ja   00000293`420acfd7\r\n    test rcx, rcx\r\n    mov  eax, 1\r\n    cmove rbx, rax\r\n    jmp  00000293`420acfbe\r\n\r\n00000293`420acfa9\r\n    call 00000293`420b02c0\r\n    test eax, eax\r\n    je   00000293`420acfd7\r\n    mov  rcx, rbx\r\n    call 00000293`420aad50\r\n    test eax, eax\r\n    je   00000293`420acfd7\r\n\r\n00000293`420acfbe \r\n    mov  rcx, [00000293`420c07f8]\r\n    mov  r8, rbx\r\n    xor  edx, edx\r\n    call [00000293`420b4298]\r\n    test rax, rax\r\n    je   00000293`420acfa9\r\n    jmp  00000293`420acfe4\r\n\r\n00000293`420acfd7\r\n    call  00000293`420ac71c\r\n    mov   [rax], 0Ch\r\n    xor   eax, eax\r\n    add   rsp, 20h\r\n    pop   rbx\r\n    ret\r\n<\/pre>\n<p>The initial comparison against <code>0xFFFFFFFF`FFFFFFFE<\/code> makes me suspect that this is <code>malloc()<\/code> or <code>operator new<\/code> because those functions begin with a check for an excessive allocation size, to avoid integer overflow.<\/p>\n<p>And indeed, that&#8217;s basically what this function is, as revealed by the indirect function call:<\/p>\n<pre>0:005&gt; dps 00000293`420b4298 L1\r\n00000293`420b4298  00007ffa`bb14cca0 ntdll!RtlAllocateHeap\r\n<\/pre>\n<p>Okay, so we found <code>malloc()<\/code> or <code>operator new<\/code>.<\/p>\n<p>This will help us understand mystery function 1 a lot better.<\/p>\n<pre>00000293`420a13e0\r\n    mov     [rsp+8], rbx\r\n    mov     [rsp+10h], rsi\r\n    mov     [rsp+18h], rdi\r\n    push    rbp\r\n    mov     rbp, rsp\r\n    sub     rsp, 80h\r\n    mov     rax, [00000293`420bf010]\r\n    xor     rax, rsp\r\n    mov     [rbp-8], rax      ; \/GS canary\r\n    mov     ecx, 40h\r\n    call    00000293`420a8478 ; allocate 64 bytes\r\n    xorps   xmm0, xmm0\r\n    mov     ecx, 18h\r\n    mov     rdi,rax           ; save first allocation\r\n    movups  [rax],xmm0        ; zero out first allocation\r\n    movups  [rax+10h],xmm0\r\n    movups  [rax+20h],xmm0\r\n    movups  [rax+30h],xmm0\r\n    call    00000293`420a8478 ; allocate 24 bytes\r\n    xor     esi,esi\r\n    mov     ecx, 80h\r\n    mov     rbx,rax           ; save second allocation\r\n    mov     [rax+0Ch], rsi    ; zero out second allocation\r\n    mov     [rax+14h], esi\r\n    mov     [rax], esi\r\n    mov     [rax+4], 10h\r\n    mov     [rax+8], 1\r\n    call    00000293`420a84b4 ; mystery function 4\r\n    mov     [rbx+10h], rax    ; save result\r\n    lea     ecx, [rsi+10h]    ; ecx = 0x10\r\n    mov     [rdi], rbx\r\n    call    00000293`420a8478 ; third allocation\r\n    lea     ecx, [rsi+40h]    ; ecx = 0x40\r\n    mov     rbx, rax\r\n    mov     [rax+8], rsi      ; initialize third allocation\r\n    mov     [rax], esi\r\n    mov     [rax+4], 10h\r\n    call    00000293`420a84b4 ; mystery function 4\r\n    mov     [rbx+8], rax\r\n    lea     ecx, [rsi+18h]    ; ecx = 0x18\r\n<\/pre>\n<p>Okay, so this function starts by allocating many memory blocks and initializing them.<\/p>\n<p>Let&#8217;s skip ahead to where it finally does something interesting.<\/p>\n<pre>    lea     rdx, [00000293`420bba90] ; LR\"(SOFTWARE\\systemconfig)\"\r\n    lea     rax, [rbp-50h]\r\n    mov     [rdi+38h], rbx\r\n    mov     r9d, 20119h       ; KEY_READ\r\n    mov     [rsp+20h], rax\r\n    xor     r8d, r8d\r\n    mov     rcx,0FFFFFFFF80000002h ; HKEY_LOCAL_MACHINE\r\n    call    qword ptr [00000293`420b4010] ; RegOpenKeyExW\r\n    test    eax, eax\r\n<\/pre>\n<p>A <code>dps 00000293`420b4010<\/code> reveals that the function pointer is <code>Reg\u00adOpen\u00adKey\u00adExW<\/code>, so the entire function call must have been<\/p>\n<pre>RegOpenKeyExW(HKEY_LOCAL_MACHINE,\r\n    L\"SOFTWARE\\\\systemconfig\", 0, KEY_READ, &amp;key);\r\n<\/pre>\n<p>Further disassembly shows that if the code successfully opens the key, it tries to read some values from it. My guess is that <code>system\u00adconfig<\/code> is where the code stores its state.<\/p>\n<p>Okay, so maybe I can speed things up by dumping strings and seeing if there&#8217;s anything that will give me a clue about the identity of this code. Recall that the <code>!address<\/code> command told us that the memory block was<\/p>\n<pre>0:001&gt; !address 00000293`420a1ee0\r\nBase Address:           00000293`420a0000\r\nEnd Address:            00000293`420ca000\r\n<\/pre>\n<p>We&#8217;ll ask <a title=\"MEX Debugging Extension for WinDbg\" href=\"https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=53304\"> the <tt>!mex<\/tt> debugger extension<\/a> to find any strings in the memory block.<\/p>\n<pre>0:005&gt; !mex.strings 00000293`420a0000 00000293`420ca000\r\n...\r\n00000293420bbd10 system\r\n00000293420bc1d4 H:\\rootkit\\r77-rootkit-master\\vs\\x64\\Release\\r77-x64.pdb\r\n<\/pre>\n<p>Okay, so I guess it&#8217;s malware, or at least self-identifies as a rootkit. And, hey, an Internet search for this rootkit name shows that its source code is public.<\/p>\n<p>The good news for the developer is that the problem is not their fault. The bad news is that since the crash dumps are submitted anonymously, they have no way of contacting the users to tell them that they have been infected with malware.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Didn&#8217;t even make it out of the gate.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-110490","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Didn&#8217;t even make it out of the gate.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110490","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=110490"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110490\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=110490"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=110490"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=110490"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}