eval补充
系统攻击
res = eval(input("请输入>>>")) print(res, type(res)) """ 请输入>>>12 12 <class 'int'> """
❝可以直接拿到关键信息,这里是不是看着没啥,那么在控制台输入呢:
❞
(venv) E:\selenium_test\def_test>python toml_read.py 请输入>>>__import__("os").system("dir") 驱动器 E 中的卷是 Job 卷的序列号是 4653-5263 E:\selenium_test\def_test 的目录 2022/11/14 19:56 <DIR> . 2022/11/14 19:56 <DIR> .. 2022/10/15 13:09 555 csv_read.py 2022/11/03 23:32 18 log.txt 2022/11/14 19:56 1,803 toml_read.py 2022/11/07 22:39 996 Yaml_read.py 2022/11/14 16:08 <DIR> __pycache__ 2022/09/17 10:56 95 作用域.py 2022/10/13 21:44 2,348 闭包.py 14 个文件 6,623 字节 3 个目录 205,870,223,360 可用字节 0 <class 'int'>
❝既然可以都到文件信息,那么我直接打开呢:
❞
def func(): return "我是清安" res = eval(input("请输入>>>")) print(res, type(res))
❝我的Py文件内容。控制台读取这个文件:
❞
(venv) E:\selenium_test\def_test>python toml_read.py 请输入>>>print(open('toml_read.py','rt',encoding='utf8').read()) # # -*- coding: utf-8 -*- # ----清安—--- # 微信:qing_an_an # 公众号:测个der def func(): return "我是清安" res = eval(input("请输入>>>")) print(res, type(res)) None <class 'NoneType'>
❝可别小看这open函数,配合eval可以直接在控制台把你整个Py文件一字不落的都读出来
❞
限制
❝之前是提到过一点点,现在来说说:
❞
l = {} l['__builtins__'] = None res = eval(input("请输入>>>"),l) print(res, type(res))
❝再次读取:
❞
(venv) E:\selenium_test\def_test>python toml_read.py 请输入>>>print(__import__("os").system("dir")) Traceback (most recent call last): File "E:\selenium_test\def_test\toml_read.py", line 57, in <module> res = eval(input("请输入>>>"),l) File "<string>", line 1, in <module> TypeError: 'NoneType' object is not subscriptable
❝报错了,就不被允许读取了。 它与eval()类似
❞
源码
def exec( __source: str | bytes | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, Any] | None = ... ) -> Any: ...
❝1、源可以是表示Python表达式的字符串或编译器()返回的代码对象 2、全局:全局必须是字典 3、局部变量:局部可以是任何映射***
❞
小例子
q = 3 g = {"n":9} l = {} exec("a=1+1", g, l) print(l)
❝i是全局名称空间,g是局部名称空间。它会将第一个参数产生的值存入到局部中,我们可以通过打印局部得到结果。
❞ ❝如果没有a亦或者局部中本来就存在一个键值对呢,一起看看:
❞
"""g中有值""" q = 3 g = {"n": 9} l = {"b": 1} exec("1+1", g, l) print(l) # {"b": 1} """g中无值""" q = 3 g = {"n": 9} l = {} exec("1+1", g, l) print(l) # {}
全局
❝当我不定义全局以及局部的时候:
❞
q = 3 g = {"n": 9} l = {} exec("a=1+1") print(l) print(a) """ {} 2 """
❝在编译器上a会提示你有误(红色下划线)。但是依然可以输出。 前面说了,是默认传入局部的,但是上述错处本身就在全局,所以全局打印是可以得到结果的。
❞
局部
def func(): q = 3 g = {"n": 9} l = {} exec("a=1+1") print(l) print(a) func()
❝这样是不被允许的。错误提示:NameError: name 'a' is not defined,名字没有定义。为什么呢? 在上述中,全局中使用局部是被允许的,那是因为在这背后有一个绑定的过程,全局使用locals等同于使用globals。 exec("a=1+1"),其默认是:exec("a=1+1",globals(),locals())。在上述中,需要分清的是,locals的值并未与当前的局部空间绑定,所以func函数不认识a。所以我们可以传入g,l进去绑定一下:
❞
def func(): q = 3 g = {"n": 9} l = {} exec("a=1+1",g,l) print(l) func()