Billy Belceb病毒編寫教程(DOS篇)有用的結構體

看雪資料發表於2015-11-15

【有用的結構體】
~~~~~~~~~~~~~~
      現在介紹我們已經討論了很多的PSP。

%PSP(Program Segment Prefix)%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSP結構如下:
 ___________________________________
|           INT 20h(CD 20)          |<------+0000h
|___________________________________|             Size:1 WORD
|    Pointer to the next segment    |<------+0002h
|___________________________________|             Size:1 WORD
|             Reserved              |<------+0004h
|___________________________________|             Size:1 BYTE
|        Far call to INT 21h        |<------+0005h
|___________________________________|             Size:5 BYTES
|       Saved INT 22h vector        |<------+000Ah 
|___________________________________|             Size:1 DWORD
|       Saved INT 23h vector        |<------+000Eh
|___________________________________|             Size:1 DWORD
|       Saved INT 24h vector        |<------+0012h 
|___________________________________|             Size:1 DWORD
|             Reserved              |<------+0016h 
|___________________________________|             Size:22 BYTES
|   Offset to Environment Segment   |<------+002Ch
|___________________________________|             Size:1 WORD
|             Reserved              |<------+002Eh
|___________________________________|             Size:46 BYTES
|         First default FCB         |<------+005Ch
|___________________________________|             Size:16 BYTES
|        Second default FCB         |<------+006Ch
|___________________________________|             Size:16 BYTES
|    Command Tail and default DTA   |<------+0080h
|___________________________________|             Size:180 BYTES
                                     Total Size:256 BYTES

     因為這個結構非常重要,讓我一步一步地解釋吧。
       offset 0000h:
     INT 20h是終止程式的過時的方法,現在我們使用INT 21h的4CH號函式。
       offset 0002h:
     這是pointer to the next segment,這個指標指向我們程式的下一段。我們利用它可以知道DOS 能給我們多少記憶體(它指向的偏移地址減去PSP的偏移地址0000)。它將以段返回給我們記憶體,所以我們必須把它乘以16來得到位元組數。
       offset 0005h: 
     這是呼叫INT 21h的一種奇特方式。而且,當然,我們可以利用它來達到我們的目的。這個函式用到CL而不是AH,而且我們只能在低於24h時呼叫這個函式。我將在TUNNELING這一章裡介紹更多。
       offset 000Ah:
     這裡儲存的是原先的INT 22h中斷向量。INT 22h當程式使用如下方法終止執行時接受控制:
- INT 20h
- INT 27h
- INT 21h(00h,21h,4Ch函式)
      offset 000Eh:`
     這裡儲存另一箇中斷的向量,INT 23h。這個中斷處理CTRL+C按鍵組合。
      offset 0012h:
    儲存在這裡的另外一箇中斷,INT 24h。這個中斷處理嚴重錯誤。這種型別錯誤的例子:當你的軟碟機裡面沒有軟盤,或者軟盤被防寫了。
      offset 002Ch:
    這裡是環境塊偏移地址的開始。
      offset 005Ch:
    這裡儲存第一個預設FCB(File Control Block檔案控制塊)。這種訪問檔案的方式通常情況下不會被程式使用(在這裡是為了和低版本的DOS相容),但是病毒作者為了使病毒更隱蔽,經常使用它。你可以在FCB結構裡看到更多的資訊。
      offset 006Ch:
    同上,這是第二個預設FCB。
      Offset 0080h:
    這一段有兩個功能:
----儲存命令尾(command tail)
---儲存D他的預設檔案緩衝區
    這兩個功能不能同時使用,所以我們開始一個程式要考慮的第一件事就是命令尾(command tail)。如果我們需要它,我建議你把它儲存到一個安全的地方(我們程式碼中的一個變數中)。命令尾的第一個位元組(80h)約束了它的長度,而且這裡,它儲存了真正的引數。D他的結構將會在這一章中介紹。

%FCB(File Control Block 檔案控制模組)%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    現在有兩種型別的FCB:普通和擴充套件型別。下面給出普通FCB:

 ________________________________ 
|  Drive Letter(0=actual,1=A...) |<----+0000h
|________________________________|           Size:1 BYTE
|    Blank padded file name      |<----+0001h
|________________________________|           Size:8 BYTES 
|   Blank padded file extension  |<----+0009h
|________________________________|           Size:3 BYTES
|      Current block number      |<----+000Ch
|________________________________|           Size:1 WORD
|      Logical record size       |<----+000Eh
|________________________________|           Size:1 WORD
|            File size           |<----+0010h
|________________________________|           Size:1 DWORD
|            File date           |<----+0014h
|________________________________|           Size:1 WORD
|            File time           |<----+0016h
|________________________________|           Size:1 WORD
|            Reserved            |<----+0018h 
|________________________________|           Size:8 BYTES
|   Record within current block  |<----+0020h
|________________________________|           Size:1 BYTE
|   Record access record number  |<----+0021h
|________________________________|           Size:1 DWORD
                                  Total Size:37 BYTES

    而在一個擴充套件FCB中,上面所有的偏移地址會向後移7個位元組,而開始的7個位元組如下:

 _____________________________________
|   FF(Signature for extended FCB)    |<---- -0007h
|_____________________________________|            Size:1 BYTE
|              Reserved               |<---- -0006h
|_____________________________________|            Size:5 BYTES
|          File attribute             |<---- -0001h
|_____________________________________|            Size:1 BYTE
                                       Total Size:44 BYTES
    檢測FCB是普通的還是擴充套件的方法是看FCB 的第一個位元組是否為FFh。如果是,那麼就為擴充套件FCB,否則就為普通FCB。
    有一種隱蔽病毒(STEALTH)方法就是改變FCB的某些值,我們將會在STEALTH一章裡具體討論。

%MCB(Memory Control Block  記憶體控制模組)% 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    我們將在駐留記憶體病毒這一章介紹它(下一章)。下面給出MCB:

 ___________________________________
|     ID(Z=last,M=there're more)    |<----+0000h
|___________________________________|           Size:1 BYTE
|     Address of associated PSP     |<----+0001h
|___________________________________|           Size:1 WORD
|  Number of paras in allocated mem |<----+0003h
|___________________________________|           Size:1 BYTE
|               Unused              |<----+0005h
|___________________________________|           Size:11 BYTES
|             Block Name            |<----+0008h
|___________________________________|           Size:8 BYTES
|     Zone of allocated memory      |<----+0010h
|___________________________________|           Size:?? PARAS
                                     Total Size: VARIABLE

%DTA(Disk Transfer Area 磁碟交換區)%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

在病毒寫作中這個結構非常重要。讓我們看:

 ___________________________________
|   Drive Letter(equal than above)  |<----+0000h
|___________________________________|           Size: 1 BYTE 
|         Search Template           |<----+0001h
|___________________________________|           Size: 11 BYTES
|             Reserved              |<----+000Ch
|___________________________________|           Size: 9 BYTES
|          File attribute           |<----+0015h
|___________________________________|           Size: 1 BYTE
|             File time             |<----+0016h
|___________________________________|           Size: 1 WORD
|             File date             |<----+0018h
|___________________________________|           Size: 1 WORD
|             File size             |<----+001Ah
|___________________________________|           Size: 1 DWORD
|    ASCIIZ Filename+extention      |<----+001Eh
|___________________________________|           Size: 13 BYTES
                                     Total Size: 43 BYTES

    原始DTA儲存在PSP的偏移地址80h處。我們可以利用INT 21h的1Ah功能儲存它。

%IVT(Interrupt Vector Table中斷向量表)%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    這個並不是“真正的”結構體。恩...讓我解釋一下吧...IVT是儲存所有中斷向量的地方(哇,天才啊!)。所有的中斷向量的位置為number_of_interrupt*4(中斷號*4)。假如我們想把INT 21h中斷向量賦給DS:DX...則:

xor ax,ax
mov ds,ax
lds dx,ds:[21h*4]

      為什麼我們清除DS?因為IVT是從地址0000:0000開始到高地址記憶體的。這種操作(不透過使用DOS)是獲得/賦給一箇中斷的向量的直接方法。有關更多的介紹將在駐留記憶體病毒(RESIDENT VIRUSES)一章中介紹。嗨...我忘記了示意圖了:)

 __________________________________
|         INT 00h vector           |<-----+0000h
|__________________________________|            Size:1 DWORD
|         INT 01h vector           |<-----+0004h
|__________________________________|            Size:1 DWORD
|
//////////////////
|__________________________________
|         INT FEh vector           |<-----+03FCh
|__________________________________|            Size:1 DWORD
|         INT FFh vector           |<-----+0400h
|__________________________________|            Size:1 DWROD
                                    Total Size:1024 BYTES

    你能想象得到“斷”行表示有256箇中斷,我不得不最佳化這篇教程(我可不想花5頁來表示它!)

%SFT(System File Table 系統檔案表)%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    這個結構真得很酷。它能幫助你使你的程式碼更健壯,更最佳化。它類似於FCB,但是,正如你看到的,它更強大。利用這個表,我們可以使病毒更隱蔽,改變檔案指標的開啟模式,屬性...這裡你看到的使DOS 4以上版本的結構(我相信在這個世界上已經沒有人用DOS 3或更低了吧)。好了,如果你想為DOS 3編寫程式碼,可以參考Ralph Brown的中斷列表。但是DOS 3的SFT是和下面的非常類似的。重要的值在相同的地方:)

 ===================================== <----+0000h
‖    Pointer to next file table     ‖           Size:1 DWORD
‖===================================‖<----+0004h
‖  Number of files in this table    ‖-----------Size:1 WORD----------
‖===================================‖<----+0000h  [3Bh bytes per file]
 |  Number of file handles of file   |            Size:1 WORD
 |___________________________________|
 |      File open mode(AH=3Dh)       |<-----+0002h
 |___________________________________|            Size:1 WORD
 |          File attribute           |<-----+0004h
 |___________________________________|            Size:1 BYTE
 |    Device info block(AX=4400h)    |<-----+0005h
 |___________________________________|            Size:1 WORD
 | If char device points next dev h. |<-----+0007h
 |       else point to DOS DPB       |            Size:1 DWORD
 |___________________________________|
 |     Starting cluster of file      |<-----+000Bh
 |___________________________________|            Size:1 WORD
 |             File time             |<-----+000Dh
 |___________________________________|            Size:1 WORD
 |             File date             |<-----+000Fh
 |___________________________________|            Size:1 WORD
 |             File size             |<-----+0011h
 |___________________________________|            Size:1 DWORD
 |      Current offset in file       |<-----+0015h
 |___________________________________|            Size:1 DWORD
 |  Relative cluster within file of  |<-----+000-}---------[If Local File]
 |      last cluster accessed        |            Size:1 WORD
 |___________________________________|
 |  Number of sector with dir entry  |<-----+001Bh
 |___________________________________|            Size:1 DWORD
 | Number of dir entry within sector |<-----+001Fh
 |___________________________________|            Size:1 BYTE
 |    Pointer to REDIRIFS records    |<-----+000-}---[Network redirector]
 |___________________________________|            Size:1 DWORD
 |                ???                |<-----+001Dh
 |___________________________________|--------Size:3 BYTES--------
 |      Filename in FCB format       |<-----+0020h
 |___________________________________|            Size:11 BYTES
 | Pointer to prev SFT sharing file* |<-----+002Bh
 |___________________________________|            Size:1 DWORD
 | Network machine num opened file*  |<-----+002Fh
 |___________________________________|            Size:1 WORD
 |     PSP segment of file owner     |<-----+0031h
 |___________________________________|            Size:1 WORD
 |  Offset to code segment of rec*   |<-----+0033h
 |___________________________________|            Size:1 WORD
 | Absolute clust num of last access |<-----+0035h
 |___________________________________|            Size:1 WORD
 |  Pointer to IFS driver for file   |<-----+0037h
 |___________________________________|            Size:1 DWORD
                                     Total Size:61 BYTES

      Uhm...我忘記訪問SFT的方法了...下面給出的程式把SFT賦給ES:DI,把檔案控制程式碼儲存到BX中。

 GetSFT:
  mov  ax,1220h
  int  2Fh
  jc  BadSFT

  xor  bx,bx
  mov  ax,1216h
  mov  bl,byte ptr es:[di]
  int  2Fh
 BadSFT:
  ret

    我強烈地建議你把返回值儲存到AX/BX中(BX非常重要:這裡我們用來儲存檔案控制程式碼)。
標誌(*)的域將會被SHARE.EXE使用

%DIB(DOS Info Block DOS資訊模組)%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    利用DIB,我們能夠訪問那些重要的不能利用其它方法訪問結構。這個結構並不是固定的在記憶體中的,我們必須利用INT 21h的52h功能。在DOS文件裡沒有這個函式的介紹。當我們呼叫這個函式的時候,我們將會在ES:BX裡得到DIB的地址。你將會得到:

 ___________________________________
|       Pointer to first MCB        |<---- -0004h
|___________________________________|            Size:1 DWORD
|       Pointer to first DPB        |<-----+0000h
|___________________________________|            Size:1 DWORD
|    Pointer to DOS last buffer     |<-----+0004h
|___________________________________|            Size:1 DWORD
|        Pointer to $CLOCK          |<-----+0008h
|___________________________________|            Size:1 DWORD
|         Pointer to CON            |<-----+000Ch
|___________________________________|            Size:1 DWORD
|      Maximum sector length        |<-----+0010h
|___________________________________|            Size:1 WORD
|    Pointer to DOS first buffer    |<-----+0012h
|___________________________________|            Size:1 DWORD
| Pointer to array of cur dir struc |<-----+0016h
|___________________________________|            Size:1 DWORD
|          Pointer to SFT           |<-----+001Ah
|___________________________________|            Size:1 DWORD
                                     Total Size:34 BYTES

%DPB(Drive Parameter Block 驅動器引數模組)%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    這個結構為我們提供了達到我們的目的的非常有用的資訊。透過使用DIB(看上文)裡的第二個指標,我們能夠知道它的位置。下面給出:

 ___________________________________
|     Drive Letter(0=A,1=B...)      |<----+0000h
|___________________________________|           Size:1 BYTE
|  Unit number within device driver |<----+0001h
|___________________________________|           Size:1 BYTE
|         Bytes per sector          |<----+0002h
|___________________________________|           Size:1 WORD
| Highest sect num within a cluster |<----+0004h
|___________________________________|           Size:1 BYTE
| Shift count for clust to sectors  |<----+0005h
|___________________________________|           Size:1 BYTE
|    Number of reserved clusters    |<----+0006h
|___________________________________|           Size:1 WORD
|          Number of FATS           |<----+0008h
|___________________________________|           Size:1 BYTE
| Number of root directory entries  |<----+0009h
|___________________________________|           Size:1 WORD
| Number of first sector with data  |<----+000Bh
|___________________________________|           Size:1 WORD
|  Number of last sector with data  |<----+000Dh
|___________________________________|           Size:1 WORD
|     Number of sector per FAT      |<----+000Fh
|___________________________________|           Size:1 BYTE
| Sector number of first dir sector |<----+0010h
|___________________________________|           Size:1 WORD
|  Address of device driver header  |<----+0012h
|___________________________________|           Size:1 DWORD
|           Media ID byte           |<----+0016h
|___________________________________|           Size:1 BYTE 
|   00h if disk accessed,else FFh   |<----+0017h
|___________________________________|           Size:1 BYTE
|        Pointer to next DPB        |<----+0018h
|___________________________________|           Size:1 DWORD
                                   Total Size:28 BYTES

%分割槽表%
~~~~~~~~
    所有編寫啟動病毒的人都知道這個結構,它是硬碟上的第一塊。它總是在第一塊的,無論在軟盤還是在硬碟上。如果是硬碟,我們就叫它MBR(Master Boot Record 主啟動記錄),如果是軟盤,就叫它啟動扇區。
    分割槽表是一個有著四個入口的陣列,在偏移地址01BEh處。下面給出每個入口的格式:

 ___________________________________
|    Boot indicator(Bootable=80h,   |<----+0000h
|        Non bootable 00h)          |          Size:1 BYTE
|___________________________________|
|  Head where the partition begins  |<----+0001h
|___________________________________|          Size:1 BYTE
| Sector where the partition begins |<----+0002h
|___________________________________|          Size:1 BYTE
|   Cylinder where the part.begins  |<----+0003h
|___________________________________|          Size:1 BYTE
|    System indicator*(What OS?)    |<----+0004h
|___________________________________|          Size:1 BYTE
|     Head where partition ends     |<----+0005h
|___________________________________|          Size:1 BYTE
|  Sector where the partition ends  |<----+0006h
|___________________________________|          Size:1 BYTE
| Cylinder where the partition ends |<----+0007h
|___________________________________|          Size:1 BYTE
|  Total blocks preceding partition |<----+0008h
|___________________________________|          Size:1 DWORD
|   Total blocks in the partition   |<----+000Ch
|___________________________________|          Size:1 DWORD
                                     Total Size:16 BYTES
(*) 01=12-bit FAT
    04=16-bit FAT

%BPB(Bios Parameter Block Bios 引數模組)%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     在以DOS為基礎的系統中,啟動記錄以一個跳轉(jump)作為開始,後面跟這一個結構體――BPB。

 _________________________________
|   OEM name and version(ASCII)   |<----+0000h
|_________________________________|           Size:8 BYTES
|         Bytes per sector        |<----+0008h
|_________________________________|           Size:1 WORD
|       Sectors per cluster       |<----+000Dh
|_________________________________|           Size:1 BYTE
|  Reserved sector(starting at 0) |<----+000Eh
|_________________________________|           Size:1 WORD
|         Number of FATs          |<----+0010h
|_________________________________|           Size:1 BYTE
|    Total sectors in partition   |<----+0011h
|_________________________________|           Size:1 WORD
|         Media descriptor        |<----+0013h
|_________________________________|           Size:1 WORD
|         Sectors per FAT         |<----+0015h
|_________________________________|           Size:1 BYTE
|        Sectors per track        |<----+0017h
|_________________________________|           Size:1 WORD
|         Number of heads         |<----+0019h
|_________________________________|           Size:1 WORD
|    Number of hidden sectors     |<----+001Dh
|_________________________________|           Size:1 WORD
                                   Total Size:29 BYTES

相關文章