企鹅的封包拦截器, 只是技术研究爱好

来源:互联网 发布:淘宝怎么样才不算盗图 编辑:程序博客网 时间:2024/05/27 00:48

当初写这个的时候是因为自己正在研究pc qq的协议, 本想用delphi写,不过没有找到完整的WinCap的delphi头文件, 只好用c++ builder了, 说实在的是第一次用wincap, 都是摸索着写的

UMain.h

//---------------------------------------------------------------------------#ifndef UMainH#define UMainH//---------------------------------------------------------------------------#include <System.Classes.hpp>#include <Vcl.Controls.hpp>#include <Vcl.StdCtrls.hpp>#include <Vcl.Forms.hpp>#include <windows.hpp>#include <pcap.h>#include <Vcl.ExtCtrls.hpp>#include <Vcl.ComCtrls.hpp>//#include <System.StrUtils.hpp>//#include <Winapi.Windows.hpp>//#include <Vcl.XPMan.hpp>#pragma comment(lib, "Packet.lib")#pragma comment(lib, "wpcap.lib")//#pragma resource "WindowsXP.res"#pragma hdrstop//---------------------------------------------------------------------------// 定义一个线程继承自 TThreadclass TMyThread : public TThread{   private:void __fastcall Execute();void StartFunc();   public: __fastcall TMyThread(bool CreateSuspended);   public: pcap_t *adhandle;};class TfrmMain : public TForm{__published:// IDE-managed ComponentsTMemo *mmo1;TPanel *pnl1;TPageControl *pgc1;TTabSheet *ts1;TTabSheet *ts2;TPanel *pnl2;TLabel *Label1;TLabel *Label2;TComboBox *cbbAdapteList;TComboBox *cbbProtocol;TButton *btnStart;TButton *btnStop;TSplitter *spl1;TLabel *Label3;TEdit *edtqq;TListView *lvpacket;TButton *btnClear;void __fastcall btnStartClick(TObject *Sender);void __fastcall FormCreate(TObject *Sender);void __fastcall btnStopClick(TObject *Sender);void __fastcall cbbProtocolChange(TObject *Sender);void __fastcall lvpacketClick(TObject *Sender);void __fastcall lvpacketColumnClick(TObject *Sender, TListColumn *Column);void __fastcall FormDestroy(TObject *Sender);void __fastcall btnClearClick(TObject *Sender);private:// User declarationspcap_t *adhandle;TMyThread *Mythread;pcap_if_t *alldevs;pcap_if_t *d;int listCount;char packet_filter[50];private:void __fastcall ListViewColumnSetting(int cbbindex);void __fastcall ListViewAddColumn(TListView *lv, String Caption, int Widht);public:// User declarations__fastcall TfrmMain(TComponent* Owner);protected:void __fastcall RecvWinCapData(TWMCopyData Message);BEGIN_MESSAGE_MAP  MESSAGE_HANDLER(WM_COPYDATA, TWMCopyData, RecvWinCapData);END_MESSAGE_MAP(TForm)};//---------------------------------------------------------------------------/* 4 字节IP地址 */typedef struct ip_address{u_char byte1;u_char byte2;u_char byte3;u_char byte4;}ip_address;/* IPv4 头 */typedef struct ip_header{u_charver_ihl;// Version (4 bits) + Internet header length (4 bits)u_chartos;// Type of serviceu_short tlen;// Total lengthu_short identification; // Identificationu_short flags_fo;// Flags (3 bits) + Fragment offset (13 bits)u_charttl;// Time to liveu_charproto;// Protocolu_short crc;// Header checksumip_addresssaddr;// Source addressip_addressdaddr;// Destination addressu_intop_pad;// Option + Padding}ip_header;/* UDP 头 */typedef struct udp_header{u_short sport;// Source portu_short dport;// Destination portu_short len;// Datagram lengthu_short crc;// Checksum}udp_header;/* 我的数据结构 */typedef struct TMyData{  char timestr[16];   // 时戳  BYTE flags;         // 数据标识 0 发送, 1 接收  char sipp[30];      // 格式化后的源IP和端口  char dipp[30];      // 格式化后的目标IP和端口  int  datalen;       // QQ数据段长度  u_char *data; // 数据指针}TMyData;/* 捕获的回调函数声明 */void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);extern PACKAGE TfrmMain *frmMain;//---------------------------------------------------------------------------#endif


UMain.dfm

object frmMain: TfrmMain  Left = 0  Top = 0  Caption = #23553#21253#25429#33719#24037#20855' By:ying32 QQ:396506155 ver 1.0'  ClientHeight = 373  ClientWidth = 745  Color = clBtnFace  DoubleBuffered = True  Font.Charset = DEFAULT_CHARSET  Font.Color = clWindowText  Font.Height = -11  Font.Name = 'Tahoma'  Font.Style = []  OldCreateOrder = False  Position = poScreenCenter  WindowState = wsMaximized  OnCreate = FormCreate  OnDestroy = FormDestroy  PixelsPerInch = 96  TextHeight = 13  object spl1: TSplitter    Left = 0    Top = 237    Width = 745    Height = 3    Cursor = crVSplit    Align = alBottom    ExplicitTop = 41    ExplicitWidth = 199  end  object mmo1: TMemo    Left = 0    Top = 240    Width = 745    Height = 92    Align = alBottom    Font.Charset = DEFAULT_CHARSET    Font.Color = clWindowText    Font.Height = -13    Font.Name = 'Courier New'    Font.Style = []    ParentFont = False    ScrollBars = ssVertical    TabOrder = 0  end  object pnl1: TPanel    Left = 0    Top = 332    Width = 745    Height = 41    Align = alBottom    BevelOuter = bvNone    TabOrder = 1  end  object pgc1: TPageControl    Left = 0    Top = 61    Width = 745    Height = 176    ActivePage = ts1    Align = alClient    TabOrder = 2    object ts1: TTabSheet      Caption = #23553#21253#39029#38754      object lvpacket: TListView        Left = 0        Top = 0        Width = 737        Height = 148        Align = alClient        Columns = <          item            Caption = #24207          end          item            Caption = #26631#35782            Width = 60          end          item            Caption = #26102#25139            Width = 80          end          item            Caption = #28304'IP:'#31471#21475            Width = 120          end          item            Caption = #30446#26631'IP:'#31471#21475            Width = 120          end          item            Caption = #38271#24230          end          item            Caption = #29256#26412#21495            Width = 60          end          item            Caption = #21629#20196            Width = 60          end          item            Caption = #21253#24207            Width = 60          end          item            Caption = 'QQ'#21495            Width = 110          end          item            Caption = #22266#23450            Width = 180          end          item            Caption = 'TEA'#21152#23494#25968#25454#27573            Width = 385          end>        DoubleBuffered = True        GridLines = True        MultiSelect = True        ReadOnly = True        RowSelect = True        ParentDoubleBuffered = False        TabOrder = 0        ViewStyle = vsReport        OnClick = lvpacketClick        OnColumnClick = lvpacketColumnClick      end    end    object ts2: TTabSheet      Caption = #20854#23427      ImageIndex = 1    end  end  object pnl2: TPanel    Left = 0    Top = 0    Width = 745    Height = 61    Align = alTop    BevelOuter = bvNone    TabOrder = 3    DesignSize = (      745      61)    object Label1: TLabel      Left = 5      Top = 13      Width = 96      Height = 13      Caption = #36873#25321#19968#20010#36866#37197#22120#65306    end    object Label2: TLabel      Left = 399      Top = 14      Width = 36      Height = 13      AutoSize = False      Caption = #21327#35758#65306    end    object Label3: TLabel      Left = 8      Top = 40      Width = 129      Height = 13      AutoSize = False      Caption = #21482#25235#21462'QQ('#20026'0'#21017#20840#37096')'#65306    end    object cbbAdapteList: TComboBox      Left = 107      Top = 11      Width = 278      Height = 21      Style = csDropDownList      TabOrder = 0    end    object cbbProtocol: TComboBox      Left = 433      Top = 11      Width = 112      Height = 21      Style = csDropDownList      ItemIndex = 0      TabOrder = 1      Text = 'PCQQ'      OnChange = cbbProtocolChange      Items.Strings = (        'PCQQ'        #23433#21331'QQ'        'IPhoneQQ'        #33258#23450#20041)    end    object btnStart: TButton      Left = 585      Top = 10      Width = 75      Height = 25      Anchors = [akRight]      Caption = #24320#22987      TabOrder = 2      OnClick = btnStartClick    end    object btnStop: TButton      Left = 666      Top = 10      Width = 75      Height = 25      Anchors = [akRight]      Caption = #20572#27490      Enabled = False      TabOrder = 3      OnClick = btnStopClick    end    object edtqq: TEdit      Left = 139      Top = 37      Width = 140      Height = 21      MaxLength = 11      NumbersOnly = True      TabOrder = 4      Text = '2482241557'    end    object btnClear: TButton      Left = 666      Top = 37      Width = 75      Height = 25      Anchors = [akRight]      Caption = #28165#38500      TabOrder = 5      OnClick = btnClearClick    end  endend


UMain.cpp

//---------------------------------------------------------------------------#include <vcl.h>#include <commctrl.h>#pragma hdrstop#include "UMain.h"//---------------------------------------------------------------------------#pragma package(smart_init)#pragma resource "*.dfm"TfrmMain *frmMain;// 定义一个接收消息窗口句柄变量HWND g_hWnd = 0;int g_Protocolflag = 0;DWORD g_onlyQQ = 0;bool g_BSort = false; // ListView升序降序控制//int ColumnToSort = 0;// 定义一个自定义消息//#define MYCOPYDATA (WM_USER + 0x23)//---------------------------------------------------------------------------__fastcall TfrmMain::TfrmMain(TComponent* Owner): TForm(Owner){}// 转换字节到十六进制文本String __fastcall ByteArrToString(BYTE *qqdata, int len){  String ret = "";  BYTE *a;  for (int i = 0; i < len; i++)  { if (i > 0)   if (i % 16 == 0) ret = ret + "\r\n"; a = (BYTE*)(qqdata + i); ret = ret + IntToHex(*(a), 2) + " ";  }  return ret;}// 高与低位字节互换int __fastcall LittleOrBigEndian(int c, int Len){   BYTE a[4] = {0}, b[4] = {0};   int result = 0;   memcpy(&a, &c, Len);   switch(Len)   {case 2: b[0] = a[1]; b[1] = a[0]; break;case 4: b[0] = a[3]; b[1] = a[2]; b[2] = a[1]; b[3] = a[0]; break;   }   memcpy(&result, &b, 4);   return result;}// 发送数据void __fastcall SendWinCapData(HWND hWd, void *Data, int Len){  TCopyDataStruct D;  D.dwData = 0;  D.cbData = Len;  D.lpData = Data;  SendMessage(hWd, WM_COPYDATA, 0, (int)&D);}// 添加柱头void __fastcall TfrmMain::ListViewAddColumn(TListView *lv, String Caption, int Widht){   TListColumn *Col = lv->Columns->Add();   Col->Caption = Caption;   Col->Width = Widht;}// 设置柱头void __fastcall TfrmMain::ListViewColumnSetting(int cbbindex){   char *lvCaption[6] = {"序", "标识", "时戳", "源IP:端口", "目标IP:端口", "长度"};   int lvWidth[6] = {50, 60, 80, 120, 120, 50};   if (cbbindex == -1) return;   if (cbbindex == cbbProtocol->Tag) return;   lvpacket->Columns->Clear();   for (int i = 0; i < 6; i++) ListViewAddColumn(lvpacket, lvCaption[i], lvWidth[i]);   switch(cbbindex)   {  // PC QQ协议默认  case 0:  ListViewAddColumn(lvpacket, "版本号", 60);  ListViewAddColumn(lvpacket, "命令"  , 60);  ListViewAddColumn(lvpacket, "包序"  , 60);  ListViewAddColumn(lvpacket, "QQ号"  , 110);  ListViewAddColumn(lvpacket, "固定", 180);  ListViewAddColumn(lvpacket, "TEA加密数据段", 385);  break;      default :         ListViewAddColumn(lvpacket, "封包数据", 855); break;   }   // 保存最后更改的 ItemIndex   cbbProtocol->Tag = cbbProtocol->ItemIndex;}// 接收WinCap数据void __fastcall TfrmMain::RecvWinCapData(TWMCopyData Message){TListItem *list;TMyData *data = (TMyData*)Message.CopyDataStruct->lpData;list = lvpacket->Items->Add();// 自序String s;s.printf(TEXT("%.4d"), lvpacket->Items->Count);list->Caption = s;//list->Caption = RightStr(list->Caption, 4);// 标识switch(data->flags){   case 0:  list->SubItems->Add("SEND");  break;   case 1:  list->SubItems->Add("RECV");  break;}// 时戳list->SubItems->Add(data->timestr);// 源IPlist->SubItems->Add(data->sipp);// 目标IPlist->SubItems->Add(data->dipp);// 数据长度list->SubItems->Add(IntToStr(data->datalen));switch(cbbProtocol->ItemIndex){   case 0: {// 版本WORD verid = 0;memcpy(&verid, (void*)(data->data + 1), 2);list->SubItems->Add(IntToHex(LittleOrBigEndian(verid, 2), 4));// 命令WORD cmd = 0;memcpy(&cmd, (void*)(data->data + 3), 2);list->SubItems->Add(IntToHex(LittleOrBigEndian(cmd, 2), 4));// 包序WORD seq = 0;memcpy(&seq, (void*)(data->data + 5), 2);list->SubItems->Add(IntToHex(LittleOrBigEndian(seq, 2), 4));// QQ号DWORD QQNum = 0;memcpy(&QQNum, (void*)(data->data + 7), 4);QQNum = LittleOrBigEndian(QQNum, 4);//String QQStr;//QQStr.printf("%ld", QQNum);// 我去这里可以直接转换哦list->SubItems->Add(QQNum);// 位置偏移int offset;            // 固定字段BYTE *FixedValue;switch(data->flags){   case 0:  FixedValue = new BYTE[11];  memcpy(FixedValue, data->data + 11, 11);  list->SubItems->Add(ByteArrToString(FixedValue, 11));  delete [] FixedValue;  offset = 11 + 11;  break;   case 1:  FixedValue = new BYTE[3];  memcpy(FixedValue, data->data + 11, 3);  list->SubItems->Add(ByteArrToString(FixedValue, 3));  delete [] FixedValue;  offset = 11 + 3;  break;}int TEALen = data->datalen - offset - 1;BYTE *TEAData = new BYTE[TEALen];memcpy(TEAData, data->data + offset, TEALen);list->SubItems->Add(ByteArrToString(TEAData, TEALen));delete [] TEAData;      break;         }   default :            list->SubItems->Add(ByteArrToString(data->data, data->datalen));        break;}}// ListView排序过程int __stdcall ListViewSort(long ItemA, long ItemB, long ParamSort){  TListItem *Item1 = (TListItem*)ItemA;  TListItem *Item2 = (TListItem*)ItemB;  if (ParamSort != 0)  { try { String txt1 = Item1->SubItems->Strings[ParamSort - 1]; String txt2 = Item2->SubItems->Strings[ParamSort - 1]; if (g_BSort)   return CompareText(txt1, txt2); else   return -CompareText(txt1,txt2); } catch(...){};  }else  { if (g_BSort)   return CompareText(Item1->Caption, Item2->Caption); else   return -CompareText(Item1->Caption, Item2->Caption);  }  return 0;}// 定义一个捕获的线程__fastcall TMyThread::TMyThread(bool CreateSuspended)   : TThread(CreateSuspended){}void __fastcall TMyThread::Execute(){ FreeOnTerminate = true; //OutputDebugStringA("线程已经进入"); StartFunc();}void TMyThread::StartFunc(){   pcap_loop(adhandle, 0, packet_handler, NULL);}//---------------------------------------------------------------------------/* 回调函数调用为每个传入数据包libpcap */void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data){struct tm *ltime;ip_header *ih;udp_header *uh;u_int ip_len;u_short sport,dport;time_t local_tv_sec;    // 我的发送数据定义TMyData SendData;(VOID)(param);/* 将时间戳到可读的格式 */local_tv_sec = header->ts.tv_sec;ltime = localtime(&local_tv_sec);strftime(SendData.timestr, sizeof(SendData.timestr), "%H:%M:%S", ltime);// 取回 ip报头的位置ih = (ip_header *) (pkt_data +14 /*14为以太网头长度*/);// 取回 UDP报头的位置ip_len = (ih->ver_ihl & 0xF) * 4;uh = (udp_header *) ((u_char*)ih + ip_len);// 从网络字节顺序转换为主机字节顺序sport = ntohs(uh->sport);dport = ntohs(uh->dport);// 源IP和端口sprintf(SendData.sipp, "%d.%d.%d.%d:%d",ih->saddr.byte1,ih->saddr.byte2,ih->saddr.byte3,ih->saddr.byte4,sport);    // 目标IP和端口sprintf(SendData.dipp, "%d.%d.%d.%d:%d",ih->daddr.byte1,ih->daddr.byte2,ih->daddr.byte3,ih->daddr.byte4,dport);    // 根据定义的协议发送数据switch(g_Protocolflag){  case 0:    // 这里过滤掉一些其它端口的包if (sport >= 4000 && sport <= 8000){// 只捕获的QQ不为0if (g_onlyQQ != 0){  DWORD tmpqq = 0;  // 读取QQ号  memcpy(&tmpqq, pkt_data + ip_len + 14 + sizeof(uh) + 4 + 7, 4);              // 如果等于当前只抓取的QQ号  if (tmpqq == g_onlyQQ)  {                // 确定QQ封包的位置SendData.data = (char*)(pkt_data + ip_len + 14 + sizeof(uh) + 4);SendData.datalen = header->len - (ip_len + 14 + sizeof(uh) + 4);SendData.flags = dport == 8000 ? 0 : 1;// 发送数据SendWinCapData(g_hWnd,   (void*)&SendData,sizeof(SendData) + header->len - 4);//OutputDebugString(ByteArrToString((char*)SendData.data, SendData.datalen).w_str());  }}else{SendData.data = (char*)(pkt_data + ip_len + 14 + sizeof(uh) + 4);SendData.datalen = header->len - (ip_len + 14 + sizeof(uh) + 4);SendData.flags = dport == 8000 ? 0 : 1;// 发送数据SendWinCapData(g_hWnd,   (void*)&SendData,sizeof(SendData) + header->len - 4);}}break;default:break;}}void __fastcall TfrmMain::btnStartClick(TObject *Sender){   char errbuf[PCAP_ERRBUF_SIZE];u_int netmask;int i;int inum;struct bpf_program fcode;String ErrMsg;if (cbbProtocol->ItemIndex == -1){   ShowMessage("请选择一个协议进行捕获。");   return;}switch(cbbProtocol->ItemIndex){  case 0 :            memset(packet_filter, 0, sizeof(packet_filter));strcpy(packet_filter, "ip and udp port 8000");break;  case 1 :  case 2 :            memset(packet_filter, 0, sizeof(packet_filter));strcpy(packet_filter, "ip and tcp port 8080"); // or port 14000break;}this->Caption = packet_filter;inum = cbbAdapteList->ItemIndex + 1;if(inum < 1 || inum > listCount){ShowMessage("请选择一个适配器。");return;}for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);if ((adhandle= pcap_open_live(d->name,// 驱动名称 65536,// 捕获的数据包大小// 65536 最大值 1,// 混合模式 (非0为混合模式) 1000,// 读取超时以毫秒计算 errbuf// 错误信息 )) == NULL){ErrMsg.printf(TEXT("无法打开适配器 %s WinPcap不支持"), errbuf);ShowMessage(ErrMsg);return;}/* 检查链路层。为简单起见,我们只支持以太网. */if(pcap_datalink(adhandle) != DLT_EN10MB){ShowMessage("这个程序只能在以太网中使用.");return;}if(d->addresses != NULL)/* 检索第一个地址的掩码的接口 */netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;else/* 如果界面是没有地址,我们假设在一个C类网络 */netmask=0xFFFFFF;//编译过滤器if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 ){ShowMessage("无法编译包过滤设置字符串, 请检查语法。");return;}//设置过滤器if (pcap_setfilter(adhandle, &fcode)<0){ShowMessage("设置过滤出错。");return;}//pcap_freealldevs(alldevs);if (adhandle){         //TThread.CreateAnonymousThread( g_hWnd = this->Handle; g_Protocolflag = cbbProtocol->ItemIndex; if (edtqq->Text.Length() == 0)   g_onlyQQ = 0; else   // 我kao ToInt 不能用,整数大于原来的了位数不够了   g_onlyQQ = LittleOrBigEndian((DWORD)edtqq->Text.ToDouble(), 4); Mythread = new TMyThread(true); Mythread->adhandle = adhandle; Mythread->Start(); btnStart->Enabled = false; cbbAdapteList->Enabled = false; cbbProtocol->Enabled = false; edtqq->Enabled = false; btnStop->Enabled = true;}else  ShowMessage("错误,未选择一个适配器或者适配器不支持等。");}//---------------------------------------------------------------------------void __fastcall TfrmMain::FormCreate(TObject *Sender){char errbuf[PCAP_ERRBUF_SIZE];listCount = 0;    String ErrMsg;/* 检索设备列表 */if(pcap_findalldevs(&alldevs, errbuf) == -1){   ErrMsg.printf(TEXT("检索列表设置出错,位于pcap_findalldevs: %s"), errbuf);   ShowMessage(ErrMsg);   return;}/* 显示列表 */for(d=alldevs; d; d=d->next){++listCount;cbbAdapteList->Items->Add(d->description);if (!d->description)  cbbAdapteList->Items->Add(d->name);}if(listCount == 0){mmo1->Lines->Add("没有接口发现!确保WinPcap安装");return;}}//---------------------------------------------------------------------------void __fastcall TfrmMain::btnStopClick(TObject *Sender){   if (adhandle) pcap_close(adhandle);   if (Mythread)   {  if (Mythread->Suspended)  {Mythread->WaitFor();Mythread->Terminate();  }   }   btnStart->Enabled = true;   cbbAdapteList->Enabled = true;   cbbProtocol->Enabled = true;   edtqq->Enabled = true;   btnStop->Enabled = false;}//---------------------------------------------------------------------------void __fastcall TfrmMain::cbbProtocolChange(TObject *Sender){   if (cbbProtocol->ItemIndex == cbbProtocol->Items->Count - 1)   { AnsiString s = InputBox("自定义过滤规则", "WinCap过滤封包规则:", ""/*"ip and udp port 8000"*/); if (s.Length() == 0) {   cbbProtocol->ItemIndex = 0;   cbbProtocol->OnChange; }else{ // 最讨厌警告了 OutputDebugString(TEXT("fffff")); if (s.Length() < (int)sizeof(packet_filter)) {   memset(packet_filter, 0, sizeof(packet_filter));   strcpy(packet_filter, s.c_str());   //OutputDebugStringA(packet_filter); } else {   cbbProtocol->ItemIndex = 0;   cbbProtocol->OnChange; } }   }   ListViewColumnSetting(cbbProtocol->ItemIndex);}//---------------------------------------------------------------------------void __fastcall TfrmMain::lvpacketClick(TObject *Sender){   int Index = lvpacket->ItemIndex;   if (Index != -1)   {  mmo1->Text = lvpacket->Items->Item[Index]->SubItems->Strings[10];  lvpacket->Tag = Index;   }}//---------------------------------------------------------------------------void __fastcall TfrmMain::lvpacketColumnClick(TObject *Sender, TListColumn *Column){   lvpacket->CustomSort(&ListViewSort, Column->Index);   g_BSort = !g_BSort;}//---------------------------------------------------------------------------void __fastcall TfrmMain::FormDestroy(TObject *Sender){   pcap_freealldevs(alldevs);}//---------------------------------------------------------------------------void __fastcall TfrmMain::btnClearClick(TObject *Sender){   lvpacket->Clear();}//---------------------------------------------------------------------------

附上一张截图吧



0 0
原创粉丝点击