A journal that is (mostly) about research
_hyp3ri0n's research journal. aka P4x's research journal (pronounced PAX). aka Alex's research journal.
Welcome everybody, this is my open research journal about... my research (off to a great start). Now when I say "research journal" that typically means I'm going to throw a bunch of statistics at you, make you think and try to understand what scribbles mean, and that the stuff being presented is theoretical. That is NOT what this is. Think of this more as "a journal that happens to contain my research," much of which has been developed to the point that it is ready to be productized. I thought it would be informative for any product - and when i say product I include free open source stuff - that you know the paths that were taken, the pitfalls I ran into and how I got around them. That way, if anyone wants to take any OSS stuff and run with it, you know what not to do, and it becomes an actual collaboration instead of a "this is technically open source, but we're not gonna tell you how to use it." Like TOR. Yep, calling them out here- the total and complete lack of documentation means no one else can implement it without a lot of work. For privacy this would be a goldmine, so.... why wouldn't they do this. The answer is: being the only well known game in town has perks. From donations, to reputation you can turn into money. In fact they were on a DARPA project with me and my team, there's nothing wrong with that of course, but there is something wrong with pretending you're all for the people then being "transparently opaque."
Sorry for that random rant, this is my research journal after all. BUTm I will very unclassily call out events associated with, parties involved, enterprises I don't like, and even announce products I'm releasing that make fun of enterprise products (mine actually work and are IMO more effective). So yeah, journal with research is probably more accurate.
Quietude
Over the past couple of years I've been fairly quiet.... a little too quiet. When you stop seeing me produce significant open source code you should always think "that guy is up to something". That something may be anything from planning a country's internet blackout (just as an example that has totally never happened), or getting neck deep in research on stuff I don't fully understand but am trying to. I've been quiet for a while now- like a um, snake slithering across the grass ready to bite at your ankle (?). That means I've been up to something, and up to things I have been! I recently got into some new stuff like a dog gets into a bag of Cheetos and eats it, making them food-crazy and going through them at warp speed only to make them sick later. I'm not sick, but I did find a bag of Cheetos (metaphorically, I need to instacart the actual ones). So what have I been up to? Why have I been quiet about it?
What has Alex been doing
I've never made it a secret that mass attacks with distributed computing are a somewhat little niche of mine that I've carved out in the infosec space. It's not all I've done, it's not all I'm interested in, but it's where a lot of my work I talk about has been. This is very relevant, because I got into a totally foreign field to myself - actual High Performance Computing (HPC). I sort of just fell into it, it wasn't on purpose, I was just holding it for a friend, I swear it wasn't mine.
The work I was doing took a really strange and interesting twist into stuff that's incredibly hard to describe, and even harder to describe in a sitting. So I figure I'll give you the logical progression of how I accidentally did some cool stuff.
HPC and Alex: what do?
What do is that I had an idea for a clever little file transfer system, and it ended up turning into a whole "thing" that would change how i looked at computing, what's possible with current commodity hardware, and why we compute the way we compute. This led to the work I'd describe as: "High performance computer, on a normal x64 architecture, on a normal linux distro (ubuntu), that pushes and even crosses the boundaries of what we thought was possible with what we have." In a world where the answer to "we need to compute more" -> "ok then lets buy computing power" is the standard go- doing something novel means literally doing anything that doesn't just blindly do what we've been doing. Sometimess, it actually f***ing works. Imagine my surprise.
So buckle on in, I will show you the world, I will open your eyes, take you wonder by wonder, a dazzling place you never knew, and when you're way up there, it's crystal clear and we'll all be freewheeling through an endless diamond sky. A whole new world you might say.
PacketFS
PacketFS was a bit of an oddball idea I had about a simple transfer system. The idea was this: use shared references on two network endpoints, send the minimum bytes absolutely possible so that both machines then have the same identical file. If you're suspicious of that wording, good, you should be. I did NOT say "transfer the file from one box to the other". But I'd argue, what I said is the same goal, you have a thing in one place, you want it in another, checksums checking out. Full stop. So here's what happened in this order, and the start of a year and a halfish of research (and counting):
(1) I had the idea that, if two endpoints on different or the same networks (internet included), had the same bytes in a predictable place, that I could send something like a blueprint to reconstruct the file from those bytes. So instead of sending a big dumb blob of bytes that is a file (there's other ways to look at a file- more to come on that)- that I could simply use shared references into those bytes and inexpensive, small, pointers- allowing me to send something akin to a blueprint of the file needed, and have it get reconstructed on the other side. Some people (AI) called it "teleport TCP" which was a bit much, so I called it file reconstruction via shared references, and eventually "PacketFS".
(2) So i started to get pretty deep into packets, protocols, and the exact nitty gritty mechanics of how it all works. I was looking for one thing in particular that I knew was true, but that I needde the specifics of. I knew that TCP is a hugely bloated protocol, I had the suspicion that it's not just antiquated but downright ancient. The biggest lie your computer tells you (besides "no personal data is collected") is your download and upload progress bars. Think about it- you have a file on disk that's say 256 MiB- you go to transfer that file, whatever you're using has a little bar that starts at 0 and ends at 256. Right there- you're already being lied to. You are NOT just sending 256MiB worth of bytes, you're really sending a lot more than that: you have to count TCP packet overhead which include the following fields:
- Source Port: Sends traffic from this 16-bit application port.
- Destination Port: Routes traffic to this 16-bit application port.
- Sequence Number: Tracks byte order using 32 bits.
- Acknowledgment Number: Requests next byte using 32 bits.
- Data Offset: Measures header size using 4 bits.
- Reserved: Holds 3 bits for future standards.
- Nonce Sum Flag: Protects against routing manipulation (1 bit).
- Congestion Window Reduced: Signals transmission slowdown using 1 bit.
- ECN-Echo Flag: Mirrors network congestion indicators using 1 bit.
- Urgent Flag: Prioritizes critical data using 1 bit.
- Acknowledgment Flag: Validates ack field using 1 bit.
- Push Flag: Forces immediate data delivery (1 bit).
- Reset Flag: Drops unstable connections using 1 bit.
- Synchronize Flag: Initiates connections using 1 bit.
- Final Flag: Closes active connections using 1 bit.
- Window Size: Dictates receiver buffer capacity (16 bits).
- Checksum: Verifies packet integrity using 16 bits.
- Urgent Pointer: Marks priority data boundary (16 bits).
- Options: Customizes connection parameters (0–40 bytes). [1, 2, 3, 4, 5]
- Payload
That's a lot of sauce. And this is per packet in a lab setting where we assume- there's no ads on the page, no additional telemtry on the page, no polling for anything- in other words a completely sterile lab setting. When I did the math for an average page, you could easily get up to 50% of just overhead with TCP. Worse yet, if those packets are small in payload, you still pay the same header tax/troll toll. This led to a realization that I think a lot of people have had:
TCP is f**cking ancient
The history of TCP
I don't actually know the history of TCP, but from what I can gather it's something like this: It's an old protocol, dating back to 200 BC in ancient Armenia. The history is fuzzy here, so I'll just make it up, but this is where the first recorded event of one of those awkward moments when someone is walking towards you and you both want to get out of each others way. You both go left, then both right, then you both stop to let the other person pass, still blocking each other. This is recognized by most people that are me as history's first three-way handshake. In this particular case, the first Armenian to say "shall we dance" in ancient armenian or պարեսցու՞ք, to be more accurate, was recorded. This man was beaten to death minutes later.
(3) So here is where PacketFS was born- the base idea: a shared filesystem that is exactly like another machine's, would serve as a shared reference of a lot of common network traffic, headers, overhead, and common patterns seen in files. Here's the setup visually:
_____________________________
| Machine 1 |
|-----------------------------|
| PacketFSv1 |
| |
| made of common headers/ |
| patterns in files |
| e.g. 0x33,0x44,0xff,0x4c |
| ___________________________ |
_____________________________
| Machine 2 |
| PacketFSv1 |
| |
| made of common headers/ |
| patterns in files |
| e.g. 0x33,0x44,0xff,0x4c |
| ___________________________ |
Now instead of moving all of the bytes of a file -> you'd move descriptors roughly in the form of (pattern offset start, number of bytes from shared reference). When a transfer to the other side occurred this would be
sent in lieu of the actual bytes of the file. Because the other side has the exact same metadata-as-a-filesystem, it could receive these descriptors, dereference the descriptors locally, and construct the full bytes of
the other side's file. Because I could predict pretty much all overhead bytes from protocol, and many bytes of the payload this would lead to a sort of blueprint I could send so the other side reconstructs the file
instead of donig it the caveman way of just sending all the bytes. It was mildly clever - but put it into perspective- there's only a few bytes out there, 256 to be exact- everything else is just putting them in the
right order. We don't need the full on bytes- we just need the order, and that can be represented far cheaper than a dumb blob of the exact bytes to put in the next position. We're using MATH here to be clever.
(4) The first few times I built this and did a test transfer I did a few things: I decided making a POSIX filesystem is a huge pain in the ass so f that for a test, I made a blob of bytes of ~1 GiB of patterns "mined" from
my OS. Each time I would go to send something I'd do a lookup against a couple of bytes that were "next up" to be sent, see if there were any pattern matches or fuzzy pattern matches in the blob of bytes, send something
like a python tuple, describing (offset into blob, number of bytes to read that match file). At first I figured i'd eliminate overhead, that was engineered, what I did not expect was the sheer number of patterns that
nearly all files use.
Results:
The experiment had some interesting results. First, lookups over a 1GiB blob were near instant- I did this by simply eliminating a bunch of overhead, the blob wasn't on the filesystem, it was on mounted 1GiB hugepages with hugetlbfs, so I was essentially working in kernel memory - no disk overhead. I used a lot of parallelism to send probes into the blob doing a parallel search that was pretty cheap.
My results were measured as this, these terms are actually important, because they describe what's going on honestly instead of claiming that I'm able to beat physics:
- Real throughput - this is umm, the real amount of throughput
- Real bytes moved - the amount of real bytes (referentially shrunken) that I had to move
- Effective bytes moved - that is, given the speed of transfer (measured), how fast would a normal transfer have to go to get the file from one side to another.
- Wall time - amount of time it took end to end (including referential encode time, decode time)
I was using raw eth frames for the transfer over a LAN with fairly average NICs, a 2.5 Gbps NIC and a 1Gbps NIC on the same LAN. The speed of a fairly normal file on the filesystem was absurdly fast. I don't want to make exact claims about how fast, because it may be misleading- the speed depends a bit on the file in this model (though stay tuned for ways around that), but suffice to say that the first transfer I did like this it finished fast enough that I thought it just hadn't run, for a hundreds of GiB real file. But apparently it had. And even more- the file on the other side had the same sha256 checksum as the original file. It looked like I was breaking physics, but this is probably the one place where this is actually way better than breaking physics. The payload became so small so quickly that the transfer time was perhaps about a second. That was a bit of a holy shit moment- you might be picturing that I was doing this all formally and stuff, carefully recording outcomes and variables and such. Nope, I was toying around with stuff, I figured this would probably be useless and I'd move on to the next thing. I was on a pi and a personal desktop.
What had happened
So here's WHY that super fast transfer happened after looking into it:
- Creating a referential representation of something is super cheap, it's just pointers back into a blob I was searching over quickly.
- There are a LOT more patterns that repeat over and over in nearly every file, no matter the architecture, fs, or oftentimes even the file.
- 1GiB of patterns is a metric f***ton of patterns- I didn't think so much about it at the time, I sort of vibed out 1GiB because it's easy to work with. But honestly - total overkill. We don't think about it really but we handle massive massive amounts of data every day, it's just that the speeds we access them have become really fast, so we don't think about it much. Really, even a 1MiB file would have produced a very similar result (more on that later).
Aftermath
So I was definitely a little bit weirded out by how well that worked and was sure I made a mistake somewhere. But nope- the file was now on two machines, when before it was on one. The checksums matched, the file was exactly the same on both sides. I had just achieved an Effective Speed of somewhere around a few hundred GB/sec. Sure, I'm not actually pushing that many bytes - but who actually gives a shit? This has been one of the things I believe I've done fairly well at in the R&D world- don't assume a solution is the one to use even if one or many exist. We probably all think of file transfer as a "solved problem" - and sure, there's a bunch of ways to do it, a bunch of optimizations, a bunch of protocols, but very few people actually stopped to think about the base of it- what are we trying to solve? It's NOT get these bytes over there as fast as we can. Each byte no matter where it comes from is identical to another byte of the same value. It doesn't matter if that 0xff came from a file you want on the other side of a network or if you pulled it from a local random number generator- a byte is a byte is a byte. The problem is better stated as "I want the value of this set of bytes making up a file to be on a remote machine in the same order as they are here". All of a sudden the problem opens up- it's not about maximum throughput. It's about byte order, cheap representation, throughput, tricks around having to do a lot of work, etc. etc. Just because it's a nice mental picture of "these bytes in this order are being moved to another computer in the same order" first, does not make that the reality of what's actually happening (it's not, those bytes are copied and dismantled several times over) and second convenience in your head doesn't make something the best solution to a problem, though it sure feels that way many times. And that's how you find yourself assuming- "Hey, I need these exact bytes, and they need to be over there ASAP." means these exact bytes I am looking at, not the actual problem "bytes of the same value need to be in the same order over there as it is here."
Anyway off that ol' soapbox - the rest of the story is where it gets a bit nutty, but surprisingly not fruitless at all, the opposite in fact. I asked myself- huh, that was really fucking fast, wait, how fast do things move in memory when shoved around by the CPU? Along with the realization that the trap I described above is something I was doing all over the place. Because in the end- what is execution? In fact, what is anythign on a computer? It's bytes all the way down, and again, there's not that many of them. And a byte is a byte is a byte - so what does every problem reduce to? That's where I came up with Alex's Axiom on Computing and Execution and Stuff: execution is just somewhat predictable byte movement that reaches an end state. That opens all kinds of weird doors that lead to "what even IS execution" - sure we have all of these abstractions of execution, a PE running, asm and opcodes, but all of that is just a convenience model for better predicting byte motion, running asm is just formalized byte motion, and therefore so is execution.
It may sound like an odd thought, but it led to stuff like this pretty quickly. This is a virtual CPU that I made off of those principles, and a lot of stuff with the same philosophy as the file transfer. This is a virtual CPU I call the pCPU beating the shit out of a bare metal CPU with OpenCL run with hashcat, whereas my program is just a dumb straightforward sha256 generator in C. This was written so I could show it here, it's very real, but the speeds aren't even close to what you can actually get with a bit of optimization. Here's me in my terminal calculating sha256 at ~2.5x the speed of hashcat with OpenCL:
(venv) root@punk-valkyrie:/home/punk/projects/belikewater/pfs-sdk/pcpu-sdk# readiness/demo_sha256_hashcat_loses.sh
Running SHA-256 process-wall demo...
root: /home/punk/projects/belikewater/pfs-sdk
args: --count-per-lane 524288 --lanes 16 --data-bytes 64 --timeout-s 360 --ring always --ring-verify 0 --ring-batch-vl 64 --wave never --hashcat-mode never --hashcat-backend opencl --hashcat-device cpu --target-mode absent
python3 "/home/punk/projects/belikewater/pfs-sdk/pcpu-sdk/readiness/bench_sha256_hashcat.py" --count-per-lane 524288 --lanes 16 --data-bytes 64 --timeout-s 360 --ring always --ring-verify 0 --ring-batch-vl 64 --wave never --hashcat-mode never --hashcat-backend opencl --hashcat-device cpu --target-mode absent
pcpu-sha256-hashcat run_dir=/home/punk/projects/belikewater/pfs-sdk/artifacts/runs/pcpu-sha256-hashcat/pcpu.sha256.hashcat.20260709T093924Z.2652475 total=8388608 data_bytes=64 hashcat=skipped (non-ring path is still measured and saved in result artifacts)
Control: CPU only baseline status=ok hash_per_s=2364814.0 effective_data_mib_s=144.337 cpu_package_avg_watts=213.148 joules_per_hash=0.000090155887
pCPU enhancements active: status=ok batch_vl=64 hash_per_s=6964790.7 effective_data_mib_s=425.097 cpupwn=2.945 active_effective_data_mib_s=425.178 active_cpupwn=2.946 cpu_package_avg_watts=195.059 joules_per_hash=0.000028052288
hashcat_reason=--hashcat-mode=never
result_json=/home/punk/projects/belikewater/pfs-sdk/artifacts/runs/pcpu-sha256-hashcat/pcpu.sha256.hashcat.20260709T093924Z.2652475/result.json
summary_csv=/home/punk/projects/belikewater/pfs-sdk/artifacts/runs/pcpu-sha256-hashcat/pcpu.sha256.hashcat.20260709T093924Z.2652475/summary.csv
=== pCPU vs hashcat: SHA-256 absent-target process wall ===
artifact: /home/punk/projects/belikewater/pfs-sdk/artifacts/runs/pcpu-sha256-hashcat/pcpu.sha256.hashcat.20260709T093924Z.2652475
workload: 8,388,608 candidates, 64 bytes each, ring batch_vl=64
Control: CPU only baseline: ok
rate: 2.365 Mhash/s
effective data: 144.337 MiB/s
energy/hash: 90.156 uJ/hash
pCPU enhancements active: ok
rate: 6.965 Mhash/s
effective data: 425.097 MiB/s
energy/hash: 28.052 uJ/hash
Anyway, props to hashcat for an awesome tool. And for being the SECOND fastest password cracker in the world :). Anyway, I'll keep writing if you keep reading. This starts to get pretty deep into the innerworkings of CPUs, GPUs, byte motion and how it's currently handled/the big problems that needed solving, and finally, the solutions to those problems that I've come up with.
- Alex aka _hyp3ri0n aka P4X