惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Vulnerabilities – Threatpost
P
Proofpoint News Feed
The Hacker News
The Hacker News
Know Your Adversary
Know Your Adversary
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tenable Blog
AWS News Blog
AWS News Blog
S
Securelist
T
Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
IT之家
IT之家
腾讯CDC
WordPress大学
WordPress大学
Spread Privacy
Spread Privacy
C
Check Point Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Engineering at Meta
Engineering at Meta
Latest news
Latest news
A
About on SuperTechFans
The Register - Security
The Register - Security
L
LINUX DO - 热门话题
T
The Exploit Database - CXSecurity.com
C
Cisco Blogs
T
Tailwind CSS Blog
Simon Willison's Weblog
Simon Willison's Weblog
阮一峰的网络日志
阮一峰的网络日志
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
T
Tor Project blog
L
Lohrmann on Cybersecurity
G
GRAHAM CLULEY
B
Blog RSS Feed
Scott Helme
Scott Helme
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
NISL@THU
NISL@THU
P
Privacy International News Feed
Security Latest
Security Latest
Recorded Future
Recorded Future
L
LangChain Blog
Cyberwarzone
Cyberwarzone
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 聂微东
Google DeepMind News
Google DeepMind News
Last Week in AI
Last Week in AI
Apple Machine Learning Research
Apple Machine Learning Research
F
Fortinet All Blogs
O
OpenAI News
T
Threat Research - Cisco Blogs
Blog — PlanetScale
Blog — PlanetScale

The Old New Thing

Raymond's hot take on Hainanese chicken - The Old New Thing The case of the DLL that was not present in memory despite not being formally unloaded, part 1 - The Old New Thing Cancellation of Windows Runtime activities is asynchronous - The Old New Thing Microspeak elaborated: Isn't escrow just a release candidate by another name? - The Old New Thing In memory of the man who put red and green squiggles under words - The Old New Thing What does it mean when the bottom bit of my HMODULE is set? - The Old New Thing Why doesn't Get­Last­Input­Info() return info for the user I'm impersonating? - The Old New Thing Windows stack limit checking retrospective, follow-up - The Old New Thing Retrofitting the WM_COPY­DATA message onto Windows 3.1 - The Old New Thing The time the x86 emulator team found code so bad that they fixed it during emulation - The Old New Thing How can I schedule work on a thread pool with low latency? Understanding the rationale behind a rule when trying to circumvent it What’s the opposite of Clip­Cursor that lets me exclude the cursor from a region? The Microsoft Company Party where everybody played name tag swap Rotation revisited: Shuffling more than three blocks, and other small notes The back cover of C++: The Programming Language also raises questions not answered by the front cover Rotation revisited: Avoiding having to calculate the gcd when doing cycle decomposition Rotation revisited: Cycle decomposition in clang’s libcxx Rotation revisited: A shocking discovery about gcc’s unidirectional rotation algorithm Rotation revisited: Another unidirectional algorithm The placeholder name for the Windows 8 experience was “modern” Sharing the result of a single Windows Runtime IAsyncOperation among multiple coroutines, part 3 Sharing the result of a single Windows Runtime IAsyncOperation among multiple coroutines, part 2 Sharing the result of a single Windows Runtime IAsyncOperation among multiple coroutines, part 1 If C# and JavaScript lets me await a Windows Runtime asynchronous operation more than once, why not C++/WinRT? A hypothetical redesign of System.Diagnostics.Process to avoid confusion over properties that are valid only when you are the one who called Start Why do you say that a COM STA thread must pump messages if I see sample code creating STA threads and not pumping messages? How do I use Win32 structures from the Windows Runtime? What is the history of the ERROR_ARENA_TRASHED error code? The classic TreeView control lets me sort by name or by lParam, but why not both? Just shows that nobody cares about debugging the parity flag any more The case of the Create­File­Mapping that always reported ERROR_ALREADY_EXISTS
The case of the DLL that was not present in memory despite not being formally unloaded, part 2 - The Old New Thing
Raymond Chen · 2026-06-26 · via The Old New Thing

Last time, we looked at crashes caused by a DLL being removed from memory behind everybody’s back, causing crashes when somebody tried to call into that no-longer-there DLL that everybody thought was still there.

A colleague of mine who was looking at other crashes coming from this process found that most of those other crashes were also of the form “a data structure was corrupted because somebody wrote the single byte 01 into it.” That piece of information made everything fall into place for my side of the investigation.

We saw earlier that the bottom bit of the HMODULE is set for datafile module handles. Therefore, if one of these stray 01 bytes happens to overwrite the bottom byte of an existing HMODULE handle, that turns it into a (fake) datafile module handle. And then, during process destruction, a component dutifully cleans up the DLLs they loaded by freeing them (say because they were stored in an RAII type like wil::unique_hmodule), the code will pass this (fake) datafile module handle to FreeLibrary. The FreeLibrary function sees the bottom bit set and says, “Oh, this must be the handle to a module that was loaded via LOAD_LIBRARY_AS_DATAFILE,” so it frees it as a datafile.

Freeing a datafile module means undoing the steps that were taken when the module was loaded as a datafile: Unmapping the DLL from memory. In particular, loading a module as a datafile does not add the DLL to the list of DLLs that were loaded as code; therefore, unloading a datafile module doesn’t remove it from that list. As far as the DLL list is concerned, the DLL is still in memory.

A one-bit error caused the code to lie and attempt to free a module handle that did not correspond to a LoadLibrary call, resulting in mass havoc.

The “DLL unmapped from memory” crash is just an alternate manifestation of the “somebody is writing 01 bytes to places they shouldn’t” bug. The original bug had a larger bucket spray than we initially thought.

The good news is that all of the crashes have funneled down to a single bug. The bad news is that you now have to debug this one memory corruption bug.

Unfortunately, at the time of this writing, the root memory corruption bug in the third party program has yet to be identified. We don’t know whether it’s coming from an operating system component or from the program itself. Though the fact that it appears to occur only in one process, where it sprays across multiple modules, suggests that it’s a problem with that program, or that there’s something peculiar about how this specific process uses the system.

If you look at the original stack trace, you can see that the problem is occurring at process termination. That’s probably why the problem has lurked for so long: Crashes at exit often go unnoticed because there is no end-user loss of functionality. The user was finished with the program anyway. Whether it exits cleanly or with a crash doesn’t affect the user much.

Sorry. Not all stories have a happy ending.

Category

Topics

Author

Raymond Chen

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.