windows下几个截包方法的总结

4 篇文章 0 订阅

    写这篇文章其实源于之前做了几个爬虫,当然,不能称为纯粹的爬虫,因为他们不单是无限制的爬网页,大多数需要实现一定的业务逻辑,而最关键的就是登陆的过程以及获取登陆以后的cookie了。

    其实第一个方法可以不用到截包,因为完全可以自己用应用程序模拟出浏览器的所有行为来登陆,比较麻烦的就是验证码识别,可以把验证码抓回来人工输入,也可以找网上的识别lib,但是,一般成功率不太可能到100%。

    但是第一个方式往往比较麻烦,一方面登陆的过程往往是防范比较严格的地方,自己写程序模拟过程比较艰辛,二是经过自己的应用程序模拟的东西不够灵活,因为浏览器不可能共享自己应用程序的cookie,所以只能把自己的应用程序当做是浏览器,那么在网页里实现的东西可能也需要做,无形中增加了难度。

    所以接下来另外的方式就是截包了。所谓的截包,就是不影响浏览器正常工作的情况下把数据包“偷”出来。本人见识短浅,就目前windows下的截包比较常用的方式应该有两个,一个是TCP层的截包,比较著名的库是winpcap,而在他之上著名的截包应用是wireshark,如果用c#调用,那还有个sharppcap是基于winpcap的;另一种方式应该是HTTP层的截包,在这方面做得比较好的工具有fiddler,httpwatcher等。

 

  •     先说TCP层的截包(即winpcap),这个主要适合的情况有有线局域网和大多数无线局域网。可惜winpcap在windows系列得不到3g无线网卡(通常是modem而不是真正的网卡)的包。

 

    调用winpcap的教程网上有很多,我这里着重说一下sharppcap,在codeproject地址是http://www.codeproject.com/Articles/12458/SharpPcap-A-Packet-Capture-Framework-for-NET。这是一个优秀的project,至少能让c#程序员轻松的调用winpcap的api。

    总结起来,sharppcap主要调用步骤有4步。

    1.找到所有可用网卡设备

	    /* Retrieve the device list */
            CaptureDeviceList devices = CaptureDeviceList.Instance;

            /*If no device exists, print error */
            if (devices.Count < 1)
            {
                log.Warn("No device found on this machine");
                return null;
            }

            if (devices.Count == 1)
            {
                return devices[0];
            }

            /* Scan the list printing every entry */
            foreach (ICaptureDevice dev in devices)
            {
                ......
            }

 

     2.开始截包,这里要注意的是DeviceMode.Promiscuous是winpcap的混杂模式,据说无线网截包时候不能使用该模式,可以换成normal什么的

 

 

	    if (device != null)
            {
                log.Info(string.Format("Found device. device name is {0}", device.Name));
                device.OnPacketArrival +=
                    new PacketArrivalEventHandler(device_OnPacketArrival);
                // Open the device for capturing
                device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
                // tcpdump filter to capture only TCP/IP packets
                changeFilter("host " + ConfigurationRepository.SystemConfiguration.Host);
                device.StartCapture();                
            }

 

      3.编写截包事件,其实这里可以拿到IP packet的,就是TCP下层的Packet,而TcpPacket就是把ip的包拿出来做了一次过滤解析,拿到IP packet有什么好处呢?你一定会注意到,Tcp协议里面其实并没有存放ip地址,他的前20个字节里面并没有出现ip地址,这对于习惯了用ip标示主机的我们来说是不太方便的,但是如果你转到ip协议一看,前二十字节就有ip地址,这个大概就是ip协议存在的目的了,而tcp协议存放的是端口(这也是为什么说是端到端的协议),其实利用端口也可以达到同样的目的,因为浏览器一般是在客户端随机开一个端口,只要你拿到并记下来这个端口,其实大多数情况下也可以当做ip来用了,因为相对来说也是唯一的。

 

 

	private static void device_OnPacketArrival(object sender, CaptureEventArgs e)
        {
            DateTime time = e.Packet.Timeval.Date;
            int len = e.Packet.Data.Length;

            Packet packet = Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data);

            TcpPacket tcpPacket = TcpPacket.GetEncapsulated(packet);

            try
            {
                ......这里就是业务逻辑                 
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }

        }private static void device_OnPacketArrival(object sender, CaptureEventArgs e)
        {
            DateTime time = e.Packet.Timeval.Date;
            int len = e.Packet.Data.Length;

            Packet packet = Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data);

            TcpPacket tcpPacket = TcpPacket.GetEncapsulated(packet);

            try
            {
                ......这里就是业务逻辑                 
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }

        }

         截包这里完了以后看业务的需要,是否还需要包重组,这个在正常的tcp应用中都是又操作系统来实现的,相对来说也比较复杂,但是在截包的时候,由于包是无序到来的,所以有时候需要自己进行tcp包重组,重组算法可以参考这个:http://www.rosoo.net/a/201012/10653.html, 个人觉得这是一篇好文,基本上已经把tcp协议吃透了想出来的算法,比较全面,作为应用,只要实现就行了。关于重组的内核代码可以参考这个:http://blog.dccmx.com/2011/03/libnids-tcp-reassembly/。实际上,只要不是特别细致的应用,是可以简化设计的。

 

         4. 最后就是关闭截包了,这里一般是业务触发某个事件来关闭截包。如下代码段

 

            if (device != null)
            {
                try
                {
                    if (device.Started)
                        device.StopCapture();
                }catch(Exception e)
                {
                    log.Error("Can't stop capture", e);
                }
                finally
                {
                    device.Close();
                }
            }

       总的来说,这种方式比较繁琐的地方在于tcp包重组,这里需要充分了解tcp协议。

 

  •          但是当3g上网卡出现后,上面的方式就不能用了,因为windows并不把modem当做一块网卡,遇到这种情况也有几种办法可以解决,一个是截取usb传输的包;另一个就是把截包推迟到上层。针对HTTP协议,可以把截包推迟到应用层。而这个思想有些类似fiddler,fiddler的实现原理就是把系统的代理切换到自己的一个服务,然后由自己转发,如果这个过程自己写,还是有点麻烦,但是稍微查一下,可以发现fiddler就提供几种方式来做这个事,第一个方式是以开发Fiddler插件的方式,第二个方式可以把fiddler当做一个standalone的应用程序,即将fiddler嵌入到自己的程序,http://www.fiddlertool.com/Fiddler/dev/(最新地址在这里http://fiddler.wikidot.com/)。实际上,如果是http的方式截包,有了这种方式以后基本上可以解决所有问题了。
        这里简单介绍一下fiddler的截包API调用,具体可以参考它那本权威的API文档。
        其实上fiddler截包也跟sharppcap截包很类似,主要也是几步:
        1.添加事件,比较常用的方法是oS.url得到请求的url,oS.oRequest.headers["any http header"]得到请求头,比如oS.oRequest.headers["Cookie"]可以轻易得到cookie
Fiddler.CONFIG.IgnoreServerCertErrors = false;

            Fiddler.FiddlerApplication.AfterSessionComplete += delegate(Fiddler.Session oS)
            {
                ......这里就是业务逻辑
            };
        2.开始截包,这里需要指定一个代理端口
Fiddler.FiddlerApplication.Startup(8877, FiddlerCoreStartupFlags.Default);
        3.停止截包
Fiddler.FiddlerApplication.Shutdown();

 

        
 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值