Шалом, недавно, после прочтенния книг о линуксе, языке си, системных вызовах, мне стало интересно, смогу ли я с накопленным багажом знаний решить какую нибудь crackme без каких-либо практических умений в реверс (Ей богу, я даже asm не знаю). Сказано - сделано. я открываю crackmes.one и методом научного тыка я решаю сделать
Приятного чтения!
Начать, наверное, стоит с того, что суть этой crackme — найти или угадать пароль. Но я, как человек, с трудом закончивший третий класс в 17 лет, решил не угадывать пароль, а поработать с логикой его проверки и немного её изменить, используя LD_PRELOAD. Но обо всём по порядку.
Ссылка скрыта от гостей
. И о моем пути решения будет рассказано в этой статьеПриятного чтения!
Для начала, запустим исполняемый файл, и оказывается, что наши экстросенсорные навыки не сильно развиты, поэтому, придется все-же как-то разбирать логику работу программы. Я воспользуюсь ldd и посмотрю, какие в принципе программа использует библиотеки, и получим вот такую информацию:
Код:
┌──(kali㉿kali)-[~/Desktop]
└─$ ldd crackme666adv
linux-vdso.so.1 (0x00007ffd57dfd000)
libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x00007f839e7e6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f839e601000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f839e5e2000)
libzstd.so.1 => /lib/x86_64-linux-gnu/libzstd.so.1 (0x00007f839e521000)
/lib64/ld-linux-x86-64.so.2 (0x00007f839ed78000)
Разберемся поименно, что есть что:
- libc.so - это, по факту, стандартная библиотека языка си,
- libzstd.so и libz.so - библиотеки, использующиеся для сжатия без потерь
- libcrypto.so - часть пакета openssl, предоставляет криптографические функции
- linux-vdso.so - виртуальная библиотека, обеспечивающая быстрый доступ к системным функциям в зависимости от архитектуры процессора.
- ld-linux-x86-64.so - это просто загрузчик динамической компановки
LD_PRELOAD - это переменная среды, которая позволяет загружать какую-либо библиотеку раньше остальных(Даже раньше, чем стандартная библиотека языка си). Т.е благодаря LD_PRELOAD можно реализовать свою реализацию функции memcmp, которая всегда будет возвращать 0, и тем самым мы по сути решаем crackmes, ибо у нас любой пользовательский ввод будет правильным. Ниже представлен код, который при запуске будет заменять вызов функции memcmp:
C:
#include <stdio.h>
int memcmp( const void *buffer1, const void *buffer2, size_t count )
{
printf("[*] proxy.so: Hooked memcmp!\n");
printf("[*] proxy.so: patching output...\n");
printf("[+] proxy.so: patched to 0 !\n");
return 0;
}