Это текстовая версия статьи, оригинал с картинками вот тут.
Продолжаю раскрывать интересную тему запуска программ нестандартными способами. В этот раз расскажу про запуск ELF-бинарника из скрипта и без записи в файловую систему.
Что тут происходит
Я уже создавал один универсальный скрипт запуска для четырех разных систем, но там в качестве основного тестового приложения использовалась Java. В этот раз решил раскопать тему упаковки и запуска именно настоящего бинарника Qt-приложения.
По мотивам вот этой статьи. Еще этой и вот этой.
Проект выложен вот тут целиком. Все тесты проводились на 64-битном Linux Manjaro с новым ядром 6.х.
Код скрипта:
#!/usr/bin/env bash
execute_elf_string(){
local bin_encoded=$1
perl -e '
# Create memfd
my $name = "";
my $fd = syscall(319, $name, 1);
if (-1 == $fd) { die "memfd_create: $!"; }
# Copy binary
open(my $fh, ">&=".$fd) or die "open: $!";
my $bin = `echo "'"$bin_encoded"'" | base64 -d | gunzip`;
print $fh $bin;
# Execute
exec {"/proc/$$/fd/$fd"} "memfd";
'
}
execute_elf_string "
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
F6Y8q/e/7v8/T8zxfXB7AAA=
"
Большая строка это как раз закодированный и сжатый бинарник, тестовое приложение.
Тестовое приложение
В оригинале в закодированном виде было простое консольное приложение, без зависимостей и подключаемых библиотек. Я же решил зайти чуть дальше и сваял полноценное графическое приложение на Qt — для теста внешних зависимостей, естественно без статической сборки, чтобы этот цирк с понями максимально походил на реальное использование, со всеми реальными проблемами.
Вот так происходит упаковка:
#!/usr/bin/env bash
mkdir Release
cd Release
cmake -DCMAKE_BUILD_TYPE=Release ..
make
gzip -f testapp
cat testapp.gz |base64 > out.base64
cat ../head.sh > final.sh
echo \" >> final.sh
cat out.base64 >> final.sh
echo \" >> final.sh
chmod +x ./final.sh
Все достаточно банально, поэтому останавливаться на этом не будем и перейдем к самому веселому:
my $fd = syscall(319, $name, 1);
Вот где колдунство! И магии тут действительно много. Сейчас буду объяснять.
Проблема
Для начала обрисую проблему:
The exec(2) system call always requires a filename or absolute path (the filename is always a char*). posix_spawn also has similar requirements for a filename.
Вообщем бинарник должен быть в файле, а файл — в файловой системе. Поэтому типичный вариант запуска бинарника из строки это использование временного файла:
echo 'main(){}' | gcc -xc -o /tmp/a.out && chmod u+x /tmp/a.out && /tmp/a.out && rm -f /tmp/a.out
Это работает но не всегда удобно, поскольку можно попасть на read-only файловую систему или нехватку свободного места.
Волшебный memfd_create
В Linux есть syscalls — системные функции, которые программы вызывают когда нужно взаимодействовать с ресурсами ОС: устройствами, памятью или диском. И уже достаточно давно есть функция memfd_create. Вот что это такое на хорошем литературном английском:
This handy little system call is something like malloc(3), but instead of returning a pointer to a chunk of memory, it returns a file descriptor which refers to an anonymous (i.e. memory-only) file. This is only visible in the filesystem as a symlink in /proc//fd/ (e.g. /proc/10766/fd/3), which, as it turns out, execve(2) will happily use to execute an ELF binary.
Вообщем она позволяет создать анонимный файл в памяти, работать с которым (как с файлом) возможно только через специальную виртуальную файловую систему /proc.
В том числе поставить туда бит выполнения и запустить. Без записи на диск.
Возвращаемся к волшебной строчке:
my $fd = syscall(319, $name, 1);
319 — числовой номер системного вызова memfd_create для x86_64 архитектуры.
Определен он в /usr/include/bits/syscall.h через цепочку вложений как:
#define __NR_memfd_create 319
Perl и syscall
Конечно же нормальные люди вызывают системные функции из Си а не из скриптов. Но мне можно, поэтому я вызываю:
my $fd = syscall(319, $name, 1);
Обожаю перл — каждую строчку можно разбирать неделями.
my $fd — объявление переменной fd и присвоение ей результата вызова системной функции, число.
$name — передача переменной c именем создаваемого файла, после вызова в этой переменной будет его имя, строка.
1 — константа MFD_CLOEXEC, определена в /usr/include/linux/memfd.h В результате успешного вызова в переменной $fd будет либо номер дескриптора созданного файла либо -1 в качестве ошибки вызова.
Проверка на ошибку:
if (-1 == $fd) { die "memfd_create: $!"; }
die — немедленный выход из программы, как вы наверное догадались.
Следующая магическая строчка:
open(my $fh, ">&=".$fd) or die "open: $!";
Что тут происходит на литературном английском:
Perl’s open(), which is normally used to open files, can also be used to turn an already-open file descriptor into a file handle by specifying something like >&=X (where X is a file descriptor) instead of a file name.
Если по простому, то мы открываем дескриптор файла как обычный файл, например для того чтобы сделать в него запись:
print $fh "test";
Но перед записью наш бинарник еще надо декодировать:
my $bin = `echo "'"$bin_encoded"'" | base64 -d | gunzip`;
base64 -d — раскодировать из формата Base64 gunzip — распаковать
Обратите внимание на `` кавычки — они означают запуск команды на исполнение, которая написана внутри таких кавычек.
| — стандартные пайпы, означает что результат вызова функции слева передается на вход функции справа.
В результате в переменной $bin должен образоваться наш бинарник в раскодированном виде.
Дальше мы его просто записываем через открытый выше дескриптор:
print $fh $bin;
И наконец запускаем:
exec {"/proc/$$/fd/$fd"} "memfd";
Снова на красивом английском:
The syntax for calling exec() is a bit odd, and explained much better in the documentation. For now, we’ll take it on faith that the file is passed as a string in curly braces and there follows a comma-separated list of process arguments. We can use the variable $$ to get the pid of our own Perl process
В общем, запуск происходит через виртуальную файловую систему /proc, в вызов подставляется PID текущего процесса ($$) и номер дескриптора нашего виртуального файла.
Elfexec
Конечно же я не один такой умный, и есть готовые интересные решения, использующие такой же подход:
echo 'IyEvYmluL3NoCmVjaG8gIkhlbGxvISIK' | base64 -d | elfexec
Про одну такую штуку стоит упомянуть:
Utility to execute ELF binary directly from stdin pipe. It is useful to run binary via SSH without copy or install it on remote systems. Да да, бинарник через pipe, именно так.
Интересный вариант с компиляцией без временных файлов и последующим запуском:
echo '
#include <unistd.h>
int main(int argc, char* argv[])
{
write(STDOUT_FILENO, "Hello!\n", 7);
return 0;
}
' | cc -xc - -o /dev/stdout | elfexec
В общем, страшная штука.