[ntp:security] [Bug 527] ntpd frequently crashes on Windows systems

bugzilla at ntp.isc.org bugzilla at ntp.isc.org
Mon Nov 21 02:05:12 PST 2005


Additional Comments From martin.burnicki at meinberg.de (Martin Burnicki)
Submitted on 2005-11-21 10:05
Heiko has told me that you've managed to build the test program "ntpload" under 
Did you also manage to reproduce the bug, i.e, do you see ntpd trapping if you 
run ntpload against it? 
I've tried to do some more tests and want to let you know what I've observed.  
The existing code is: 
if (lpo != NULL) 
  HeapFree(hHeapHandle, 0, lpo); 
In the debugger the disassembled code looks like this: 
390:          HeapFree(hHeapHandle, 0, lpo); 
00401C6A 8B F4                mov         esi,esp 
00401C6C 8B 45 0C             mov         eax,dword ptr [ebp+0Ch] 
00401C6F 50                   push        eax 
00401C70 6A 00                push        0 
00401C72 8B 0D C0 08 48 00    mov         ecx,dword ptr [hHeapHandle 
00401C78 51                   push        ecx 
00401C79 FF 15 E4 46 4D 00    call        dword ptr [__imp__HeapFree at 12 
00401C7F 3B F4                cmp         esi,esp 
00401C81 E8 4C 75 04 00       call        _chkesp (004491d2) 
If I step normally through the code then the call above goes into the HeapFree 
function, the address which has been stored in the __imp__HeapFree at 12 variable 
at program load time. At the beginning of the HeapFree function (which is at 
address 0x7c92043d here) the ESP and EBP register hold the following values: 
  ESP: 0xBBFEB8 
  EBP: 0xBBFF0C 
If ntpd runs into the trap then one of the addresses in the stack trace is 
0xBBFF0C (see the initial report). That means the CPU tries to execute bytes on 
the stack, which does not represent meaningful code and thus leads to the trap. 
Interestingly, while I've been playing around to find out more I've called the 
HeapFree function via another function pointer: 
/* Clear the heap */ 
if (lpo != NULL) 
  BOOL (WINAPI *HeapFreeFnc)(HANDLE hHeap,DWORD dwFlags, LPVOID lpMem)  
    = HeapFree; 
  HeapFreeFnc(hHeapHandle, 0, lpo); 
The resulting code is: 
389:      if (lpo != NULL) 
00401C64 83 7D 0C 00          cmp         dword ptr [ebp+0Ch],0 
00401C68 74 21                je          OnWriteComplete+5Bh (00401c8b) 
390:      { 
391:          BOOL (WINAPI *HeapFreeFnc)(HANDLE hHeap,DWORD dwFlags,  
                    LPVOID lpMem) = HeapFree; 
00401C6A A1 E4 46 4D 00       mov         eax,[__imp__HeapFree at 12 (004d46e4)] 
00401C6F 89 45 F8             mov         dword ptr [HeapFreeFnc],eax 
392:          HeapFreeFnc(hHeapHandle, 0, lpo); 
00401C72 8B F4                mov         esi,esp 
00401C74 8B 4D 0C             mov         ecx,dword ptr [ebp+0Ch] 
00401C77 51                   push        ecx 
00401C78 6A 00                push        0 
00401C7A 8B 15 C0 08 48 00    mov         edx,dword ptr [hHeapHandle 
00401C80 52                   push        edx 
00401C81 FF 55 F8             call        dword ptr [HeapFreeFnc] 
00401C84 3B F4                cmp         esi,esp 
00401C86 E8 47 75 04 00       call        _chkesp (004491d2) 
393:      } 
I've run ntpd with this modification for more than 30 minutes with more than 
20000 req/sec by ntpload, while the original code on the same system traps 
after 1 or 2 seconds.  
I know that this should not make a difference if everything works as it should, 
but in fact it behaves differently. 
In the code above the function pointer is a local variable which is also 
located on the stack, so the stack layout is different from the original code. 
Everytime HeapFree is to be called its address is copied from 
__imp__HeapFree at 12 to HeapFreeFnc first, then the function is called indirectly 
via HeapFreeFunc. Since this works OK, the original function address saved in 
__imp__HeapFree at 12 does not seem to be overwritten by some bogus code, what I 
first thought it could have been. 
If I declare the function pointer as static, however, it is *not* located on 
the stack and the program traps just as with the original code. 
Hm, I'm not quite sure which conclusion I should draw. It looks like the stack 
is messed up since the function address is still valid, but execution continues 
on the stack, i.e. a return address on the stack may have been overwritten.  
If you have any additional thoughts, please let me know. 

Martin Burnicki <martin.burnicki at meinberg.de>

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.

More information about the security mailing list