Кто сеет ветер, тот пожнёт бурю

А давай пожнём бурю! Как мы любим. Недавно я писал пост про readonly и переменные. Ну так вот, заансетить переменную можно и другим способом.

Не спеши переключать канал, будет ОХУЕННО интересно.

Bash теперь не менее опасен, чем Perl.

ctypes — это не просто очередная скриптовая библиотека: эта штука позволяет вызывать функции из shared-библиотек на C прямо из Bash-скриптов. Охуеть, да?

Можно сказать, это внештатный модуль для Bash с огромным функционалом. Где не справился Bash, справится Bash + ctypes.

Могу сравнить это с паскалем и вставками на ассемблере, ох любил я это дело в школе. Учительница по информатике плакала кровавыми слезами, когда читала мои исходники. А потом вообще просто начала ставить пятерки, чтобы не видеть моих брейнфаков.

Давай попрактикуемся. Собираем модуль ctypes.

git clone https://github.com/taviso/ctypes.sh.git
cd ctypes.sh
./autogen.sh
./configure
make
sudo make install

По умолчанию вся эта байда ставится в папку /usr/local/bin и /usr/local/lib. Но при сборке путь можно изменить через параметр PREFIX=$HOME make install.

Так собрали, установили. Чо дальше? А дальше пишем самую простую so библиотеку:

#include <stdio.h>

void hello_bashdays() {
    printf("Hello, Bashdays!\n");
}

Компилируем:

gcc -shared -o /tmp/bashdays.so bashdays.c

На выходе получаем готовый файл bashdays.so с функцией hello_bashdays. Проверяем, какие символы доступны в скомпилированной библиотеке:

nm -g /tmp/bashdays.so

Команда nm покажет все глобальные функции и переменные, которые доступны в библиотеке bashdays.so. Мне выдало такое:

w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w __cxa_finalize@GLIBC_2.2.5
w __gmon_start__
0000000000001119 T hello_bashdays
U puts@GLIBC_2.2.5

Ок. Всё верно! Символ T перед названием функции означает, что функция глобальная. А символ U (puts) означает, что эту функцию можно вызвать извне.

Ну и теперь с помощью ctypes мы можем вызвать эту функцию из Bash-скрипта.

#!/bin/bash

source /usr/local/bin/ctypes.sh

dlopen "/tmp/bashdays.so"
dlcall "hello_bashdays"

Опа нихуя! На экран получаем результат выполнения C-функции hello_bashdays. Собственно, Hello, Bashdays!

И это всего лишь верхушка айсберга, если копнуть глубже…

Вот несколько отзывов на ctypes:

  • Это отвратительно
  • Это должно прекратиться
  • Вы зашли слишком далеко
  • Это шутка?

Вот такие интересные штуки существуют. Надеюсь, тебе понравилось. Теперь ты знаешь, как собирать shared object-файлы и легко вызывать оттуда функции.

Аа забыл, как заансетить переменную:

readonly VAR=123
source /usr/local/bin/ctypes.sh
dlcall unbind_variable string:VAR

Вот и всё. И никаких тебе танцев с GDB. Переменная VAR обнулена.

Примени это с умом, ведь на тёмную сторону перейти очень легко. Увы, но я уже там!

🌐 Страница проекта на GitHub