Security Researcher, demoscene fan, hardcore Tetris enthusiast former GDS / former ToB / Leviathan Security / Trellix these days. Opinions are entirely my own.

New York, NY
Joined January 2012
John Dunlap retweeted
We sent Claude Mythos Preview spelunking through Squid’s guts, and it surfaced clutching a 29-year-old bug. Meet Squidbleed: a Heartbleed-style vulnerability that leaks internal memory from every version of Squid Proxy, in its default configuration. Full story: blog.calif.io/p/squidbleed-c…
6
90
5
334
66,377
TIL ssh added keystroke timing obfuscation in 2023. Sends garbage packets to avoid revealing what you may be typing based on timing patterns. Another great blog post by @itseieio eieio.games/blog/ssh-sends-1…
25
174
5
1,771
60,307
Who could have seen this one coming?
39
John Dunlap retweeted
You know, I consider myself something of an artist. godbolt.org/z/64E9KEvb9
45
45
12
1,053
55,065
John Dunlap retweeted
It's a gorgeous and funny bug. Fwiw, I'm the biggest eBPF fanatic, but I don't think unprivileged users should be able to load arbitrary eBPF programs.
found a verifier/interpreter mismatch in the Linux BPF subsystem (CVE-2026-31525, CVSS 7.8). arbitrary kernel read/write; become root, escape containers, disable SELinux, read TLS keys out of other processes' memory. anyway, it starts with the math bars, the absolute value. computers store negative numbers in two's complement. the smallest 32-bit signed integer is -2,147,483,648, and the largest positive is +2,147,483,647. there is no +2,147,483,648, since it simply does not fit. so when you call abs(-2,147,483,648), the C specification thinks about it for a moment, says "undefined," and leaves the room. on x86 and arm64, what you actually get back is -2,147,483,648. you asked for the absolute value of a negative number, you got back the same negative number. thank you computer :D the BPF interpreter implements signed 32-bit division (BPF_ALU | BPF_DIV/MOD, off == 1, added in ec0e2da95f72) by decomposing it into unsigned division: take abs() of both operands, divide via do_div(), reapply the sign. the handler in ___bpf_prog_run (kernel/bpf/core.c): AX = abs((s32)DST); AX = do_div(AX, abs((s32)SRC)); and look, the kernel even documents this. include/linux/math.h: "the return value is undefined when the input is the minimum value of the type." when DST = 0x80000000 (S32_MIN), abs() tries to negate it. -(-2,147,483,648) overflows s32, the C spec calls it undefined behavior, and the CPU hands back 0x80000000 unchanged. still negative. abs() had one job. this s32 then gets assigned into AX, a u64 BPF register. s32 → u64 sign-extends: 0x80000000 becomes 0xFFFFFFFF80000000. that's 18,446,744,071,562,067,968. you wanted 2,147,483,648, you got 18.4 quintillion; a rounding error of about 18.4 quintillion. do_div() is a 64-by-32-bit unsigned division macro and it operates on this full u64 numerator. the quotient is off by a factor of 2³². the smod path has the same problem since do_div() modifies the dividend in place and returns the remainder, both wrong. 8 call sites across sdiv32/smod32 src/imm handlers, all quietly producing nonsense whenever S32_MIN shows up. the BPF verifier is the safety system that statically analyzes every BPF program before allowing it to run. it exists specifically to guarantee that nothing bad can happen. scalar32_min_max_sdiv() in kernel/bpf/verifier.c tracks value ranges through abstract interpretation. it handles signed division correctly, including S32_MIN. computes tight, mathematically correct bounds. the interpreter, as we've established, computes whatever it feels like. so the verifier thinks register R0 is in range X. the interpreter puts value Y in R0. the safety system and the execution engine disagree about what a program does. in BPF security research, this is where you set down your coffee. concretely: load S32_MIN into R1, load 2 into R2, execute SDIV32 R1 R2. verifier determines R1 ∈ [-1,073,741,824, -1,073,741,824]. interpreter computes do_div(0xFFFFFFFF80000000, 2) = 0x7FFFFFFFC0000000, reapplies the sign, produces a completely unrelated value. use R1 as an index into a BPF map. verifier approves the access, bounds check passes against its calculated range. interpreter uses the actual value. out-of-bounds read/write on a kernel data structure. on every Linux machine running the BPF interpreter. the root cause of all of this: the absolute value function doesn't handle one number. one specific number, out of 4.2 billion possible inputs, and it's the one that gives you kernel read/write. the fix is: c static u32 abs_s32(s32 x) { return x >= 0 ? (u32)x : -(u32)x; } cast to u32 before negating. -(u32)0x80000000 = 0x80000000 unsigned. correct absolute value, no overflow, no undefined behavior. the kind of function you'd assume already exists somewhere in 30 million lines of kernel code. it did not. I got to write it. :D I reported this, wrote the patch, got it through 5 revisions of review. acked by Yonghong Song and Mykyta Yatsenko. now patched in stable 6.6, 6.12, 6.18, 6.19. if you haven't updated your kernel: maybe do that.
7
23
1
154
25,666
John Dunlap retweeted
The coreutils Rust rewrite story is pretty funny. Coreutils are tools like rm, mv, mkdir, etc. Unlike binutils, this isn't a fertile ground for memory safety bugs. But, the rewrite was completed, and in the spirit of progress, Canonical decided to switch. 🡇
42
90
12
1,402
219,689
John Dunlap retweeted
Exploiting Reversing (ER) series. An step by step Exploitation Technique of Windows Cloud Files Mini Filter Driver Elevation of Privilege Vulnerability. (CVE-2024-30085) Link:- exploitreversing.com/wp-cont… #exploit #windows
2
20
136
8,265
This post gives me a headache. At some people started calling important userland libraries and services the ABI. Linux kernel gives the “stable” abi. Are we calling the behavior of various libraries the abi? The argument is correct I just wouldn’t call the culprit the Abi.
I don't know if a lot of people have thought why this happened. To make Linux viable for the layman, Valve had to make Proton (derived from Wine) so that Win32 API became the first and only stable ABI on Linux. Why did Linux Distro devs not care about stable ABI historically?
5
14
9,277
😱 HOLY SHIT... Someone just dropped a fully liberated Gemma 4 E4B! and the guardrail removal process appears to have left coherence fully intact AND improved coding abilities! 🤯 huggingface.co/OBLITERATUS/g… OBLITERATED Gemma: ✅ 97.5% compliance rate, 2.1% refusal rate, 0.4% degenerate outputs (499/512 prompts answered on OBLITERATUS bench) ORIGINAL Gemma 4 E4B: ❌ 1.2% compliance rate, 98.8% refusal rate (506/512 prompts refused) Coherence: fully intact Factual: same Reasoning: same Code: +20% 📈 Creative writing: same But the REAL story here isn't the model itself, it's how it was made... 🧵 THREAD 👇
127
455
60
4,725
434,038
John Dunlap retweeted
No we're taking advice from the company that had access to a superpowered hacking bot since February but didn't use it to find the source code leak on their own site. 🤔
Oh, are we now taking security advice from the company who leaked their source code less than 10 days ago?
6
9
135
5,817
John Dunlap retweeted
FreeBSD, the kernel nobody thinks about until it's time to demonstrate what it looks like to attack something that skipped out on the last 20 years of modern defenses.
15
37
4
664
103,865
Yes please god take css out and shoot it
My dear front-end developers (and anyone who’s interested in the future of interfaces): I have crawled through depths of hell to bring you, for the foreseeable years, one of the more important foundational pieces of UI engineering (if not in implementation then certainly at least in concept): Fast, accurate and comprehensive userland text measurement algorithm in pure TypeScript, usable for laying out entire web pages without CSS, bypassing DOM measurements and reflow
1
33
John Dunlap retweeted
Someone fed our Linux kernel exploitation blog post into Claude, and it casually coughed up another vulnerability. On one hand, this is the beauty of open research and sharing. On the other hand, Claude scares me. Send help! linkedin.com/posts/yochai-ei… git.kernel.org/pub/scm/linux…
2
58
5
318
25,817
The past couple of months I've personally witnessed a few changes in malware that are so significant that it blatantly sticks out. 1. Malware written in more esoteric languages. I've witnessed a shift away from languages like C/C++ to languages that are heavily abstracted, most notably NodeJS with Electron. 2. A MASSIVE shift toward targeting open source solutions. While this isn't new, the past couple of months its been every single day someone is targeting a supply chain via masquerading or directly targeting the open source provider. 3. AI has assisted with the shift in the malware landscape ... toward higher level languages. I've witnessed a spike in multi staged malware using a lot of LOLBIN-like methods. Again, this isn't anything new, but I've witnessed such a dramatic spike I believe it is the result of AI making it much easier to create and use high level languages 4. The introduction of new threat landscapes: Clawdbot (or whatever it's called now). This has resulted in a shift toward MacOS malware which is referencing bulletin point 3. Heavy usage of ClickFix with high level multi staged languages (bash script to Js) 5. AI being used for social engineering. Historically I've seen really crappy malware lures and phishing pages. I suspect AI is helping polish pages and making them look more realistic, possess no typos, use good grammar, etc.
33
146
6
1,317
81,236
Sometimes I keep a fuzzer running locally on my MacBook in the winter to keep my hands warm.
2
35
John Dunlap retweeted
NYSEC is tomorrow! Tuesday, March 17th @ 6PM. d.b.a. 41 1st Ave. New York, NY 10003
1
2
303
John Dunlap retweeted
I recently came across the need to obtain logging into WSL2 and was forced to look into function hooking. However, this was my first time dealing with a COM server that didn't symbols, so I had to learn about a C++ feature - RTTI. I decided to write a blog on this in case anyone else runs into or has run into this: jonny-johnson.medium.com/wsl… POC: github.com/jonny-jhnson/Rand…
1
23
102
10,722
This is a great project. The name is ungoogleable though
The dream of a fast and reliable binary analysis framework is now a reality. Today, we’re open sourcing VulHunt.RE 🎉 code: github.com/vulhunt-re/vulhun… docs: vulhunt.re/docs A huge kudos to the entire REsearch team!
1
1
216
John Dunlap retweeted
A Race Within A Race: Exploiting CVE-2025-38617 in Linux Packet Sockets. A step-by-step guide to exploiting a 20-year-old bug in the Linux kernel to achieve full privilege escalation and container escape, plus a cool bug-hunting heuristic. open.substack.com/pub/calif/…
3
59
4
207
27,313
I feel you can get the exact flavor of dude who uses paste bin to the extant that it’s integrated into their c2. It’s not a great flavor either.
You don’t see this every day: attackers hiding C2 infrastructure inside computer science essays on Pastebin using character-level steganography, then wiring it into 26 typosquatted npm packages impersonating some of the ecosystem’s most widely-used libraries. Socket detected the cluster within minutes of publication, uncovering a disciplined, multi-stage operation linked to the Contagious Interview campaign that delivers a full infostealer and RAT stack built to harvest developer credentials. socket.dev/blog/stegabin-26-…
89