> То есть с памятью запрещено делать:
> 1. Изменять статус +x если изначально память была выделена как не исполняемая.
> 2. Менять режим с только для чтения ro на rw.
> 3. Изменить статус на исполняемый анонимной области памяти.
> 4. Изменить RELRO добавив возможность записи +w.Интерпретатору (тому который, внимание ирония: без JIT) это до одного места (в ином случае, помимо кучи модулей и библиотек, тот же REPL питона или интерактивный шелл не будут работать, т.к. там основное действие - читать и исполнять ввод пользователя):
# part of a bigger script
# ...
# this is our simple log script, we log all logins. Nothing can go wrong, we have no RWX, no +x … trust me, I know what I'm doing!
echo "$(date): Bad guy tried to log in and steal your pr0n with invalid username: $USER, action: access denied" > important.log
# ...
и
% # simulate bad guy login
USER="$(rm -rf ~/*)"; echo "$(date): $USER tried to log in and watch pr0n, access denied > importantlog.log
код интерпретатора (*sh) остался неизменным. Правда пользователю от этого вряд ли сильно легче.
> Проверить new.code на 2 питоне мне не удалось. Видать плохо старался, надо функции больше параметров...
Наверное у Вас Особый Питон, не такой как у всех остальных, без возможности переопределения методов, eval, exec, import - *завидует* (угу, вот щаз прям побегу полноценный, красивый и гладкий PoC писать … сразу после глажки шнурков)
> Пробовал на 3 питоне:
> import code
> foo.__code__=code(...)
> TypeError: module object is not callable
Если вы считаете, что это не работает из-за режима W^X, то у меня для вас плохие новости: вызов модуля не работает вообще у всех (это такое ограничение ЯП).
В тройке это делается так:
>>> import os
>>> def foo(): print(1+1)...
>>> foo.__code__ = compile("print(os.listdir('/'))",'<string>','single')
>>> foo()
[ 'usr', 'dev', 'mnt', 'tmp'
или с code
import code, os
def foo(): print(1+1)
foo()
2
x=code.compile_command("import os;print(os.listdir('/'))")
foo.__code__ = x
foo()
[ 'usr', 'dev', 'mnt'
> Мене вот эта фигня досаждает:
> import numpy
> ........
> File "/usr/lib/python/site-packages/numpy/core/_internal.py", line 14, in <module>
> import ctypes
> То есть сработал пункт 3 запретов деествий с памятью.
Угу, срабатывание при попытке загрузки сишной либы питоном через жо^W "универсальным" для кучи ОС методом (интересующиеся могут глянуть в ctypes.__init__) все расставило на свои места.
Правда, можно просто записать любую либу и подгризить ее штатными методом (это не будет ANONYMOUS_MAP), но пссст, это тайное знание.
Ну и подгружать и выполнять свежую, измененную библиотеку питона из питона - можно хоть каждую секунду.
% cat load.py && echo "print(1+2)">mylib.py && python3 load.py&
import time,imp,mylib
while True:
try:
imp.reload(mylib)
except Exception as ex:
print(ex)
except:
pass
time.sleep(3)
3
3
3
% echo "import os;print(os.listdir())" > mylib.py
[ 'serv.py', 'clipnotify',% echo "import runpy;print('0wn3d');runpy.run_module('http.server',run_name='__main__')" > mylib.py
0wn3d
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
127.0.0.1 - - [08/Apr/2019 18:59:04] "GET / HTTP/1.1" 200 -
Увы.