我必须从 netcat 获取输出,对其进行解码并返回。
输入后:
nc cs2107.spro.ink 9000
我得到的输出是这样的:
Welcome to the Proof of work challenge!
Rules: i will provide hex encoded byte strings to you.
Your task is to decode it and calculate the md5 hash in hex encoded format and return it back to me. You will need to do this 500 times!
Ready? Go!
cdde140fffda1da2bc3f
MD5:
所以我必须获取该十六进制编码的字符串,对其进行解码并再次输出,这应该会发生 500 次。
我想我知道我必须做什么,但我不知道如何在unix中编码。我认为需要 .sh 文件?但我不太确定。
从 nc cs2107.spro.ink 9000 开始
从 nc 输出中搜索十六进制字符串
解码并计算 md5 哈希值
最后,寄回
编辑:
我知道我可以通过这样做保存 nc 的输出
nc cs2107.spro.ink 9000 > somefile.txt
然后我如何专门搜索十六进制字符串?
我如何解码十六进制字符串?
最后如何将结果返回到终端?
edit2:所以我可以使用 python 来完成这项任务。一些提示是使用子进程模块或套接字模块。当我读到的时候尝试用子进程来做
subprocess.Popen
保持命令在后台运行
我目前被这个问题困扰
import subprocess
p = subprocess.Popen('nc cs2107.spro.ink 9000', shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE)
a = subprocess.Popen('grep ^[0-9a-f] | xxd -r | md5sum | awk "{print $1}" ', stdin = p.stdout, stdout = subprocess.PIPE)
现在我被困在试图将 a 返回到 p 中
答案1
这是一个部分解决方案,我对 netcat 脚本输入的发生感到沮丧。
- 然后我如何专门搜索十六进制字符串?
这是一种简单的方法:
$nc -d cs2107.spro.ink 9000 > file
Welcome to the Proof of Work Challenge.
Rules: I will provide hex encoded byte strings to you.
Your task is to decode it and calculate the md5 hash.
Return the md5 hash in hex encoded format back to me.
You will need to do this 500 times.
Ready? Go!
eeb105fb2f5e24216bd2
MD5:
在这里,我最初有一个sed
选择特定行 #7 的命令,但是在解决第一个十六进制编码的字节字符串后,立即给出下一个输出。所以我只是将其更改为匹配十六进制字符的正则表达式:
$cat file.txt | grep '^[a-f0-9]'
eeb105fb2f5e24216bd2
- 如何解码十六进制字符串?
$cat file.txt | grep '^[a-f0-9]' | xxd -r -p | md5
92b34e4055a92b9ec32b15f89cc22389
所以我得到了验证,这可以手动进行:
Welcome to the Proof of Work Challenge.
Rules: I will provide hex encoded byte strings to you.
Your task is to decode it and calculate the md5 hash.
Return the md5 hash in hex encoded format back to me.
You will need to do this 500 times.
Ready? Go!
eeb105fb2f5e24216bd2
MD5: 92b34e4055a92b9ec32b15f89cc22389
Correct.
9ecbc2b8d14ae903dce5
- 最后如何将结果返回到终端?
最后一个问题确实是最大的问题。我无法让它发挥作用。我写了几个脚本,但都没有解决问题。问题如吉尔斯提到的,是您需要保持连接打开足够长的时间来读取数据,并将其反馈给仍然打开的程序。这会干扰在 shell 上使用管道命令的正常方法,就像我上面发布的那样。
这是我一直未能在 shell 脚本中正确实现的伪代码:
- for循环,迭代500次。作品。
- 保持与 cs2107.spro.ink 9000 的连接打开。正在进行中。
- 读取服务器发送的位。作品。
- 解码十六进制字符串。作品。
- 计算 md5 哈希值。作品。
- 发送输入以打开连接。进行中。
- 重复步骤 3-6。
- 结尾。
这是我尝试过的一些资源
- 使用输入/输出命名管道进行 TCP 连接
- https://serverfault.com/questions/188936/writing-to-stdin-of-background-process/297095#297095
- https://stackoverflow.com/questions/21130757/send-commands-to-socket-using-netcat
- https://superuser.com/questions/261900/how-can-i-pipe-commands-to-a-netcat-that-will-stay-alive
- https://stackoverflow.com/questions/2559076/how-do-i-redirect-output-to-a-variable-in-this-shell-function
- http://www.linuxquestions.org/questions/programming-9/dynamically-supply-input-to-netcat-in-a-script-793526/
如果您找到解决方案,我很想知道解决方案。也许我稍后会再试一次。
答案2
你是对的,我们需要进行套接字编程才能与服务器通信。我之前尝试过 Python,但最终使用了普通的旧 Bash 脚本。
对于初学者,您可以按照此处的教程了解如何使用 Bash 初始化套接字:http://hacktux.com/bash/socket
第1步:初始化套接字
您可以利用 Bashexec
和 unix 重定向<>
在伪路径上创建套接字。路径语法是/dev/<protocol>/<host>/<port>
exec 3<>/dev/tcp/cs2107.spro.ink/9000;
第 2 步:读取服务器输出
我们需要从服务器输出中读取编码字节。这可以通过命令来完成cat
,但它不会按您的预期工作。这是因为服务器正在等待客户端的输入,并且没有 EOF 字符。 (我猜它与流数据有关)为了防止这种情况,您需要避免读取超出服务器输出的内容,即停止在第 7 行。
head -7 <&3
第 3 步:数据的抓取和转换
egrep -o '^[0-9a-f]{20}' | xxd -r -p | md5sum
读取信息块后,我们可以使用egrep来检索十六进制字节。由于hexdump的长度是固定的,我们可以利用正则表达式来提取所需的数据。
通过管道xxd -r -p
将 hexdump 转换为二进制并将其输出为纯文本。md5sum
然后会做一些肮脏的工作并为我们计算答案。
第四步:写回服务器
awk '{print $1}' >&3;
在我的例子中, md5sum 在字符串末尾输出答案和额外字符,因此我使用awk
打印第一列并写回服务器。
第5步:再重复499次
与步骤2-4类似,只不过我们需要修改步骤2,因为服务器在后续响应中只会输出“正确”,而不是长的介绍性文本。修改head
为读取 2 行。我们还需要再执行 499 次:
for i in {1..499}
do
head -2 <&3 | egrep -o '^[0-9a-f]{20}' | xxd -r -p | md5sum | awk '{print $1}' >&3;
done
第五步:夺旗
一旦所有 500 响应完成,就可以通过捕获套接字来检索该标志。
cat <&3
P/SI 采用与 OP 相同的模块并执行相同的作业,所以我想我会在这里分享我的答案。模块结束后碰巧发现了这篇文章。
答案3
只需使用管道:
...
process_rcvd_msg() {
while IFS= read -r msg && [[ -n $msg ]]; do
... do whatever you want with the message ...
echo "Received: $msg"
done
}
... more code ...
# Start listening to TCP requests and processing them
nc -k -vv -l 1234 | process_rcvd_msg
... few more code here ...
将数据发送到服务器甚至更容易:
...
send_msg() {
local host="$1" ; shift
local port="$1" ; shift
local params="$*"
exec 9<>/dev/tcp/$host/$port
printf "%s" "$params" >&9
exec 9<&-
}
... do something here ...
# Send the message to the server
send_msg localhost 1234 "Dumb message is here!!! Let's see what happens..."
... do year another thing ...
希望有帮助。干杯!
答案4
使用调用的 shell 执行此操作nc
很困难,因为您需要保持连接打开并从中获取数据nc
、处理该数据并将其反馈回同一实例nc
。这是可以做到的,但是很难。
如果你能用同一种语言与网络交互并控制数据流,那就容易多了。如果您使用 shell bash、ksh 或 ksh 之一,那么您可以使用它们的网络功能:这些 shell 可以是 TCP 客户端。例如,下面是一个从服务器读取行并逐一回显它们的脚本:
{
while IFS= read -r line <&3; do
echo "$line" >&3
done
} 3<>/dev/tcp/cs2107.spro.ink/9000
要解码十六进制字符串,请查找xxd
.我会让你弄清楚数据处理逻辑。