[Syser patch]

Discussion in 'Реверсинг' started by 0x0c0de, 11 Apr 2009.

  1. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    [Syser v1.99 patch]

    Заметка по сабжу.
    Итак, давно у меня чесались руки разобраться с этой багой в Syser, которая бросает систему в бсод при NtLoadDriver(0). Что меня побудило патчить сисер? Побудило то, что на форуме сабжа мне так и не ответили с февраля месяца. Идеально, конечно, чтобы сами девелоперы пофиксили, но пока новой версии не вышло.
    Изложу сейчас как что. В общем патчить будем SysBoot.sys (описание баги http://0x0c0de.livejournal.com/1689.html).

    Задача такова. Надо в перехватчике NtLoadDriver

    Code:
    .text:00011AD9 usDriverName    = dword ptr  8
    .text:00011AD9
    .text:00011AD9                 push    ebp
    .text:00011ADA                 mov     ebp, esp
    .text:00011ADC                 sub     esp, 0Ch
    .text:00011ADF                 push    esi
    .text:00011AE0                 mov     esi, [ebp+usDriverName]
    .text:00011AE3                 push    edi
    .text:00011AE4                 push    esi
    .text:00011AE5                 call    NtLoadDriverOrig
    .text:00011AEB                 mov     edi, eax
    .text:00011AED                 movzx   eax, word ptr [esi]
    
    cразу после вызова оригинальной функции поместить проверку на ее возвращаемое значение. Добавим новую секцию размером 0x100. Для этих целей удобно юзать CFF Explorer. Назовем ее .fixbug. Характеристики секции укажем такие же как и у секции .text (executable, readable, not pageable и содержащая код). После этого жмем rebuild image size в контекстном меню. Сохраняемся.

    Теперь непосредственно к патчу. По адресу 00011AEB ставим jmp на новую секцию.

    Code:
    .text:00011AE5                 call    NtLoadDriverOrig
    .text:00011AEB                 jmp     loc_15E05
    
    а в секции код проверки

    Code:
    .fixbug:00015E05 loc_15E05:                              ; CODE XREF: sub_11AD9+12j
    .fixbug:00015E05                 nop
    .fixbug:00015E06                 nop
    .fixbug:00015E07                 nop
    .fixbug:00015E08                 cmp     eax, 0C0000000h
    .fixbug:00015E0D                 ja      short loc_15E2B
    .fixbug:00015E0F                 nop
    .fixbug:00015E10                 nop
    .fixbug:00015E11                 nop
    .fixbug:00015E12                 nop
    .fixbug:00015E13                 nop
    ....
    .fixbug:00015E1E                 nop
    .fixbug:00015E1F                 nop
    .fixbug:00015E20                 nop
    .fixbug:00015E21                 mov     edi, eax
    .fixbug:00015E23                 movzx   eax, word ptr [esi]
    .fixbug:00015E26                 jmp     loc_11AF0 // пусть syser продолжает обработку
    .fixbug:00015E2B ; ---------------------------------------------------------------------------
    .fixbug:00015E2B
    .fixbug:00015E2B loc_15E2B:                              ; CODE XREF: sub_11AD9+4334j
    .fixbug:00015E2B                 nop
    .fixbug:00015E2C                 jmp     loc_11B9E // выход из функции
    
    Все элементарно. Если возвращаемое значение больше 0C0000000h, то произошла ошибка и драйвер не загружен. А значит управление передаем на

    Code:
    .text:00011B9E loc_11B9E:                              ; CODE XREF: sub_11AD9+4353j
    .text:00011B9E                 pop     edi
    .text:00011B9F                 pop     esi
    .text:00011BA0                 leave
    .text:00011BA1                 retn    4
    
    Если же драйвер успешно загрузился (а это подразумевает, что и в структуре с именем загружаемого дрова тоже все ок), то выполняем затертые джампом инструкции и продолжаем выполнение с

    Code:
    text:00011AF0 loc_11AF0:                              ; CODE XREF: sub_11AD9+434Dj
    .text:00011AF0                 shr     eax, 1
    .text:00011AF2                 push    eax
    
    Вот так. Однако, это еще не все. Патченный драйвер не загрузится (будет ERROR_BAD_DRIVER), если не пофиксить црц в pe-заголовке. Сделать это можно с помощью PeEditor-a в PeTools. Просто пересчитать поле Checksum в Optional Header. Это все. Теперь можно спокойно передавать NtLoadDriver всякие невалидные указатели. это, конечно же, временное решение до тех пор, пока разработчики сами не исправят.
     
    6 people like this.
  2. 0verbreaK

    0verbreaK Elder - Старейшина

    Joined:
    30 Apr 2008
    Messages:
    318
    Likes Received:
    42
    Reputations:
    -3
    Молодец, сам нарвался пару раз на NtLoadDriver(0)