PWN PYTHON. Модуль для CTF соревнований.

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 ;)

Report Page