Cool-Y.github.io/2019/03/28/逆向工程实验/index.html
2019-04-01 15:21:38 +08:00

1526 lines
62 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="逆向,破解,">
<meta name="description" content="软件保护方式 功能限制 时间限制 运行时长限制 使用日期限制 使用次数限制 警告窗口 分析工具 静态分析工具 IDA W32Dasm lordPE Resource Hacker 动态分析工具 OllyDbg WinDbg 对抗分析技术 反静态分析技术 花指令 自修改代码技术 多态技术 变形技术 虚拟机保护技术 反动态分析技术 检测调试状态 检测用户态调试器">
<meta name="keywords" content="逆向,破解">
<meta property="og:type" content="article">
<meta property="og:title" content="逆向工程与软件破解">
<meta property="og:url" content="https://cool-y.github.io/2019/03/28/逆向工程实验/index.html">
<meta property="og:site_name" content="混元霹雳手">
<meta property="og:description" content="软件保护方式 功能限制 时间限制 运行时长限制 使用日期限制 使用次数限制 警告窗口 分析工具 静态分析工具 IDA W32Dasm lordPE Resource Hacker 动态分析工具 OllyDbg WinDbg 对抗分析技术 反静态分析技术 花指令 自修改代码技术 多态技术 变形技术 虚拟机保护技术 反动态分析技术 检测调试状态 检测用户态调试器">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553759246/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E5%9B%BE%E7%89%871.png">
<meta property="og:image" content="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553772615/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B71.png">
<meta property="og:image" content="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553773066/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B72.png">
<meta property="og:image" content="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553775053/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B74.png">
<meta property="og:image" content="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553775817/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B75.png">
<meta property="og:image" content="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553776239/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B76.png">
<meta property="og:image" content="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553858953/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B77.png">
<meta property="og:image" content="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553937461/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B79.png">
<meta property="og:image" content="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553937531/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B711.png">
<meta property="og:updated_time" content="2019-04-01T07:21:11.060Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="逆向工程与软件破解">
<meta name="twitter:description" content="软件保护方式 功能限制 时间限制 运行时长限制 使用日期限制 使用次数限制 警告窗口 分析工具 静态分析工具 IDA W32Dasm lordPE Resource Hacker 动态分析工具 OllyDbg WinDbg 对抗分析技术 反静态分析技术 花指令 自修改代码技术 多态技术 变形技术 虚拟机保护技术 反动态分析技术 检测调试状态 检测用户态调试器">
<meta name="twitter:image" content="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553759246/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E5%9B%BE%E7%89%871.png">
<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/03/28/逆向工程实验/">
<title>逆向工程与软件破解 | 混元霹雳手</title>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
<div class="container sidebar-position-left page-post-detail">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-wrapper">
<div class="site-meta ">
<div class="custom-logo-site-title">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">混元霹雳手</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle"></p>
</div>
<div class="site-nav-toggle">
<button>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section">
<i class="menu-item-icon fa fa-fw fa-home"></i> <br>
首页
</a>
</li>
<li class="menu-item menu-item-about">
<a href="/about/" rel="section">
<i class="menu-item-icon fa fa-fw fa-user"></i> <br>
关于
</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags/" rel="section">
<i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
标签
</a>
</li>
<li class="menu-item menu-item-categories">
<a href="/categories/" rel="section">
<i class="menu-item-icon fa fa-fw fa-th"></i> <br>
分类
</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section">
<i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
归档
</a>
</li>
<li class="menu-item menu-item-bookmarks">
<a href="/bookmarks/" rel="section">
<i class="menu-item-icon fa fa-fw fa-map"></i> <br>
书签
</a>
</li>
<li class="menu-item menu-item-search">
<a href="javascript:;" class="popup-trigger">
<i class="menu-item-icon fa fa-search fa-fw"></i> <br>
搜索
</a>
</li>
</ul>
<div class="site-search">
<div class="popup search-popup local-search-popup">
<div class="local-search-header clearfix">
<span class="search-icon">
<i class="fa fa-search"></i>
</span>
<span class="popup-btn-close">
<i class="fa fa-times-circle"></i>
</span>
<div class="local-search-input-wrapper">
<input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
</div>
</div>
<div id="local-search-result"></div>
</div>
</div>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<div id="posts" class="posts-expand">
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="https://cool-y.github.io/2019/03/28/逆向工程实验/">
<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">逆向工程与软件破解</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-03-28T15:25:04+08:00">
2019-03-28
</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 class="post-comments-count">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-comment-o"></i>
</span>
<a href="/2019/03/28/逆向工程实验/#comments" itemprop="discussionUrl">
<span class="post-comments-count gitment-comments-count" data-xid="/2019/03/28/逆向工程实验/" itemprop="commentsCount"></span>
</a>
</span>
<span id="/2019/03/28/逆向工程实验/" class="leancloud_visitors" data-flag-title="逆向工程与软件破解">
<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="字数统计">
2.3k 字
</span>
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-clock-o"></i>
</span>
<span title="阅读时长">
8 分钟
</span>
</div>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="软件保护方式"><a href="#软件保护方式" class="headerlink" title="软件保护方式"></a>软件保护方式</h1><ol>
<li>功能限制</li>
<li>时间限制</li>
</ol>
<ul>
<li>运行时长限制</li>
<li>使用日期限制</li>
<li>使用次数限制</li>
</ul>
<ol start="3">
<li>警告窗口</li>
</ol>
<h2 id><a href="#" class="headerlink" title></a><img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553759246/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E5%9B%BE%E7%89%871.png" alt></h2><h1 id="分析工具"><a href="#分析工具" class="headerlink" title="分析工具"></a>分析工具</h1><ol>
<li>静态分析工具</li>
</ol>
<ul>
<li>IDA</li>
<li>W32Dasm</li>
<li>lordPE</li>
<li>Resource Hacker</li>
</ul>
<ol start="2">
<li>动态分析工具</li>
</ol>
<ul>
<li>OllyDbg</li>
<li>WinDbg</li>
</ul>
<hr>
<h1 id="对抗分析技术"><a href="#对抗分析技术" class="headerlink" title="对抗分析技术"></a>对抗分析技术</h1><ol>
<li>反静态分析技术</li>
</ol>
<ul>
<li>花指令</li>
<li>自修改代码技术</li>
<li>多态技术</li>
<li>变形技术</li>
<li>虚拟机保护技术</li>
</ul>
<ol start="2">
<li>反动态分析技术</li>
</ol>
<ul>
<li>检测调试状态</li>
<li>检测用户态调试器</li>
<li>检测内核态调试器</li>
<li>其他方法父进程检测StartupInfo 结构时间差通过Trap Flag检测</li>
</ul>
<ol start="3">
<li>发现调试器后的处理</li>
</ol>
<ul>
<li>程序自身退出</li>
<li>向调试器窗口发送消息使调试器退出</li>
<li>使调试器窗口不可用</li>
<li>终止调试器进程</li>
</ul>
<hr>
<h1 id="PE文件格式基础"><a href="#PE文件格式基础" class="headerlink" title="PE文件格式基础"></a>PE文件格式基础</h1><hr>
<h1 id="加壳脱壳"><a href="#加壳脱壳" class="headerlink" title="加壳脱壳"></a>加壳脱壳</h1><hr>
<h1 id="反调试技术"><a href="#反调试技术" class="headerlink" title="反调试技术"></a>反调试技术</h1><p>反调试技术,程序用它来识别是否被调试,或者让调试器失效。为了阻止调试器的分析,当程序意识到自己被调试时,它们可能改变正常的执行路径或者修改自身程序让自己崩溃,从而增加调试时间和复杂度。</p>
<h3 id="探测windows调试器"><a href="#探测windows调试器" class="headerlink" title="探测windows调试器"></a>探测windows调试器</h3><ol>
<li>使用windows API<br>使用Windows API函数探测调试器是否存在是最简单的反调试技术。<br>通常防止使用API进行反调试的方法有在程序运行期间修改恶意代码使其不能调用API函数或修改返回值确保执行合适的路径还有挂钩这些函数。<br>常用来探测调试器的API函数有<code>IsDebuggerPresent</code> <code>CheckRemoteDebuggerPresent</code> <code>NtQueryInformationProcess</code> <code>OutputDebuggString</code></li>
<li>手动检测数据结构<br>程序编写者经常手动执行与这些API功能相同的操作</li>
</ol>
<ul>
<li>检查BeingDebugged属性</li>
<li>检测ProcessHeap属性</li>
<li>检测NTGlobalFlag</li>
</ul>
<ol start="3">
<li>系统痕迹检测<br>通常我们使用调试工具来分析程序但这些工具会在系统中驻留一些痕迹。程序通过搜索这种系统的痕迹来确定你是否试图分析它。例如查找调试器引用的注册表项。同时程序也可以查找系统的文件和目录查找当前内存的痕迹或者查看当前进程列表更普遍的做法是通过FindWindows来查找调试器。<h3 id="识别调试器的行为"><a href="#识别调试器的行为" class="headerlink" title="识别调试器的行为"></a>识别调试器的行为</h3>在逆向工程中可以使用断点或单步调试来帮助分析但执行这些操作时会修改进程中的代码。因此可以使用几种反调试技术探测INT扫描、完整性校验以及时钟检测等几种类型的调试器行为。</li>
<li>INT扫描<br>调试器设置断点的基本机制是用软件中断INT 3机器码为0xCC临时替换程序中的一条指令。因此可以通过扫描INT 3修改来检测。</li>
<li>执行代码校验和检查<br>与INT扫描目的相同但仅执行机器码的CRC或MD5校验和检查。</li>
<li>时钟检测<br>被调试时,进程的运行速度大大降低,常用指令有:<code>rdstc</code> <code>QueryPerformanceCounter</code> <code>GetTickCount</code>,有如下两种方式探测时钟:</li>
</ol>
<ul>
<li>记录执行一段操作前后的时间戳</li>
<li>记录触发一个异常前后的时间戳<h3 id="干扰调试器的功能"><a href="#干扰调试器的功能" class="headerlink" title="干扰调试器的功能"></a>干扰调试器的功能</h3>本地存储(TLS)回调TLS回调被用来在程序入口点执行之前运行代码这发生在程序刚被加载到调试器时<br>使用异常使用SEH链可以实现异常程序可以使用异常来破坏或探测调试器调试器捕获异常后并不会将处理权立即返回给被调试进程。<br>插入中断插入INT 3、INT 2D、ICE<h3 id="调试器漏洞"><a href="#调试器漏洞" class="headerlink" title="调试器漏洞"></a>调试器漏洞</h3>PE头漏洞、OutputDebugString漏洞</li>
</ul>
<hr>
<h1 id="实验一:软件破解"><a href="#实验一:软件破解" class="headerlink" title="实验一:软件破解"></a>实验一:软件破解</h1><h2 id="对象"><a href="#对象" class="headerlink" title="对象"></a>对象</h2><p><a href="https://res.cloudinary.com/dozyfkbg3/raw/upload/v1553761280/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/crack.exe1" target="_blank" rel="noopener">crack.exe</a>28.0 KB</p>
<ul>
<li>无保护措施:无壳、未加密、无反调试措施</li>
<li>用户名至少要5个字节</li>
<li>输入错误验证码时输出“Bad Boy!”</li>
</ul>
<h2 id="爆破"><a href="#爆破" class="headerlink" title="爆破"></a>爆破</h2><h3 id="查找显示注册结果相关代码"><a href="#查找显示注册结果相关代码" class="headerlink" title="查找显示注册结果相关代码"></a>查找显示注册结果相关代码</h3><p>当输入错误验证码时程序会输出“Bad Boy”因此我们将程序拖入IDA以流程图显示函数内部的跳转。查找“Bad Boy”字符串我们可以定位到显示注册结果的相关代码<br><img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553772615/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B71.png" alt></p>
<h3 id="查找注册码验证相关代码"><a href="#查找注册码验证相关代码" class="headerlink" title="查找注册码验证相关代码"></a>查找注册码验证相关代码</h3><p>用鼠标选中程序分支点,按空格切换回汇编指令界面<br><img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553773066/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B72.png" alt></p>
<p>可以看到这条指令位于PE文件的.text节并且IDA已经自动将地址转换为运行时的内存地址<code>VA:004010F9</code></p>
<h3 id="修改程序跳转"><a href="#修改程序跳转" class="headerlink" title="修改程序跳转"></a>修改程序跳转</h3><ul>
<li>现在关闭IDA换用OllyDbg进行动态调试来看看程序时如何分支跳转的<code>Ctrl+G</code>直接跳到由IDA得到的<code>VA:004010F9</code>处查看那条引起程序分支的关键指令</li>
<li>选中这条指令按F2设置断点再按F9运行程序这时候控制权会回到程序OllyDbg暂时挂起。到程序提示输入名字和序列号随意输入名字大于五个字节点击ok后OllyDbg会重新中断程序收回控制权如图<br><img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553775053/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B74.png" alt></li>
<li><p>验证函数的返回值存于EAX寄存器中if语句通过以下两条指令执行</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cmp eax,ecx</span><br><span class="line">jnz xxxxxxx</span><br></pre></td></tr></table></figure>
</li>
<li><p>也就是说当序列号输入错误时EAX中的值为0跳转将被执行。<br>如果我们把<code>jnz</code>这条指令修改为<code>jz</code>,那么整个程序的逻辑就会反过来。<br>双击<code>jnz</code>这条指令,将其改为<code>jz</code>,单击”汇编”将其写入内存<br><img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553775817/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B75.png" alt><br>可以看到此时程序执行了相反的路径</p>
</li>
<li><p>上面只是在内存中修改程序我们还需要在二进制文件中也修改相应的字节这里考察VA与文件地址之间的关系</p>
</li>
<li>用LordPE打开.exe文件查看PE文件的节信息<br><img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553776239/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B76.png" alt><br>根据VA与文件地址的换算公式<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">文件偏移地址 = VA - Image Base - 节偏移</span><br><span class="line"> = 0x004010F9 - 0x00400000 - 0</span><br><span class="line"> = 0x10F9</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>也就是说这条指令在PE文件中位于<code>10F9</code>字节处使用010Editer打开crack.exe将这一字节的<code>75(JNZ)`</code>改为<code>74(JZ)`</code>,保存后重新执行,破解成功!</p>
<h2 id="编写注册机"><a href="#编写注册机" class="headerlink" title="编写注册机"></a>编写注册机</h2><h3 id="查找显示注册结果相关代码-1"><a href="#查找显示注册结果相关代码-1" class="headerlink" title="查找显示注册结果相关代码"></a>查找显示注册结果相关代码</h3><p>通过查找字符串“good boy”等我们可以找到显示注册结果的相关代码</p>
<h3 id="查找注册码验证相关代码-1"><a href="#查找注册码验证相关代码-1" class="headerlink" title="查找注册码验证相关代码"></a>查找注册码验证相关代码</h3><p>因为检测密钥是否正确时会将结果返回到EAX寄存器中因此在检测密钥前必然会对EAX寄存器清空由此我们可以找到注册码验证的相关代码。<br><img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553858953/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B77.png" alt></p>
<h3 id="根据注册码验证代码编写注册机"><a href="#根据注册码验证代码编写注册机" class="headerlink" title="根据注册码验证代码编写注册机"></a>根据注册码验证代码编写注册机</h3><p>分析上图算法按tab键转换为高级语言<br><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">for ( i = 0; i &lt; v6; v12 = v10 )</span><br><span class="line"> v10 = (v6 + v12) * lpStringa[i++];</span><br><span class="line">if ( (v12 ^ 0xA9F9FA) == atoi(v15) )</span><br><span class="line"> MessageBoxA(hDlg, aTerimaKasihKer, aGoodBoy, 0);</span><br></pre></td></tr></table></figure></p>
<p>可以看出生成注册码主要在for循环中完成之后将生成的注册码与输入相比较判断是否正确。<br>所以,只要能弄明白<code>v6v12v10v15</code>的含义,我们就可以轻松的编写注册机。<br>打开ollybdg在进入循环之前设下断点动态调试程序<br><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></pre></td><td class="code"><pre><span class="line">004010CC |&gt; /8B4D 10 |mov ecx,[arg.3] //此时ecx为name</span><br><span class="line">004010CF |. 8B55 0C |mov edx,[arg.2] //edx为0x1908</span><br><span class="line">004010D2 |. 03D3 |add edx,ebx //edx加上name的长度ebx</span><br><span class="line">004010D4 |. 0FBE0C08 |movsx ecx,byte ptr ds:[eax+ecx] //ecx=61h</span><br><span class="line">004010D8 |. 0FAFCA |imul ecx,edx //61h(a) * edx</span><br><span class="line">004010DB |. 40 |inc eax //eax加1初始为0</span><br><span class="line">004010DC |. 894D 0C |mov [arg.2],ecx</span><br><span class="line">004010DF |. 3BC3 |cmp eax,ebx //循环是否结束</span><br></pre></td></tr></table></figure></p>
<p><code>arg.3</code>为输入的<code>name</code><code>arg.2</code>初始为<code>0x1908</code><code>ebx</code><code>name</code>的长度,<code>eax</code>每次循环加1直到等于长度<br>因此,我们可以对参数的含义进行解释如下<br><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">v12 = 6408; //0x1908</span><br><span class="line">v10 = 6408; //0x1908</span><br><span class="line">v6 = len(name);</span><br><span class="line">v12 = input_serial;</span><br><span class="line">for ( i = 0; i &lt; v6; i++ )&#123;</span><br><span class="line"> v12 = v10</span><br><span class="line"> v10 = (v6 + v12) * lpStringa[i];</span><br><span class="line">&#125;</span><br><span class="line">if ((v12 ^ 0xA9F9FA) == atoi(v15))&#123;</span><br><span class="line"> MessageBoxA(hDlg, aTerimaKasihKer, aGoodBoy, 0);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>可见,<code>v12^0xA9F9FA</code>的结果即是正确的注册码,我们编写一个<a href="https://res.cloudinary.com/dozyfkbg3/raw/upload/v1553937750/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/reg.cpp" target="_blank" rel="noopener">简单的程序</a>帮助我们生成注册码:<br><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></pre></td><td class="code"><pre><span class="line">#include &lt;iostream&gt;</span><br><span class="line">#include&lt;stdio.h&gt;</span><br><span class="line"></span><br><span class="line">using namespace::std;</span><br><span class="line">int main()&#123;</span><br><span class="line"> int v12;</span><br><span class="line"> int v10 = 6408; //0x1908</span><br><span class="line"> string name;</span><br><span class="line"> cout &lt;&lt; &quot;请输入name: &quot;;</span><br><span class="line"> cin &gt;&gt; name;</span><br><span class="line"> int len = name.size();</span><br><span class="line"> for(int i = 0; i &lt; len+1; i++ )&#123;</span><br><span class="line"> v12 = v10;</span><br><span class="line"> v10 = (len + v12) * name[i];</span><br><span class="line"> &#125;</span><br><span class="line"> cout&lt;&lt;&quot;\n&quot;&lt;&lt;&quot;注册码为: &quot;&lt;&lt;(v12 ^ 0xA9F9FA)&lt;&lt;endl;</span><br><span class="line"> return 0;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>计算出”testname”的对应注册码<br><img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553937461/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B79.png" alt><br>注册成功!</p>
<h2 id="-1"><a href="#-1" class="headerlink" title></a><img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1553937531/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/%E6%8D%95%E8%8E%B711.png" alt></h2><h1 id="实验二:软件反动态调试技术分析"><a href="#实验二:软件反动态调试技术分析" class="headerlink" title="实验二:软件反动态调试技术分析"></a>实验二:软件反动态调试技术分析</h1><h2 id="对象-1"><a href="#对象-1" class="headerlink" title="对象"></a>对象</h2><p><a href="https://res.cloudinary.com/dozyfkbg3/raw/upload/v1553779243/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/CrackMe1.exe1" target="_blank" rel="noopener">CrackMe1.exe</a> 1641.0 KB<br>无保护措施:无壳、未加密、无反调试措施<br>使用OllyDbg对该程序进行调试时程序会自动退出</p>
<h2 id="要求"><a href="#要求" class="headerlink" title="要求"></a>要求</h2><ol>
<li>分析CrackMe1.exe是如何通过父进程检测实现反OllyDbg调试的</li>
<li>分析除父进程检测外,该程序用到的反动态调试技术</li>
</ol>
<hr>
<h1 id="实验三:加花加密反调试技术分析"><a href="#实验三:加花加密反调试技术分析" class="headerlink" title="实验三:加花加密反调试技术分析"></a>实验三:加花加密反调试技术分析</h1><h2 id="对象-2"><a href="#对象-2" class="headerlink" title="对象"></a>对象</h2><p><a href="https://res.cloudinary.com/dozyfkbg3/raw/upload/v1553779413/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/CrackMe2.exe1" target="_blank" rel="noopener">CrackMe2.exe</a> 9.00 KB<br>保护措施:部分加花、部分加密、简单反调试<br>根据(提示)[<a href="https://res.cloudinary.com/dozyfkbg3/raw/upload/v1553779403/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/Crackme2%E6%8F%90%E7%A4%BA.docx]分析该程序" target="_blank" rel="noopener">https://res.cloudinary.com/dozyfkbg3/raw/upload/v1553779403/%E8%BD%AF%E4%BB%B6%E7%A0%B4%E8%A7%A3/Crackme2%E6%8F%90%E7%A4%BA.docx]分析该程序</a></p>
<h2 id="内容"><a href="#内容" class="headerlink" title="内容"></a>内容</h2><ol>
<li>加壳脱壳深入理解</li>
<li>尝试手动脱壳</li>
<li>分析CrackMe2.exe中花指令</li>
<li>分析CrackMe2.exe中的被加密的函数的功能</li>
<li>分析CrackMe2.exe中的反调试手段</li>
<li>分析CrackMe2.exe中混合的64位代码的功能</li>
</ol>
</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/破解/" rel="tag"># 破解</a>
</div>
<div class="post-nav">
<div class="post-nav-next post-nav-item">
<a href="/2019/03/25/Samba-CVE/" rel="next" title="小米路由器与Samba漏洞CVE-2017-7494">
<i class="fa fa-chevron-left"></i> 小米路由器与Samba漏洞CVE-2017-7494
</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"></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">11</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">27</span>
<span class="site-state-item-name">标签</span>
</a>
</div>
</nav>
<div class="links-of-author motion-element">
<span class="links-of-author-item">
<a href="https://github.com/Cool-Y" target="_blank" title="GitHub">
<i class="fa fa-fw fa-github"></i>GitHub</a>
</span>
<span class="links-of-author-item">
<a href="mailto:cool.yim@whu.edu.cn" target="_blank" title="E-Mail">
<i class="fa fa-fw fa-envelope"></i>E-Mail</a>
</span>
<span class="links-of-author-item">
<a href="https://www.instagram.com/yan__han/" target="_blank" title="Instagram">
<i class="fa fa-fw fa-instagram"></i>Instagram</a>
</span>
</div>
</div>
</section>
<!--noindex-->
<section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
<div class="post-toc">
<div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#软件保护方式"><span class="nav-number">1.</span> <span class="nav-text">软件保护方式</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#"><span class="nav-number">1.1.</span> <span class="nav-text"></span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#分析工具"><span class="nav-number">2.</span> <span class="nav-text">分析工具</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#对抗分析技术"><span class="nav-number">3.</span> <span class="nav-text">对抗分析技术</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#PE文件格式基础"><span class="nav-number">4.</span> <span class="nav-text">PE文件格式基础</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#加壳脱壳"><span class="nav-number">5.</span> <span class="nav-text">加壳脱壳</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#反调试技术"><span class="nav-number">6.</span> <span class="nav-text">反调试技术</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#探测windows调试器"><span class="nav-number">6.0.1.</span> <span class="nav-text">探测windows调试器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#识别调试器的行为"><span class="nav-number">6.0.2.</span> <span class="nav-text">识别调试器的行为</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#干扰调试器的功能"><span class="nav-number">6.0.3.</span> <span class="nav-text">干扰调试器的功能</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#调试器漏洞"><span class="nav-number">6.0.4.</span> <span class="nav-text">调试器漏洞</span></a></li></ol></li></ol><li class="nav-item nav-level-1"><a class="nav-link" href="#实验一:软件破解"><span class="nav-number">7.</span> <span class="nav-text">实验一:软件破解</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#对象"><span class="nav-number">7.1.</span> <span class="nav-text">对象</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#爆破"><span class="nav-number">7.2.</span> <span class="nav-text">爆破</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#查找显示注册结果相关代码"><span class="nav-number">7.2.1.</span> <span class="nav-text">查找显示注册结果相关代码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#查找注册码验证相关代码"><span class="nav-number">7.2.2.</span> <span class="nav-text">查找注册码验证相关代码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#修改程序跳转"><span class="nav-number">7.2.3.</span> <span class="nav-text">修改程序跳转</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#编写注册机"><span class="nav-number">7.3.</span> <span class="nav-text">编写注册机</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#查找显示注册结果相关代码-1"><span class="nav-number">7.3.1.</span> <span class="nav-text">查找显示注册结果相关代码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#查找注册码验证相关代码-1"><span class="nav-number">7.3.2.</span> <span class="nav-text">查找注册码验证相关代码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#根据注册码验证代码编写注册机"><span class="nav-number">7.3.3.</span> <span class="nav-text">根据注册码验证代码编写注册机</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#-1"><span class="nav-number">7.4.</span> <span class="nav-text"></span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#实验二:软件反动态调试技术分析"><span class="nav-number">8.</span> <span class="nav-text">实验二:软件反动态调试技术分析</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#对象-1"><span class="nav-number">8.1.</span> <span class="nav-text">对象</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#要求"><span class="nav-number">8.2.</span> <span class="nav-text">要求</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#实验三:加花加密反调试技术分析"><span class="nav-number">9.</span> <span class="nav-text">实验三:加花加密反调试技术分析</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#对象-2"><span class="nav-number">9.1.</span> <span class="nav-text">对象</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#内容"><span class="nav-number">9.2.</span> <span class="nav-text">内容</span></a></li></ol></li></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">17k</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://aimingoo.github.io/gitmint/style/default.css">
<script src="https://aimingoo.github.io/gitmint/dist/gitmint.browser.js"></script>
<!-- END LOCAL -->
<script type="text/javascript">
function renderGitment(){
var gitment = new Gitmint({
id: window.location.pathname,
owner: 'Cool-Y',
repo: 'gitment-comments',
lang: "" || navigator.language || navigator.systemLanguage || navigator.userLanguage,
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>