> For the complete documentation index, see [llms.txt](https://0xb0b.gitbook.io/writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xb0b.gitbook.io/writeups/tryhackme/2025/directory.md).

# Directory

{% embed url="<https://tryhackme.com/room/directorydfirroom>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

***

For this challenge, we are provided with a PCAP file. We first analyze it using Wireshark. Based on the SYN requests and the RST-ACK responses from 10.0.2.74, we can quickly tell that a port scan has taken place.

<figure><img src="/files/oGFKsW3ntf7AHQvIm137" alt=""><figcaption></figcaption></figure>

The first `3610` pakets are related to the port scan, after that we can discover some HTTP traffic.&#x20;

<figure><img src="/files/fhYN9utjZPHJuIxBELR3" alt=""><figcaption></figcaption></figure>

## What ports did the threat actor initially find open? Format: from lowest to highest, separated by a comma.

To answer the following questions, we try to use TShark. TShark is the command‑line network protocol analyzer companion to Wireshark, capable of capturing, decoding, and filtering packet data directly in a terminal.

The question now is about the open ports that the attacker has found. Means, that we get an answer via `SYN ACK` response indicating an open port.

We use the knowledge from our first insight via Wireshark that the scan extends to packet `3610` and limit the analysis to this.

The `-c` option in TShark specifies the number of packets to capture or read from a file. With `-c 3610` tshark will process only the first `3610` packets from the `traffic-1725627206938.pcap` file. Once it reaches the limit of `3610` packets, it will stop processing. We filter TCP packets where both the SYN and ACK flags are set `-Y "tcp.flags.syn == 1 && tcp.flags.ack == 1"`, and print only each packet’s TCP source‑port field `-T fields -e tcp.srcport`.  We then sort the ports numerically, removes duplicates, and outputs the unique list as a single comma‑separated line `| sort -n | uniq | paste -sd ','`.

{% code overflow="wrap" %}

```
tshark -r traffic-1725627206938.pcap -c 3610 -T fields -e tcp.srcport -Y "tcp.flags.syn == 1 && tcp.flags.ack == 1" | sort -n | uniq | paste -sd ','
```

{% endcode %}

<figure><img src="/files/vzDqa7JZcyyLNJ4sncF1" alt=""><figcaption></figcaption></figure>

## The threat actor found four valid usernames, but only one username allowed the attacker to achieve a foothold on the server. What was the username?&#x20;

We skip the Nmap traffic and scroll down the traffic shown in Wireshark, until we reach packet no. `4667`, there the KRB5 traffic starts. From this traffic we can potentially extract the username that allowed the attacker to achieve foothold.

<figure><img src="/files/w0TWQ3L72tD2PSNjXNGP" alt=""><figcaption></figcaption></figure>

Scrolling down to `4679` we see an error for `PREAUTH_REQUIRED.`

<figure><img src="/files/3yVY7SNAFvGD6e8XI8V7" alt=""><figcaption></figcaption></figure>

We see some authentication attempts resulting in unknown principals errors. The errors stop occuring after packet no. `4785`.

<figure><img src="/files/dJ1KEVvwPMHWOXXHCkeQ" alt=""><figcaption></figcaption></figure>

On packet no. `4817` we don't see any error after an AS-REQ and could extract the username here.

<figure><img src="/files/usajlpxtJpHBC4QnQJzZ" alt=""><figcaption></figcaption></figure>

Solving this task with TShark we check the fields available to extract related to kerberos.

```
tshark -G fields | grep -i kerberos
```

<figure><img src="/files/sP5keUsQMqvR1BeOB6Nx" alt=""><figcaption></figcaption></figure>

With the following command we extract every matching packet containing the Kerberos client principal name string `kerberos.CNameString` and its realm `kerberos.crealm`. We assume the last entries are the ones, that made a successful login.

{% code overflow="wrap" %}

```
tshark -r traffic-1725627206938.pcap -Y "kerberos" -T fields -e kerberos.CNameString -e kerberos.crealm
```

{% endcode %}

{% code overflow="wrap" %}

```
tshark -r traffic-1725627206938.pcap -Y "kerberos" -T fields -e kerberos.CNameString -e kerberos.crealm | awk 'NF==2 {print $2 "\\" $1}'
```

{% endcode %}

<figure><img src="/files/XVuaG5rGsjYDwQGHcmqi" alt=""><figcaption></figcaption></figure>

## The threat actor captured a hash from the user in question 2. What are the last 30 characters of that hash?

{% hint style="info" %}
What we are looking for is an encrypted message or blob of information, not a hash, that is used by Kerberos for authentication. The AS-REP is an encrypted packet, not a hash. It is encrypted using AES, RC4, or even public-key cryptography (PKINIT).

[Marjan Sterjev](https://www.linkedin.com/in/marjansterjev) had pointed out my post on LinkedIn regarding this topic, and I agree with him that we should use precise terminology. Thank you, for your clarification!
{% endhint %}

The requested information is contained in the packets that transmit the kerberos.cipher. Filtering these packets will allow us to extract the last 30 characters.

{% code overflow="wrap" %}

```
tshark -r traffic-1725627206938.pcap -Y 'kerberos and kerberos.CNameString == "larry.doe"' -T fields -e kerberos.checksum -e kerberos.cipher -e kerberos.CNameString -e frame.number
```

{% endcode %}

<figure><img src="/files/pVcVQHuotQOsLpG5yzlc" alt=""><figcaption></figcaption></figure>

We extract the frame number too, and see that the blob was transferred in the packet before `4817`.

<figure><img src="/files/zzMFD4GXp7ZBNFSLqoss" alt=""><figcaption></figcaption></figure>

Next, we just extract `kerberos.cipher` field from the last request...

{% code overflow="wrap" %}

```
tshark -r traffic-1725627206938.pcap -Y 'kerberos and kerberos.CNameString == "larry.doe"' -T fields -e kerberos.cipher | tail -n 1
```

{% endcode %}

<figure><img src="/files/jFIDu5XJrQ0pqjAxMojc" alt=""><figcaption></figcaption></figure>

... and use AWK to print the last 30 characters of the blob.

{% code overflow="wrap" %}

```
tshark -r traffic-1725627206938.pcap -Y 'kerberos and kerberos.CNameString == "larry.doe"' -T fields -e kerberos.cipher | tail -n 1 | awk '{print substr($0, length($0)-29)}'
```

{% endcode %}

<figure><img src="/files/TZnakgUU2ZaVofXtb9QM" alt=""><figcaption></figcaption></figure>

## What is the user's password?

While researching about KRB traffic, we came across the following resource:

{% embed url="<https://blog.xpnsec.com/kerberos-attacks-part-2/>" %}

It is depicted there how to use the following script to extract any AS-REP ciphers transferred in a PCAP file. Unfortunately, this is no longer available.

{% embed url="<https://github.com/openwall/john/blob/bleeding-jumbo/run/krbpa2john.py>" %}

But we get an alternative here:

{% embed url="<https://github.com/truongkma/ctf-tools/blob/master/John/run/krbpa2john.py>" %}

After we have converted the `pcap` file as described and used the `pdml` file with the script `krbpa2john.py` , we have not received any output. We were only able to partially reconstruct the Kerberos cipher using the `krb2john.py` script provided by John, the `user@domain.com` was missing. We already got that information - see question 2. We can already see that it is a `Kerberos 5, etype 23, AS-REP` blob.&#x20;

<figure><img src="/files/Dj3zhPeTbPLQkhDELrXy" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Nea5yLcK2o9j25O60BME" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/3jAw4El4btcy9dRBPbZS" alt=""><figcaption></figcaption></figure>

The following TShark attempt shows how to reconstruct it manually. We can extract all the required information with the command below.

{% code overflow="wrap" %}

```
tshark -r traffic-1725627206938.pcap -Y 'kerberos and kerberos.CNameString == "larry.doe"' -T fields -e kerberos.CNameString -e kerberos.crealm -e kerberos.sname_string -e kerberos.checksum -e kerberos.cipher -e kerberos.info_salt | tail -n 1
```

{% endcode %}

<figure><img src="/files/UymuakdKkvfd0deSFHwd" alt=""><figcaption></figcaption></figure>

To reconstruct the required format by hashcat to crack it, the second part of the `kerberos.cipher` field is relevant.

{% code overflow="wrap" %}

```
tshark -r traffic-1725627206938.pcap -Y "frame.number==4817" -T fields -e kerberos.cipher
```

{% endcode %}

<figure><img src="/files/ZO6CnpR7zJU92AGEwBy5" alt=""><figcaption></figcaption></figure>

We use AWK to combine everything into the format required by hashcat.

{% code overflow="wrap" %}

```
tshark -r traffic-1725627206938.pcap -Y "frame.number==4817" -T fields -e kerberos.cipher -e kerberos.CNameString -e kerberos.crealm | \
awk -F'\t' '{split($1,a,","); print "$krb5asrep$23$"$2"@"$3":"a[2]}' | \
awk -F':' '{prefix_len=length($1) + 33; print substr($0, 1, prefix_len) "$" substr($0, prefix_len+1)}'

```

{% endcode %}

<figure><img src="/files/5qnDQ9n9hFExT86yTqtw" alt=""><figcaption></figcaption></figure>

Next, we crack it using `rockyou.txt`.

```
hashcat -a0 -m18200 directory.hash /usr/share/wordlists/rockyou.txt
```

<figure><img src="/files/yyOZI8KK64wc4YZt4VfJ" alt=""><figcaption></figcaption></figure>

## What were the second and third commands that the threat actor executed on the system? Format: command1,command2

After the authentication of larry.doe we see traffic on 5985. Port 5985 is used for **Windows Remote Management - WinRM**, indicating remote command execution or administrative access after authentication.

<figure><img src="/files/df58tbk1KevoEWxhLFlr" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/dTnHEPDVyjbs4AKn9CWV" alt=""><figcaption></figcaption></figure>

However, the traffic is encrypted.

<figure><img src="/files/5h3xbswemvyV72fgoAgm" alt=""><figcaption></figcaption></figure>

After a short research we come across the following tool for decrypting winrm traffic. This is possible for us, as we have the user's password.

{% embed url="<https://github.com/h4sh5/decrypt-winrm?tab=readme-ov-file>" %}

Unfortunately, it throws errors.

```
python3 winrm_decrypt.py -p 'REDACTED' ../traffic-1725627206938.pcap
```

<figure><img src="/files/AAhFXvDFWR8EjnAXXvjh" alt=""><figcaption></figcaption></figure>

In the description of the repo we see a reference to a fork. We try to use that instead.

<figure><img src="/files/3r1yU7KK98hjjhDRWQYX" alt=""><figcaption></figcaption></figure>

We run the script from the fork and are able to decrypt the traffic. We directly write it to a file.

[https://gist.github.com/jborean93/d6ff5e87f8a9f5cb215cd49826523045/ ](<https://gist.github.com/jborean93/d6ff5e87f8a9f5cb215cd49826523045/ >)&#x20;

{% code overflow="wrap" %}

```
python3 winrm_decrypt.py -p 'REDACTED' ./traffic-1725627206938.pcap > decrypted_traffic.txt
```

{% endcode %}

<figure><img src="/files/kUlGvm4aTZl5fDVVsQFH" alt=""><figcaption></figcaption></figure>

When scrolling through the decrypted traffic, we recognize a schema. The commands are base64 encoded in arguments  tags.

<figure><img src="/files/5THU2H0hWmlssGofPmJa" alt=""><figcaption></figcaption></figure>

We extract them and write them to a file.

```
grep -oP '(?<=<rsp:Arguments>).*?(?=</rsp:Arguments>)' decrypted_traffic.txt
```

{% code overflow="wrap" %}

```
grep -oP '(?<=<rsp:Arguments>).*?(?=</rsp:Arguments>)' decrypted_traffic.txt > encoded_arguments.txt
```

{% endcode %}

<figure><img src="/files/XD1gX7L9wmmtZQmBI7ox" alt=""><figcaption></figcaption></figure>

Next, we decode each argument.

```
while read line; do                                                     
  echo "$line" | base64 --decode >> arguments.txt
  echo "" >> arguments.txt
done < encoded_arguments.txt
```

<figure><img src="/files/pWnvooVegdKjYPNZQIP2" alt=""><figcaption></figcaption></figure>

We find the first command: `whoami`

<figure><img src="/files/afzqUm5yEvuJly7VwCDs" alt=""><figcaption></figcaption></figure>

To make it more readable we use grep. And now find all commands made including the flag.

```
grep -a '<S N="V">' arguments.txt | awk -F'[<>]' '{print $3}'
```

<figure><img src="/files/RzEFQp5hDO6bcXOydhPA" alt=""><figcaption></figcaption></figure>

## What is the flag?

```
grep -a '<S N="V">' arguments.txt | awk -F'[<>]' '{print $3}'
```

<figure><img src="/files/SRd4UvtFvdkOsM6oA3Vn" alt=""><figcaption></figcaption></figure>

## Recommendation

Marjan Sterjevs version of the script does not need password or nt\_hash:

<https://pastebin.com/u2jCceRX>

> If -e is specified on the input, the script will try to:
>
> * process the WWW-Authenticate and Authorization NTLMSSP Negotiation messages
> * crack the password with John The Riper and finally
> * decode, process and output the string content of the WinRM messages; it looks for RSP CommandLine content and the associated response streams.

<https://www.linkedin.com/posts/marjansterjev_directory-activity-7353043871032827904-3vc1?utm_source=share&utm_medium=member_desktop&rcm=ACoAAEQHbzcBmjOtd0QWGGhWpdy2mzZ2j-geKp8>
