При частой работе с различными шестнадцатеричными и бинарными файлами требуется выделить некие особые последовательности символов (сигнатуры, подписи, блоки данных), которые представлены в виде 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, и поэтому дальнейший поиск данных остается на плечах пользователя этого скромного рецепта.