PWN PYTHON. Модуль для CTF соревнований.
moderator E7
Всем привет ! В данной статье познакомимся с таким инструментом как pwntools для написания эксплоитов.
О pwntools
Исторически pwntools использовался как своего рода DSL для написания эксплойтов. Чтобы начать пользоваться, импортируем модуль from pwn import *
В предыдущей версии pwntools приносили всевозможные приятные побочные эффекты.
Но в новой версии изменили структуру модуля , их поделиле на два "подмодуля" .
Первый , для того чтобы сделать код модуля понятным и быстрым в написании эксплоита
Второй , в котором останется все возможная функциональность прежденего pwn
pwnlib, будет нашим хорошим, чистым модулем Python, а pwnбудет использоваться во время CTF. В данной статье пойдет речь о pwn и немного затронем pwnlib.
PWN— Набор инструментов, оптимизированный для CTF .
Как уже говорилось, модуль оптимизирован под CTF , потому что он должен выполнять практически тоже самое что и pwnlib , но только вмещаться в наименьшее колличество кода. Это цель этого модуля и делает он следующие:
- Импортирует всё с верхнего уровня
pwnlibвместе с функциями из множества подмодулей. Это означает, что если вы делаетеimport pwnили жеfrom pwn import *, у вас будет доступ ко всему, что вам нужно, чтобы написать эксплойт. - Вызов pwnlib.term.init() , нужен чтобы перевести ваш терминал в "сырой" режим и реализуетов всю функциональность.
- Настройка
pwnlib.context.log_levelдля "info" . - Пытается спарсить некоторые значения из
sys.argvи каждое корректно спрасеное значение, он удаляет
Установка
pwntools лучше всего поддерживается в 64-разрядных версиях Ubuntu LTS (14.04, 16.04, 18.04 и 20.04). Большая часть функций должна работать с любым дистрибутивом, подобным Posix (Debian, Arch, FreeBSD, OSX и т. д.).
$ apt-get update $ apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential $ python3 -m pip install --upgrade pip $ python3 -m pip install --upgrade pwntools
Начало работы
Чтобы познакомиться с pwntools, давайте сначала рассмотрим несколько примеров.
При написании эксплойтов , pwntools обычно придерживается подхода «кухонной раковины»(kitchen sink).
>>> from pwn import *
Это импортирует множество функций в глобальное пространство имен. Мы можем сейчас собирать, разбирать, упаковывать, распаковывать и многое другое с помощью одной функции.
Полный список всего импортируемого доступен в документации .
Создание соединений
Вам нужно обратиться к бинарному файлу, чтобы его разгадать, верно? pwntools упрощает эту глупую задачу благодаря модуля pwnlib.tubes.
Этот модуль предоставляет стандартный интерфейс для общения с процессами, сокетами, последовательными портами, и всевозможными вещями, а также несколько отличных помощников для общих задач. Например, есть инструмент для удаленного подключения посредством pwnlib.tubes.remote:
>>> conn = remote('ftp.ubuntu.com',21)
>>> conn.recvline() # doctest: +ELLIPSIS
b'220 ...'
>>> conn.send(b'USER anonymous\r\n')
>>> conn.recvuntil(b' ', drop=True)
b'331'
>>> conn.recvline()
b'Please specify the password.\r\n'
>>> conn.close()
Также легко установить слушателя:
>>> l = listen()
>>> r = remote('localhost', l.lport)
>>> c = l.wait_for_connection()
>>> r.send(b'hello')
>>> c.recv()
b'hello'
Взаимодействовать с процессами легко благодаря pwnlib.tubes.process. :
>>> sh = process('/bin/sh')
>>> sh.sendline(b'sleep 3; echo hello world;')
>>> sh.recvline(timeout=1)
b''
>>> sh.recvline(timeout=5)
b'hello world\n'
>>> sh.close()
Мы можете не только программно взаимодействовать с процессами, но и фактически взаимодействовать с ними:
>>> sh.interactive() # doctest: +SKIP $ whoami user
Есть даже модуль SSH для тех случаев, когда вам нужно подключить SSH в коробку для выполнения local/setuid exploit с pwnlib.tubes.ssh. Вы можете быстро порождать процессы и получать результат, или создать процесс и взаимодействовать с ним, как с process tube.
>>> shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
>>> shell['whoami']
b'bandit0'
>>> shell.download_file('/etc/motd')
>>> sh = shell.run('sh')
>>> sh.sendline(b'sleep 3; echo hello world;')
>>> sh.recvline(timeout=1)
b''
>>> sh.recvline(timeout=5)
b'hello world\n'
>>> shell.close()
Упаковка целочисленных типов данных
Общей задачей в написании эксплойта является преобразование целых чисел по мере того, как их видит Python, и их представление в виде последовательности байтов.
Обычные люди прибегают к встроенному модулю struct.
pwntools делает это проще с помощью pwnlib.util.packing. Можно забыть про распаковку кода и не засорять свой код вспомогательными подпрограммами.
>>> import struct
>>> p32(0xdeadbeef) == struct.pack('I', 0xdeadbeef)
True
>>> leet = unhex('37130000')
>>> u32(b'abcd') == struct.unpack('I', b'abcd')[0]
True
Операции упаковки/распаковки определены для многих битовых разрядностей.
>>> u8(b'A') == 0x41 True
Установкать целевой архитектуры и ОС
Целевая архитектура обычно может быть указана в качестве аргумента подпрограммы, которая ее требует.
>>> asm('nop')
b'\x90'
>>> asm('nop', arch='arm')
b'\x00\xf0 \xe3'
Однако его также можно установить один раз в глобальном context. Здесь также можно установить операционную систему, размер слова и порядок следования байтов.
>>> context.arch = 'i386' >>> context.os = 'linux' >>> context.endian = 'little' >>> context.word_size = 32
Кроме того, вы можете использовать сокращение для одновременной установки всех значений.
>>> asm('nop')
b'\x90'
>>> context(arch='arm', os='linux', endian='big', word_size=32)
>>> asm('nop')
b'\xe3 \xf0\x00'
Настройка детализации ведения журнала
Вы можете контролировать уровень детализации стандартного журнала pwntools через context.
Например, такая настройка :
>>> context.log_level = 'debug'
Приводит к тому, что все данные, отправленные и полученные tube , будут выведенны на экран.
Ассемблирование и Дизассемблирование
В pwn есть подмодуль отвечающий за ассемблирование и дизассемблирование shell-кода -pwnlib.asm
Пример использования:
>>> enhex(asm('mov eax, 0'))
'b800000000'
Также работает и в обратную сторону:
>>> print(disasm(unhex('6a0258cd80ebf9')))
0: 6a 02 push 0x2
2: 58 pop eax
3: cd 80 int 0x80
5: eb f9 jmp 0x0
Однако вам даже не нужно писать собственный шелл-код в большинстве случаев. время! pwntools поставляется с pwnlib.shellcraft модуль, который полон полезными шелл-кодами, экономящими время.
Другие инструменты
Никогда не записывайте еще один шестнадцатеричный дамп, благодаря pwnlib.util.fiddling.
Найдите смещения в вашем буфере, которые вызывают сбой, благодаря pwnlib.cyclic.
>>> cyclic(20) b'aaaabaaacaaadaaaeaaa' >>> # Assume EIP = 0x62616166 (b'faab' which is pack(0x62616166)) at crash time >>> cyclic_find(b'faab') 120
Манипуляции с ELF
Просмотр частичной или полной информации из файла и о файле , можно осуществить с помощью следующего мощного подмодуля -pwnlib.elf.
>>> e = ELF('/bin/cat')
>>> print(hex(e.address)) #doctest: +SKIP
0x400000
>>> print(hex(e.symbols['write'])) #doctest: +SKIP
0x401680
>>> print(hex(e.got['write'])) #doctest: +SKIP
0x60b070
>>> print(hex(e.plt['write'])) #doctest: +SKIP
0x401680
Вы даже можете редактировать и сохранять файлы.
>>> e = ELF('/bin/cat')
>>> e.read(e.address, 4)
b'\x7fELF'
>>> e.asm(e.address, 'ret')
>>> e.save('/tmp/quiet-cat')
>>> disasm(open('/tmp/quiet-cat','rb').read(1))
' 0: c3 ret'
Серия руководств по pwntools можно найти на официальном репозитории: https://github.com/Gallopsled/pwntools-tutorial#readme
С любовью от E7 ;)