Простые вопросы и решения для новичков

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

  1. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Не хотите ли вы составить такую тему? Простых вопросов и ответов на них, когда начинаешь программировать в ядре можно застрять на сущим пустяке надолго. Я думаю такой faq Сейчас приведу несколько примеров.

    Вопрос: Как организовать вывод отладочных сообщений, который бы сам отключался в релиз-версии?
    В ответ два пути:
    1) Использовать KdPrint((<параметры>))
    2) Сделать аналогичную вещь самому:
    Код (Text):
    1. #ifdef DBG
    2. #define Log(_x_) DbgPrint _x_
    3. #else
    4. #define Log(_x_)
    5. #endif
    Вопрос: Как вывести в отладочные сообщения UNICODE_STRING или ANSI_STRING?
    Ответ:
    Код (Text):
    1. PUNICODE_STRING pUStr;
    2. PANSI_STRING    pAStr;
    3. ...
    4. KdPrint(("Unicode string: %wZ\n", pUStr));
    5. KdPrint(("ANSI    string: %Z\n",  pAStr));
    Вопрос: Как "спать" в режиме ядра?
    Ответ:
    Код (Text):
    1. //--------------------------------------------//
    2. // Спасть опеределенное количество милисекунд //
    3. // msec - кол-во милисекунд                   //
    4. //--------------------------------------------//
    5. NTSTATUS ZwSleep(DWORD msec)
    6. {
    7.     LARGE_INTEGER li;
    8.     li.QuadPart = Int32x32To64(-10000, msec);
    9.     return KeDelayExecutionThread(KernelMode, FALSE, &li);
    10. }
    Вопрос: Как генерировать случайные числа в режиме ядра?
    Ответ:
    Код (Text):
    1. //-----------------------------------------------------//
    2. // Получить зерно для рандомизатора от тика процессора //
    3. //-----------------------------------------------------//
    4. DWORD RandomGetSeed()
    5. {
    6.     LARGE_INTEGER ticks;
    7.  
    8.     KeQueryTickCount(&ticks);
    9.     ticks.QuadPart = ticks.QuadPart * KeQueryTimeIncrement();
    10.     return (DWORD)(ticks.QuadPart / 1000); // Милисекунды
    11. }
    12.  
    13. //-----------------------------------------------//
    14. // Получить случайное число в заданном интервале //
    15. // min - минимум                                 //
    16. // max - максимум                                //
    17. // seed - зерно рандомизатора                    //
    18. //-----------------------------------------------//
    19. DWORD Random(DWORD min, DWORD max, DWORD seed)
    20. {
    21.     if(max == 0 || min >= max) { return RtlRandomEx(&seed); }
    22.     else { return (min + (RtlRandomEx(&seed) % (max - min + 1))); }
    23. }
    PS Решения не претендуют на то, чтобы быть единственно верными. Можете критиковать))
    PPS Извиняйте, если подобный faq уже был, я не нашел.
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Вопрос: Как получить текущее время?
    Код (Text):
    1. //--------------------------------------//
    2. // Получить текущее время               //
    3. // tf - возврат времени через структуру //
    4. //--------------------------------------//
    5. NTSTATUS ZwGetCurrentTime(PTIME_FIELDS tf)
    6. {
    7.     LARGE_INTEGER time;
    8.     KeQuerySystemTime(&time);              // Системное время
    9.     ExSystemTimeToLocalTime(&time, &time); // Перевод в локализированное время
    10.     RtlTimeToTimeFields(&time, tf);        // Перевод в годы, месяцы, дни, часы, минуты, секунды, милисекунды
    11.     return STATUS_SUCCESS;
    12. }
     
  3. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Удобная функция для запроса системной информации.
    Код (Text):
    1. //------------------------------------------------------------------------------//
    2. // Запросить системную информацию                                               //
    3. // SystemInformationClass - класс системной информации                          //
    4. // SystemInformation - возврат распределенного для системной информации буффера //
    5. //------------------------------------------------------------------------------//
    6. NTSTATUS ZwGetSystemInfoTable(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID* SystemInformation)
    7. {
    8.     DWORD    size     = 0x4000;
    9.     DWORD    size_out = 0;
    10.     PVOID    ptr      = 0;
    11.     NTSTATUS status   = STATUS_SUCCESS;
    12.  
    13.     // Проверяем параметры
    14.     if(SystemInformation == NULL)
    15.     { return STATUS_INVALID_PARAMETER_2; }
    16.  
    17.     do
    18.     {
    19.         // Распределяем память под буффер
    20.         ptr = Memory_Alloc(size);
    21.         if(ptr == NULL)
    22.         { return STATUS_NO_MEMORY; }
    23.  
    24.         // Запрашиваем системную информацию
    25.         status = ZwQuerySystemInformation(SystemInformationClass, ptr, size, &size_out);
    26.         if (status == STATUS_INFO_LENGTH_MISMATCH)
    27.         {
    28.             // Если буффера не хватило
    29.             Memory_Free(ptr);
    30.             if(SystemInformationClass == SystemCallCounts || SystemInformationClass == SystemModuleInformation)
    31.             { size = size_out; }
    32.             else { size *= 2; }                  
    33.         }
    34.     } while (status == STATUS_INFO_LENGTH_MISMATCH);
    35.  
    36.     // Возвращаем результаты
    37.     if (status == STATUS_SUCCESS)
    38.     { *SystemInformation = ptr; return STATUS_SUCCESS; }
    39.     else
    40.     { Memory_Free(ptr); return status; }
    41. }
     
  4. T800

    T800 Member

    Публикаций:
    0
    Регистрация:
    7 дек 2006
    Сообщения:
    293
    Адрес:
    Moscow
    Поддерживаю такое начинание. Сам только 3-ю неделю эту тематику изучаю, но на таких "проблемах" не застревал)
     
  5. TermoSINteZ

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

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    Замечание (пока одно)
    Код (Text):
    1. ptr = Memory_Alloc(size);
    Это что такое ? Это проверяется на IRQL (какой пул используется)?
    Ну а так.. продолжайте :)
     
  6. Ox8BFF55

    Ox8BFF55 New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2009
    Сообщения:
    181
    Да вы не тем занимаетесь...
    Чаще требуется установить правильный Complete, или отменить Irql, или power manager! А вообще вся дорога в WINDDK\src\
     
  7. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    Функции для простой работы с файлами:
    Код (Text):
    1. ULONG GetFileSize(HANDLE hFile, PULONG FileSizeHigh)
    2. {
    3.     FILE_STANDARD_INFORMATION FileStandard;
    4.     IO_STATUS_BLOCK IoStatusBlock;
    5.  
    6.     NTSTATUS ns = ZwQueryInformationFile(
    7.         hFile,
    8.         &IoStatusBlock,
    9.         &FileStandard,
    10.         sizeof(FILE_STANDARD_INFORMATION),
    11.         FileStandardInformation
    12.     );
    13.     if (!NT_SUCCESS(ns))
    14.     {
    15.         DbgMsg(__FILE__, __LINE__, "ZwQueryInformationFile() fails; status: 0x%.8x\n", ns);
    16.         return -1;        
    17.     }
    18.  
    19.     if (FileSizeHigh != NULL)
    20.         *FileSizeHigh = FileStandard.EndOfFile.u.HighPart;
    21.  
    22.     return FileStandard.EndOfFile.u.LowPart;
    23. }
    24. //--------------------------------------------------------------------------------------
    25. BOOLEAN ReadFromFile(PUNICODE_STRING FileName, PVOID *Data, PULONG DataSize)
    26. {
    27.     BOOLEAN bRet = FALSE;
    28.     NTSTATUS ns;
    29.     OBJECT_ATTRIBUTES ObjAttr;
    30.     HANDLE hFile;
    31.     IO_STATUS_BLOCK StatusBlock;
    32.  
    33.     *Data = NULL;
    34.     *DataSize = 0;
    35.  
    36.     InitializeObjectAttributes(&ObjAttr, FileName,
    37.         OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE , NULL, NULL);
    38.  
    39.     ns = ZwOpenFile(
    40.         &hFile,
    41.         FILE_READ_DATA | SYNCHRONIZE,
    42.         &ObjAttr,
    43.         &StatusBlock,
    44.         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
    45.         FILE_SYNCHRONOUS_IO_NONALERT
    46.     );
    47.     if (NT_SUCCESS(ns))
    48.     {
    49.         ULONG FileSize = GetFileSize(hFile, NULL);
    50.         if (FileSize > 0)
    51.         {
    52.             PVOID FileData = ExAllocatePool(NonPagedPool, FileSize);
    53.             if (FileData)
    54.             {
    55.                 RtlZeroMemory(FileData, FileSize);
    56.  
    57.                 ns = ZwReadFile(hFile, 0, NULL, NULL, &StatusBlock, FileData, FileSize, 0, NULL);
    58.                 if (NT_SUCCESS(ns))
    59.                 {
    60.                     bRet = TRUE;
    61.                     *Data = FileData;
    62.                     *DataSize = FileSize;
    63.                 }
    64.                 else
    65.                 {
    66.                     DbgMsg(__FILE__, __LINE__, "ZwReadFile() fails; status: 0x%.8x\n", ns);
    67.                     ExFreePool(FileData);
    68.                 }
    69.             }
    70.             else
    71.             {
    72.                 DbgMsg(__FILE__, __LINE__, "ExAllocatePool() fails\n");
    73.             }
    74.         }
    75.  
    76.         ZwClose(hFile);
    77.     }
    78.     else
    79.     {
    80.         DbgMsg(__FILE__, __LINE__, "ZwOpenFile() fails; status: 0x%.8x\n", ns);
    81.     }    
    82.  
    83.     return bRet;
    84. }
    85. //--------------------------------------------------------------------------------------
    86. BOOLEAN DumpToFile(PUNICODE_STRING FileName, PVOID Data, ULONG DataSize)
    87. {
    88.     BOOLEAN bRet = FALSE;
    89.     NTSTATUS ns;
    90.     OBJECT_ATTRIBUTES ObjAttr;
    91.     HANDLE hFile;
    92.     IO_STATUS_BLOCK StatusBlock;
    93.  
    94.     InitializeObjectAttributes(&ObjAttr, FileName,
    95.         OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE , NULL, NULL);
    96.  
    97.     ns = ZwCreateFile(
    98.         &hFile,
    99.         FILE_ALL_ACCESS | SYNCHRONIZE,
    100.         &ObjAttr,
    101.         &StatusBlock,
    102.         NULL,
    103.         FILE_ATTRIBUTE_NORMAL,
    104.         0,
    105.         FILE_OVERWRITE_IF,
    106.         FILE_SYNCHRONOUS_IO_NONALERT,
    107.         NULL,
    108.         0
    109.     );
    110.     if (NT_SUCCESS(ns))
    111.     {
    112.         ns = ZwWriteFile(hFile, NULL, NULL, NULL, &StatusBlock, Data, DataSize, NULL, NULL);
    113.         if (NT_SUCCESS(ns))
    114.         {
    115.             bRet = TRUE;        
    116.         }
    117.         else
    118.         {
    119.             DbgMsg(__FILE__, __LINE__, "ZwWriteFile() fails; status: 0x%.8x\n", ns);
    120.         }        
    121.  
    122.         ZwClose(hFile);
    123.     }
    124.     else
    125.     {
    126.         DbgMsg(__FILE__, __LINE__, "ZwOpenFile() fails; status: 0x%.8x\n", ns);
    127.     }    
    128.  
    129.     return bRet;
    130. }
    131. //--------------------------------------------------------------------------------------
    132. BOOLEAN DeleteFile(PUNICODE_STRING usFileName)
    133. {
    134.     BOOLEAN bRet = FALSE;    
    135.     OBJECT_ATTRIBUTES ObjAttr;
    136.     IO_STATUS_BLOCK IoStatusBlock;
    137.     HANDLE FileHandle;
    138.  
    139.     DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): '%wZ'\n", usFileName);
    140.  
    141.     InitializeObjectAttributes(&ObjAttr, usFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
    142.  
    143.     // open file
    144.     NTSTATUS ns = ZwCreateFile(
    145.         &FileHandle,
    146.         DELETE,
    147.         &ObjAttr,
    148.         &IoStatusBlock,
    149.         NULL,
    150.         FILE_ATTRIBUTE_NORMAL,
    151.         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
    152.         FILE_OPEN,
    153.         FILE_NON_DIRECTORY_FILE,
    154.         NULL,
    155.         0
    156.     );    
    157.     if (NT_SUCCESS(ns))
    158.     {
    159.         FILE_BASIC_INFORMATION FileBsicInfo;
    160.        
    161.         ns = ZwQueryInformationFile(
    162.             FileHandle,
    163.             &IoStatusBlock,
    164.             &FileBsicInfo,
    165.             sizeof(FileBsicInfo),
    166.             FileBasicInformation
    167.         );
    168.         if (NT_SUCCESS(ns))
    169.         {
    170.             // chenge file attributes to normal
    171.             FileBsicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
    172.            
    173.             ns = ZwSetInformationFile(
    174.                 FileHandle,
    175.                 &IoStatusBlock,
    176.                 &FileBsicInfo,
    177.                 sizeof(FileBsicInfo),
    178.                 FileBasicInformation
    179.             );
    180.             if (!NT_SUCCESS(ns))
    181.             {
    182.                 DbgMsg(__FILE__, __LINE__, "ZwSetInformationFile() fails; status: 0x%.8x\n", ns);    
    183.             }
    184.         }    
    185.         else
    186.         {
    187.             DbgMsg(__FILE__, __LINE__, "ZwQueryInformationFile() fails; status: 0x%.8x\n", ns);    
    188.         }
    189.  
    190.         FILE_DISPOSITION_INFORMATION FileDispInfo;
    191.         FileDispInfo.DeleteFile = TRUE;    
    192.  
    193.         // ... and delete it
    194.         ns = ZwSetInformationFile(
    195.             FileHandle,
    196.             &IoStatusBlock,
    197.             &FileDispInfo,
    198.             sizeof(FILE_DISPOSITION_INFORMATION),
    199.             FileDispositionInformation
    200.         );
    201.         if (!NT_SUCCESS(ns))
    202.         {
    203.             DbgMsg(__FILE__, __LINE__, "ZwSetInformationFile() fails; status: 0x%.8x\n", ns);    
    204.         }
    205.         else
    206.             bRet = TRUE;
    207.  
    208.         ZwClose(FileHandle);
    209.     }        
    210.     else
    211.     {
    212.         DbgMsg(__FILE__, __LINE__, "ZwCreateFile() fails; status: 0x%.8x\n", ns);
    213.     }
    214.  
    215.     return bRet;
    216. }
    Функция, которая создаёт по привязанному потоку на каждый CPU:
    Код (Text):
    1. typedef struct _PROCESSOR_THREAD_PARAM
    2. {
    3.     KAFFINITY Mask;
    4.     PKSTART_ROUTINE Routine;
    5.     PVOID Param;
    6.  
    7. } PROCESSOR_THREAD_PARAM,
    8. *PPROCESSOR_THREAD_PARAM;
    9.  
    10. void __stdcall ProcessorThread(PVOID Param)
    11. {
    12.     PPROCESSOR_THREAD_PARAM ThreadParam = (PPROCESSOR_THREAD_PARAM)Param;
    13.    
    14.     // bind thread to specific processor
    15.     KeSetSystemAffinityThread(ThreadParam->Mask);
    16.    
    17.     // execute payload on this processor
    18.     ThreadParam->Routine(ThreadParam->Param);
    19. }
    20.  
    21. void ForEachProcessor(PKSTART_ROUTINE Routine, PVOID Param)
    22. {
    23.     // get bitmask of active processors
    24.     KAFFINITY ActiveProcessors = KeQueryActiveProcessors();    
    25.  
    26.     for (KAFFINITY i = 0; i < sizeof(KAFFINITY) * 8; i++)
    27.     {
    28.         KAFFINITY Mask = 1 << i;
    29.         // check if this processor bit present in mask
    30.         if (ActiveProcessors & Mask)
    31.         {
    32.             HANDLE hThread;
    33.             PROCESSOR_THREAD_PARAM ThreadParam;
    34.            
    35.             ThreadParam.Mask    = Mask;
    36.             ThreadParam.Param   = Param;
    37.             ThreadParam.Routine = Routine;
    38.            
    39.             // create thread for this processor
    40.             NTSTATUS ns = PsCreateSystemThread(
    41.                 &hThread,
    42.                 THREAD_ALL_ACCESS,
    43.                 NULL, NULL, NULL,
    44.                 ProcessorThread,
    45.                 &ThreadParam
    46.             );
    47.             if (NT_SUCCESS(ns))
    48.             {
    49.                 PVOID Thread;                
    50.                 // get pointer to thread object
    51.                 ns = ObReferenceObjectByHandle(
    52.                     hThread,
    53.                     THREAD_ALL_ACCESS,
    54.                     NULL,
    55.                     KernelMode,
    56.                     &Thread,
    57.                     NULL
    58.                 );
    59.                 if (NT_SUCCESS(ns))
    60.                 {
    61.                     // waiting for thread termination
    62.                     KeWaitForSingleObject(Thread, Executive, KernelMode, FALSE, NULL);
    63.                     ObDereferenceObject(Thread);
    64.                 }
    65.                 else
    66.                 {
    67.                     DbgMsg(__FILE__, __LINE__, "ObReferenceObjectByHandle() fails; status: 0x%.8x\n", ns);
    68.                 }                
    69.  
    70.                 ZwClose(hThread);
    71.             }
    72.             else
    73.             {
    74.                 DbgMsg(__FILE__, __LINE__, "PsCreateSystemThread() fails; status: 0x%.8x\n", ns);
    75.             }
    76.         }
    77.     }
    78. }
    Функция, которая возвращает номер сисколла по имени Native-функции:
    Код (Text):
    1. ULONG GetSyscallNumber(char *lpszName)
    2. {
    3.     // get base address of ntdll.dll, that mapped into the system process
    4.     PVOID NtdllBase = KernelGetModuleBase("ntdll.dll");
    5.     if (NtdllBase)
    6.     {
    7.         // get function addres by name hash
    8.         ULONG FuncRva = KernelGetExportAddress(NtdllBase, lpszName);
    9.         if (FuncRva)
    10.         {
    11.             PUCHAR Func = (PUCHAR)NtdllBase + FuncRva;
    12. #ifdef _X86_
    13.             // check for mov eax,imm32
    14.             if (*Func == 0xB8)
    15.             {
    16.                 // return imm32 argument (syscall numbr)
    17.                 return *(PULONG)((PUCHAR)Func + 1);
    18.             }
    19. #elif _AMD64_
    20.             // check for mov eax,imm32
    21.             if (*(Func + 3) == 0xB8)
    22.             {
    23.                 // return imm32 argument (syscall numbr)
    24.                 return *(PULONG)(Func + 4);
    25.             }
    26. #endif
    27.         }  
    28.     }    
    29.  
    30.     return 0;
    31. }
    Возвращение имени объекта по дескриптору и приведение к стандартному виду имён, возвращаемых ZwQuerySystemInformation(SystemModuleInformation):
    Код (Text):
    1. POBJECT_NAME_INFORMATION GetObjectNameByHandle(HANDLE hObject)
    2. {
    3.     PVOID pObject;
    4.     NTSTATUS ns;
    5.     POBJECT_NAME_INFORMATION ObjNameInfo = NULL;
    6.  
    7.     ns = ObReferenceObjectByHandle(hObject, 0, 0, KernelMode, &pObject, NULL);
    8.     if (NT_SUCCESS(ns))
    9.     {
    10.         ObjNameInfo = GetObjectName(pObject);
    11.         ObDereferenceObject(pObject);
    12.     }
    13.     else
    14.         DbgMsg(__FILE__, __LINE__, "ObReferenceObjectByHandle() fails; status: 0x%.8x\n", ns);
    15.  
    16.     return ObjNameInfo;
    17. }
    18. //--------------------------------------------------------------------------------------
    19. POBJECT_NAME_INFORMATION GetFullNtPath(PUNICODE_STRING Name)
    20. {
    21.     NTSTATUS ns;
    22.     OBJECT_ATTRIBUTES ObjAttr;
    23.     HANDLE hFile;
    24.     IO_STATUS_BLOCK StatusBlock;
    25.     POBJECT_NAME_INFORMATION ObjNameInf;
    26.  
    27.     InitializeObjectAttributes(&ObjAttr, Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE , NULL, NULL);
    28.  
    29.     ns = ZwOpenFile(
    30.         &hFile,
    31.         FILE_READ_DATA | SYNCHRONIZE,
    32.         &ObjAttr,
    33.         &StatusBlock,
    34.         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
    35.         FILE_SYNCHRONOUS_IO_NONALERT
    36.     );
    37.     if (!NT_SUCCESS(ns))
    38.     {
    39.         return NULL;
    40.     }
    41.  
    42.     ObjNameInf = GetObjectNameByHandle(hFile);
    43.  
    44.     ZwClose(hFile);
    45.  
    46.     return ObjNameInf;
    47. }
    48. //--------------------------------------------------------------------------------------
    49. BOOLEAN GetNormalizedModulePath(PANSI_STRING asPath, PANSI_STRING asNormalizedPath)
    50. {
    51.     BOOLEAN bRet = FALSE;
    52.     ANSI_STRING asFullPath;
    53.     UNICODE_STRING usPath;
    54.     char *lpszWnd = "\\WINDOWS\\", *lpszNt = "\\WINNT\\", *lpszLetter = "\\SystemRoot\\";
    55.  
    56.     if (strlen(lpszWnd) >= asPath->Length)
    57.     {
    58.         return FALSE;
    59.     }
    60.  
    61.     if (!strncmp(asPath->Buffer, lpszWnd, strlen(lpszWnd)) ||
    62.         !strncmp(asPath->Buffer, lpszNt, strlen(lpszNt)))
    63.     {        
    64.         ULONG Ptr = 0;
    65.         if (!strncmp(asPath->Buffer, lpszWnd, strlen(lpszWnd)))
    66.         {
    67.             Ptr = strlen(lpszWnd);
    68.         }
    69.         else if (!strncmp(asPath->Buffer, lpszNt, strlen(lpszNt)))
    70.         {
    71.             Ptr = strlen(lpszNt);
    72.         }
    73.  
    74.         ULONG FullPathLen = asPath->Length - Ptr + strlen(lpszLetter) + 1;
    75.         char *lpszFullPath = (char *)ExAllocatePool(NonPagedPool, FullPathLen);
    76.         if (lpszFullPath)
    77.         {
    78.             RtlZeroMemory(lpszFullPath, FullPathLen);
    79.  
    80.             strcpy(lpszFullPath, lpszLetter);
    81.             strncat(lpszFullPath, asPath->Buffer + Ptr, asPath->Length);            
    82.  
    83.             RtlInitAnsiString(&asFullPath, lpszFullPath);
    84.         }
    85.         else
    86.         {
    87.             DbgMsg(__FILE__, __LINE__, "ExAllocatePool() fails\n");
    88.             return FALSE;
    89.         }
    90.     }    
    91.     else
    92.     {
    93.         asFullPath.Buffer = asPath->Buffer;
    94.         asFullPath.Length = asPath->Length;
    95.         asFullPath.MaximumLength = asPath->MaximumLength;
    96.     }
    97.  
    98.     NTSTATUS ns = RtlAnsiStringToUnicodeString(&usPath, &asFullPath, TRUE);
    99.     if (NT_SUCCESS(ns))
    100.     {
    101.         POBJECT_NAME_INFORMATION ObjName = GetFullNtPath(&usPath);
    102.         if (ObjName)
    103.         {
    104.             NTSTATUS ns = RtlUnicodeStringToAnsiString(asNormalizedPath, &ObjName->Name, TRUE);
    105.             if (NT_SUCCESS(ns))
    106.             {
    107.                 bRet = TRUE;    
    108.             }  
    109.             else
    110.             {
    111.                 DbgMsg(__FILE__, __LINE__, "RtlUnicodeStringToAnsiString() fails; status: 0x%.8x\n", ns);
    112.             }
    113.  
    114.             ExFreePool(ObjName);
    115.         }
    116.  
    117.         RtlFreeUnicodeString(&usPath);
    118.     }
    119.     else
    120.     {
    121.         DbgMsg(__FILE__, __LINE__, "RtlAnsiStringToUnicodeString() fails; status: 0x%.8x\n", ns);
    122.     }
    123.  
    124.     if (asFullPath.Buffer != asPath->Buffer)
    125.     {
    126.         RtlFreeAnsiString(&asFullPath);
    127.     }
    128.  
    129.     return bRet;
    130. }
     
  8. wf_

    wf_ New Member

    Публикаций:
    0
    Регистрация:
    18 окт 2009
    Сообщения:
    40
    кстате по поводу ZwGetSystemInfoTable - совсем не обязательно вызывать ZwQuerySystemInformation в цикле:
    http://msdn.microsoft.com/en-us/library/ms725506%28VS.85%29.aspx
    т.е. можно наверно записать так http://www.everfall.com/paste/id.php?0s18sicf3smr
    а вообще да, продолжайте =)
     
  9. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    А вот %уй :dntknw:
    В некоторых случаях (я с этим часто сталкивался на SystemObjectInformation) второй вызов ZwQuerySystemInformation возвращает тот же статус ошибки. Так что у Rel всё правильно сделанно - в цикле надёжнее.
     
  10. wf_

    wf_ New Member

    Публикаций:
    0
    Регистрация:
    18 окт 2009
    Сообщения:
    40
    ок, принято. Наверно размер выходной структуры изменяется между 2-мя вызовами
     
  11. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    как бы состояние системы между двумя вызовами может измениться.
    И ReturnLength будет содержать устаревшее значение.
     
  12. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Поэтому обычно второй вызов делается с буфером, размер которого = ReturnLength * 2. За исключением ситуаций, когда информация требуется часто и её может быть много.
     
  13. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    Cr4sh
    Спасибо за полезные исходники - давно искал как динамически узнавать номер сервиса.
     
  14. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    Может кому-то понадобится, в процесс написания дрова в VS C++ 2008 было выявлено, что в DDK начиная с NT версии нету DWORD, поэтому юзать надо ULONG. Думаю заменить типа не составит труда :) Ещё не работает макро для вывода отладочной инфы, правильно вот так будет:
    Код (Text):
    1. #ifdef DBG
    2. #define Log DbgPrint
    3. #else
    4. #define Log
    5. #endif
    Если ещё что-то замечу когда будет время отпишу.
     
  15. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    ой, это тоже моя функция... PagedPool используется...

    вообще говоря, мне гораздо удобнее работать с типами, длины которых явно указаны в названии, поэтому:
    Код (Text):
    1. #define QWORD  __int64
    2. #define DWORD  unsigned long
    3. #define WORD   unsigned short  
    4. #define BYTE   unsigned char  
    5. #define PQWORD __int64*        
    6. #define PDWORD unsigned long*  
    7. #define PWORD  unsigned short*
    8. #define PBYTE  unsigned char*
    все работает, вы неправильно вызываете... такое построение макроса требует наличия двойных скобок:
    Код (Text):
    1. Log(("Number: %d", number));
    ваш вариант тоже вполне подходит...
     
  16. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    блин... сегодня весь день думал, почему я не сделал так, как вы предложили, а сделал так, как сделал... дело в том, что ваши дефайны не отключат логирование в релиз версии... смотрите сами:
    Код (Text):
    1. #ifdef DBG
    2. #define Log DbgPrint
    3. #else
    4. #define Log
    5. #endif
    то есть запись в дебаг версии будет верная, то есть при вызове Log("n = %d", n); компилятор получит DbgPrint("n = %d", n)... но в релиз версии в результате такой записи компилятор получит ("n = %d", n) - то есть будет синтаксическая ошибка при компиляции... более того, отвечу почему именно двойные скобки... можно было написать:
    Код (Text):
    1. #define Log(_x_) DbgPrint(_x_)
    по логике все должно нормально работать, но если Log принимает у нас более одного параметра, то при компиляции выдается ворнинг, что мы пытаемся вызвать функцию с большим числом параметров и все последующие параметры после первого игнорируются...
     
  17. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    Правда?) Ну прям чудеса какие-то... Делаем-с так для теста:
    Код (Text):
    1. //#define DBG
    2.  
    3. #ifdef DBG
    4. #define Log DbgPrint
    5. #else
    6. #define Log
    7. #endif
    Всё прекрасно работает...
     
  18. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    З.Ы. Тестовая запись была как:
    Код (Text):
    1. ...
    2. Log("Status for smth is %X %s\n", st, "LOL!");
    3. ...
     
  19. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    Пошерстил все эти исходники - код очень неполный, многих использующихся функций не хватает. На данный момент интересует реализация KernelGetExportAddress.
     
  20. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    d2k9
    sysload.c
    Код (Text):
    1. NTKERNELAPI
    2. PVOID
    3. MmGetSystemRoutineAddress (
    4.     __in PUNICODE_STRING SystemRoutineName
    5.     )
    6.  
    7. /*++
    8.  
    9. Routine Description:
    10.  
    11.     This function returns the address of the argument function pointer if
    12.     it is in the kernel or HAL, NULL if it is not.
    13.  
    14. Arguments:
    15.  
    16.     SystemRoutineName - Supplies the name of the desired routine.
    17.  
    18. Return Value:
    19.  
    20.     Non-NULL function pointer if successful.  NULL if not.
    21.  
    22. Environment:
    23.  
    24.     Kernel mode, PASSIVE_LEVEL, arbitrary process context.
    25.  
    26. --*/
    27.  
    28. {
    29.     PKTHREAD CurrentThread;
    30.     NTSTATUS Status;
    31.     PKLDR_DATA_TABLE_ENTRY DataTableEntry;
    32.     ANSI_STRING AnsiString;
    33.     PLIST_ENTRY NextEntry;
    34.     UNICODE_STRING KernelString;
    35.     UNICODE_STRING HalString;
    36.     PVOID FunctionAddress;
    37.     LOGICAL Found;
    38.     ULONG EntriesChecked;
    39.  
    40.     ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
    41.  
    42.     EntriesChecked = 0;
    43.     FunctionAddress = NULL;
    44.  
    45.     KernelString.Buffer = (const PUSHORT) KERNEL_NAME;
    46.     KernelString.Length = sizeof (KERNEL_NAME) - sizeof (WCHAR);
    47.     KernelString.MaximumLength = sizeof KERNEL_NAME;
    48.  
    49.     HalString.Buffer = (const PUSHORT) HAL_NAME;
    50.     HalString.Length = sizeof (HAL_NAME) - sizeof (WCHAR);
    51.     HalString.MaximumLength = sizeof HAL_NAME;
    52.  
    53.     do {
    54.         Status = RtlUnicodeStringToAnsiString (&AnsiString,
    55.                                                SystemRoutineName,
    56.                                                TRUE);
    57.  
    58.         if (NT_SUCCESS (Status)) {
    59.             break;
    60.         }
    61.  
    62.         KeDelayExecutionThread (KernelMode, FALSE, (PLARGE_INTEGER)&MmShortTime);
    63.  
    64.     } while (TRUE);
    65.  
    66.     //
    67.     // Arbitrary process context so prevent suspend APCs now.
    68.     //
    69.  
    70.     CurrentThread = KeGetCurrentThread ();
    71.     KeEnterCriticalRegionThread (CurrentThread);
    72.     ExAcquireResourceSharedLite (&PsLoadedModuleResource, TRUE);
    73.  
    74.     //
    75.     // Check only the kernel and the HAL for exports.
    76.     //
    77.  
    78.     NextEntry = PsLoadedModuleList.Flink;
    79.     while (NextEntry != &PsLoadedModuleList) {
    80.  
    81.         Found = FALSE;
    82.  
    83.         DataTableEntry = CONTAINING_RECORD(NextEntry,
    84.                                            KLDR_DATA_TABLE_ENTRY,
    85.                                            InLoadOrderLinks);
    86.  
    87.         if (RtlEqualUnicodeString (&KernelString,
    88.                                    &DataTableEntry->BaseDllName,
    89.                                    TRUE)) {
    90.  
    91.             Found = TRUE;
    92.             EntriesChecked += 1;
    93.  
    94.         }
    95.         else if (RtlEqualUnicodeString (&HalString,
    96.                                         &DataTableEntry->BaseDllName,
    97.                                         TRUE)) {
    98.  
    99.             Found = TRUE;
    100.             EntriesChecked += 1;
    101.         }
    102.  
    103.         if (Found == TRUE) {
    104.  
    105.             FunctionAddress = MiFindExportedRoutineByName (DataTableEntry->DllBase,
    106.                                                            &AnsiString);
    107.  
    108.             if (FunctionAddress != NULL) {
    109.                 break;
    110.             }
    111.  
    112.             if (EntriesChecked == 2) {
    113.                 break;
    114.             }
    115.         }
    116.  
    117.         NextEntry = NextEntry->Flink;
    118.     }
    119.  
    120.     ExReleaseResourceLite (&PsLoadedModuleResource);
    121.     KeLeaveCriticalRegionThread (CurrentThread);
    122.  
    123.     RtlFreeAnsiString (&AnsiString);
    124.  
    125.     return FunctionAddress;
    126. }
    127. PVOID
    128. MiFindExportedRoutineByName (
    129.     IN PVOID DllBase,
    130.     IN PANSI_STRING AnsiImageRoutineName
    131.     )
    132.  
    133. /*++
    134.  
    135. Routine Description:
    136.  
    137.     This function searches the argument module looking for the requested
    138.     exported function name.
    139.  
    140. Arguments:
    141.  
    142.     DllBase - Supplies the base address of the requested module.
    143.  
    144.     AnsiImageRoutineName - Supplies the ANSI routine name being searched for.
    145.  
    146. Return Value:
    147.  
    148.     The virtual address of the requested routine or NULL if not found.
    149.  
    150. --*/
    151.  
    152. {
    153.     USHORT OrdinalNumber;
    154.     PULONG NameTableBase;
    155.     PUSHORT NameOrdinalTableBase;
    156.     PULONG Addr;
    157.     LONG High;
    158.     LONG Low;
    159.     LONG Middle;
    160.     LONG Result;
    161.     ULONG ExportSize;
    162.     PVOID FunctionAddress;
    163.     PIMAGE_EXPORT_DIRECTORY ExportDirectory;
    164.  
    165.     PAGED_CODE();
    166.  
    167.     ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) RtlImageDirectoryEntryToData (
    168.                                 DllBase,
    169.                                 TRUE,
    170.                                 IMAGE_DIRECTORY_ENTRY_EXPORT,
    171.                                 &ExportSize);
    172.  
    173.     if (ExportDirectory == NULL) {
    174.         return NULL;
    175.     }
    176.  
    177.     //
    178.     // Initialize the pointer to the array of RVA-based ansi export strings.
    179.     //
    180.  
    181.     NameTableBase = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNames);
    182.  
    183.     //
    184.     // Initialize the pointer to the array of USHORT ordinal numbers.
    185.     //
    186.  
    187.     NameOrdinalTableBase = (PUSHORT)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
    188.  
    189.     //
    190.     // Lookup the desired name in the name table using a binary search.
    191.     //
    192.  
    193.     Low = 0;
    194.     Middle = 0;
    195.     High = ExportDirectory->NumberOfNames - 1;
    196.  
    197.     while (High >= Low) {
    198.  
    199.         //
    200.         // Compute the next probe index and compare the import name
    201.         // with the export name entry.
    202.         //
    203.  
    204.         Middle = (Low + High) >> 1;
    205.  
    206.         Result = strcmp (AnsiImageRoutineName->Buffer,
    207.                          (PCHAR)DllBase + NameTableBase[Middle]);
    208.  
    209.         if (Result < 0) {
    210.             High = Middle - 1;
    211.         }
    212.         else if (Result > 0) {
    213.             Low = Middle + 1;
    214.         }
    215.         else {
    216.             break;
    217.         }
    218.     }
    219.  
    220.     //
    221.     // If the high index is less than the low index, then a matching
    222.     // table entry was not found. Otherwise, get the ordinal number
    223.     // from the ordinal table.
    224.     //
    225.  
    226.     if (High < Low) {
    227.         return NULL;
    228.     }
    229.  
    230.     OrdinalNumber = NameOrdinalTableBase[Middle];
    231.  
    232.     //
    233.     // If the OrdinalNumber is not within the Export Address Table,
    234.     // then this image does not implement the function.  Return not found.
    235.     //
    236.  
    237.     if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) {
    238.         return NULL;
    239.     }
    240.  
    241.     //
    242.     // Index into the array of RVA export addresses by ordinal number.
    243.     //
    244.  
    245.     Addr = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
    246.  
    247.     FunctionAddress = (PVOID)((PCHAR)DllBase + Addr[OrdinalNumber]);
    248.  
    249.     //
    250.     // Forwarders are not used by the kernel and HAL to each other.
    251.     //
    252.  
    253.     ASSERT ((FunctionAddress <= (PVOID)ExportDirectory) ||
    254.             (FunctionAddress >= (PVOID)((PCHAR)ExportDirectory + ExportSize)));
    255.  
    256.     return FunctionAddress;
    257. }