Select Page

TL;DR

When buying computers for our consultants, we try not to skimp. I’ve never heard someone seriously say, “Oof. This computer is way too fast and way too powerful.” In fact, it’s usually the opposite. Fast systems mean less waiting, more testing, more time to think, and fewer excuses. A responsive machine with a solid GPU isn’t just a luxury—it’s a productivity multiplier. If you’re doing real work, especially the kind that involves crunching hashes or analyzing datasets, underpowered hardware is just a tax on your time.

When it comes to pen testing, people sometimes ask, “Which OS should I use? Windows or Linux?” The answer is obviously, “YES!” Virtual machines make it easy to use each OS to the max, and WSL 2 on Windows has added one more option to the table. When I installed WSL 2 and fired up a fresh Debian instance, everything felt zippy and slick—until I needed GPU horsepower. Whether you’re running local AI models or doing a little password cracking, GPUs are essential nowadays. Hashcat reigns supreme as the pen testers go-to password cracker, but without GPU support, it defaults to using the CPU via OpenCL. It works—but slower-ly.

I ran a benchmark on the NT hash and saw ~1200 MH/s. Respectable, but not what I’d expect from a modern laptop with a discrete GPU. That’s when I realized I was staring at a 13th Gen i9, but not even the integrated graphics show up in my workload. Where’s that NVIDIA RTX 4060 I paid for?? Even though it’s a mobile GPU, it should be able to deliver 25-30 times the performance of my CPU! I paid for it, so I want to use it. All of it.

Welcome to the GPU passthrough problem.

By default, WSL doesn’t pass your GPU through to the underlying Linux VM. Yes, I could run Hashcat natively on Windows, but I do have some pride. Plus, if I’m doing any real work with password lists, I’d much rather have cut, sed, grep, and awk than try to pipe text through PowerShell’s object soup. Sorry, PS fanboys—sometimes a pipe should just be a pipe.

Paying for a GPU and not being able to use it makes me a sad panda. But dealing with NVIDIA drivers on bare metal Linux has also made me a sad panda. So, if you’re like me and you too want to avoid being a sad panda, let’s get GPU compute working inside WSL 2 with Debian without the hassle of NVIDIA Linux drivers so Hashcat can make full use of our hardware investments!

BTW, if you need to install WSL 2, you can learn how to do there here, but I’ll give you the TL;DR version before we get started:

wsl --install

That’s literally it. (Side note: Did you know WSL is an acronym? It’s how you make Windows Suck Less. OK. Not really. But actually…really.)


Step 1: Install a Debian WSL 2 Instance

You could use Ubuntu here too—it works just fine with CUDA in WSL 2. But we’re rolling with Debian because it’s a bit leaner, cleaner, and frankly, less… orange. Plus, no weird Snap shenanigans to worry about. If you have more than one WSL 2 machine of the same distro, you’ll need to provide a name to differentiate them. We’ll call ours Hashtastic.

wsl --install -d Debian --name Hashtastic

Follow the prompts to create your Unix user. This machine will be your CUDA playground.


Step 2: Install Hashcat

This will get you the latest version of Hashcat in the Debian packages, but the latest and greatest versions of Hashcat can be downloaded from the Hashcat site (https://hashcat.net/hashcat/) or the Hashcat GiHub (https://github.com/hashcat/hashcat/releases). Version 7 dropped last week and has some exciting new features, but that will be a post for another day. For now, let’s keep it simple and stick to apt:

sudo apt update && sudo apt install -y hashcat

Try a benchmark:

hashcat -b -m 1000

The output should show something like this:

* Device #1: pthread-haswell-13th Gen Intel(R) Core(TM) i9-13900H
Speed.#1.........: 1207.8 MH/s

We’re CPU-only so far. That line in the output shows Hashcat using the CPU through OpenCL’s pthread implementation—specifically the i9-13900H. The reported speed of ~1200 MH/s might look fast, but it’s peanuts compared to what the GPU can do. The numbers after the speed indicate how the hashing kernels are configured: acceleration factor, loop count, thread count, and vector width. These values are auto-tuned for the CPU but are no match for the raw power of a GPU. Time to change that.


Step 3: Enable contrib for CUDA packages

As for modifying sources.list, Debian doesn’t enable access to contrib repositories by default. These components are required to install proprietary drivers like NVIDIA’s CUDA packages, which aren’t part of the open-source main repository. Without these lines, apt simply won’t know where to find them.

sudo sed -i.bak '/^deb .*deb.debian.org.* bookworm main$/ s/$/ contrib/' /etc/apt/sources.list

OK. So, I kind of hate it when people throw long, complex commands in their blogs and don’t bother to break them down. (It’s even worse if it’s in a pen test report, amirite?!?)

If you want to see the sed command broken down Barney style, expand this…

There are three parts to that command. The command, the sed script, and the file sed will target. Altogether, they look for lines in /etc/apt/sources.list that start with “deb“, contain “deb.debian.org“, and end with “bookworm main“. When found, it appends “contrib” to the line.

The Command: sudo sed -i.bak

sudo – We’re editing a system file, so we’ll need root access to do so. sudo let’s us run the next command as root.

sed – This is the “stream editor”, which is different from the old school text editor called ed. (I’ve never used ed, but I’ve been yelled at by a few old seasoned professionals that used it regularly.) sed let’s you stream text through it and search and replace text at the same time. A common usage pattern is command | sed 's/TEXT_TO_FIND/REPLACEMENT_TEXT/' > newfile. That’s all well and good, but we don’t want a new file, in this case. Which is a great segue to -i.

-i.bak – Since we don’t want a new file, sed gives us the -i option to make in-line changes to sources.list. Remember how I said this was an important file to the system? Well, it is. You can Google why or EAFO your way to knowledge. (That’s Experiment And Find Out. I’d like to keep this blog PG-13, if possible.) So, if it’s so important, we should probably make a backup copy before we sedit the file, right? (I think I just made up sedit, but I kind of like it.) The wonderful authors of sed thought the same. So, whatever text follows the -i is appended to a copy copy the tool creates before it makes the in-line changes.

The sed Script

To understand the sed script a little better, let’s break it down into sub parts:

  1. The Regex Search Pattern: /^deb .*deb.debian.org.* bookworm main$/
    • /.../ – The slashes delimit the regular expression in sed.
    • ^ – Anchors the match to the start of the line.
    • deb – Matches the literal string deb followed by a space.
    • .* – The . matches any single character, and * means “match zero or more occurrences of the preceding element. Combined together, .* matching any number of any character.
    • deb.debian.org – Matches the literal text deb.debian.org. The dot, here, is not escaped. So, it matches any single character, but in this context it still works for the literal dots in the hostname. If you wanted exactly a dot, you’d need to escape the dots with a backslash like this: deb\.debian\.org.
    • .* – Again, “match anything” after deb.debian.org until the next literal match.
    • bookworm main – This is preceded by another space, so this matches the space and the literal text bookworm main
    • $ – The dollar sign signifies the end of a line of text in regex. So, with this bumped up against bookworm main, it means bookworm main will be the last group of printable characters on the line.
  2. The Substitution command: s/$/ contrib/
    • s/.../.../ – This is the substitute command. Similar to the regex search pattern above, a substitute command start with s and is followed by another regex search pattern and text to replace anything that matches the search pattern.
    • $ – The regex pattern to match — In this case, we’re going to replace the end of the line with new text. I doesn’t actually replace $, but more inserts it before the $. Beginning and ends of lines are treated a little differently than the rest of the file.
    • contrib – The text to insert at the end of the line.

Step 4: Install CUDA Toolkit

Before we can use our shiny new additions to sources.list, we need to install wget so we can download and install NVIDIA’s key rings. Without the keyring, apt won’t find the packages.

sudo apt install -y wget
wget \ https://developer.download.nvidia.com/compute/cuda/repos/debian11/x86_64/cuda-keyring_1.0-1_all.deb
sudo dpkg -i cuda-keyring_1.0-1_all.deb

Now that apt knows how to find the CUDA toolkit—thanks to adding contrib—we can finally install NVIDIA’s proprietary GPU libraries. These packages live outside the open-source main repo, so this step wouldn’t work without that earlier tweak. With cuda-toolkit-12-2, we’re pulling in everything Hashcat needs to talk to your RTX GPU.

sudo apt update && sudo apt install -y cuda-toolkit-12-2

This pulls in the toolkit and runtime libraries for CUDA 12.2. It’s a chunky install (~3GB), so grab a coffee.


Step 5: Re-run Hashcat with CUDA support

Try the benchmark again—this is where the magic happens:

hashcat -b -m 1000

Now you should see two devices:

* Device #1: NVIDIA GeForce RTX 4060 Laptop GPU
* Device #2: Intel Core i9 CPU

And the speed?

Speed.#1.........: 32765.6 MH/s
Speed.#2.........: 1939.0 MH/s
Speed.#*.........: 34704.6 MH/s

Now that’s more like it. We’re pushing over 34 billion hashes per second thanks to the GPU.


Final Thoughts

With a few tweaks and one big install, your WSL 2 instance can go from “meh” to “metal-melting.” Whether you’re cracking passwords or training ML models, CUDA inside WSL 2 makes Windows a viable workstation OS for heavy compute—without spinning up a full Linux dual boot or dedicated VM.

In short: you’re no longer leaving performance on the table. Or, more accurately, in the GPU.

And if you’re looking for a TL;DR, try this:

wsl --install -d Debian --name Hashtastic
sudo apt update && sudo apt install -y hashcat
hashcat -b -m 1000
sudo sed -i.bak '/^deb .*deb.debian.org.* bookworm main$/ s/$/ contrib/' /etc/apt/sources.list
sudo apt install -y wget
wget \ https://developer.download.nvidia.com/compute/cuda/repos/debian11/x86_64/cuda-keyring_1.0-1_all.deb
sudo dpkg -i cuda-keyring_1.0-1_all.deb
sudo apt update && sudo apt install -y cuda-toolkit-12-2
hashcat -b -m 1000

Need a penetration test or just help with a security project? We’d love to help.

Share This

Did you find this helpful?

Share it with your friends!