Справочная информация:
Написание подтверждения концепции, которая включает в себя выполнение машинного кода в программе Python.Чтобы сделать это на OSX, мне пришлось использовать ctypes и libc.dylib и следующие вызовы функций:
(с отключенным SIP)
- valloc для выделения выровненной памяти
- mprotect для предоставления разрешения wrx на выделенную память
- memmove для копирования исполняемого кода в выделенную память;бросать;и выполнить ...
Проблема :
Проблема возникает при вызове функции mprotect, где она всегда возвращает -1 в случае сбоя.
Сценарий: (логика почти идентична системе linux, поскольку они оба относятся к семейству posix)
import ctypes
buf = "machine code..."
libc = cytpes.CDLL('libc.dylib')
size = len(buf)
buf_ptr = ctypes.c_char_p(buf)
# allocate aligned memory space
alloc_space = ctypes.c_void_p(ctypes.valloc(size))
# this always evaluates true, and mprotect fails every attempt
if 0 != libc.mprotect(alloc_space, size, 1 |2 |4):
print "mprotect failed"
ctypes.mmove(alloc_space, buf_ptr, size)
Теперь mmove завершится ошибкой с сообщением об ошибке segfault (b/ c записывает пространство памяти, которое, вероятно, имело только право на чтение), и программа приходит в хаот ...
Проблема в mprotect, этот метод очень хорошо работает в Linux, теперь я вижу, что результатысильно отличаются для Mac OSX
Вопрос:
Есть ли в Mac OSX дополнительные функции безопасности (даже с отключенным SIP), которые ограничивают тип операции mprotect?И если да, то как можно это обойти?
ОБНОВЛЕНИЕ:
Согласно @DietrichEpp, предложенному в комментариях, использование use_errno = True для вызова ctypes.CDLL сгенерировалоERRNO.Это оценивается как errno: 12, Невозможно выделить память.Это errno - значение для ENOMEM на странице руководства mprotect.
Хотя на странице руководства было несколько ENOMEM, я подозреваю, что это последний сценарий: (б / с не было ошибки при вызове valloc)
ENOMEM Changing the protection of a memory region would result in the
total number of mappings with distinct attributes (e.g., read
versus read/write protection) exceeding the allowed maximum.
(For example, making the protection of a range PROT_READ in
the middle of a region currently protected as
PROT_READ|PROT_WRITE would result in three mappings: two
read/write mappings at each end and a read-only mapping in the
middle.)
Я подозреваю, что osx имеет особые ограничения и установил максимальные сопоставления для каждого процесса, следовательно, добавив больше разрешений, новое сопоставление того же процесса превысит такой максимальный предел (сколько сопоставлений с привилегиями exec / write на процесс),Если мои предположения были верны, как мы можем обойти это?