отслеживание записи из r0 в r3

Тема в разделе "WASM.NT.KERNEL", создана пользователем volodya, 22 ноя 2008.

  1. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    в DDK это есть и это парсабельно. другой вопрос если во входных структурах есть указатели, по которым идет запись, это определить куда сложнее
     
  2. Folk Acid

    Folk Acid New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2005
    Сообщения:
    432
    Адрес:
    Ukraine
    Еще один неочевидный момент: если для всех ring3 дескрипторов одно и то же значение cs, то как тогда осуществляется разделение на адресные пространства разных процессов? Перезаписью при переключении задач LDT, или на уровне PAE? И как происходит виртуализация адресного пространства при работе из ring0 в контексте процесса. Еще неясен момент с многоядерными системами.

    В-принципе, у кого остался SoftICE - то понты проверить.
     
  3. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    С помощью страничного преобразования. В регистре CR3 находится физический адрес каталога страниц, каждая запись которого ссылается на таблицу страниц. Не вдаваясь в детали, получается так, что виртуальный адрес, перед тем как быть отправленным на шину адреса заменяется на физический по этим таблицам. Благодаря этому один и тот же виртуальный адрес может ссылаться на разные физические. При переключении процессов CR3 меняется на адрес другого каталога, так процессы защищаются друг от друга. Каждая страница имеет бит привелегий (user/supervisor). Код с уровнем привелегий CPL > 0 не может обращаться к страницам supervisor, так ядро защищается от пользовательских процессов.

    Подробности хорошо описаны в Intel Manual 3A.
     
  4. Folk Acid

    Folk Acid New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2005
    Сообщения:
    432
    Адрес:
    Ukraine
    Mika0x65
    Спасибо за ответ. Твою статью про страничную адресацию я читал.

    Вот тут все доходчиво написано.

    http://www.wasm.ru/forum/viewtopic.php?id=29511
     
  5. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Обкашляли тему с Great. Порешили писать перехватчик + трассировщик. Перехватчик будет болтаться на SDT для ntosrknl + win32k.sys. Трассировщик будет отслеживать попытки записи в r3 путем манипуляций с PDPT.
     
  6. zorro

    zorro New Member

    Публикаций:
    0
    Регистрация:
    8 ноя 2008
    Сообщения:
    33
    Я все же советую обратить внимание на Probe.

    Понятно, что код r0 может писать в r3 как угодно, но ведь сейчас речь идет не о произвольном коде, а о ядре Windows. Microsoft все же не авантюристы, и имеют правило проверять указатели перед записью в r3.

    В частности обратите внимание на обращение к _MmUserProbeAddress и его копиям, например _Win32UserProbeAddress для win32k.sys.

    Примеры:

    Код (Text):
    1. PAGE:004B09A3 ; NTSTATUS __stdcall NtQueryDefaultUILanguage(PLANGID LanguageId)
    2. PAGE:004B09A3 _NtQueryDefaultUILanguage@4 proc near   ; DATA XREF: .text:0040DAF0o
    3. PAGE:004B09A3
    4. PAGE:004B09A3 var_24          = dword ptr -24h
    5. PAGE:004B09A3 var_19          = byte ptr -19h
    6. PAGE:004B09A3 ms_exc          = CPPEH_RECORD ptr -18h
    7. PAGE:004B09A3 LanguageId      = dword ptr  8
    8. PAGE:004B09A3
    9. PAGE:004B09A3 ; FUNCTION CHUNK AT PAGE:0053A09E SIZE 00000008 BYTES
    10. PAGE:004B09A3
    11. PAGE:004B09A3                 push    14h
    12. PAGE:004B09A5                 push    offset dword_4236C0
    13. PAGE:004B09AA                 call    __SEH_prolog
    14. PAGE:004B09AF                 xor     edi, edi
    15. PAGE:004B09B1                 and     [ebp+ms_exc.disabled], edi
    16. PAGE:004B09B4                 mov     eax, large fs:124h
    17. PAGE:004B09BA                 mov     [ebp+var_24], eax
    18. PAGE:004B09BD                 mov     al, [eax+140h]
    19. PAGE:004B09C3                 mov     [ebp+var_19], al
    20. PAGE:004B09C6                 mov     esi, [ebp+LanguageId]
    21. PAGE:004B09C9                 test    al, al
    22. PAGE:004B09CB                 jz      short loc_4B09E0
    23. PAGE:004B09CD                 mov     eax, _MmUserProbeAddress
    24. PAGE:004B09D2                 cmp     esi, eax
    25. PAGE:004B09D4                 jnb     loc_53A09E
    26. PAGE:004B09DA
    27. PAGE:004B09DA loc_4B09DA:                             ; CODE XREF: NtQueryDefaultUILanguage(x)+896FEj
    28. PAGE:004B09DA                 mov     ax, [esi]
    29. PAGE:004B09DD                 mov     [esi], ax
    30. PAGE:004B09E0
    31. PAGE:004B09E0 loc_4B09E0:                             ; CODE XREF: NtQueryDefaultUILanguage(x)+28j
    32. PAGE:004B09E0                 push    1
    33. PAGE:004B09E2                 push    esi
    34. PAGE:004B09E3                 push    offset aMultiuilanguag ; "MultiUILanguageId"
    35. PAGE:004B09E8                 call    _ExpGetCurrentUserUILanguage@12 ; ExpGetCurrentUserUILanguage(x,x,x)
    36. PAGE:004B09ED                 test    eax, eax
    37. PAGE:004B09EF                 jge     short loc_4B09FA
    38. PAGE:004B09F1                 mov     ax, ds:_PsInstallUILanguageId
    39. PAGE:004B09F7                 mov     [esi], ax
    40. PAGE:004B09FA
    41. PAGE:004B09FA loc_4B09FA:                             ; CODE XREF: NtQueryDefaultUILanguage(x)+4Cj
    42. PAGE:004B09FA                                         ; PAGE:0053A0C4j
    43. PAGE:004B09FA                 or      [ebp+ms_exc.disabled], 0FFFFFFFFh
    44. PAGE:004B09FE                 mov     eax, edi
    45. PAGE:004B0A00                 call    __SEH_epilog
    46. PAGE:004B0A05                 retn    4
    47. PAGE:004B0A05 _NtQueryDefaultUILanguage@4 endp
    А вот из win32k.sys:

    Код (Text):
    1. .text:BF815A15 ; __stdcall NtUserBeginPaint(x, x)
    2. .text:BF815A15 _NtUserBeginPaint@8 proc near           ; DATA XREF: .data:BF999FD0o
    3. .text:BF815A15
    4. .text:BF815A15 var_6C          = dword ptr -6Ch
    5. .text:BF815A15 var_68          = dword ptr -68h
    6. .text:BF815A15 var_60          = dword ptr -60h
    7. .text:BF815A15 var_5C          = dword ptr -5Ch
    8. .text:BF815A15 var_1C          = dword ptr -1Ch
    9. .text:BF815A15 ms_exc          = CPPEH_RECORD ptr -18h
    10. .text:BF815A15 arg_0           = dword ptr  8
    11. .text:BF815A15 arg_4           = dword ptr  0Ch
    12. .text:BF815A15
    13. .text:BF815A15 ; FUNCTION CHUNK AT .text:BF815A0C SIZE 00000004 BYTES
    14. .text:BF815A15
    15. .text:BF815A15                 push    5Ch
    16. .text:BF815A17                 push    offset unk_BF98D648
    17. .text:BF815A1C                 call    __SEH_prolog
    18. .text:BF815A21                 mov     eax, ___security_cookie
    19. .text:BF815A26                 mov     [ebp+var_1C], eax
    20. .text:BF815A29                 mov     esi, [ebp+arg_0]
    21. .text:BF815A2C                 mov     edi, [ebp+arg_4]
    22. .text:BF815A2F                 call    _EnterCrit@0    ; EnterCrit()
    23. .text:BF815A34                 mov     ecx, esi
    24. .text:BF815A36                 call    @ValidateHwnd@4 ; ValidateHwnd(x)
    25. .text:BF815A3B                 mov     [ebp+var_60], eax
    26. .text:BF815A3E                 test    eax, eax
    27. .text:BF815A40                 jz      short loc_BF815A0C
    28. .text:BF815A42                 mov     ecx, _gptiCurrent
    29. .text:BF815A48                 mov     edx, [ecx+28h]
    30. .text:BF815A4B                 mov     [ebp+var_6C], edx
    31. .text:BF815A4E                 lea     edx, [ebp+var_6C]
    32. .text:BF815A51                 mov     [ecx+28h], edx
    33. .text:BF815A54                 mov     [ebp+var_68], eax
    34. .text:BF815A57                 inc     dword ptr [eax+4]
    35. .text:BF815A5A                 lea     ecx, [ebp+var_5C]
    36. .text:BF815A5D                 push    ecx
    37. .text:BF815A5E                 push    eax
    38. .text:BF815A5F                 call    _xxxBeginPaint@8 ; xxxBeginPaint(x,x)
    39. .text:BF815A64                 mov     ebx, eax
    40. .text:BF815A66                 and     [ebp+ms_exc.disabled], 0
    41. .text:BF815A6A                 mov     eax, _Win32UserProbeAddress
    42. .text:BF815A6F                 cmp     edi, eax
    43. .text:BF815A71                 jnb     short loc_BF815A9B
    44. .text:BF815A73
    45. .text:BF815A73 loc_BF815A73:                           ; CODE XREF: NtUserBeginPaint(x,x)+8Cj
    46. .text:BF815A73                 push    10h
    47. .text:BF815A75                 pop     ecx
    48. .text:BF815A76                 lea     esi, [ebp+var_5C]
    49. .text:BF815A79                 rep movsd
    50. .text:BF815A7B                 or      [ebp+ms_exc.disabled], 0FFFFFFFFh
    51. .text:BF815A7F                 call    _ThreadUnlock1@0 ; ThreadUnlock1()
    52. .text:BF815A84
    53. .text:BF815A84 loc_BF815A84:                           ; CODE XREF: NtUserBeginPaint(x,x)-7j
    54. .text:BF815A84                 call    _LeaveCrit@0    ; LeaveCrit()
    55. .text:BF815A89                 mov     eax, ebx
    56. .text:BF815A8B                 mov     ecx, [ebp+var_1C]
    57. .text:BF815A8E                 call    @__security_check_cookie@4 ; __security_check_cookie(x)
    58. .text:BF815A93                 call    __SEH_epilog
    59. .text:BF815A98                 retn    8
    60. .text:BF815A9B ; ---------------------------------------------------------------------------
    61. .text:BF815A9B
    62. .text:BF815A9B loc_BF815A9B:                           ; CODE XREF: NtUserBeginPaint(x,x)+5Cj
    63. .text:BF815A9B                 mov     dword ptr [eax], 0
    64. .text:BF815AA1                 jmp     short loc_BF815A73
    65. .text:BF815AA1 _NtUserBeginPaint@8 endp
    Понятно, что потребуется писать анализатор кода, понятно что он не везде сумеет справиться, но покрыть 80-90% случаев имхо можно уже через несколько дней.
     
  7. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Смысл покрывать 90% кода? Это потеря точности. Мы уже теряем точность, т.к. ограничиваемся только code flow. И все остальные ветки кода не выполняем. Следовательно, мы не можем быть уверенными в том, что функция действительно не пишет в r3.

    Формальную уверенность может дать лишь фаззер и то, только в том случае, если будет доказано, что он способен перебрать все входные параметры. Кстати, и то не факт. Если внутри у функции есть еще какие-то свои ветвления не только по параметрам из r3, но и по каким-то флуктуациям в r0 - все печально.

    А твой вариант (мало того, что мы уже страдаем потерей точности), предлагает еще ее уменьшить.
     
  8. zorro

    zorro New Member

    Публикаций:
    0
    Регистрация:
    8 ноя 2008
    Сообщения:
    33
    Нет, мой вариант основан не на перехвате обращений к этим переменным, а на статическом анализе всего кода, отправными точками для которого являются эти переменные. Соответственно отпадает проблема с code flow, т.к. анализу подвергнутся все закоулки ядра.

    А под 90% я имел ввиду простецкий наколеночный алгоритм, который при серьезном подходе сможет покрыть и больше. И кстати я далеко не уверен, что фаззер на code flow даст большую точность.
     
  9. CrystalIC

    CrystalIC New Member

    Публикаций:
    0
    Регистрация:
    26 июл 2008
    Сообщения:
    500
    1. Анализ кода. Ничего не даст. Например, некоторые функции используют обмен данными между процессорами/потоками, ожидание требует вызова планировщика. Не удастся отследить вызов простым анализом кода.
    2. Стек. Сервис требует чтобы параметры его находились в стеке. Но те 4 юзермодные точки(KiUser*) вызываются ядром при наступлении определённого события и параметры имеют тоже в стеке.
    С учётом сказанного, пример - сервис ожидания. Если обработка очереди потока разрешена и очередь потока не пуста, до возврата из сервиса будет вызван APC(KiUserApcDispatcher()).
    Есчо пример - исключение, если в сервис переданы невалидные параметры возникнет исключение и будет вызван KiUserExceptionDispatcher(), параметры тоже будут записаны в стеке.
     
  10. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Статический анализ дизассемблированного кода - то еще дело. На тему symbolic execution много копий сломано. Не будем, пожалуй, ее здесь поднимать. Замнем для ясности.
     
  11. 4VR

    4VR New Member

    Публикаций:
    0
    Регистрация:
    21 ноя 2008
    Сообщения:
    25
    Практически единственно правильный метод. Опоздал я с предложением))
     
  12. zorro

    zorro New Member

    Публикаций:
    0
    Регистрация:
    8 ноя 2008
    Сообщения:
    33
    CrystalIC
    Ты улавливаешь разницу между статикой и динамикой? Ты часом Sleep'ы в листингах дизассемблера не выжидаешь с секундомером?)) Что же касается юзермодных точек, то они точно также делают ProbeForWrite() перед заполнением стека. ;)

    Кстати, насчет исключений. Считаешь, что исключение в ядре вызовет KiUserExceptionDispatcher? :)
     
  13. CrystalIC

    CrystalIC New Member

    Публикаций:
    0
    Регистрация:
    26 июл 2008
    Сообщения:
    500
    zorro
    А ты типа вобще тупой)
     
  14. zorro

    zorro New Member

    Публикаций:
    0
    Регистрация:
    8 ноя 2008
    Сообщения:
    33
    CrystalIC
    Ага, помнишь мы вместе снимались в "Тупой и еще тупее".))
     
  15. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    на самом деле есть метод лучше (ку, PROFi :)) - он предложил сравнивать адресное пространство до и после выполнения функции. это учтет некоторые моменты, не учитываемые перехватом #PF, но в данном случае пока не требуется их учитывать.
    а я тем временем заканчиваю реализацию своего метода. NtCreateFile и NtReadFile уже нормально пашут под трейсером. правда не шибко шустро. все-таки приходится реагировать на все обращения к юзермодному АП.
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Great
    Ты же сказал что это самоубийство :)
    Не забываем про трассировку ветвлений(MSR_DEBUG_CTL и тп.), это во много раз ускорит.
    [Хотя хз, дизасм время наверно спалит.]
     
  17. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Трассировки почти нет - под трейсом выполняются еденичные инструкции.

    Я говорил про другое - про полную трассировку и дизасм каждой инструкции и определение, обращается она к памяти или нет. Это действительно самоубийство.
    У меня (volodya уже писал про предложенные мной PDPT.Valid) просто делается невалидным все юзермодное АП и ловятся ошибки страниц. На время одной инструкции включается TF и разрешается обращение а потом снова выключается TF и запрещается обращение.
     
  18. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Great
    Понятно, значит рестарт инструкций после исключения)
     
  19. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Хм, неплохо. А как быть если cr3 будет загружен новый адрес? Чисто теоретическое предположение. Допустим в ринг0 сидит какая то бяка, которая работает со своими каталогами страниц, о которых мы ничего не знаем.
     
  20. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Мысля в голову пришла, правда толком еще не обкатал. Можно попробовать контролировать запись в user-space, поигравшись с дескрипторами data-сегментов. Если принять за аксиому, что все адреса <80000000h это user-space, то задав сегмент как expand-down и выставив ему лимит 80000000h, мы будем гарантированно ловить запись в меньшие адреса по #GP. Правда и чтение тоже :) Зато не надо заморачиваться с переключением контекстов и соответственно сменой каталогов страниц.