Большая часть программ от 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.

То же самое выдал онлайн-вычислитель:
"
Вот так, без траты времени на реализацию собственной функции или использования чужого большого кода, мы сделали такую чудесную программку. Было несложно и весело.
Предполагаем, что мы в нужной степени ленивые программисты, знаем С, в ладах с 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().
#include <stdio.h> #include <windows.h> typedef INT (WINAPI *UndocFoo)(INT accumCRC32, const BYTE* buffer, UINT buflen); int main() { HMODULE hDLL = GetModuleHandle(TEXT("ntdll.dll")); if (hDLL == NULL) { puts("[-] Failed to find ntdll.dll\n"); return EXIT_FAILURE; } puts("[+] Got ntdll.dll handle\n"); UndocFoo ComputeCrc32 = (UndocFoo)GetProcAddress(hDLL, "RtlComputeCrc32"); if (ComputeCrc32 == NULL) { puts("[-] Failed to find RtlComputeCrc32\n"); return EXIT_FAILURE; } puts("[+] Found RtlComputeCrc32 address\n"); puts("[*] Calling RtlComputeCrc32...\n"); BYTE buffer[] = {0x01, 'a', 7}; INT iCRC32 = ComputeCrc32(INT(0), (BYTE*)buffer, 3); printf("[+] Computed CRC32 --> 0x%x\n\n", iCRC32); puts("Press any key to quit\n"); getchar(); return EXIT_SUCCESS; }

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

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