lemonyte/safe-exec
GitHub: lemonyte/safe-exec
一个用于拦截 Python 中 exec() 和 eval() 调用并揭示混淆代码真实内容的轻量安全分析工具。
Stars: 4 | Forks: 0
# safe-exec
`safe-exec` 提供了一个上下文管理器,用于阻止在 Python 代码中调用 `exec` 和 `eval`,并揭示尝试调用的代码。
这对于从使用 `exec` 或 `eval` 作为入口点的混淆恶意软件样本中检索反混淆代码非常有用。
## 安装
```
pip install safe-exec
```
或者从源码安装:
```
pip install git+https://github.com/lemonyte/safe-exec.git
```
支持 Python 3.10 到 3.13 版本。
## 简单示例
`safe` 上下文管理器接受 `exec` 或 `eval` 作为参数。
```
>>> from safe_exec import safe
>>> with safe(exec):
... from base64 import b64decode
... exec(b64decode("cHJpbnQoJ29iZnVzY2F0ZWQgY29kZScp"))
safe_exec.ExecBlockedError: blocked execution of b"print('obfuscated code')"
```
你也可以使用 `runpy` 模块在 `safe` 上下文中执行另一个脚本:
```
>>> import runpy
>>> with safe(exec), safe(eval):
... runpy.run_path("path/to/script.py")
```
## 高级用法
`safe` 还可以用作装饰器,以阻止在函数中调用 `exec` 或 `eval`:
```
from safe_exec import safe
@safe(exec)
@safe(eval)
def untrusted_func():
exec("print('This is an untrusted function')")
untrusted_func()
```
以及作为一个函数,用于将第三方函数注册为不受信任的调用者:
```
from safe_exec import safe
import runpy
runpy.run_path = safe(exec)(runpy.run_path)
```
但是,对于大多数用例,建议使用上下文管理器,因为它确保在退出上下文后恢复被覆盖的函数。
### 允许特定调用
`safe-exec` 提供了 `allow_exec` 和 `allow_eval` 上下文装饰器,分别用于允许对 `exec` 和 `eval` 的特定调用。
它们可以用作装饰器,应用于应该被允许调用 `exec` 或 `eval` 的函数:
```
from safe_exec import allow_exec, allow_eval
@allow_exec
@allow_eval
def trusted_func():
exec("print('This is a trusted function')")
eval("print('This is a trusted function')")
trusted_func()
```
作为上下文管理器,用于临时允许函数调用 `exec` 或 `eval`:
```
from safe_exec import allow_exec, allow_eval
def semi_trusted_func():
exec("print('This is a semi-trusted function')")
eval("print('This is a semi-trusted function')")
with allow_exec(semi_trusted_func), allow_eval(semi_trusted_func):
semi_trusted_func() # Calls are allowed here.
semi_trusted_func() # Calls are blocked here.
```
或者作为函数,用于将第三方函数注册为允许的调用者:
```
from safe_exec import allow_eval
import collections
allow_eval(collections.namedtuple)
```
### `safe` 与 `allow_exec` 和 `allow_eval` 的区别
这两组上下文管理器的目的略有不同,因此接口也不同。
`safe` 创建一个“安全”上下文,在其中对 `exec` 或 `eval` 的调用会被阻止。
如果用作装饰器,它不会对被装饰的函数本身执行任何操作。
另一方面,`allow_exec` 和 `allow_eval` 需要将可调用对象(除了 `exec` 或 `eval` 之外)作为参数。
这是因为无论它们是用作装饰器还是上下文管理器,它们都会将该可调用对象注册为 `exec` 或 `eval` 的受信任调用者。
## 误报
由于 `exec` 和 `eval` 在 Python 标准库中的许多地方被使用,`safe-exec` 可能会阻止一些必要的代码运行。如果您遇到误报,请[提交 issue](https://github.com/lemonyte/safe-exec/issues)。
作为临时的解决方法,如果您能确定依赖于 `exec` 或 `eval` 的调用函数,您可以使用 `allow_exec` 和 `allow_eval` 上下文管理器将其注册为受信任的调用者。
对 `exec` 和 `eval` 的合法调用是通过检查调用者的栈帧来允许的。如果调用者的代码对象存在于受信任调用者列表中,则允许该调用。此类调用将作为信息性消息进行记录。
```
>>> from safe_exec import safe
>>> import logging
>>> logging.basicConfig(level=logging.INFO)
>>> from typing import NamedTuple
>>> with safe(eval):
... Foo = NamedTuple("Foo", [("bar", int)])
INFO:safe_exec:allowed eval call by 'namedtuple' from '.../lib/collections/__init__.py':345
```
## 许可证
[MIT 许可证](LICENSE.txt)
标签:DAST, DNS 反向解析, eval拦截, exec拦截, 上下文管理器, 代码分析, 凭证管理, 反混淆, 恶意软件分析, 沙箱, 混淆代码分析, 逆向工具, 钩子, 钩子函数, 防御解混淆