9

WCC: Гримуар компьютерного колдуна

Серия Жестокие эксперименты

Рассказываю об одном весьма необычном инструменте, способном удивить даже очень изысканную публику. Поскольку с его помощью можно быстро и безболезненно.. сменить пол любимой программе для Linux. Добро пожаловать, снова.

Вдумчивое чтение содержимого этих терминалов может привести в дурку, я предупредил.

Вдумчивое чтение содержимого этих терминалов может привести в дурку, я предупредил.

The Witchcraft Compiler Collection

Сей замечательный проект — отличное доказательство существования черной магии и колдовства тому, как мало на самом деле мы знаем об устройстве собственных программ.

По крайней мере лично автор весьма смутно представляет, как эта адская штука вообще работает, несмотря на весь свой опыт и многолетнюю практику:

WCC is a collection of compilation tools to perform binary black magic on the GNU/Linux and other POSIX platforms.

Да да, "черная магия" тут дословная цитата из описания проекта, а не выдумки или особенности перевода.

Если вкратце, WCC это такой набор очень специфичных утилит для препари.. исследования чужих программ.

Информации об этой штуке в сети крайне мало, фактически помимо проекта на Github, существует лишь одна интересная презентация, показанная на конференции Defcon, слайды из которой также использовались в статье.

Так что материал получился весьма редким.

Сборка и инвольтация эгрегора

К сожалению проект успел немного устареть, хотя и присутствует в виде готовых пакетов во многих дистрибутивах Linux. Однако в Mageia, которую автор использовал ради колдовской ступы на логотипе в качестве тестовой среды, WCC почему-то не оказалось, так что пришлось собирать руками.

Согласно описанию, необходимо установить следующие пакеты:

capstone, glibc, libbfd, libdl, zlib, libelf, libreadline, libgsl, make

Однако libbfd ныне стал частью пакета binutils и отдельно более не поставляется, а binutils скорее всего уже установлен по-умолчанию.

Забираем исходники и запускаем сборку:

git clone https://github.com/endrazine/wcc.git
git submodule init && git submodule update && make

Конечно же попытка собрать себе "гримуар электронного колдуна" из исходников закончится закономерным провалом:

Вы же не думали, что будет легко?

Вы же не думали, что будет легко?

Взывание к темным богам и поиск проблемы, взятой из трассировки выше в разных поисковиках:

undefined reference to `sframe_encoder_write'

привел наконец к вот такому багрепорту из трекера Debian. Там же был обнаружен и этот адский патч для WCC:

diff -Nru wcc-0.0.2+dfsg/debian/patches/binutils_shared.patch wcc-0.0.2+dfsg/debian/patches/binutils_shared.patch
--- wcc-0.0.2+dfsg/debian/patches/binutils_shared.patch 2020-03-21 19:02:12.000000000 +0200
+++ wcc-0.0.2+dfsg/debian/patches/binutils_shared.patch 2023-01-18 16:09:29.000000000 +0200
@@ -12,7 +12,7 @@
-all::
- $(CC) $(CFLAGS) wcc.c -o wcc -lbfd -lelf -lcapstone
+all:
-+ $(CC) $(CFLAGS) wcc.c -o wcc -l:libbfd.a -lz -ldl -liberty -lelf -lcapstone
++ $(CC) $(CFLAGS) wcc.c -o wcc -l:libbfd.a -l:libsframe.a -lz -ldl -liberty -lzstd -lelf -lcapstone
# $(CC) $(CFLAGS) -m32 -Wl,-rpath /home/jonathan/solution-exp/unlinking/awareness/self/wcc/src/wcc/lib32/ wcc.c -o wcc32 -lelf ./lib32/libbfd-2.24-system.so ./lib32/libcapstone.so.3

cp wcc ../../bin/

Как можно догадаться из этих двух строчек (если вы приличный маг):

-+ $(CC) $(CFLAGS) wcc.c -o wcc -l:libbfd.a -lz -ldl -liberty -lelf -lcapstone
++ $(CC) $(CFLAGS) wcc.c -o wcc -l:libbfd.a -l:libsframe.a -lz -ldl -liberty -lzstd -lelf -lcapstone

для завершения сборки необходимо изменить паметры, передаваемые линковщику.

Что я и проделал в файле src/wcc/Makefile:

После исправления, сборка заканчивается успешно и в каталоге bin появляются готовые к использованию "колдунские" приложения:

Колдовской набор.

Колдовской набор.

Теперь можно начинать плести заклинания.

Колдунство первое: превращаем приложение в библиотеку

Нет это не шутка и не прикол, это та самая "черная магия" от системной разработки, которой не научат на курсах по вайбкодингу.

Согласно описанию, все достаточно просто, хоть и необычно - примерно как обнаружить у девушки из Тайланда кадык:

Transforming an ELF executable binary into an ELF shared library.

Последовательность заклинаний шагов выглядит так:

Превращение утилиты cat в разделяемую библиотеку.

Превращение утилиты cat в разделяемую библиотеку.

После вызова этих нечистивых команд, то что было рождено программой для Linux, внезапно становится разделяемой библиотекой. А узревший такое в живую быдлокодер уезжает в дурку, отсыпаться и отдыхать.

Теперь рассказываю как это колдунство работает, внимание на экран:

Из презентации WCC для Defcon.

Из презентации WCC для Defcon.

На скриншоте выше видно, что по факту в файле изменился лишь один байт, точнее поле заголовка ELF64:

Из заголовочных файлов формата ELF.

Из заголовочных файлов формата ELF.

Хотя назначение этого поля не является секретом и присутствует даже в Википедии, помимо официального руководства, до столь затейливого его применения никто на моей памяти не доходил. Кроме авторов WCC.

При вызове, первым шагом происходит откат работы линковщика:

The primary use of wcc is to "unlink" (undo the work of a linker) ELF binaries, either executables or shared libraries, back into relocatable shared objects. The following command line attempts to unlink the binary /bin/ls (from GNU binutils) into a relocatable file named /tmp/ls.o

Пример вызова:

wcc -c /bin/ls -o /tmp/ls.o

По идее уже на этой стадии должен быть получен «relocable file», с которым может работать обычный gcc. Например должна отрабатывать команда:

gcc /tmp/ls.o -o /tmp/ls.so -shared

К сожалению в моей Mageia это не сработало, поэтому был использован альтернативный вариант "очищения":

cp /bin/ls /tmp/ls.o
wld --libify /tmp/ls.o

Результат выполнения команды wld теперь спокойно распознается обычным компилятором gcc:

gcc /tmp/ls.o -o /tmp/ls.so -shared

И в результате действительно получается разделяемая библиотека, которую можно спокойно линковать с вашим приложением:

file /tmp/ls.so
/tmp/ls.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=68d93a1d888eb560b8842
55a59c37cd6be0adddd, not stripped

Пример использования такой библиотеки, созданной с помощью темного ритуала из чужой программы показан на этом слайде:

Вставляет покруче Некрономикона.

Вставляет покруче Некрономикона.

Но едем дальше.

Получение имени пользователя радикальным способом - через рефлексию в плеере VLC (!)

Получение имени пользователя радикальным способом - через рефлексию в плеере VLC (!)

Колдунство второе: рефлексия для.. чистого С

Следующий уровень безудержного колдовского веселья показан на скриншоте выше, но разумеется нуждается в пояснениях:

The witchcraft shell accepts ELF shared libraries, ELF ET_DYN executables and Witchcraft Shell Scripts written in Punk-C as an input. It loads all the executables in its own address space and makes their API available for programming in its embedded interpreter.

Вообще этот абзац - один сплошной "майндфак" для всех, кто хоть немного знаком с языком С, в лучших традициях Лавкрафта погружающий разум несчастных быдлокодеров во мрак ультрахардкора.

Хотя авторы WCC на голубом глазу заявляют:

This provides for binaries functionalities similar to those provided via reflection on languages like Java.

до рефлексии уровня Java/.NET тут все же очень далеко и вызывать столь интересным образом методы в чужих библиотеках получается далеко не всегда.

Теперь рассказываю, как можно попробовать сие темное колдунство в действии. Интерпретатору wsh из состава WCC скармливается разделяемая библиотека или ELF-приложение:

wsh /usr/sbin/apache2

К сожалению стабильность работы вызывает вопросы, поэтому тут 50/50 — колдунство может сработать, а может выпасть segmentation fault. Если был передан бинарник — автоматически произойдет его «библификация», описанная выше.

Если сработало, появится сообщение зелеными буквами на черном фоне:

loading of libified binary succeeded

И можно будет пытаться вызывать:

a = ap_get_server_banner()
print(a)

Код выше — отдельный язык, такая своеобразная помесь С и Lua, с весьма поэтическим названием:

The resulting API, a powerful combination of lua and C API is called Punk-C

Авторы решили не заморачиваться с типами данных, поэтому и родилась на свет эта дикая помесь ужа с ежом С и Lua.

Так выглядит более сложный пример использования:

#!/usr/bin/wsh

-- Computing a MD5 sum using cryptographic functions from foreign binaries
-- (eg: sshd/OpenSSL)

function str2md5(input)

out = calloc(33, 1)
ctx = calloc(1024, 1)

MD5_Init(ctx)
MD5_Update(ctx, input, strlen(input))
MD5_Final(out, ctx)

free(ctx)
return out
end

input = "Message needing hashing\n"
hash = str2md5(input)
hexdump(hash,16)

exit(0)

Для демонстрации работы необходимо вначале загрузить одну из библиотек, реализующих функции MD5-хеширования, что и было немедленно проделано:

Считаем MD5-хеш с помощью метода, вызванного через рефлексию из бинарника sshd.

Считаем MD5-хеш с помощью метода, вызванного через рефлексию из бинарника sshd.

Как видите все работает и действительно отображается MD5-хеш для введенной строки, вычисленный с помощью вызова функции из бинарника sshd.

Без исходников и без линковки.

Но это далеко не все колдовские приколы, которые позволяет творить WCC.

Колдунство третье: восстановление флагов сборки

Хотя авторы WCC опять несколько преувеличивают, рассказывая про возможность восстановления абсолютно всех флагов сборки:

When compiling C code, it is often required to pass extra arguments to the compiler to signify which shared libraries should be explicitly linked against the compile code. Figuring out those compilation parameters can be cumbersome. The wldd commands displays the shared libraries compilation flags given at compile time for any given ELF binary.

На практике же речь идет только о библиотеках:

Ключи сборки mplayer.

Ключи сборки mplayer.

Так что речь больше про удобство использования, чем про уникальный функционал.

Колдунство четвертое: генератор заголовков

Последнее в этой статье, но далеко не последнее по важности и применимости:

The wcch command takes an ELF binary path as a command line, and outputs a minimal C header file declaring all the exported global variables and functions from the input binary. This automates prototypes declaration when writing C code and linking with a binary for which C header files are not available.

Вот тут действительно респект и жертвоприношение уважение, поскольку столь мощное колдунство может сильно помочь в разработке:

Генерация заголовочного .h файла из бинарника sshd. Без исходного кода.

Генерация заголовочного .h файла из бинарника sshd. Без исходного кода.

Но все же стоит помнить про ограничения технологии и не ждать 100% корректности получаемых заголовков.

В качестве иллюстрации, так выглядит небольшая часть заголовков методов, полученных этим генератором:

cat /tmp/sshd.h |head -c 500


/**
* Automatically generated by the Witchcraft Compiler Collection 0.0.9
**/
extern void *optind;
extern void *obstack_alloc_failed_handler;
extern void *error_message_count;
extern void *argp_err_exit_status;
extern void *_IO_2_1_stderr_;
extern void *stdin;
extern void *program_invocation_short_name;
[alex@illuminati wcc]$

Думаю очевидно, что артефакты вроде:

extern void *_IO_2_1_stderr_;
extern void *stdin;

придется долго вычищать вручную, чтобы полученный заголовочный файл можно было использовать.

Резюмируя

WCC это по истине необычный и редкий проект, к сожалению (или к счастью) неизвестный широкой программерской публике.

Хотя его использование требует серьезной подготовки и определенных навыков, а работа утилит часто нестабильна - эффект в виде зарева полыхающих пердаков быдлокодеров простых разработчиков выходит эпический.

Если вы занимаетесь серьезной разработкой на C/C++ под Linux и ненавидите человескую расу, думаю стоит ознакомиться с этой штукой поближе, чтобы включить WCC в свои темные планы и нечестивые эксперименты.

P.S.

Оригинал статьи в нашем блоге, статья была опубликована на Хабре.

GNU/Linux

1.2K постов15.6K подписчиков

Правила сообщества

Все дистрибутивы хороши.

Будьте людьми.

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества

Недвижимость и ремонт

Теги

Популярные авторы

Сообщества