如何编写病毒代码学习笔记

时间:2024-02-22 18:10:50
原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题





如何编写病毒代码?

 首先我把最重要的两个方面列举出来。

  1. 处理病毒各个绝对地址的重定位。

  2. 所有需调用的api函数地址,均通过动态搜索来获得。

  做到以上2点,我们的病毒代码就可以移植到任意的程序中。没错,就和我们写shellcode一样。




先来看一些代码的优化方法:


(1)测试寄存器是否为0
     

     cmp     eax,00000000h                   ; 6 bytes
     jz      bribriblibli                    ; 2 bytes (if jz is short)
     

  
  optimization:
     
     or      eax,eax                         ; 2 bytes
     jz      bribriblibli                       ; 2 bytes (if jz is short)



     xchg    eax,ecx                         ; 1 byte
     jecxz   bribriblibli                   ; 2 bytes (if it is short)



 (2)测试寄存器是否为-1

     cmp     eax,0FFFFFFFFh                  ; 6 bytes
     jz      insumision                    ; 2 bytes (if short)

 optimization:

     inc     eax                                   ; 1 byte
     xchg    eax,ecx                            ; 1 byte
     jecxz   insumision                         ; 2 bytes (if short)
     dec     ecx                                 ; 1 byte 


     inc     eax                                  ; 1 byte
     jz      insumision                        ; 2 bytes
     dec     eax                                ; 1 byte


 (3)寄存器清0并传送低位字数值

    xor     eax,eax                         ; 2 bytes
     mov     ax,word ptr [esi+6]             ; 4 bytes

 optimization:

     movzx   eax,word ptr [esi+6]            ; 4 bytes

 (4) 关于push的优化

    mov   eax, 50h                   ; 5 bytes

 optimization:
     push  50h                        ; 2 bytes 
     pop      eax                        ; 1 bytes
     


     push   0                         ; 2 bytes 
     push   0                         ; 2 bytes 
     push   0                         ; 2 bytes 
     push   0                         ; 2 bytes 
     push   0                         ; 2 bytes 
     push   0                         ; 2 bytes 
     push   0                         ; 2 bytes 

 optimization:

     xor   eax, eax                           ; 2 bytes 
     push   eax                     ; 1 byte 
     push   eax                     ; 1 byte 
     push   eax                     ; 1 byte 
     push   eax                     ; 1 byte 
     push   eax                     ; 1 byte 
     push   eax                     ; 1 byte 
     push   eax                     ; 1 byte 


     push   7                         ; 2 bytes 
     pop   ecx                     ; 1 byte 
 _loop: 
     push   0                         ; 2 bytes 
     loop   _loop                    ; 2 bytes 

 (5) 操作FS寄存器相关优化

    push    dword ptr fs:[00000000h]        ; 6 bytes
     mov     fs:[0],esp                      ; 6 bytes
     [...]
     pop     dword ptr fs:[00000000h]        ; 6 bytes
     
 optimization:

     xor     eax,eax                         ; 2 bytes
     push    dword ptr fs:[eax]              ; 3 bytes
     mov     fs:[eax],esp                    ; 3 bytes
     [...]
     pop     dword ptr fs:[eax]              ; 3 bytes

 (6) 字符串操作

    mov al/ax/eax, [esi]                ; 2/3/2 bytes 
     inc esi                          ; 1 byte 

 optimization:
     lodsb/w/d                          ; 1 or 2 byte 

  到达字符串尾部。

    lea     edi,[ebp+ASCIIz_variable]       ; 6 bytes
  @@1:   
     cmp     byte ptr [edi],00h              ; 3 bytes
     inc     edi                             ; 1 byte
     jz      @@2                             ; 2 bytes
     jmp     @@1                             ; 2 bytes
  @@2:   
     inc     edi                             ; 1 byte

 optimization:
     lea     edi,[ebp+ASCIIz_variable]       ; 6 bytes
     xor     al,al                           ; 2 bytes
  @@1:   
     scasb                                   ; 1 byte
     jnz     @@1                             ; 2 bytes



 (7)乘法 

     mov     ecx,28h                         ; 5 bytes
     mul     ecx                             ; 2 bytes


 optimization:
     imul    eax,eax,28h                     ; 3 bytes



 (8)置edx寄存器为0.
     xor  edx, edx                      ; 2 bytes

 optimization:
     cdq                              ; 1 bytes



 (9)交换寄存器4字节的顺序

    mov eax, 00200000h                   ; 5 bytes 
     bswap eax                         ; 2 bytes 
     ;eax = 00002000h now 



 (10)乘2、除2

     shl   eax, 1                     ; 2 bytes
     ;*2
     
     shr  eax, 1                        ; 2 bytes
     ;/2      

 (11)分配堆栈空间

    push    ebp                             ; 1 byte
     mov     ebp,esp                         ; 2 bytes
     sub     esp,20h                         ; 3 bytes

 optimization:
     enter   20h,00h                         ; 4 bytes



 (12)压入字符串指针时尽量使用
    call  @f
     db  \'string\', 0
     @@:

下面的代码例子,是首先通过VirtualAlloc申请一段ShellcodeSize大小的可读可写可执行内存区,然后将我们按照病毒思路编写的Shellcode Copy到申请的内存区中。然后call eax, 跳转到我们申请的内存区中去执行。从这个例子我们可以看到,我们的Shellcode(Virus Code)可以移植到任意的内存地址中去执行,它完成了我们预期想要的目的

.386  
02.    .model flat, stdcall  
03.    option casemap:none  
04.      
05.include windows.inc  
06.include kernel32.inc  
07.includelib kernel32.lib  
08.  
09.    .code  
10.      
11.ShellCode:  
12.    call GetKrnlBase        ; Get kernel32.dll base address  
13.    call Dels  
14.Dels:  
15.    pop ebx  
16.    sub ebx, Dels  
17.    lea edi, [ebx + szFuncs]    ; 重定位szFuncs  
18.    push edi            ; szFuncs  
19.    push eax            ; kernel32.dll base address  
20.    call GetFuncAddress  
21.    call @f  
22.    db \'user32.dll\', 0  
23.@@:  
24.    call dword ptr [edi]        ; LoadLibrary user32  
25.      
26.    push edi  
27.    push eax  
28.    call GetFuncAddress     ; Get User32 Func  
29.      
30.    mov edx, edi            ; edx = szFuncs的偏移  
31.    add edx, szText - szFuncs   ; edx加上szFuncs和szText的偏移 = szText  
32.      
33.    xor eax, eax  
34.    push eax  
35.    push eax              
36.    push edx            ; push szText  
37.    push eax  
38.    call dword ptr [edi + 4]    ; MessageBoxA  
39.    ret  
40.      
41.szFuncs     dd 0a412fd89h       ; LoadLibraryA  
42.        dd 014d14c51h       ; MessageBoxA  
43.        dd 0  
44.szText      db \'如何编写病毒代码例子\', 0  
45.  
46.GetKrnlBase:  
47.  
48.    assume fs:nothing  
49.    mov eax, fs:[30h]  
50.    mov eax, [eax + 0ch]  
51.    mov eax, [eax + 1ch]        ; 第一个LDR_MODULE  
52.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
53.; 压入kernel32.dll的unicode字符串  
54.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
55.    push dword ptr 006ch  
56.    push dword ptr 6c0064h      
57.        push dword ptr 2e0032h      
58.        push dword ptr 33006ch      
59.        push dword ptr 65006eh      
60.        push dword ptr 720065h      
61.        push word ptr 006bh      
62.        mov ebx, esp            ; ebx指向字符串  
63.          
64._Search:  
65.    or eax, eax  
66.    jz _NotFound  
67.    inc eax  
68.    jz _NotFound  
69.    dec eax  
70.    lea esi, [eax + 1ch]    ; esi指向UNICODE_STRING结构  
71.    xor ecx, ecx  
72.    mov cx, 13      ; 比较长度  
73.    mov esi, [esi + 4]  ; 获得UNICODE_STRING结构的Buffer成员  
74.    mov edi, ebx        ; edi指向kernel32unicode字符串  
75.    repz cmpsw  
76.    or ecx, ecx     ; ecx减完说明相等  
77.    jz _Found  
78.    mov eax, [eax]      ; 获取下一个LDR_MODULE  
79.    jmp _Search  
80.      
81._NotFound:  
82.    or eax, 0ffffffffh  
83.    jmp _Over  
84.      
85._Found:  
86.    mov eax, [eax + 08h]    ; 获得地址  
87.      
88._Over:  
89.    add esp, 26  
90.    ret  
91.  
92.GetFuncAddress:  
93.  
94.    pushad  
95.    mov  ebx, [esp + 4 * 8 + 4]     ; ebx  = hModule  
96.    mov edx, [ebx + 3ch]        ; PE  
97.    mov esi, [ebx + edx + 78h]  ; Export Table RVA  
98.    lea esi, [esi + ebx + 18h]  ; Export Table VA+18H NumberOfNames  
99.    lodsd  
100.    xchg eax, ecx  
101.    lodsd  
102.    add eax, ebx  
103.    xchg eax, ebp           ; ebp = AddressOfFunctions  
104.    lodsd  
105.    add eax, ebx  
106.    xchg eax, edx           ; edx = AddressOfNames  
107.    lodsd  
108.    add eax, ebx  
109.    push eax            ; [esp] = AddressOfNameOrdinals  
110.    mov esi, edx  
111.      
112._Next_Func:  
113.    lodsd  
114.    add eax, ebx  
115.      
116.    ; Make Func Hash  
117.    xor edx, edx  
118._Make_Hash:  
119.    rol edx, 3  
120.    xor dl, byte ptr [eax]  
121.    inc eax  
122.    cmp byte ptr [eax], 0  
123.    jnz _Make_Hash  
124.      
125.    mov eax, [esp]  
126.    add dword ptr [esp], 2  
127.    mov edi, [esp + 4 * 8 + 8 + 4]  
128._Scan_Dw_Funcs:  
129.    cmp dword ptr [edi], edx  
130.    jnz _Next_List          ; 不等于比较hash list的下一个hash  
131.      
132.    movzx eax, word ptr [eax]  
133.    mov eax, [ebp + eax * 4]  
134.    add eax, ebx            ; 获得api地址  
135.    stosd               ; 将其填充到对应的edi指向的hash list处  
136.    jmp _Ret  
137.      
138._Next_List:  
139.    scasd               ; 增加edi使其指向下一个hash  
140.    cmp dword ptr [edi], 0  
141.    jnz _Scan_Dw_Funcs    
142.  
143._Ret:  
144.    loop _Next_Func  
145.    pop ecx  
146.    popad  
147.    ret 4 * 2  
148.  
149.ShellCodeSize equ $ - ShellCode     ; ShellCode到此处的代码长度  
150.      
151.Start:  
152.    invoke VirtualAlloc, NULL, ShellCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE  
153.    pushad  
154.    push ShellCodeSize  
155.    pop ecx  
156.    push ShellCode  
157.    pop esi  
158.    xchg eax, edi  
159.    rep movsb  
160.    popad  
161.    call eax  
162.    ret  
163.      
164.    end Start  
View Code