您的位置:首页 > 编程语言

一个简单的抓包代码

2015-12-12 21:17 239 查看
// 抓包.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdlib.h>
#include <winsock2.h>
#include <filesystem>
#include <mstcpip.h>

#pragma comment(lib, "WS2_32.lib")   //加载动态库 ws23_2.dll(system32)

#define OK 0
#define ERROR -1

#define HOST_NAME_LEN 256
#define MY_PORT 10001  //打开端口用1024以上的,1024以下的被系统或特定程序使用
#define BUFF_LEN 65535

void PrintData(char szBuf[], int iLen)
{
//printf("RCV: %s\n", szBuf);
//捕获的数据一定不是字符串
//打印16进制数据
printf("REC:\n");
for (int i = 12; i < iLen; i++)
{
printf("%02x ", szBuf[i] & 0xff);
}
printf("\n");
return;
}

int CaptureData(){
SOCKET iFd;   //套接字
char szHostName[HOST_NAME_LEN];   //计算机名
HOSTENT *pHost;
WSADATA stWsa;    //用于打开动态链接库
SOCKADDR_IN stAddr = { 0 };
DWORD dwInBuff = 1;
DWORD dwOutBuff;
DWORD dwBytesRet;
int iRet;
char szBuf[BUFF_LEN];

//0x0202版本号
//不等于就是加载失败
if (WSAStartup(0x0202, &stWsa) != OK)   //对winsock服务初始化,第一个参数是版本号,第二个参数用来接收winsock实现的具体细节
{
printf("Wsa StartUp failed\n");
return ERROR;
}

if (gethostname(szHostName, HOST_NAME_LEN) != OK)   //返回本地主机的主机名,两个参数分别是存放主机名的数组以及数组长度
{
WSACleanup();     //终止ws2_32.dll的使用
return ERROR;
}
printf("hostName:%s\n", szHostName);
pHost = gethostbyname(szHostName);    //返回指针,指向给定主机名的主机信息
printf("MyIP: %d.%d.%d.%d\n", pHost->h_addr_list[0][0] & 0xff,       //取出后8位,每个数字由32位组成,前面全是1
pHost->h_addr_list[0][1] & 0xff,
pHost->h_addr_list[0][2] & 0xff,
pHost->h_addr_list[0][3] & 0xff);

//整数表示的ip
stAddr.sin_addr.s_addr = *(unsigned long*)pHost->h_addr;   //设置IP地址
//printf("%xu\n", stAddr.sin_addr.s_addr);
stAddr.sin_family = AF_INET;    //设置协议族
stAddr.sin_port = htons(MY_PORT);   //设置端口号

//接收原始数据流,因为要接收的数据是发往所有端口的
iFd = socket(AF_INET, SOCK_RAW, IPPROTO_IP);   //创建一个套接字,af:地址描述, type:套接口类型, protocol:协议
if (iFd == INVALID_SOCKET)
{
printf("socket failed:%d\n", WSAGetLastError());
WSACleanup();
return ERROR;
}

if (bind(iFd, (SOCKADDR*)&stAddr, sizeof(SOCKADDR)) != OK)   //将一固定的地址绑定在套接字描述符上
{
printf("bind failed:%d\n",WSAGetLastError());
WSACleanup();
closesocket(iFd);
return ERROR;
}
//设置iFd守包规则,SIO_RCVALL接收所有的包,输入缓冲区地址及大小,输出缓冲区大小及地址,输出实际字节数的地址
iRet = WSAIoctl(iFd, SIO_RCVALL, &dwInBuff, sizeof(dwInBuff),
&dwOutBuff, sizeof(dwOutBuff), &dwBytesRet, NULL, NULL);
if (iRet != OK)
{
printf("IOCTL failed.\n");
WSACleanup();
closesocket(iFd);
return ERROR;
}

while (true)
{
memset(szBuf, 0, BUFF_LEN);
iRet = recv(iFd, szBuf, BUFF_LEN, 0);
if (iRet < 0)
{
break;
}
else{
PrintData(szBuf, iRet);
}
}

WSACleanup();
closesocket(iFd);
return OK;
}

int _tmain(int argc, _TCHAR* argv[])
{

CaptureData();
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: