В предыдущей статье была представлена конструкция среды для выполнения вопросов CTF PWN. В этой статье мы покажем, как использовать Pwntools, чтобы быстрее решать проблемы.
Pwntools — это платформа CTF и библиотека разработки уязвимостей, разработанная на Python и предназначенная для того, чтобы пользователи могли просто и быстро писать эксплойты. Охватывает почти все инструменты, необходимые для написания сценариев вопросов pwn.
from pwn import *
Установление соединения особенно важно для решения вопросов pwn. Во время соревнования вам обычно предоставляется файл вопросов pwn (обычно файл elf для Linux) и адрес nc.
Поэтому нам необходимо установить соединение с сервером nc и файлом elf.
Мы можем использовать модуль pwnlib.elf для подключения программных файлов.
elf = ELF('./process') #processПрограммный файл, указанный в вопросе
После подключения к файлу программы мы можем использовать встроенные методы для быстрого поиска адресов функций и серий функций.
Подключаемся к серверу через модуль pwnlib.tubes
r = remote('ip',port) #Заполните ip и порт, указанные в вопросе, в соответствующей позиции
После подключения к серверу вы можете использовать встроенные методы для выполнения ряда интерактивных операций, таких как отправка и получение данных с сервера.
Мы можем указать pwntools рабочую среду нашей программы, указав целевую архитектуру и операционную систему, и pwntools автоматически поможет нам настроить соответствующий формат компиляции и порядок байтов.
context.arch = 'i386' Для # 32-битной программы установлено значение i386; для 64-битной программы установлено значение amd64;
context.binary = './process' #Вы можете использовать этот метод, чтобы автоматически установить подходящее значение.
context.os = 'linux'
context.log_level = 'debug' #Отладочную информацию можно вывести на экран
context.terminal = ['tmux', 'splitw', '-h'] #Сообщите pwntools информацию о своем терминале, чтобы облегчить последующую динамическую отладку
context.endian = 'big' #Устанавливаем порядок байтов с прямым порядком байтов и с прямым порядком байтов на младший
Разобравшись с некоторыми из вышеописанных приготовлений, можно попробовать начать взаимодействовать с программой.
r.recv() #получать данные
r.recvline() #Получаем данные строки
r.recvall() #получать данные до тех пор, пока не будет достигнут EOF
r.send() #Отправить данные
r.sendline() #sendonelineданные
r.sendlineafter('str',payload) #При получении указанных данных Отправить данные
r.interactive()
Когда мы успешно подключаемся к файлу программы, мы можем использовать pwntools для быстрого получения адреса функции.
Например, получите адрес функции puts:
puts_got_addr = elf.got['puts'] #Get putsfunctiongot адрес таблицы
puts_plt_addr = elf.plt['puts'] #Получить адрес таблицы putsfunctionplt
puts_sym_addr = elf.symbols['puts'] #Получить адрес таблицы символов putsфункции
Когда мы отвечаем на вопросы, мы часто используем шеллкод, но поиск соответствующего шеллкода в Интернете каждый раз сильно снизит нашу эффективность при ответе на вопросы. Модуль шеллкрафта может помочь нам автоматически генерировать шеллкод.
shellcraft.sh()
Операции упаковки и распаковки часто используются при отправке и получении данных.
p32() #Упаковать данные в 32-битный двоичный формат, порядок байтов задается context.endian
p64() #Упаковать данные в 64-битный двоичный формат, порядок байтов задается context.endian
u32() #Распаковываем данные в 32-битном двоичном формате
u64() #Распаковываем данные в 64-битном двоичном формате
Иногда мы также используем операции сборки, например хотим отправить шеллкод:
shellcode = asm(shellcraft.sh())
r.sendline(shellcode)