我遇到的问题是,运行程序后,它出错说我的 argv 包含 1 个条目,并且需要将其设置为 0
import subprocess
args = ['/challenge/embryoio_level75']
subprocess.run(args)
Run Code Online (Sandbox Code Playgroud)
Key*_*Usr 11
rici的评论更新:
\n显然这个黑客也是可能的:
\nimport subprocess\nsubprocess.run([], executable="/path/to/executable")\nRun Code Online (Sandbox Code Playgroud)\nPython、C/C++ 和其他语言将第一个值 ( argv[0]) 保留为当前运行的可执行文件的值并自动设置。
对于 Python 来说,sys.argv[0]将是以下之一:
-c""(空字符串)您可以使用以下方法进行测试:
\nexec -a "" python -c \'import sys;print(sys.argv[0]);input("pause")\'\nexec -a "" python <file>\nexec -a "" python # then print sys.argv[0] manually\nRun Code Online (Sandbox Code Playgroud)\nPython 本身os.execvpe()在底层使用 Linux/Posix 函数来生成进程。该函数禁止将空args参数传递给子进程本身。
下面是一个非常简单的用于打印的 C 程序argv[0]。或者import sys;print(sys.argv[0]),但使用python -c \'<code>\'or生成python <file>可能会添加不必要的参数,因此我使用 C 来防止噪音。
// gcc -o a.out main.c\n#include <stdio.h>\n\nint main(int argc, char* argv[]) {\n printf("%s\\n", argv[0]);\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n直接使用 Python 生成子进程os.execvpe()
import os\nos.execvpe("./a.out", [], {}) # error\nos.execvpe("./a.out", ["-"], {}) # but this works\nRun Code Online (Sandbox Code Playgroud)\n它仍然会为您提供子进程中的第一个参数,它要求您定义该值,因此您可以使用任何内容而不是可执行文件的路径。
\n不幸的是,即使使用os.execl()(如在 C 中)和类似的方法也会被处理,因此它们会阻止您传递该值,即使标准允许这种行为。
\n\n各种 exec* 函数采用加载到进程中的新程序的参数列表。在每种情况下,这些参数中的第一个参数都会作为新程序自己的名称传递给新程序,而不是作为用户可能在命令行上键入的参数。对于 C 程序员来说,这是传递给程序\xe2\x80\x99s main() 的 argv[0]。例如, os.execv(\'/bin/echo\', [\'foo\', \'bar\']) 只会在标准输出上打印 bar ;foo 似乎会被忽略。(来源)
\n
最有趣的部分是,CPython 的实现使用_execvpe()其 exec 函数对于正常查找来说是“未定义”的。它可能是热补丁的,就像创建内置函数一样,从 C 语言直接通过操作模块的globals存储来创建。
如果我们深入挖掘一下,我们会发现 CPython 的实现阻止我们在这里进行破解。
\n还有另一种方法,那就是通过将unistd.hisexec包装为库(例如使用Cython或ctypes)或传递shell=True给子进程并从 shell 调用它来直接利用 \ :
# int execl(const char *pathname, const char *arg, ..., /*, (char *) NULL */);\nimport ctypes\nlib = ctypes.CDLL("libc.so.6")\nlib.execl("./a.out", None)\nRun Code Online (Sandbox Code Playgroud)\nimport subprocess\nsubprocess.run(["exec", "-a", "", "./a.out"], shell=True)\nRun Code Online (Sandbox Code Playgroud)\n它仍然会创建第一个argv,但与 CPython 不同,它至少是空字符串。
然而,这是 Linux 特有的。不过它可能在 MacOS 上运行。对于 Windows,您可能需要检查CreateProcess()该lpApplicationName参数。
额外:使用 CPython 3.10,您可以访问sys.orig_argv它将提取与上面的 C 代码相同的值。orig_argv注意和之间的区别argv:
$ docker run -it -u 0:0 python:3.10 bash\nroot@a801e79a4264:/# exec -a "" python\nPython 3.10.2 (main, Feb 8 2022, 04:44:29) [GCC 10.2.1 20210110] on linux\nType "help", "copyright", "credits" or "license" for more information.\n>>> import sys\n>>> sys.orig_argv\n[]\n>>> sys.argv\n[\'\']\n>>> \nRun Code Online (Sandbox Code Playgroud)\n正如 rici 所提到的,使用解释器的二进制文件实现合理的目标会有点问题,因此嵌入将对此有所帮助。其中一种嵌入类型非常简单,只需利用PyInstaller:
\n$ docker run -it -u 0:0 python:3.10 bash\nroot@149accac00c8:/# exec -a "" python main.py \n# import sys;print(sys.argv, sys.orig_argv)\n[\'main.py\'] [\'\', \'main.py\']\nRun Code Online (Sandbox Code Playgroud)\n与
\n$ docker run -it -u 0:0 python:3.10 bash\nroot@21a9fed751b8:/# pip install pyinstaller\nroot@21a9fed751b8:/# pyinstaller --onefile main.py\nroot@21a9fed751b8:/# bash # spawn subprocess to prevent exec closing the window\nroot@21a9fed751b8:/# exec -a "" dist/main \n[\'\'] []\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
714 次 |
| 最近记录: |