ПереZагруZка

Тема в разделе "WASM.WIN32", создана пользователем kero, 12 дек 2009.

  1. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Дело было на XP...
    На днях прикидывал пути решения регулярной на форумах задачки: скрытный (в смысле - скрыв окна) запуск приложения.
    И один из вариантов с WH_CBT преподнес сюрприз, отмеченный мнемоникой в заголовке.

    Суть в том, что совершенно легальные действия по изменению Z-order
    после нажатия стандартного сочетания Win+D или соответствующей кнопки на Quick Launch
    приводят к немедленной перезагрузке с извещением о серьезной ошибке...

    В аттаче - минимальный рабочий пример (+ исходник): обычный шаблон создания простого окна,
    только перед вызовом CreateWindowEx - в своем потоке ставим хук WH_CBT,
    на HCBT_CREATEWND устанавливаем наше окно в самый низ Z-order, и затем хук снимаем. Вот и все.
    Полученное окно спрятано за "рабочий стол", поэтому на таскбаре оставлена кнопка, контроля ради.

    Ну, и теперь - Win+D !

    P.S.
    Проверил только на XP-pro-sp2, и, конечно, очень интересует, как там на других WinOS? Не поленитесь, дайте знать.
     
  2. CyberManiac

    CyberManiac New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2003
    Сообщения:
    2.473
    Адрес:
    Russia
    Win7x64 благополучно ушла в синьку. В Микрософт должны быть в восторге :)
     
  3. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Привет CyberManiac-у!
    Спасибо за инфу по 7 :)
     
  4. sometime

    sometime Odessa

    Публикаций:
    0
    Регистрация:
    22 апр 2009
    Сообщения:
    227
    Адрес:
    sunday
    Vista SP2 x86 - зависла)
     
  5. AntiB

    AntiB New Member

    Публикаций:
    0
    Регистрация:
    23 мар 2007
    Сообщения:
    393
    Win7 x32 RC1 7100 валится спать в бсод :lol:
     
  6. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    sometime, AntiB
    Спасибо, что не поленились :)
     
  7. mansurv

    mansurv New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2009
    Сообщения:
    38
    Windows 2000 SP4, XP SP3, XP x64, 7 RTM x32, все виртуальные и все валятся в бсод!
     
  8. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    Не все уязвимости эксплуатируемы (не все что катится, то круглое.. даже дополнить по смыслу).
    Но ошибка очень интересна. Браво kero.
     
  9. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Спасибо, братцы, за внимание! :)

    А кстати, сначала и хотел обозвать заметку именно "Z-уязвимость", но потом решил, что не так поймут :)
     
  10. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Вариация:

    1) SetWindowsHookEx(WH_CBT,offset HookProc,0,(GetCurrentThreadId))
    - заменено на
    SetWindowsHookEx(WH_CBT,offset HookProc,hInst,0)

    2) GetClassName(wParam,addr buf,MAX_PATH) + lstrcmpi(addr buf,offset _wnd)
    - заменено на
    lstrcmpi(CBT_CREATEWND.CREATESTRUCT.lpszClass,offset _wnd)

    У меня (XP-pro-sp2) BSOD сохранился, а у вас?
     
  11. AntiB

    AntiB New Member

    Публикаций:
    0
    Регистрация:
    23 мар 2007
    Сообщения:
    393
    новый вариант работает под Win7 x32 RC1 7100 (нету бсода)
     
  12. Derek

    Derek New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2008
    Сообщения:
    121
    win2k SP4 x86 //vmware
    winXP SP3 x86 //vmware
    win2k3 SP2 x86 //vmware

    Везде BSOD
     
  13. RamMerLabs

    RamMerLabs Well-Known Member

    Публикаций:
    0
    Регистрация:
    11 сен 2006
    Сообщения:
    1.426
    kero
    на XP SP3 благополучуно запускается, так же завершается. бсода нет, но и окна тоже.
    если запускать в ольке - окно есть. бсода нет.
     
  14. RamMerLabs

    RamMerLabs Well-Known Member

    Публикаций:
    0
    Регистрация:
    11 сен 2006
    Сообщения:
    1.426
    правда олька от случая к случаю отказывается трейсить после win+D
     
  15. Derek

    Derek New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2008
    Сообщения:
    121
    Windows 7 Build 7600 x86 (physical host) - BSOD'а нет на обеих версиях; окно присутствует, по Win-D просто сворачивается.
     
  16. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    AntiB Derek RamMerLabs , приветствую!

    Я правильно понял - все вами сказанное относится к варианту #2 ?
    Или и к #1 ?
    Уточните, plz.

    А пока - #3, с MB (грубо, но коротко):
    Код (Text):
    1. .data
    2.  _wnd  db "wnd",0
    3. .data?
    4.  hhook dd ?
    5. .code
    6.  
    7. HookProc proc uses ebx edi nCode:UINT,wParam:WPARAM,lParam:LPARAM
    8.   .if nCode==HCBT_CREATEWND
    9.     mov ebx,lParam
    10.     assume ebx:PTR CBT_CREATEWND
    11.     mov edi,[ebx].lpcs
    12.     assume edi:PTR CREATESTRUCT
    13.     .if [edi].lpszClass==WC_DIALOG
    14.       invoke GetDesktopWindow
    15.       mov edx,eax
    16.       invoke GetWindow,eax,GW_CHILD
    17.       invoke GetWindow,eax,GW_HWNDLAST ; (Progman)
    18.       invoke GetWindow,eax,GW_CHILD    ; (SHELLDLL_DefView)
    19.       mov [ebx].hWndInsertAfter,eax
    20.     .endif
    21.     assume edi:nothing
    22.     assume ebx:nothing  
    23.     xor eax,eax  
    24.   .else
    25.     invoke CallNextHookEx,hhook,nCode,wParam,lParam
    26.   .endif
    27.   ret
    28. HookProc endp
    29.  
    30. start:
    31.   invoke GetModuleHandle,0
    32.   invoke SetWindowsHookEx,WH_CBT,offset HookProc,eax,0
    33.   mov hhook,eax
    34.   invoke MessageBox,0,offset _wnd,offset _wnd,0
    35.   invoke UnhookWindowsHookEx,hhook
    36.   invoke ExitProcess,eax
    37. end start
     
  17. Derek

    Derek New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2008
    Сообщения:
    121
    #1 #2 #3
    ОС
    Windows XP Pro SP3 x86 (VMware) BSOD BSOD BSOD (msgbox скрыт)
    Windows 2000 Pro SP4 X86 (VMware) BSOD BSOD BSOD (msgbox скрыт)
    Windows Server 2003 SP2 x86 (VMware) BSOD BSOD BSOD (msgbox скрыт)
    Windows 7 Build 7600 x86 (physical host) - - - (msgbox отображается)
     
  18. Derek

    Derek New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2008
    Сообщения:
    121
    #Уехали номера вариантов, но, думаю, понятно
     
  19. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Derek
    Ага, спасибо.
    Вы - первый, кто привел пример виндов без бсод :)
    Значит, Windows 7 Build 7600 x86 ...
     
  20. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    kero, спасибо за информацию. Всем остальным тоже спасибо. Посмотрели, оценили, сделали небольшой write-up. (Тред захвачен, лол).

    Part 1/2
    Код (Text):
    1. kd> vertarget
    2. Windows 7 Kernel Version 7600 MP (1 procs) Free x86 compatible
    3. Product: WinNt, suite: TerminalServer SingleUserTS
    4. Built by: 7600.16385.x86fre.win7_rtm.090713-1255
    5. Machine Name:
    6. Kernel base = 0x82854000 PsLoadedModuleList = 0x8299c810
    7. Debug session time: Wed Oct  7 21:40:26.171 2009 (GMT+3)
    8. System Uptime: 0 days 0:09:12.800
    9.  
    10. kd> g
    11. Access violation - code c0000005 (!!! second chance !!!)
    12. win32k!ValidateParentDepth+0x58:
    13. 8f4445dd cmp     dword ptr [eax+2Ch],0
    14.  
    15. kd> kn99
    16.  # ChildEBP RetAddr  
    17. 00 8cd01c9c 8f440dc4 win32k!ValidateParentDepth+0x58
    18. 01 8cd01cb4 8f41848e win32k!ValidateNewParent+0x28
    19. 02 8cd01cf4 8f418799 win32k!xxxSetParent+0x66
    20. 03 8cd01d24 8289742a win32k!NtUserSetParent+0x89
    21. 04 8cd01d24 772664f4 nt!KiFastCallEntry+0x12a
    22. 05 0020fba4 76b5c6a2 ntdll!KiFastSystemCallRet
    23. 06 0020fba8 75d31490 USER32!NtUserSetParent+0xc
    24. 07 0020fbc8 75d3153a SHELL32!CDesktopBrowser::_SwapParents+0x30
    25. 08 0020fbfc 75d315d8 SHELL32!CDesktopBrowser::_Raise+0xd5
    26. 09 0020fc14 75bf6749 SHELL32!CDesktopBrowser::_OnRaise+0x26
    27. 0a 0020fc44 75c28423 SHELL32!CDesktopBrowser::_WndProcBS+0x772
    28. 0b 0020fc64 76b686ef SHELL32!CDesktopBrowser::s_DesktopWndProc+0x67
    29. 0c 0020fc90 76b68876 USER32!InternalCallWinProc+0x23
    30. 0d 0020fd08 76b689b5 USER32!UserCallWinProcCheckWow+0x14b
    31. 0e 0020fd68 76b68e9c USER32!DispatchMessageWorker+0x35e
    32. 0f 0020fd78 75c2903e USER32!DispatchMessageW+0xf
    33. 10 0020fdac 75c28bfb SHELL32!CDesktopBrowser::_PeekForAMessage+0x153
    34. 11 0020fdc8 75b8b497 SHELL32!CDesktopBrowser::_MessageLoop+0x1e
    35. 12 0020fdd4 007930b9 SHELL32!SHDesktopMessageLoop+0x29
    36. 13 0020fe80 0079aa68 Explorer!wWinMain+0x54a
    37. 14 0020ff14 75af1174 Explorer!_initterm_e+0x1b1
    38. 15 0020ff20 7727b3f5 kernel32!BaseThreadInitThunk+0xe
    39. 16 0020ff60 7727b3c8 ntdll!__RtlUserThreadStart+0x70
    40. 17 0020ff78 00000000 ntdll!_RtlUserThreadStart+0x1b
    Можно видеть, что бсод получаем, когда explorer.exe пытается переназначить родителя одному из окон. Зачем он это делает, не суть есть важно, потому что на самом деле это действие лишь манифистирует проблему, возникшую раньше.

    BOOL win32k!ValidateParentDepth(PWND pwnd, PWND pwndNewParent);
    pwnd – указатель на структуру окна, родителя которой предстоит сменить.
    pwndNewParent – указатель на структуру окна, которое должно стать новым родителем для pwnd.
    В данном случае pwnd указывает на окно с классом "SHELLDLL_DefView", являющееся дочерним относительно top-level окна "Program Manager" (его класс имеет имя "Progman"). Его потенциальный новый родитель (pwndNewParent) – top-level окно класса "WorkerW".
    Назначение функции - проверить, не превысит ли максимальная глубина новосоздаваемых связей Родитель-Потомок значения переменной win32k!gNestedWindowLimit ( == 0x32 по умолчанию). Если превысит, то функцию вернёт "FALSE" и репарентирование не будет произведено. Максимальная глубина считается как число вертикальных связей от DesktopWindow до pwndNewParent + число вертикальных связей от pwnd до самого нижнего элемента его поддерева.
        
        
    Расклад окон, слегка похожий на реальный:
    [​IMG]
        
        
    Применяемая система связей между окнами позволяет выполнить обход дерева (который нужен для узнавания глубины) без использования рекурсии (и без её эмуляции через списки и т.п.), чем и пользуется процедура ValidateParentDepth(). Так вот. В этой функции имеется небольшая ошибка, которая не представляет совершенно никакой угрозы безопасности: если у pwnd есть дочерние окна, то вместо максимальной глубины поддерева с вершиной в pwnd подсчитывается максимальная глубина среди поддеревьев, начинающихся с pwnd и со следующих за ним саблингов.
    Например, мы хотим присвоить в качестве нового родителя для Child A1 окно Child B3. Правильный подход: Child B1 <–> Window B <–> Desktop Window [2] + Child A1 <–> Child A11 [1] == 3.
    Реальный (неверный) подход: Child B1 <–> Window B <–> Desktop Window [2] + max( Child A1 <–> Child A11 [1], Child A2 <–> Child A21 [1] + Child A22 <–> Child A221 [1] == [2] ) == 4.
    А вот если бы мы присваивали Child B3 в качестве родителя для Child A2, то оба подхода дали бы ответ "4".
    Эта ошибка очень незначительна, однако если бы её не было, то представленный вариант кода не вызвал бы бсод.
        
    kero удалось поломать нормальный расклад окон:    
    [​IMG]
        
    Видно, что окно "wnd" является следующим в Z-порядке относительно "SHELLDLL_DefView", однако у этих двух окон разные родители! Такого в принципе быть не должно – и, вероятно, в дебажной версии win32k один бы наткнулся на ассерт едва попытавшись провернуть нечто подобное. Условием конца обхода для ValidateParentDepth() должно было бы являться достижение pwnd – однако из-за ошибки таким условием является достижение _родителя_ pwnd (настоящего, ещё не изменённого). Поскольку порядок окон поломан, функция "пропускает" окно Progman'а и продолжает подниматься вверх, доходя до самого верхнего DesktopWindow, далее до нуля, и, наконец, пытается прочитать указатель на следующего сиблинга у нуль-окна, чем вызывает фатальную ошибку страницы.
        
    Интересно, что, даже аллоцировав память по нулевому адресу и создав там подложную оконную структуру, мы ничего не добъёмся от рассмотренной процедуры – ValidateParentDepth() ничего не изменяет и вызывает лишь одну функцию, на раннем этапе выполнения. Необходимо рассматривать корень проблемы.
        
    TLDR:
    Функция ValidateParentDepth() содержит незначительную ошибку, благодаря которой проявилась ошибка реальная. Эксплуатация незначительной ошибки видится невозможной.