2023/08/05

pexpect笔记和应用

Pexpect 笔记和应用

参考资料

Pexpect 简介

Pexpect 是一个纯 Python 模块,用于自动化控制交互命令行应用程序,如 ssh, ftp, telnet 等。它的工作原理类似于 Tcl 语言的 Expect 库。

Pexpect 的基本工作流程可以分为三个步骤:

  1. 启动 (Spawn): 使用 pexpect.spawn() 方法执行一个子程序。

  2. 等待 (Expect): 使用 child.expect() 方法等待子程序输出特定的模式(如字符串、正则表达式)。

  3. 发送 (Send): 当 expect() 匹配到期望的模式后,使用 child.send()child.sendline() 方法向子程序发送指令。

这三步,尤其是后两步,会循环执行,从而完成复杂的自动化交互任务。

Pexpect 核心类与方法

pexpect.spawn()

spawn() 方法用于启动一个子程序,并返回一个子程序的句柄(child 对象),后续的所有交互都通过这个句柄进行。

输出:

注意: spawncommand 参数被视为一个整体。如果需要使用管道 | 或重定向 > 等 shell 特性,需要直接调用 shell 来执行命令:

child.expect() 方法

expect() 是 Pexpect 的核心,它会读取子程序的输出,直到匹配到指定的模式。

  • 参数 pattern: 可以是字符串、正则表达式、pexpect.EOF (文件结束)、pexpect.TIMEOUT (超时),或者由这些元素组成的列表

  • 返回值:

    • 如果 pattern 是单个模式,成功匹配返回 0

    • 如果 pattern 是一个列表,成功匹配则返回该模式在列表中的索引

  • 异常: 如果在指定时间内(默认为30秒)没有匹配到任何模式,会抛出 pexpect.TIMEOUT 异常。

为了避免程序因超时而卡死,通常会将 pexpect.EOFpexpect.TIMEOUT 作为模式列表的最后一个元素,用于异常处理。

此外,还有一些更具体的匹配方法:

  • child.expect_exact(): 只匹配纯字符串,不解释为正则表达式。

  • child.expect_list(): 只匹配正则表达式列表。expect() 内部其实调用了此方法。

child.send()child.sendline()

  • child.send(str): 向子程序发送一个字符串,不带换行符。

  • child.sendline(str): 发送一个字符串,并在末尾自动添加换行符 (\r\n),模拟用户按下回车。这在交互式应用中最为常用

child.interact() 方法

interact() 方法会将终端的控制权完全交给用户,允许用户直接与子程序交互。这在需要手动操作的场景(如调试)中非常有用。


应用案例:自动化 CTF 答题

CTF Logo

案例背景: 通过 SSH (ssh noname.plus -p2023) 连接到一个 CTF 挑战。程序要求输入玩家ID,然后开始一个记忆数字的游戏。游戏规则是在数字出现后,立即原样输入,坚持11轮以上即可获胜。

挑战难点: 远程终端为了美观,使用了 ANSI 转义序列来显示彩色文本。这些颜色代码会混在正常的数字字符中,直接读取 child.before 会得到类似 \x1b[31m1\x1b[0m\x1b[32m2\x1b[0m 这样的乱码,需要过滤掉这些非数字字符。

解决方案: 编写一个函数,使用正则表达式过滤掉 ANSI 颜色代码,提取出纯净的数字字符串,然后发送给服务器。

0 评论:

发表评论