Предлагаемая к ознакомлению статья расскажет как из популярного инструмента лечения от компьютерных вирусов сделать загружаемый по сети (pxe-bootable) вариант. Материал будет полезен системным администраторам, работникам сервис-центров и, возможно, кому-то еще, кому часто приходится реанимировать зараженные вирусами компьютеры.
Статья актуальна для версии Kaspersky Rescue Disk 10.0.31.4 (последняя на момент публикации версия).
Задача сводится к нескольким пунктам:
Требования к серверной части:
Требования к клиентской части:
Скрипт prepare.sh запускается один раз с целью подготовить все необходимое, а именно:
Листинг prepare.sh:
Патч retranslator.patch
Патч squashfs.patch
Если все прошло без ошибок, то в папке ./squashfs4.2/squashfs-tools/ появятся два исполняемых файла — mksquashfs и unsquashfs, а в папке ./retranslator появится готовое к работе локальное зеркало антивирусных баз.
Это основной скрипт, результатом работы которого являются три файла: ядро «rescue», рамдиск «rescue.igz» и файл конфигурации «menu.cfg» для pxelinux.
Листинг make_rescue.igz.sh:
Патч init.patch
Патч dmsquash-live-root.patch
Патч config.xml.patch меняет всего лишь две настройки: во-первых, включает проверку файлов «по формату», и, во-вторых, отключает проверку архивов:
По завершении работы скрипта файл ${tftproot_dir}/${dest_dir}/menu.cfg будет иметь примерно такое содержимое:
Остается добавить в ваш pxelinux.cfg/default такую строку (конечно, изменив путь на свой):
И, чтобы было совсем понятно, приведу часть моего pxelinux.cfg/default
У меня меню выглядит вот так:
Процесс загрузки:
Ура, всё работает:
Напоследок остается добавить задание в crontab. Если вы хотите обновлять образ ежедневно, скажем, в восемь часов утра, то конфиг будет такой:
Не забудьте изменить пути на свои!
P.S. скачать архив со всеми скриптами и патчами можно тут.
Статья актуальна для версии Kaspersky Rescue Disk 10.0.31.4 (последняя на момент публикации версия).
Постановка задачи
Задача сводится к нескольким пунктам:
- Адаптировать Kaspersky Rescue Disk 10 (далее просто KRD10) к загрузке по сети.
- Предусмотреть локальное зеркало обновлений, из которого можно было бы периодически обновлять антивирусные базы, не скачивая каждый раз свежий iso-образ.
- Изменить кое-какие настройки антивируса по-умолчанию. Например, проверка архивов подчас занимает много времени, а каждый раз снимать перед сканом одну и ту же галку в настройках утомительно.
- Максимально автоматизировать выполнение перечисленных выше пунктов, сведя количество необходимых к нажатию кнопок до минимума.
Системные требования
Требования к серверной части:
- Операционная система Ubuntu 10.04 или новее. Я тестировал скрипты с Ubuntu 10.04 Server x32 и Ubuntu 11.10 Desktop x32. Если у вас иной дистрибутив Linux, то, возможно, потребуется что-то изменить.
- Работают сервисы dhcp и tftp.
- Настроен pxelinux (имеется загрузчик pxelinux.0, конфигурационный файл pxelinux.cfg/defult и т.п).
Требования к клиентской части:
- Сетевой адаптер с поддержкой PXE BOOT ROM.
- Не менее 512MB RAM.
Скрипт prepare.sh
Скрипт prepare.sh запускается один раз с целью подготовить все необходимое, а именно:
- Установить недостающие пакеты (или убедиться в их наличии).
- Скачать iso-образ KRD10.
- Скачать утилиту обновления антивирусных баз.
- Скачать и собрать из исходников squashfs-tools.
Листинг prepare.sh:
#!/bin/sh
# Объявляем переменные
krd10_src="http://rescuedisk.kaspersky-labs.com/rescuedisk/updatable/kav_rescue_10.iso"
retranslator_src="http://utils.kaspersky.com/updater/retranslator_5.0.0.9/Linux/retranslator-5.0.0-9.tar.gz"
squashfs_src="http://jaist.dl.sourceforge.net/project/squashfs/squashfs/squashfs4.2/squashfs4.2.tar.gz"
# Установка недостающих пакетов
echo && echo "STEP 1 : Do you have zlib, lzma, g++ and patch?"
apt-get -q -y install zlib1g-dev liblzma-dev lzma g++ patch
# Скачиваем необходимые файлы
echo && echo "STEP 2 : I need to download some files..."
# KRD10
wget -nc -c $krd10_src
if [ "$?" -ne "0" ]; then
echo
echo "Can't download Kaspersky Rescue Disk 10 iso image!"
echo
exit 1
fi
# Утилита обновления антивирусных баз
wget -nc -c $retranslator_src
if [ "$?" -ne "0" ]; then
echo
echo "Can't download RETRANSLATOR!"
echo
exit 1
fi
# Исходники squashfs-tools
wget -nc -c $squashfs_src
if [ "$?" -ne "0" ]; then
echo
echo "Can't download SQUASHFS package!"
echo
exit 1
fi
# Распаковка
echo && echo "STEP 3 : Let's see what's inside..."
tar -xzf retranslator-5.0.0-9.tar.gz
tar -xzf squashfs4.2.tar.gz
# Патчим файлы конфигурации
echo && echo "STEP 4 : Patching config files..."
# Настройка утилиты обновления антивирусных баз
patch -p0 -i retranslator.patch
# Настройка Makefile (активация опции поддержки XZ-сжатия)
patch -p0 -i squashfs.patch
# Собираем squashfs4.2
echo && echo "STEP 5 : Building squashfs4.2 with XZ support..."
make -C ./squashfs4.2/squashfs-tools/
Патч retranslator.patch
--- ./retranslator/retranslator.bak 2010-07-14 02:51:11.000000000 +1100
+++ ./retranslator/retranslator.conf 2012-01-08 18:30:56.438109054 +1100
@@ -35,23 +35,23 @@
#
# Optional specification of components to be retranslated.
#
-RetranslateComponentsList=AVS, CORE, BLST, Updater
+RetranslateComponentsList=EMU,KDB,QSCAN,RD
#
# Optional specification of OS filter.
#
-#os2=Win;Mac;Linux
+os2=Linux
#
# Optional specification of instruction set filter.
#
-#instrset=kernel:i386,x64;user:i386;
+instrset=kernel:i386;user:i386;
#
# Optional specification of application filter.
#
-#application=WKS 6.0.4.1424;
+application=RD 10.*.*.*;
#
# Optional specification of build filter.
@@ -182,5 +182,5 @@
# this level if you are reporting bugs in the product. Do not forget to turn
# it off afterwords. Debug messages have 'D' mark in the log file.
#
-ReportLevel=9
+ReportLevel=3
Патч squashfs.patch
--- ./squashfs4.2/squashfs-tools/Makefile.bak 2011-03-01 06:04:15.000000000 +1000
+++ ./squashfs4.2/squashfs-tools/Makefile 2012-03-13 12:20:20.823261029 +1100
@@ -26,7 +26,7 @@
# To build using XZ Utils liblzma - install the library and uncomment
# the XZ_SUPPORT line below.
#
-#XZ_SUPPORT = 1
+XZ_SUPPORT = 1
############ Building LZO support ##############
Если все прошло без ошибок, то в папке ./squashfs4.2/squashfs-tools/ появятся два исполняемых файла — mksquashfs и unsquashfs, а в папке ./retranslator появится готовое к работе локальное зеркало антивирусных баз.
Скрипт make_rescue.igz.sh
Это основной скрипт, результатом работы которого являются три файла: ядро «rescue», рамдиск «rescue.igz» и файл конфигурации «menu.cfg» для pxelinux.
Листинг make_rescue.igz.sh:
#!/bin/sh
# Переход в каталог, из которого запущен этот скрипт, актуально для запуска из crontab.
cd $(cd $(dirname $0) && pwd)
# Объявляем переменные.
krd10_iso="http://rescuedisk.kaspersky-labs.com/rescuedisk/updatable/kav_rescue_10.iso"
# Корневая папка tftp (в ней должен также быть загрузчик pxelinux.0 и т.п.),
# измените путь на свой.
tftproot_dir="/storage/tftproot"
# Папка назначения относительно tftproot_dir, измените путь на свой.
dest_dir="apps/kaspersky"
# Установите download_iso="1" если хотите, чтобы каждый раз скачивался свежий образ KRD10.
# Менять не рекомендуется, оставлено для отладки.
download_iso="0"
# Установите update_liveos="0" если не хотите менять настройки KRD10 или добавлять свои файлы.
update_liveos="1"
# Установите compress_lzma="1" если хотите сжать конечный образ.
# Эффективность сжатия не велика, по-умолчанию отключено.
compress_lzma="0"
# Скачиваем образ KRD10 если соответствующий флаг установлен.
echo && echo "STEP 1 : Downloading iso image..."
if [ "${download_iso}" = "1" ]; then
if [ -e "kav_rescue_10.iso" ]; then
mv -f kav_rescue_10.iso kav_rescue_10.iso.bak
fi
wget -nv ${krd10_iso}
else
echo "This step was skipped."
fi
# Обновляем антивирусные базы
echo && echo "STEP 2 : Downloading anti-virus bases..."
# Запоминаем версию старых баз (sed нужен для избавления от символа "возврата каретки" в конце строки).
if [ -e "retranslator/bases/bases/av/kdb/i386/old/kdb.stt" ]; then
old_base=`cat retranslator/bases/bases/av/kdb/i386/old/kdb.stt | sed 's/\x0D$//'`
else
old_base="did not update yet"
fi
./retranslator/retranslator
# Запоминаем версию новых баз.
new_base=`cat retranslator/bases/bases/av/kdb/i386/old/kdb.stt | sed 's/\x0D$//'`
echo "Old base version : ${old_base}"
echo "New base version : ${new_base}"
# Короткая версия баз (только дата выпуска, без кол-ва известных вирусов) пригодится позднее.
base_ver=`echo ${new_base} | sed 's/.*;//'`
# Монтируем iso образ.
echo && echo "STEP 3 : Mounting iso image..."
mkdir iso && mount -o loop kav_rescue_10.iso iso/
# Запоминаем версию образа
disk_ver=`cat iso/rescue/KRD.VERSION | sed 's/; $//'`
echo "Disk version : ${disk_ver}"
# Распаковка rescue.igz.
echo && echo "STEP 4 : Decompressing rescue.igz..."
mkdir tmp
cp iso/boot/rescue.igz ./tmp/rescue.lzma
mkdir initrd
cd initrd && lzcat -S lz ../tmp/rescue.lzma | cpio -i --no-absolute-filenames && cd ../
# Самые главные патчи!
echo && echo "STEP 5 : Patching some files..."
# Блокируем поиск загрузочного диска, указываем скрипту монтировать содержимое LiveCD
# из готового образа, который соберем на шаге 7.
patch -p0 -i init.patch
patch -p0 -i dmsquash-live-root.patch
# Изменение настроек, добавление пользовательских файлов можно делать на этом этапе.
echo && echo "STEP 6 : Patching LiveOS..."
if [ "${update_liveos}" = "1" ]; then
# Образ упакован с xz-компрессией! Распаковываем по-умолчанию в squashfs-root.
./squashfs4.2/squashfs-tools/unsquashfs iso/rescue/LiveOS/squashfs.img
# Внутри еще один образ, монтируем его.
mkdir mnt && mount -o loop -t auto squashfs-root/LiveOS/ext3fs.img mnt
# Патч меняет кое-какие настройки (см. содержимое патча config.xml.patch ниже).
patch -p0 -i config.xml.patch
# Свои файлы можно кидать в ./mnt прямо СЕЙЧАС
# Упаковываем измененный образ и заметаем следы.
umount mnt && rm -rf mnt
./squashfs4.2/squashfs-tools/mksquashfs squashfs-root squashfs.img -comp xz
rm -rf squashfs-root
else
echo "This step was skipped."
fi
# Собираем образ загрузочного диска "с нуля".
echo && echo "STEP 7 : Building livecd.squash..."
mkdir -p livecd/rescue/help
cp iso/rescue/help/*.txt livecd/rescue/help/
cp -r iso/rescue/help/English livecd/rescue/help
cp -r iso/rescue/help/Russian livecd/rescue/help
cp iso/rescue/KRD.VERSION livecd/rescue/
cp iso/livecd livecd/
# Если было выбрано изменение настроек, пользуемся образом, собранным на предыдущем шаге...
if [ "${update_liveos}" = "1" ]; then
mkdir livecd/rescue/LiveOS && mv squashfs.img livecd/rescue/LiveOS/
# ...В противном случае используем "родной".
else
cp -r iso/rescue/LiveOS livecd/rescue
fi
# Собираем папку с обновленными базами!
mkdir -p livecd/rescue/bases/Stat
cp retranslator/bases/index/u0607g.xml livecd/rescue/bases/Stat/
cp retranslator/bases/bases/av/kdb/i386/*.ini livecd/rescue/bases/
cp retranslator/bases/bases/av/kdb/i386/*.kdc livecd/rescue/bases/
cp retranslator/bases/bases/av/kdb/i386/*.kdl livecd/rescue/bases/
cp retranslator/bases/bases/av/kdb/i386/*.xml livecd/rescue/bases/
mv livecd/rescue/bases/kdb-i386-0607g.xml livecd/rescue/bases/kdb-0607g.xml
cp retranslator/bases/bases/av/kdb/i386/old/kdb.stt livecd/rescue/bases/Stat/
cp retranslator/bases/bases/av/kdb/i386/old/kavbase.mft livecd/rescue/bases/
cp retranslator/bases/bases/av/emu/i386/* livecd/rescue/bases/
cp retranslator/bases/bases/av/qscan/i386/u/* livecd/rescue/bases/
# WindowsUnlocker тоже обновляем из зеркала.
mkdir livecd/rescue/bases/data
cp retranslator/bases/AutoPatches/rd/rd-0607g.xml livecd/rescue/bases/
cp retranslator/bases/AutoPatches/rd/windowsunlocker livecd/rescue/bases/data/
# Упаковываем.
./squashfs4.2/squashfs-tools/mksquashfs livecd initrd/livecd.squash
# Собираем обновленный rescue.igz.
echo && echo "STEP 8 : Building rescue.igz..."
if [ "${compress_lzma}" = "1" ]; then
# с lzma сжатием
echo "Lzma compress enabled."
cd ./initrd && find . | cpio -o -Hnewc | lzma -c > ../rescue.igz && cd ../
else
# без lzma сжатия
echo "Lzma compress disabled."
cd ./initrd && find . | cpio -o -Hnewc > ../rescue.igz && cd ../
fi
# Перемещаем полученный образ, чистим временные папки.
echo && echo "STEP 9 : Moving image and cleaning temp dirs..."
if [ ! -d ${tftproot_dir}/${dest_dir} ]; then
mkdir -p ${tftproot_dir}/${dest_dir}
fi
cp -f iso/boot/rescue ${tftproot_dir}/${dest_dir}/
mv -f rescue.igz ${tftproot_dir}/${dest_dir}/
rm -rf tmp
rm -rf livecd
rm -rf initrd
umount iso && rm -rf iso
# Создаем конфиг для pxelinux. Конфиг будет не простой, а красивый...
echo && echo "STEP 10 : Pxelinux config..."
echo "LABEL kaspersky_rescue_disk_10" > ${tftproot_dir}/${dest_dir}/menu.cfg
echo "MENU LABEL Kaspersky Rescue Disk ${disk_ver}-${base_ver}" >> ${tftproot_dir}/${dest_dir}/menu.cfg
echo "KERNEL ${dest_dir}/rescue" >> ${tftproot_dir}/${dest_dir}/menu.cfg
echo "APPEND initrd=${dest_dir}/rescue.igz root=live rootfstype=auto vga=791 init=/init kav_lang=ru udev liveimg doscsi nomodeset quiet splash" >> ${tftproot_dir}/${dest_dir}/menu.cfg
echo "TEXT HELP" >> ${tftproot_dir}/${dest_dir}/menu.cfg
echo "Disk version : ${disk_ver}" >> ${tftproot_dir}/${dest_dir}/menu.cfg
echo "New base version : ${new_base}" >> ${tftproot_dir}/${dest_dir}/menu.cfg
echo "Old base version : ${old_base}" >> ${tftproot_dir}/${dest_dir}/menu.cfg
echo "Rescue.igz build date : `date +%H:%M/%d.%m.%y`" >> ${tftproot_dir}/${dest_dir}/menu.cfg
echo "ENDTEXT" >> ${tftproot_dir}/${dest_dir}/menu.cfg
echo && cat ${tftproot_dir}/${dest_dir}/menu.cfg
Патч init.patch
--- ./initrd/init.bak 2012-03-11 23:30:56.000000000 +1100
+++ ./initrd/init 2012-03-12 00:09:33.165699617 +1100
@@ -270,7 +270,7 @@
# [ $main_loop -gt $RDRETRY ] \
# && { flock -s 9 ; emergency_shell "No root device \"$root\" found"; } 9>/.console_lock
if [ $main_loop -gt $RDRETRY ]; then
- CDROM_DEVICES="/dev/sr*"
+ CDROM_DEVICES="/livecd.squash"
for i in $CDROM_DEVICES
do
/sbin/dmsquash-live-root $i
@@ -288,7 +288,7 @@
unset RDRETRY
if ! ismounted "/run/initramfs/live"; then
- CDROM_DEVICES="/dev/sr*"
+ CDROM_DEVICES="/livecd.squash"
for i in $CDROM_DEVICES
do
/sbin/dmsquash-live-root $i
Патч dmsquash-live-root.patch
--- ./initrd/sbin/dmsquash-live-root.bak 2012-03-11 23:30:56.000000000 +1100
+++ ./initrd/sbin/dmsquash-live-root 2012-03-12 00:07:12.531467569 +1100
@@ -28,47 +28,47 @@
overlay=$(getarg rd.live.overlay overlay)
# CD/DVD media check
-[ -b $livedev ] && fs=$(blkid -s TYPE -o value $livedev)
-if [ "$fs" = "iso9660" -o "$fs" = "udf" ]; then
- check="yes"
-fi
-getarg rd.live.check check || check=""
+#[ -b $livedev ] && fs=$(blkid -s TYPE -o value $livedev)
+#if [ "$fs" = "iso9660" -o "$fs" = "udf" ]; then
+# check="yes"
+#fi
+#getarg rd.live.check check || check=""
-if [ -n "$check" ]; then
- [ -x /bin/plymouth ] && /bin/plymouth --hide-splash
- checkisomd5 --verbose $livedev || :
- if [ $? -ne 0 ]; then
- die "CD check failed!"
- exit 1
- fi
- [ -x /bin/plymouth ] && /bin/plymouth --show-splash
-fi
+#if [ -n "$check" ]; then
+# [ -x /bin/plymouth ] && /bin/plymouth --hide-splash
+# checkisomd5 --verbose $livedev || :
+# if [ $? -ne 0 ]; then
+# die "CD check failed!"
+# exit 1
+# fi
+# [ -x /bin/plymouth ] && /bin/plymouth --show-splash
+#fi
# determine filesystem type for a filesystem image
-det_img_fs() {
- local _img="$1" _loop=$(losetup -f) _fs
- losetup $_loop $_img; _fs=$(det_fs $_loop); losetup -d $_loop
- echo $_fs
-}
+#det_img_fs() {
+# local _img="$1" _loop=$(losetup -f) _fs
+# losetup $_loop $_img; _fs=$(det_fs $_loop); losetup -d $_loop
+# echo $_fs
+#}
for arg in $CMDLINE; do case $arg in ro|rw) liverw=$arg ;; esac; done
# mount the backing of the live image first
mkdir -m 0755 -p /run/initramfs/live
-if [ -f $livedev ]; then
- # no mount needed - we've already got the LiveOS image in initramfs
- # check filesystem type and handle accordingly
- case `det_img_fs $livedev` in
- squashfs) SQUASHED=$livedev ;;
- auto) die "cannot mount live image (unknown filesystem type)" ;;
- *) FSIMG=$livedev ;;
- esac
-else
- mount -n -t $fstype -o ${liverw:-ro} $livedev /run/initramfs/live
+#if [ -f $livedev ]; then
+# # no mount needed - we've already got the LiveOS image in initramfs
+# # check filesystem type and handle accordingly
+# case `det_img_fs $livedev` in
+# squashfs) SQUASHED=$livedev ;;
+# auto) die "cannot mount live image (unknown filesystem type)" ;;
+# *) FSIMG=$livedev ;;
+# esac
+#else
+ mount -n -t auto -o ro $livedev /run/initramfs/live
if [ "$?" != "0" ]; then
die "Failed to mount block device of live image"
exit 1
fi
-fi
+#fi
# overlay setup helper function
do_live_overlay() {
Патч config.xml.patch меняет всего лишь две настройки: во-первых, включает проверку файлов «по формату», и, во-вторых, отключает проверку архивов:
--- ./mnt/etc/kl/config.xml.bak 2012-02-07 09:03:33.000000000 +1100
+++ ./mnt/etc/kl/config.xml 2012-03-13 12:45:20.000000000 +1100
@@ -795,8 +795,8 @@
<tDWORD name="ExcludeByMask">0</tDWORD>
<tDWORD name="MandatoryScanPeriod">7</tDWORD>
<tDWORD name="RootkitScan">1</tDWORD>
- <tDWORD name="ScanArchived">1</tDWORD>
- <tDWORD name="ScanFilter">1</tDWORD>
+ <tDWORD name="ScanArchived">0</tDWORD>
+ <tDWORD name="ScanFilter">0</tDWORD>
<tDWORD name="ScanFixed">1</tDWORD>
<tDWORD name="ScanMail">0</tDWORD>
<tDWORD name="ScanMailBases">0</tDWORD>
Настройка pxelinux
По завершении работы скрипта файл ${tftproot_dir}/${dest_dir}/menu.cfg будет иметь примерно такое содержимое:
LABEL kaspersky_rescue_disk_10
MENU LABEL Kaspersky Rescue Disk 10.0.31.4-201206200949
KERNEL apps/kaspersky/rescue
APPEND initrd=apps/kaspersky/rescue.igz root=live rootfstype=auto vga=791 init=/init kav_lang=ru udev liveimg doscsi nomodeset quiet splash
TEXT HELP
Disk version : 10.0.31.4
New base version : 8154585;201206200949
Old base version : 8151532;201206190812
Rescue.igz build date : 22:23/20.06.12
ENDTEXT
Остается добавить в ваш pxelinux.cfg/default такую строку (конечно, изменив путь на свой):
INCLUDE apps/kaspersky/menu.cfg
И, чтобы было совсем понятно, приведу часть моего pxelinux.cfg/default
DEFAULT vesamenu.c32
PROMPT 0
TIMEOUT 100
ONTIMEOUT local
MENU TITLE -= PXE Boot Menu =-
MENU BACKGROUND menu.jpg
MENU COLOR border 30;44 #00000000 #00000000 none
MENU COLOR unsel 37;44 #90ffffff #00000000 std
MENU COLOR sel 7;37;40 #70ffffff #20ff8000 all
MENU COLOR hotsel 1;7;37;40 #e0ffffff #20ff8000 all
LABEL local
MENU LABEL Boot from local drive
localboot 0
LABEL memtest86p
MENU LABEL MemTest86+ v4.20
KERNEL memdisk
APPEND initrd=apps/memtest.bin
INCLUDE apps/drweb/menu.cfg
INCLUDE apps/kaspersky/menu.cfg
У меня меню выглядит вот так:
Процесс загрузки:
Ура, всё работает:
Заключение
Напоследок остается добавить задание в crontab. Если вы хотите обновлять образ ежедневно, скажем, в восемь часов утра, то конфиг будет такой:
SHELL=/bin/sh
00 8 * * * /storage/projects/kaspersky_rescue_disk_10/make_rescue.igz.sh > /storage/projects/kaspersky_rescue_disk_10/results.log 2>&1
Не забудьте изменить пути на свои!
P.S. скачать архив со всеми скриптами и патчами можно тут.