; Kon-B00t Boot Sector ; reverse engineering done by Peter Kleissner ; code will be executed from 0000h:7C00h org 0000h:7C00h ; do the usual initialization of the processors registers 00000000 FA cli 00000001 33C0 xor ax,ax 00000003 8ED0 mov ss,ax 00000005 8ED8 mov ds,ax 00000007 8EC0 mov es,ax ; set the stack to 0000h:7C00h 00000009 B8007C mov ax,0x7c00 0000000C 8BE0 mov sp,ax ; jump to segment 0000h 0000000E 68007C push word 0x7c00 ; initial start address 00000011 1E push ds ; cs = 0000h 00000012 68167C push word Initial_Code_Start ; ip = 7C16h 00000015 CB retf Initial_Code_Start: 00000016 FB sti ; reactivate interrupts 00000017 1E push ds ; segment = 0000h 00000018 50 push ax ; offset = 0000h 00000019 8816EA7C mov [Store_Drive +1],dl ; remember the boot drive 0000001D E83800 call word Execute_VGA_Code ; allocate 5 KB from the end of memory and relocate 00000020 832E130405 sub word [0x413],byte 5 ; using "base memory size in KB" of BIOS Data Area (0040h:0013h) 00000025 A11304 mov ax,[0x413] ; get the new memory address 00000028 C1E006 shl ax,6 ; * 64 = * 1024 / 16 (= segment address) 0000002B 8EC0 mov es,ax ; of course es will point to the memory ; read 9 sectors from logical sector 1 to the newly allocated memory 0000002D B80902 mov ax,0x209 ; Function 02h = "Read Sector[s]", 9 sectors to read 00000030 33C9 xor cx,cx ; Cylinder Number = 0 00000032 32F6 xor dh,dh ; first floppy drive (you can't use it in your second :D) 00000034 8BD9 mov bx,cx ; es:bx -> transfer buffer 00000036 83C102 add cx,byte +0x2 ; Sector Number = 2 (= second sector) 00000039 CD13 int 0x13 ; read! 0000003B 725F jc Error_Handler ; if any error occurs notify the user ; backup original interrupt 13h vector 0000003D A14E00 mov ax,[4*13h + 2] ; segment of Interrupt 13h handler 00000040 26A30400 mov [es:0x4],ax ; store into the read sectors 00000044 A14C00 mov ax,[4*13h + 0] ; offset of Interrupt 13h handler 00000047 26A30200 mov [es:0x2],ax ; store into the read sectors ; install interrutp 13h hook 0000004B B85B00 mov ax,0x5B ; code will start at offset 5Bh 0000004E 8C064E00 mov [4*13h + 2],es ; int 13h segment = 0000h 00000052 A34C00 mov [4*13h + 0],ax ; int 13h segment = 005Bh ; jump to the relocated code 00000055 06 push es ; cs = 9XXXh 00000056 53 push bx ; ip = 0000h 00000057 CB retf Execute_VGA_Code: ; executes 2 sectors from sector 8Ah and passes it 128 sectors of data ; store register contents (that will be later modified) 00000058 06 push es 00000059 1E push ds 0000005A 60 pushaw ; read 2 sectors from sector 138 to address 0000h:2C00h 0000005B B88A00 mov ax,0x8A ; from sector 8Ah 0000005E B90200 mov cx,0x2 ; 2 sectors 00000061 BB002C mov bx,0x2C00 ; 0000h:2C00h 00000064 E85B00 call word Read_Sectors_LoopyLoop ; allocate 65 KB, so TrueCrypt will never have enough memory :) 00000067 832E130441 sub word [0x413],65 ; again using MEM 0040h:0013h - BASE MEMORY SIZE IN KBYTES 0000006C A11304 mov ax,[0x413] ; get the base address 0000006F C1E006 shl ax,0x6 ; calculating the segment address (* 1024 / 16) 00000072 8EC0 mov es,ax ; es and ds will point to the new allocated memory 00000074 8ED8 mov ds,ax ; read 126 sectors from sector 13 to offset 0000h 00000076 B80D00 mov ax,13 ; sector number 13 00000079 33DB xor bx,bx ; offset 0000h to memory of allocated 41 KB 0000007B B97E00 mov cx,7Eh ; 126 sectors 0000007E E84100 call word Read_Sectors_LoopyLoop ; read! ; read 2 sectors from sector 11 and append them to the read contents 00000081 B80B00 mov ax,11 ; sector number 11 00000084 BB00FC mov bx,126 * 512 ; append them 00000087 B90200 mov cx,2 ; 2 sectors 0000008A E83500 call word Read_Sectors_LoopyLoop ; read! ; es:bx = 9XXXh:0000h, 65 KB allocated memory & 128 sectors read in there, data ; 0000h:2C00h contains the code (2 sectors read) 0000008D 6A00 push byte +0x0 ; segment = 0000h 0000008F 68002C push word 0x2c00 ; offset = 2C00h 00000092 CB retf ; call that code ; remove the allocated 65 KB data 00000093 8306130441 add word [0x413],byte +0x41 ; no longer used, no longer required ; restore the register contents 00000098 61 popaw 00000099 1F pop ds 0000009A 07 pop es 0000009B C3 ret Error_Handler: ; display "Err" on the screen 0000009C 6800B8 push word 0xb800 ; segment B800h = Textmode Buffer 0000009F 07 pop es ; -> access over es 000000A0 B08E mov al,0x8E ; set the character color to use 000000A2 26C606000045 mov byte [es:0x0],0x45 ; display 'E' 000000A8 26A20100 mov [es:0x1],al ; (character color) 000000AC 26C606020072 mov byte [es:0x2],0x72 ; display 'r' 000000B2 26A20300 mov [es:0x3],al ; (character color) 000000B6 26C606040072 mov byte [es:0x4],0x72 ; display 'r' 000000BC 26A20500 mov [es:0x5],al ; (character color) Endless_loop: ; note by PK: 000000C0 EBFE jmp short Endless_loop ; use cli, hlt, no onse uses endless loops Read_Sectors_LoopyLoop: ; ax = logical sector number ; cx = sector count ; es:bx = sector buffer ; read sector for sector 000000C2 E80900 call word Read_CHS_Sectors ; read one sector of it 000000C5 81C30002 add bx,512 ; seek in the buffer to the next sector 000000C9 40 inc ax ; -> next sector 000000CA 49 dec cx ; repeat cx times 000000CB 75F5 jnz Read_Sectors_LoopyLoop 000000CD C3 ret Read_CHS_Sectors: ; this code is more old than I am ; ax = logical sector number 000000CE 60 pushaw ; store register contents 000000CF 33D2 xor dx,dx ; dx:ax / 36 000000D1 B124 mov cl,36 ; 36 sectors per track? 000000D3 48 dec ax ; -1 to get correct sector number 000000D4 F6F1 div cl ; => Sector Number / Sectors per Track = Cylinder Number 000000D6 8AE8 mov ch,al ; store the cylinder numer in ch 000000D8 80FC12 cmp ah,18 ; on head 1/2? 000000DB 7205 jc Read_CHS_Sectors_SetHead ; if ah > 18 then head 1 000000DD FEC6 inc dh ; head +1 000000DF 80EC12 sub ah,18 ; and -18 because of using the next head UGLY UGLY UGLY Read_CHS_Sectors_SetHead: 000000E2 8ACC mov cl,ah ; use the correct sector number 000000E4 FEC1 inc cl ; sector number, starting from 1 000000E6 B80102 mov ax,0x201 ; Function 02h = "Read Sector[s]", 1 sector to read Store_Drive: 000000E9 B212 mov dl,0x12 ; the correct BIOS driver number will be patched at runtime 000000EB F9 stc 000000EC CD13 int 0x13 ; read the sectors! 000000EE 72AC jc Error_Handler ; if any error occurs notify the user 000000F0 FB sti 000000F1 61 popaw ; restore register contents and return 000000F2 C3 ret ; fill with nops times 510-($-$$) db 90h Boot_Signature dw 0AA55h