Яндекс.Метрика

    Песочница

    Пример использования недокументированной функции Windows

    Большая часть программ от Sysinternals использует недокументированные функции. Мне хватило этого факта, чтобы заинтересоваться этой темой. Интересно, как крутые дядьки используют неописанные функции в своих не менее крутых программах.

    Предполагаем, что мы в нужной степени ленивые программисты, знаем С, в ладах с WinAPI и с архитектурой современной ОС Windows и у нас есть Ida Pro, хе-хе. Хотим красиво, быстро и эффективно выполнить задачу, не изобретая велосипед (и чтоб ещё сильно не перенапрячь руки и голову).
    Поищем подопытную функцию. Много вкусного можно найти в ntdll.dll. Сам я пишу из-под Win7 64, но взял 32-битную версию чудесной библиотеки. На всякий случай: %SystemDisk%\Windows\System32\ntdll.dll.

    Чтобы было просто, откроем ntdll в Ida и посмотрим, какие функции экспортируются. Если нет Ida, то можно взять любую программу работающую с PE-файлами (например, PETools). Нас интересуют функции с приставкой Rtl (Run Time Library). То есть во время выполнения нашего кода мы можем попросить эту системную функцию об услуге.

    После небольшого поиска простенькой функции, таковая нашлась — RtlComputeCrc32.



    Двойным щелчок по имени функции получаем её дизассемблированный код. Изучать функцию можно и любым другим дизассемблером вроде HDasm или W32Dasm. Чтобы не тратить место, приведу псевдокод RtlComputeCrc32, любезно предоставленный декомпилятором Ida (в теле функции нажать F5, если Hex-Rays Decompiler имеется в плагинах Edit->Plugins).



    Сразу получаем много информации! Надо подумать, что мы, собственно, ищем. Нам нужно:
    1) имя функции, чтобы получить её адрес в ntdll;
    2) прототип функции, чтобы создать правильный указатель на неё;
    3) примерный принцип работы, чтобы передать ей корректные аргументы и правильно обработать результат;

    Пункты 1-2 у нас уже есть из псевдокода. Задача наша теперь разобраться в функции и на её основе написать программу, высчитывающую CRC32 от чего-то.

    По псевдокоду легко понять, что функция перебирает байты массива a2, размер которого a3, а а1 — инициализирующее значение алгоритма. Проделав вычисления с байтами, получает индекс из таблицы RtlCrc32Table (двойной щелчок покажет монструозную таблицу). Гуглим CRC32 и примеры реализации и понимаем, что всё верно.

    Дело за малым — воспользоваться добычей. Я сделал пустое консольное приложение в Visual Studio, но делать, естественно, можно и в любой другой среде.

    GetModuleHandle() возвращает хэндл ntdll, GetProcAddress() — адрес функции. Используем указатель на функцию типа UndocFoo для вызова RtlComputeCRC32().






    Успех. Проверить можно с помощью любого онлайн-вычислителя.
    Наши байты 016107 дали CRC32 = 0x1c017c60.



    То же самое выдал онлайн-вычислитель:

    "

    Вот так, без траты времени на реализацию собственной функции или использования чужого большого кода, мы сделали такую чудесную программку. Было несложно и весело.