The Tale of Two Meltdowns

April 26 is a day of structural failures. Forty years ago today, the core of Reactor 4 in Pripyat was exposed. It was a disaster born of bad design and brittle management. Exactly thirteen years after the reactor blew, a student in Taiwan named Chen Ing-Hau decided to commemorate the date with a different kind of meltdown. We called it CIH, but most people remember it simply as the Chernobyl virus.
While the 1986 disaster was an accident of physics, the 1999 virus was a deliberate masterclass in exploiting the muddy permissions of the Windows 9x kernel.

The Parasite in the Padding

Before CIH, viruses were bulky. Most malware worked by appending itself to the end of an executable file, which immediately changed the file size. If an antivirus saw that a file had suddenly grown, it flagged the infection. CIH was a space-filler. It didn’t add anything to the total length of the file. Instead, it searched for the null-padding gaps within the Portable Executable (PE) header.
The virus fragmented its own code to fit into these alignment gaps. It became invisible to the simple size-check logic of the era. This snippet shows how the virus iterated through the PE section headers to find a “cave” large enough to hold its fragments (code adapted from the original).

; Finding space in the PE sections (CIH Source)
LoopNextSection:
    add esi, 28h                ; Move to next Section Header (size is 40 bytes)
    mov eax, [esi+10h]          ; SizeOfRawData (size on disk)
    sub eax, [esi+08h]          ; VirtualSize (actual size in memory)
    cmp eax, VirusSize          ; Is the slack space big enough?
    jl  LoopNextSection         ; If not, keep looking

The Ring 0 Killswitch

Windows 9x was a fragile environment. It lacked the strict separation between user applications and the kernel that we take for granted today. CIH exploited this by hijacking the Interrupt Descriptor Table (IDT). By using the sidt instruction, it could locate the address of the IDT in memory.

The virus then modified the entry for Interrupt 3 (the breakpoint interrupt). Once the gate was changed to point to the virus code, calling int 3 shifted execution into Ring 0. Suddenly, the malware had the same privileges as the operating system (adapted for the blog post):

; The infamous IDT trick to gain Ring 0
    sidt [ebp+IDT_Addr]         ; Store the IDT base address
    mov  ebx, [ebp+IDT_Addr+2]  ; Load the address into EBX
    add  ebx, 8 * 3             ; Navigate to the Int 3 gate (8 bytes per gate)
        
    ; ... Logic to overwrite the gate with the virus entry point ...

    int  3

With kernel access, the virus could bypass any software-based BIOS write protection. When the clock hit April 26, it initiated a flash overwrite that turned the computer into a brick. This forced the industry to move toward physical jumpers and eventually the more secure UEFI standards we use now.

Software can have physical consequences. Whether it is a graphite-tipped control rod or a few bytes of assembly hidden in a header, the result is the same when the system loses its integrity.

You can find the full code of a later version of the virus here. Note that this has been modified a bit compared to the original (See changelog in the header section)

Did you experience the CIH meltdown?

II was lucky and did not get hit by CIH virus, but I know several that did (mostly via Back Orifice 2000 – for those of you remembering that one). I would love to hear your recovery stories or if you still have a motherboard somewhere in the attic that fell victim to the space-filler.