ExRaiseHardError и Windows 7

Тема в разделе "WASM.NT.KERNEL", создана пользователем katrus, 30 апр 2009.

  1. katrus

    katrus New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    612
    Недавно Great опубликовал интерсный метод для выдачи модального диалога из ядра.
    http://gr8.cih.ms/?entry=entry015.

    Обнаружил, что в Windows 7, данный метод не работает. ExRaiseHardError возвращает STATUS_SUCCESS, но диалог не отображается. Можно ли как-то это "поправить".
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Я, кстати, апдейтнул исходный код, чтобы выводить диалог из контекста любого процесса.
    (код в блоге работает только из system)

    нужно доставить WorkItem системному процессу и + там поменял ExRaiseHardError на ZwRaiseHardError
    http://www.everfall.com/paste/id.php?ynz09b03jl5l - исходник

    вызывать нужно DisplayMessage как и раньше. она все сделает.
    но предварительно в инициализации вызвать GuiInitialize()
    как реализовать GetFunctionSdtNumber, думаю, сами разберетесь. Найти базу ntdll, найти в экспорте ntdll функцию и вынуть оттуда номер из инструкции mov eax, NUMBER

    Посмотрим. я себе как раз слил win7 (по работе надо было).
     
  3. katrus

    katrus New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    612
    А можно ли полный исходник, или скомпилированный драйвер? Хочется быстро проверить - работает ли данный метод в Win7 или нет?
     
  4. katrus

    katrus New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    612
    Great
    Начал рабраться сам, не могу понять, что такое
    Код (Text):
    1. extern PEPROCESS PsSystemProcess;
    Где PsSystemProcess определен?
     
  5. wasm_test

    wasm_test wasm test user

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

    ну собственно раз так усердно просите..
    код GetFunctionSsdtNumber и нужных ей функций
    Код (Text):
    1. #include "nt.h"
    2.  
    3.  
    4. PVOID OriginalSdt;
    5.  
    6. typedef struct _SYSTEM_MODULES {
    7.   ULONG                ModulesCount;
    8. #pragma warning(disable: 4200)
    9.   SYSTEM_MODULE_INFORMATION        Modules[0];
    10. #pragma warning(default: 4200)
    11. } SYSTEM_MODULES, *PSYSTEM_MODULES;
    12.  
    13.  
    14. PVOID
    15. GetSystemInformation (
    16.     SYSTEM_INFORMATION_CLASS InfoClass
    17.     )
    18. /**
    19.     Get system information by class.
    20.     ZwQuerySystemInformation wrapper
    21. */
    22. {
    23.     NTSTATUS Status;
    24.     PVOID Buffer;
    25.     ULONG Size = PAGE_SIZE * 4;
    26.    
    27.     ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
    28.  
    29.     do
    30.     {
    31.         ULONG t;
    32.  
    33.         Buffer = ExAllocatePool (PagedPool, Size);
    34.  
    35.         Status = ZwQuerySystemInformation ( InfoClass,
    36.                                             Buffer,
    37.                                             Size,
    38.                                             &t );
    39.  
    40.         if (!NT_SUCCESS(Status))
    41.             ExFreePool (Buffer);
    42.  
    43.         Size = Size + PAGE_SIZE*4;
    44.     }
    45.     while (Status == STATUS_INFO_LENGTH_MISMATCH);
    46.  
    47.     if (!NT_SUCCESS(Status))
    48.     {
    49.         return NULL;
    50.     }
    51.  
    52.     return Buffer;
    53. }
    54.  
    55. PVOID FindNtdll()
    56. {
    57.     PSYSTEM_MODULES Modules = (PSYSTEM_MODULES) GetSystemInformation (SystemModuleInformation);
    58.     PVOID Ntdll = NULL;
    59.  
    60.     if (Modules)
    61.     {
    62.         for (ULONG i=0; i<Modules->ModulesCount; i++)
    63.         {
    64.             _strlwr (Modules->Modules[i].ImageName);
    65.  
    66.             if (strstr (Modules->Modules[i].ImageName, "ntdll"))
    67.             {
    68.                 Ntdll = Modules->Modules[i].Base;
    69.                 break;
    70.             }
    71.         }
    72.  
    73.         ExFreePool (Modules);
    74.     }
    75.  
    76.     return Ntdll;
    77. }
    78.  
    79. PVOID
    80. FindImageProcedureByNameOrPointer(
    81.     IN PVOID Base,
    82.     IN PCHAR FunctionName OPTIONAL,
    83.     IN PVOID FunctionEntry OPTIONAL
    84.     )
    85. {
    86.     PIMAGE_DOS_HEADER mz;
    87.     PIMAGE_FILE_HEADER pfh;
    88.     PIMAGE_OPTIONAL_HEADER poh;
    89.     PIMAGE_EXPORT_DIRECTORY pexd;
    90.     PULONG AddressOfFunctions;
    91.     PULONG AddressOfNames;
    92.     PUSHORT AddressOfNameOrdinals;
    93.     ULONG i;
    94.    
    95.     // Get headers
    96.     *(PUCHAR*)&mz = (PUCHAR)Base;
    97.     *(PUCHAR*)&pfh = (PUCHAR)Base + mz->e_lfanew + sizeof(IMAGE_NT_SIGNATURE);
    98.     *(PIMAGE_FILE_HEADER*)&poh = pfh + 1;
    99.  
    100.     // Get export
    101.     *(PUCHAR*)&pexd = (PUCHAR)Base + poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    102.     *(PUCHAR*)&AddressOfFunctions = (PUCHAR)Base + pexd->AddressOfFunctions;
    103.     *(PUCHAR*)&AddressOfNames = (PUCHAR)Base + pexd->AddressOfNames;
    104.     *(PUCHAR*)&AddressOfNameOrdinals = (PUCHAR)Base + pexd->AddressOfNameOrdinals;
    105.  
    106.     // Find function
    107.     for( i=0; i<pexd->NumberOfNames; i++ )
    108.     {
    109.         PCHAR name = ((char*)Base + AddressOfNames[i]);
    110.         PVOID addr = (PVOID*)((ULONG)Base + AddressOfFunctions[AddressOfNameOrdinals[i]]);
    111.  
    112.         if (ARGUMENT_PRESENT (FunctionName))
    113.         {
    114.             if( !strcmp( name, FunctionName ) )
    115.             {
    116.                 return addr;
    117.             }
    118.         }
    119.         else if (ARGUMENT_PRESENT (FunctionEntry))
    120.         {
    121.             if (FunctionEntry == addr)
    122.                 return name;
    123.         }
    124.         else
    125.         {
    126.             ASSERTMSG ("SHOULD NOT REACH HERE", ARGUMENT_PRESENT(FunctionName) || ARGUMENT_PRESENT(FunctionEntry));
    127.         }
    128.     }
    129.    
    130.     return NULL;
    131. }
    132.  
    133. ULONG GetFunctionSdtNumber (PCHAR Function)
    134. {
    135.     static PVOID Ntdll = NULL;
    136.  
    137.     if (!Ntdll)
    138.     {
    139.         Ntdll = FindNtdll();
    140.         if (!Ntdll)
    141.             return -1;
    142.     }
    143.  
    144.     ULONG Number = -1;
    145.     PVOID Proc = FindImageProcedureByNameOrPointer (Ntdll, Function, NULL);
    146.     if (Proc)
    147.     {
    148.         Number = *(ULONG*)( (PUCHAR)Proc + 1 );
    149.     }
    150.  
    151.     return Number;
    152. }
    код DriverEntry
    Код (Text):
    1. PEPROCESS PsSystemProcess;
    2.  
    3. // Driver entry point
    4. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
    5. {
    6.     KdPrint(("[~] DriverEntry()\n"));
    7.  
    8.     PsSystemProcess = PsGetCurrentProcess();
    9.  
    10.     GuiInitialize();
    11.  
    12.     DisplayMessage (L"The matrix has you", OptionOk);
    13.  
    14.     KdPrint(("[+] Driver initialization successful\n"));
    15.     return STATUS_UNSUCCESSFUL;
    16. }
    код nt.h со всякими полезными определениями структур http://www.everfall.com/paste/id.php?8vv1owxtiaqy

    теперь если все части вместе собрать, должно скопмпилироваться. полных исходников/бинарей не выслать не могу - дорабатывал уже в другом проекте, где это юзается и там много лишнего кода. но того, что я дал, должно хватить для компиляции
     
  6. katrus

    katrus New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    612
    Great
    Большое спасибо! Все скомпилировалось. Под ХР работает, по Win7 - нет. ExRaiseHardError банальным образом ничего не делает.
     
  7. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Да, я пореверсил, оказалось, что в вин7 csrss.exe не обрабатывает hard errorы от процесса System, откуда я собственно и вызываю.
    Надо вызывать из контекста другого процесса. Например, lsass.exe

    Кстати, в висте кто-нибудь тестил?
     
  8. katrus

    katrus New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    612
    Да попробовал - не работает.
     
  9. katrus

    katrus New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    612
    Кстати, если кому нужно - готовый компилируемый пример с кодом Great.
     
  10. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Наверное, в висте тоже блочится.
    Я пока что писать аттач к lsass для висты/вин7 не буду. Работа ждет.
    Будет время - напишу
     
  11. katrus

    katrus New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    612
    То есть достаточно найти PKPROCESS lsass и заменить
    Код (Text):
    1. KeStackAttachProcess ((PKPROCESS)PsSystemProcess, &ApcState);
    на
    Код (Text):
    1. KeStackAttachProcess ((PKPROCESS)ps_lsass, &ApcState)
    ?
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    А не проще будет поток создать и нормальную MessageBox* вызвать ?
    И окно нормально будет и никаких проблем с совместимостью.
     
  13. katrus

    katrus New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    612
    Может и проще. Но, соданный из ядра поток не будет GUI потоком. Сколько я не возился - не смог зарегистрировать созданный из ядра поток и превратить его в GUI. Доплнительное достоинство ExRaiseHardError - созданный диалог модален и отпадает необходимость в синхонизации. Еще очень важное достоинство - любой антивирус относится абсолютно равнодушно к ExRaiseHardError.
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Любой антивирус и детектор руткитов относится равнодушно к регистрации дебуггера и сервису 0x30404 порта \ApiPort создающему удалённый поток, также как и захват контекста и всё остальное.
     
  15. ntcdm

    ntcdm New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2007
    Сообщения:
    247
    Clerk
    Извините пожалуйста за оффтопик, но где можно почитать про сервисы портов, в частности интересует \SmApiPort \ApiPort и \WxApiPort ?
     
  16. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    документированно нигде.
    в исходниках win2k, если у тебя есть.
    либо разреверсить CreateProcessInternalW и CsrClientCallServer и посмотреть как оно общается с ApiPort
     
  17. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    А между тем это просто.
     
  18. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    PsConvertToGuiThread ?
     
  19. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Эта функция будет вызвана при вызове любого теневого сервиса автоматически, зачем вручную её юзать.
     
  20. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Посмотрел как оболочка выводин сообщения(это если в NtRaiseHardError указать OptionOkNoWait).
    csrss обрабатывает запрос на порт, в конечном итоге HardErrorHandler() -> CheckShellHardError() посылает сообщение проводнику, который выводит сообщение. В трей сообщение выводится если параметр ShellErrorMode = 1 в разделе HKLM\System\CurrentControlSet\Control\Windows. Главное параметры корректные передать, иначе слетит проводник. Вот пример:
    Код (Text):
    1. .data
    2. MessageId   ULONG ? ; -> RegisterWindowMessage()
    3. SizeOfData  ULONG (_ends - Undef2)
    4. MsgData     PVOID Undef2
    5. Undef2      ULONG 0
    6. Status      NTSTATUS STATUS_SUCCESS
    7. Undef3      ULONG 0
    8. DtMsgTitle  ULONG (offset MsgTitle - offset Undef2)
    9. DtMsgText   ULONG (offset MsgText - offset Undef2)
    10. MsgTitle    WCHAR "M","e","s","s","a","g","e",":",0
    11. MsgText     WCHAR "H","e","l","l","o"," ","W","o","r","l","d","!",0
    12. _ends       db 0
    13.  
    14. MsgName CHAR "HardError",0
    15.  
    16. .code
    17. Entry proc
    18. Local Result:ULONG
    19.     invoke RegisterWindowMessage, addr MsgName
    20.     mov MessageId,eax
    21.     invoke GetTaskmanWindow     ;'MSTaskSwWClass'
    22.     mov edx,eax
    23.     invoke SendMessageTimeout, edx, WM_COPYDATA, 0, addr MessageId, SMTO_NORMAL or SMTO_ABORTIFHUNG, 3000, addr Result
    24.     ret
    25. Entry endp
    26. end Entry
    Структура сообщения, но не все поля определил:
    Код (Text):
    1. HARDERROR_MESSAGE struct
    2. MessageId       ULONG ? ; -> RegisterWindowMessage()
    3. SizeOfData      ULONG ?
    4. MsgData         PVOID ?
    5. ;[...]
    6. ;MsgData:
    7. DtAppName       ULONG ?     ; (MsgData + DtAppName):PWCHAR
    8. Status          NTSTATUS ?
    9. Undefined2      ULONG ?     ;
    10. DtMsgTitle      ULONG ?     ; OPTIONAL, (MsgData + DtMsgTitle):PWCHAR
    11. DtMsgText       ULONG ?     ; (MsgData + DtMsgText):PWCHAR
    12. ;Buffer         WCHAR 1 DUP (?)
    13. HARDERROR_MESSAGE ends
    ID обязательно для этой строки, иначе в проводнике проверка и он не пропустит вызов. Собственно результат:
    [​IMG]
    Разумеется из ядра это не юзабельно. Нужно посмотреть как там на ErrorPort сообщения посылаются посредством LpcRequestWaitReplyPort().