Пример конфигурационного файла module.cfg
:
# module.cfg
[Image1]
type=KERNEL
host_path=vmlinux
coverage=False
map=System.map
textstart=0xffffffff81000000
[Image2]
type=USER
host_path=exe/dpkg
coverage=True
debuginfo=exe/dpkg.dbg
[Image3]
type=USER
host_path=exe/apt-get
coverage=True
[Image4]
type=USER
host_path=exe/cat
coverage=True
debuginfo=exe/cat-8.32-31.fc35.x86_64.debug
tieddebug=exe/dwp
vmidb=vmidb/Image4.bin
[Image5]
type= PYTHON
host_path=lib/python3.9
guest_path=/usr/bin/python3.9
coverage=False
debuginfo=lib/02f8a561c3abdb9c8d8c859d4243bd8c3f928f.debug
vmidb=vmidb/Image5.bin
Конфигурационный файл содержит набор секций с префиксом Image
.
В каждой такой секции описывается отдельный бинарный файл.
В этой секции могут быть объявлены следующие поля: type
, host_path
, guest_path
, coverage
, map
, textstart
, debuginfo
, tieddebug
, vmidb
.
Поле type
Для каждого раздела типа Image
обязательно нужно указать его тип, который может быть одним из следующих:
USER
: пользовательский модульKERNEL
-- модуль ядраPYTHON
-- модуль PythonJAVA
-- модуль JavaCSHARP
-- модуль C#SHARED_LIBRARY
-- модуль разделяемой библиотеки
Обычно это поле заполняется автоматически либо при создании конфигурационного файла, либо при загрузке отладочной информации.
Поля host_path и guest_path
Каждый раздел типа Image
обязательно должен содержать хотя бы одно из полей host_path
или guest_path
.
host_path
-- путь к бинарному файлу в хостовой системеguest_path
-- путь к бинарному файлу в гостевой системе
Рекомендуется использовать guest_path
, так как указание host_path
требует дополнительного этапа анализа -- поиска модуля в гостевом образе.
Поле coverage
Для каждого раздела типа Image
обязательно должен быть указать флаг coverage
, который отвечает за попытку выгрузки исходного кода
для данного бинарного файла (необходима для дальнейшего сбора покрытия кода). По умолчанию coverage
установлен в значение "истина"
для всех пользовательских модулей.
Поля map, debuginfo и tieddebug
-
map
-- содержит путь к файлу с символьной информацией, сгенерированной компилятором или дизассемблером IDA (при использовании IDA для генерации map файлов нужно выставлять галочку Segmentation information). -
debuginfo
-- указывает путь к ELF-файлу, содержащему основную отладочную информацию. (Получить информацию о местоположении этого файла можно с помощью командыreadelf -wk <ваш путь к бинарному файлу>
) -
tieddebug
-- указывает путь к ELF-файлу, который содержит альтернативные отладочные символы, дополнительно к тем, что указаны вdebuginfo
. (Получить информацию о местоположении этого файла можно с помощью командыreadelf -wk <ваш путь к файлу с основной отладочной информацией>
)
Эти поля следует использовать, если вы предоставляете бинарный файл без отладочной информации и хотите получить более качественный анализ, например, для отображения имен функций в SNatch.
Поле textstart
При указании поля map
может быть задано поле textstart
.
Как правило, нет необходимости определять textstart
вручную, потому что это просходит автоматически.
В случае, если Natch не сможет определить смещение, будет выведено сообщение.
Поле textstart
используется, если адреса в символьном файле абсолютные, а в исполняемом файле нет.
Так как модуль может загружаться в разные места памяти, необходимо вычислить смещение каждой функции от начала секции .text
.
В поле textstart
как раз и указывается адрес начала секции .text
.
Это поле нужно в редких случаях, например, для ядерных модулей (см. ниже). В остальных случаях можно ничего не указывать.
Чтобы получить информацию о секциях в исполняемом файле, можно использовать утилиту readelf:
readelf -S <config_name>
Пример, когда textstart
необходимо указывать:
map-файл:
ffffffffa0000bed t cleanup_module
ffffffffa00008c2 t logring_syslog_write_raw
ffffffffa0000a4b t init_module
ffffffffa000098d t logring_syslog_write
вывод утилиты readelf:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
0000000000000c8c 0000000000000000 AX 0 0 4
Нас интересуют секции типа PROGBITS
. Если у них указан нулевой адрес, то их не получится
сопоставить с map-файлом при его загрузке в Natch.
Поэтому необходимо вручную определить адрес секции .text
.
Пример, когда textstart
не нужен:
map-файл:
00000006:000000000000C000 .init_proc
00000007:000000000000C030 .wget_netrc_db_free
00000007:000000000000C040 .wget_bar_update
00000007:000000000000C050 .seteuid
00000007:000000000000C060 .chdir
00000007:000000000000C070 .fileno
00000007:000000000000C080 .wget_list_free
00000007:000000000000C090 .dup2
00000007:000000000000C0A0 .printf
вывод утилиты readelf:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[11] .init PROGBITS 000000000000c000 0000c000
0000000000000017 0000000000000000 AX 0 0 4
Адрес секции здесь указан и он соответствует адресам, записанным в map-файле,
поэтому параметр textstart
можно не указывать.
Поле vmidb
Отладочная и символьная информация из исполняемых файлов может быть заранее разобрана и сохранена
во время работы конфигурационных скриптов. Путь к полученному хранилищу записывается в поле vmidb
.
Данное поле заполняется автоматически и не требует ручного вмешательства или корректировки.