Сплайсинг в нулевом кольце на новых версиях ядра (Виста, Вин7)

Тема в разделе "WASM.NT.KERNEL", создана пользователем d2k9, 31 янв 2010.

  1. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    Решил я написать дров для хука чего-нибудь, т.е. просто заготовку на все случаи жизни. Покопался я в тырнете и пришёл к выводу, что на данный момент чтобы похукать что-нибудь в ядре является сплайсинг т.к. из-за пг от мелкомягких на новых версиях ядра теневую таблицу сервисов уже геморно модифицировать. И пошёл я тогда к старой доброй статье №3 от мс-рема из его цикла статей про хуки. Там он хукает NtOpenProcess. И решил я похукать тоже самое :) Выяснилось, что этот примитив хорошо работает на хрюше сп3 х86, но уже на висте х86 бсодит. Я начал рыть, вспомнив, что функции по прологу и эпилогу вроде как различаются в разных версиях ядер. Так оно и оказалось, продизасмил я парочку ntoskrnl и вот что у меня получилось:
    1) начало функции на Win XP x86
    Код (Text):
    1. NTSTATUS __stdcall NtOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
    2. public NtOpenProcess
    3. NtOpenProcess   proc near            
    4. var_D4          = dword ptr -0D4h
    5. var_B8          = dword ptr -0B8h
    6. var_A8          = dword ptr -0A8h
    7. var_A4          = dword ptr -0A4h
    8. var_38          = dword ptr -38h
    9. AccessMode      = byte ptr -34h
    10. var_30          = dword ptr -30h
    11. var_2C          = dword ptr -2Ch
    12. var_28          = dword ptr -28h
    13. Object          = dword ptr -24h
    14. var_20          = dword ptr -20h
    15. var_1A          = byte ptr -1Ah
    16. var_19          = byte ptr -19h
    17. ms_exc          = CPPEH_RECORD ptr -18h
    18. arg_0           = dword ptr  8
    19. AccessMask      = dword ptr  0Ch
    20. arg_8           = dword ptr  10h
    21. arg_C           = dword ptr  14h
    22. push    0C4h
    23. push    offset stru_4130D8
    24. call    __SEH_prolog
    25. xor     esi, esi
    26. mov     [ebp+var_2C], esi
    27. xor     eax, eax
    28. lea     edi, [ebp+var_28]
    29. stosd
    30. mov     eax, large fs:124h
    31. mov     al, [eax+140h]
    32. mov     [ebp+AccessMode], al
    33. test    al, al
    34. jz      loc_5059A8
    35. mov     [ebp+ms_exc.disabled], esi
    36. mov     eax, MmUserProbeAddress
    37. mov     ecx, [ebp+arg_0]
    38. cmp     ecx, eax
    39. jnb     loc_5214EE
    2) Vista x86
    Код (Text):
    1. NTSTATUS __stdcall NtOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
    2. public NtOpenProcess
    3. NtOpenProcess   proc near                                                  
    4. PreviousMode    = byte ptr -4
    5. ProcessHandle   = dword ptr  8
    6. DesiredAccess   = dword ptr  0Ch
    7. ObjectAttributes= dword ptr  10h
    8. ClientId        = dword ptr  14h
    9. mov     edi, edi
    10. push    ebp
    11. mov     ebp, esp
    12. push    ecx
    13. push    ecx
    14. mov     eax, large fs:124h
    15. mov     al, [eax+0E7h]
    16. mov     ecx, [ebp+ClientId]
    17. mov     edx, [ebp+ObjectAttributes]
    18. mov     [ebp+PreviousMode], al
    19. push    dword ptr [ebp+PreviousMode] ; PreviousMode
    20. push    dword ptr [ebp+PreviousMode] ; char
    21. push    [ebp+DesiredAccess] ; int
    22. push    [ebp+ProcessHandle] ; int
    23. call    sub_5C77E5
    24. leave
    25. retn    10h
    26. NtOpenProcess   endp
    3) Win7 x64 до кучи
    Код (Text):
    1. NTSTATUS __stdcall NtOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
    2. public NtOpenProcess
    3. NtOpenProcess   proc near                                          
    4. PreviousMode    = byte ptr -4
    5. ProcessHandle   = dword ptr  8
    6. DesiredAccess   = dword ptr  0Ch
    7. ObjectAttributes= dword ptr  10h
    8. ClientId        = dword ptr  14h
    9. mov     edi, edi
    10. push    ebp
    11. mov     ebp, esp
    12. push    ecx
    13. push    ecx
    14. mov     eax, large fs:124h
    15. mov     al, [eax+13Ah]
    16. mov     ecx, [ebp+ClientId]
    17. mov     edx, [ebp+ObjectAttributes]
    18. mov     [ebp+PreviousMode], al
    19. push    dword ptr [ebp+PreviousMode] ; PreviousMode
    20. push    dword ptr [ebp+PreviousMode] ; char
    21. push    [ebp+DesiredAccess] ; int
    22. push    [ebp+ProcessHandle] ; int
    23. call    sub_611AC8
    24. leave
    25. retn    10h
    26. NtOpenProcess   endp
    И так, видно, что в хрюше начало функции:
    Код (Text):
    1. push    0C4h
    2. push    offset stru_4130D8
    3. call    __SEH_prolog
    4. xor     esi, esi
    5. mov     [ebp+var_2C], esi
    6. xor     eax, eax
    7. lea     edi, [ebp+var_28]
    8. stosd
    9. mov     eax, large fs:124h
    В висте и вин7 одинаково:
    Код (Text):
    1. mov     edi, edi
    2. push    ebp
    3. mov     ebp, esp
    4. push    ecx
    5. push    ecx
    6. mov     eax, large fs:124h
    Непонятно какое mov edi,edi и остальной мусор видно мешают и поэтому не получается нормально похучить. Я сейчас думаю над тем как можно сделать универсальный вариант - по-видимому нужен дизассемблер для динамического определения способа хука. Если кто-то может меня наставить на путь истинный буду только благодарен :)
    Заранее говорю всем спасибо и в частности Great, Clerk за их светлые мысли.
     
  2. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Светлая мысль заключается в разделении системного адресного пространства. Обычно во всех процессах эта область памяти(вся выше юзерспейса) линейно отображена на физическую память(исключая уникальное Hyper Space). Во всех процессах например заголовок ядра имеет одинаковый физический адрес. Изменить PTE мы можем, скопировать данные из текущей страницы в новую и загрузить в PTE адрес новой страницы. Тогда в этом процессе по соответствующему виртуальному адресу будут находится иные данные, чем по томуже адресу в другом процессе. Например модифицируем ядро из одного процесса, это не затронет наш процесс с изменённой таблицей страниц, например он будет юзать оригинальное ядро. Для такой модификации необходим аттачь к процессу(перезагрузка PDBR). Так всяко детекторы руткитов обычно сканят память ядра из своего процесса. Это позволяет скрываться от них(пока только в теории).
     
  3. reader323

    reader323 New Member

    Публикаций:
    0
    Регистрация:
    8 июл 2009
    Сообщения:
    134
    d2k9
    Офигеть. Аффтар топика не лезь в ядро с такими познаниями и открой для себя Microsoft Detours.
     
  4. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Service Pack какой на этой системе? Ниже SP2, да?

    Это чтобы сплайс удобнее ставить было (hotpatch).

    Делай как хотфиксы и будет тебе универсальный вариант на всех системах, начиная с Windows XP SP2.
     
  5. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    Ха-ха. Юзермодной либой в ядре?) Ну-ну. А может мелкомякие уже придумали либу для сплайса в ядре обходя свою же защиту PatchGuard? Бугага, сначала думай, а потом пиши.
     
  6. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    x64
    Windows XP SP3 x86.
    Сейчас рассматриваю варианты обходя PatchGuard для нахождения наиболее приемлимого. Я забыл, что он контролит целостность образов и понял откуда эти бсоды дурацкие при патчинге функций, зря я их только мучал в дизасме.
     
  7. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Ты уверен, что правильно дизасмил? На этой системе код почти любой функции ядра выглядит так:

    Код (Text):
    1. nop
    2. nop
    3. nop
    4. nop
    5. nop
    6. ; здесь начало функции
    7. mov edi, edi
    Я бы не стал с этим связываться в легальном продукте.

    К PG имеет отношение вроде бы только один bugcheck, это CRITICAL_STRUCTURE_CORRUPTION, код 0x109.
     
  8. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    x64
    Как по вашему контролировать сст в легальном продукте ?
     
  9. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Увы, не все так просто для воплощения теории. Часть вызовов из процесса будет выполняться в arbitrary context.
     
  10. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Речь шла не о SDT, а о том, что бороться с PG, как ты говоришь, на лету, - бесполезно, обойти его можно только раз и навсегда, внедрившись в загрузчик системы. Ну а из загрузчика уже можно и SDT похукать и всё, что нужно. Возможно, есть ещё варианты типа модификации некоторых полей ETHREAD, но не факт, что это ещё работает, проверять надо.
     
  11. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    J0E
    Уточните. По мойму всё гладко будет.
    x64
    Тоесть легальные продукты будут внедряться в лодер ?
     
  12. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Уже внедряются.
     
  13. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    d2k9
    Тебя обманули. Это х32.

    x64
    >Уже внедряются.
    Например?

    d2k9
    >начало функции на Win XP x86
    >push 0C4h
    В общем-то, такое вполне можно допустить. Например, в х64 не используется "mov edi, edi" – вместо этого код строится таким образом, чтобы первая инструкция функции занимала больше одного байта. Возможно, при компиляции ядра XP sp3 был использован подобный подход.
     
  14. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Не хотелось бы говорить об этом пока, но информация точная.
     
  15. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Для примера. Поток некоторого процесса принимает пакет из сети. Вызовы по вершине стека драйверов выполняются в его контексте, пока все гладко. но когда придет пакет и сработает колбэк в ндисе - контекст будет от произвольного процесса, где код не патчен и не гладко.
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    J0E
    Причём тут ндис и калбэки. Я про кодосекции ядра говорил. Например я смогу дёргать системные функци в обход перехватчиков и это не будет видно из контекста другого процесса.
     
  17. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    Это не так. Перехватить одну KeBugCheckEx мало т.к. там есть промежуточный вызов RtlCaptureContext который может завершиться бсодом. Ну ничё, я работаю в этом направлении :)
     
  18. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Попробовал страничку подменить:
    Код (Text):
    1. PDE_BASE    equ 0C0300000H
    2. PTE_BASE    equ 0C0000000H
    3.  
    4. PDE_P   equ 1B
    5. PDE_PS  equ 10000000B
    6. PTE_P   equ 1B
    7.  
    8.     ASSUME FS:NOTHING
    9. KiSubstitutePhysicalPage proc uses ebx esi edi OldPage:PVOID
    10. Local Status:NTSTATUS
    11. Local Mdl:PVOID
    12.     mov Status,STATUS_UNSUCCESSFUL
    13.     and OldPage,NOT(PAGE_SIZE - 1)
    14.     mov ebx,OldPage
    15.     mov eax,Cr3 ; ..Pcb.DirectoryTableBase[0]
    16.     shr ebx,22
    17.     and eax,NOT(PAGE_SIZE - 1)  ; PDBR
    18.     lea ebx,dword ptr [eax + 4*ebx] ; Phys. PDE
    19.     mov eax,ebx
    20.     and eax,NOT(PAGE_SIZE - 1)
    21.     and ebx,(PAGE_SIZE - 1)
    22.     invoke MmMapIoSpace, Eax, 0, PAGE_SIZE, MmNonCached ; ..PDE_BASE
    23.     test eax,eax    ; PDE
    24.     jz Error
    25.     mov edi,dword ptr [eax + ebx]
    26.     mov esi,eax
    27.     test edi,PDE_P
    28.     jz Unmap
    29.     test edi,PDE_PS
    30.     jz PageTable
    31.     mov edi,400*PAGE_SIZE   ; 4M
    32.     jmp Copy   
    33. ; PT
    34. PageTable:
    35.     invoke MmUnmapIoSpace, Eax, PAGE_SIZE
    36.     mov ecx,OldPage
    37.     and edi,NOT(PAGE_SIZE - 1)
    38.     shr ecx,12
    39.     and ecx,1111111111B
    40.     lea ebx,[edi + 4*ecx]   ; Phys. PTE
    41.     mov eax,ebx
    42.     and eax,NOT(PAGE_SIZE - 1)
    43.     and ebx,(PAGE_SIZE - 1)
    44.     invoke MmMapIoSpace, Eax, 0, PAGE_SIZE, MmNonCached ; ..PTE_BASE
    45.     test eax,eax    ; PTE
    46.     mov esi,eax
    47.     jz Exit
    48.     test dword ptr [eax + ebx],PTE_P
    49.     jz Unmap
    50.     mov edi,PAGE_SIZE   ; 4K
    51. Copy:
    52.     invoke MmAllocateContiguousMemory, Edi, -1, 0
    53. ;   invoke MmAllocatePagesForMdl, 0, 0, 0, -1, 0, PAGE_SIZE, Edi
    54.     test eax,eax
    55. ;   mov Mdl,eax ; PMDL
    56.     jz Unmap
    57. ;   invoke MmMapLockedPages, Mdl, KernelMode
    58.     test eax,eax
    59. ;   jz FreeMdl
    60.     cld
    61.     mov ecx,edi
    62.     push esi
    63.     shr ecx,2
    64.     mov edi,eax
    65.     mov esi,OldPage
    66.     rep movsd
    67.     pop esi
    68.     mov edi,eax
    69.     invoke MmGetPhysicalAddress, Eax    ; ..VIRTUAL_TO_PHYSICAL
    70.     test eax,eax
    71.     jz UnmapMdl
    72. ; Insert page.
    73.     mov ecx,dword ptr [esi + ebx]
    74.     and ecx,(PAGE_SIZE - 1)
    75.     or eax,ecx
    76.     mov dword ptr [esi + ebx],eax
    77.     invoke KeFlushEntireTb, TRUE, TRUE
    78.     mov Status,STATUS_SUCCESS
    79.     jmp Unmap
    80. UnmapMdl:
    81.     invoke MmFreeContiguousMemory, Edi
    82. ;   invoke MmUnmapLockedPages, Edi, Mdl
    83. FreeMdl:
    84. ;   invoke MmFreePagesFromMdl, Mdl
    85. ;   invoke ExFreePool, Mdl
    86. Unmap:
    87.     invoke MmUnmapIoSpace, Esi, PAGE_SIZE
    88. Error:
    89.     mov eax,Status
    90. Exit:
    91.     ret
    92. KiSubstitutePhysicalPage endp
    P4, XP. Для 4K страниц работает как и должно - заменяет физическую страницу. Но для ядра(собственно ядро, нтос) камень в даун уходит, там страницы 4M, траблы какието(спейс линейный) не понятно почему :dntknw:
     
  19. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    d2k9
    Ну ёлки зелёные, откуда мы тут знаем, что там у тебя где бсодит?
    Сплайсинг должен нормально работать и в икспи x86 и в висте x86 и в 7 x86 (у меня работал)
    Да и таблица сервисов там на ура подменяется.
    PG он то только на x64 (насколько мне известно; я в 64 битах не копался - проца соотв. нет. если это не так - уж не обессудьте).

    дай чтоле код багчека из BSoD, а лучше !analyze -v
    Как я уже писал где-то, крики "у меня то-то не работает" или же вообще то-то не делает что-то" не являются описанием проблемы)
    Все в идеале должно работать, значит косяк у тебя.

    PS. А Clerk опять кидается красивыми кодами совершенно не по теме. [здесь была намеренная провокация с намёком на оскорбление. ай-ай-ай, нехорошо ;) ]
     
  20. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    Great
    Всё отлично работает на х86 начиная с ХР и заканчивая Вин7. Проблема только в ПГ на х64.