При частой работе с различными шестнадцатеричными и бинарными файлами требуется выделить некие особые последовательности символов (сигнатуры, подписи, блоки данных), которые представлены в виде ASCII символов.
В этом рецепте я покажу код, который покажет все ASCII последовательности в некотором исполняемом файле. Этот код вы можете использовать для изучения исполняемых файлов на предмет наличия разных интересных вещей и закономерностей, а также как очень ценный инструмент по выделению plain-данных из самого файла.
Итак, код рецепта:
import std.algorithm; import std.ascii; import std.conv; import std.file; import std.range; import std.string; import std.stdio; auto getASCII(dstring source) { return source .filter!(a => a.to!dchar.isPrintable) .map!(a => [a]) .join; } void main(string[] arguments) { File file; scope(exit) { (cast(dstring) std.file.read(arguments[0])) .splitLines .map!(a => getASCII(a)) .filter!`a != ""` .each!(a => a.writeln); } }
Запускаем файл рецепта, указывая в качестве опции командной строки файл, который будет подвергнут изучению. Программа считывает файл в бинарном режиме, разбивает его на строки с помощью splitLines, затем каждая строка обрабатывается функцией getASCII (профильтровывает строку, оставляя только печатаемые, т.е видимые на экране, символы ASCII), после чего происходит отсеивание только непустых строк и вывод их в терминал.
Функция getASCII получая на вход строку осуществляет фильтрацию печатаемых символов, переводя их в dchar и выделяя только те, что имеют визуальное представление в экране терминала (с помощью isPrintable). После того, как отработал алгоритм filter, с помощью анонимной функции тождественности, отображающей символ в одномерный массив с символом (функция a => [a]). Отображение дает набор массивов символов, которые затем склеиваются с помощью алгоритма join в единый массив, который будет являться строкой-источником для дальнейшей обработки.
Использовать эту миниатюрную программу очень просто, но стоит учесть, что будут выведены абсолютно все символы из бинарного файла, которые хоть как-то соответствует кодировке ASCII, и поэтому дальнейший поиск данных остается на плечах пользователя этого скромного рецепта.